mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-16 10:53:31 +00:00
Merge
This commit is contained in:
commit
2dbed37b5e
@ -135,15 +135,11 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
|
||||
}
|
||||
// Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
|
||||
if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
|
||||
if(functionNode.isNamedFunctionExpression() && !functionNode.usesSelfSymbol()) {
|
||||
final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
|
||||
if(selfSymbol != null) {
|
||||
if(selfSymbol.isFunctionSelf()) {
|
||||
selfSymbol.setNeedsSlot(false);
|
||||
selfSymbol.clearFlag(Symbol.IS_VAR);
|
||||
}
|
||||
} else {
|
||||
assert functionNode.isProgram();
|
||||
if(selfSymbol != null && selfSymbol.isFunctionSelf()) {
|
||||
selfSymbol.setNeedsSlot(false);
|
||||
selfSymbol.clearFlag(Symbol.IS_VAR);
|
||||
}
|
||||
}
|
||||
return functionNode;
|
||||
@ -189,7 +185,7 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
* @param body the body of the FunctionNode we are entering
|
||||
*/
|
||||
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
|
||||
// This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers.
|
||||
// This visitor will assign symbol to all declared variables.
|
||||
body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
|
||||
@Override
|
||||
protected boolean enterDefault(final Node node) {
|
||||
@ -200,16 +196,17 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
|
||||
@Override
|
||||
public Node leaveVarNode(final VarNode varNode) {
|
||||
if (varNode.isStatement()) {
|
||||
final IdentNode ident = varNode.getName();
|
||||
final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body;
|
||||
final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
|
||||
if (varNode.isFunctionDeclaration()) {
|
||||
symbol.setIsFunctionDeclaration();
|
||||
}
|
||||
return varNode.setName(ident.setSymbol(symbol));
|
||||
final IdentNode ident = varNode.getName();
|
||||
final boolean blockScoped = varNode.isBlockScoped();
|
||||
if (blockScoped && lc.inUnprotectedSwitchContext()) {
|
||||
throwUnprotectedSwitchError(varNode);
|
||||
}
|
||||
return varNode;
|
||||
final Block block = blockScoped ? lc.getCurrentBlock() : body;
|
||||
final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
|
||||
if (varNode.isFunctionDeclaration()) {
|
||||
symbol.setIsFunctionDeclaration();
|
||||
}
|
||||
return varNode.setName(ident.setSymbol(symbol));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -356,6 +353,10 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
|
||||
} else {
|
||||
symbol.setHasBeenDeclared();
|
||||
// Set scope flag on top-level block scoped symbols
|
||||
if (function.isProgram() && function.getBody() == block) {
|
||||
symbol.setIsScope();
|
||||
}
|
||||
}
|
||||
} else if ((flags & IS_INTERNAL) != 0) {
|
||||
// Always create a new definition.
|
||||
@ -485,20 +486,31 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
final Block body = lc.getCurrentBlock();
|
||||
|
||||
initFunctionWideVariables(functionNode, body);
|
||||
acceptDeclarations(functionNode, body);
|
||||
defineFunctionSelfSymbol(functionNode, body);
|
||||
}
|
||||
|
||||
if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
|
||||
// It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
|
||||
// anonymous.
|
||||
final String name = functionNode.getIdent().getName();
|
||||
assert name != null;
|
||||
assert body.getExistingSymbol(name) == null;
|
||||
defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
|
||||
if(functionNode.allVarsInScope()) { // basically, has deep eval
|
||||
lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
|
||||
}
|
||||
private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
|
||||
// Function self-symbol is only declared as a local variable for named function expressions. Declared functions
|
||||
// don't need it as they are local variables in their declaring scope.
|
||||
if (!functionNode.isNamedFunctionExpression()) {
|
||||
return;
|
||||
}
|
||||
|
||||
acceptDeclarations(functionNode, body);
|
||||
final String name = functionNode.getIdent().getName();
|
||||
assert name != null; // As it's a named function expression.
|
||||
|
||||
if (body.getExistingSymbol(name) != null) {
|
||||
// Body already has a declaration for the name. It's either a parameter "function x(x)" or a
|
||||
// top-level variable "function x() { ... var x; ... }".
|
||||
return;
|
||||
}
|
||||
|
||||
defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
|
||||
if(functionNode.allVarsInScope()) { // basically, has deep eval
|
||||
// We must conservatively presume that eval'd code can dynamically use the function symbol.
|
||||
lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -540,7 +552,7 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
final int flags;
|
||||
if (varNode.isAnonymousFunctionDeclaration()) {
|
||||
flags = IS_INTERNAL;
|
||||
} else if (lc.getCurrentFunction().isProgram()) {
|
||||
} else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
|
||||
flags = IS_SCOPE;
|
||||
} else {
|
||||
flags = 0;
|
||||
@ -1044,6 +1056,15 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
return !(units == null || units.isEmpty());
|
||||
}
|
||||
|
||||
private void throwUnprotectedSwitchError(final VarNode varNode) {
|
||||
// Block scoped declarations in switch statements without explicit blocks should be declared
|
||||
// in a common block that contains all the case clauses. We cannot support this without a
|
||||
// fundamental rewrite of how switch statements are handled (case nodes contain blocks and are
|
||||
// directly contained by switch node). As a temporary solution we throw a reference error here.
|
||||
final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const");
|
||||
throwParserException(msg, varNode);
|
||||
}
|
||||
|
||||
private void throwParserException(final String message, final Node origin) {
|
||||
if (origin == null) {
|
||||
throw new ParserException(message);
|
||||
|
||||
@ -48,11 +48,13 @@ final class AstSerializer {
|
||||
private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
|
||||
static byte[] serialize(final FunctionNode fn) {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out,
|
||||
new Deflater(COMPRESSION_LEVEL)))) {
|
||||
final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
|
||||
try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
|
||||
oout.writeObject(removeInnerFunctionBodies(fn));
|
||||
} catch (final IOException e) {
|
||||
throw new AssertionError("Unexpected exception serializing function", e);
|
||||
} finally {
|
||||
deflater.end();
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@ -3080,6 +3080,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
if (isConditionalCatch) {
|
||||
loadExpressionAsBoolean(exceptionCondition);
|
||||
nextCatch = new Label("next_catch");
|
||||
nextCatch.markAsBreakTarget();
|
||||
method.ifeq(nextCatch);
|
||||
} else {
|
||||
nextCatch = null;
|
||||
@ -3092,7 +3093,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
method._goto(afterCatch);
|
||||
}
|
||||
if(nextCatch != null) {
|
||||
method.label(nextCatch);
|
||||
method.breakLabel(nextCatch, lc.getUsedSlotCount());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3264,6 +3265,13 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
emitContinueLabel(continueLabel, liveLocalsOnContinue);
|
||||
}
|
||||
|
||||
if (loopNode.hasPerIterationScope() && lc.getParentBlock().needsScope()) {
|
||||
// ES6 for loops with LET init need a new scope for each iteration. We just create a shallow copy here.
|
||||
method.loadCompilerConstant(SCOPE);
|
||||
method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
|
||||
method.storeCompilerConstant(SCOPE);
|
||||
}
|
||||
|
||||
if(method.isReachable()) {
|
||||
if(modify != null) {
|
||||
lineNumber(loopNode);
|
||||
|
||||
@ -525,7 +525,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Lo
|
||||
|
||||
if (isAlwaysTrue(test)) {
|
||||
//turn it into a for node without a test.
|
||||
final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, ForNode.IS_FOR).accept(this);
|
||||
final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, 0).accept(this);
|
||||
lc.replace(whileNode, forNode);
|
||||
return forNode;
|
||||
}
|
||||
|
||||
@ -152,6 +152,10 @@ public class MapCreator<T> {
|
||||
flags |= Property.NOT_WRITABLE;
|
||||
}
|
||||
|
||||
if (symbol.isBlockScoped()) {
|
||||
flags |= Property.IS_LEXICAL_BINDING;
|
||||
}
|
||||
|
||||
// Mark symbol as needing declaration. Access before declaration will throw a ReferenceError.
|
||||
if (symbol.isBlockScoped() && symbol.isScope()) {
|
||||
flags |= Property.NEEDS_DECLARATION;
|
||||
|
||||
@ -45,14 +45,14 @@ public final class ForNode extends LoopNode {
|
||||
/** Iterator symbol. */
|
||||
private Symbol iterator;
|
||||
|
||||
/** Is this a normal for loop? */
|
||||
public static final int IS_FOR = 1 << 0;
|
||||
|
||||
/** Is this a normal for in loop? */
|
||||
public static final int IS_FOR_IN = 1 << 1;
|
||||
public static final int IS_FOR_IN = 1 << 0;
|
||||
|
||||
/** Is this a normal for each in loop? */
|
||||
public static final int IS_FOR_EACH = 1 << 2;
|
||||
public static final int IS_FOR_EACH = 1 << 1;
|
||||
|
||||
/** Does this loop need a per-iteration scope because its init contain a LET declaration? */
|
||||
public static final int PER_ITERATION_SCOPE = 1 << 2;
|
||||
|
||||
private final int flags;
|
||||
|
||||
@ -264,4 +264,9 @@ public final class ForNode extends LoopNode {
|
||||
JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
|
||||
return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPerIterationScope() {
|
||||
return (flags & PER_ITERATION_SCOPE) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1091,6 +1091,15 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
|
||||
return getFlag(USES_SELF_SYMBOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
|
||||
* anonymous function expression, and it isn't a program).
|
||||
* @return true if this is a named function expression
|
||||
*/
|
||||
public boolean isNamedFunctionExpression() {
|
||||
return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(final Function<Symbol, Type> localVariableTypes) {
|
||||
return FUNCTION_TYPE;
|
||||
|
||||
@ -597,6 +597,20 @@ public class LexicalContext {
|
||||
throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the current context is inside a switch statement without explicit blocks (curly braces).
|
||||
* @return true if in unprotected switch statement
|
||||
*/
|
||||
public boolean inUnprotectedSwitchContext() {
|
||||
for (int i = sp; i > 0; i--) {
|
||||
final LexicalContextNode next = stack[i];
|
||||
if (next instanceof Block) {
|
||||
return stack[i - 1] instanceof SwitchNode;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
|
||||
@ -177,4 +177,10 @@ public abstract class LoopNode extends BreakableStatement {
|
||||
* @return new loop node if changed otherwise the same
|
||||
*/
|
||||
public abstract LoopNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes);
|
||||
|
||||
/**
|
||||
* Does this loop have a LET declaration and hence require a per-iteration scope?
|
||||
* @return true if a per-iteration scope is required.
|
||||
*/
|
||||
public abstract boolean hasPerIterationScope();
|
||||
}
|
||||
|
||||
@ -45,19 +45,16 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
|
||||
/** Is this a var statement (as opposed to a "var" in a for loop statement) */
|
||||
private final int flags;
|
||||
|
||||
/** Flag that determines if this function node is a statement */
|
||||
public static final int IS_STATEMENT = 1 << 0;
|
||||
|
||||
/** Flag for ES6 LET declaration */
|
||||
public static final int IS_LET = 1 << 1;
|
||||
public static final int IS_LET = 1 << 0;
|
||||
|
||||
/** Flag for ES6 CONST declaration */
|
||||
public static final int IS_CONST = 1 << 2;
|
||||
public static final int IS_CONST = 1 << 1;
|
||||
|
||||
/** Flag that determines if this is the last function declaration in a function
|
||||
* This is used to micro optimize the placement of return value assignments for
|
||||
* a program node */
|
||||
public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 3;
|
||||
public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 2;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -69,7 +66,7 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
|
||||
* @param init init node or null if just a declaration
|
||||
*/
|
||||
public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init) {
|
||||
this(lineNumber, token, finish, name, init, IS_STATEMENT);
|
||||
this(lineNumber, token, finish, name, init, 0);
|
||||
}
|
||||
|
||||
private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) {
|
||||
@ -259,14 +256,6 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
|
||||
return setFlags(flags | flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a var statement (as opposed to a var initializer in a for loop).
|
||||
* @return true if this is a var statement (as opposed to a var initializer in a for loop).
|
||||
*/
|
||||
public boolean isStatement() {
|
||||
return (flags & IS_STATEMENT) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a function declaration.
|
||||
* @return true if this is a function declaration.
|
||||
|
||||
@ -150,4 +150,9 @@ public final class WhileNode extends LoopNode {
|
||||
}
|
||||
return test == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPerIterationScope() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
@ -44,6 +45,7 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.api.scripting.ClassFilter;
|
||||
@ -54,6 +56,8 @@ import jdk.nashorn.internal.objects.annotations.Property;
|
||||
import jdk.nashorn.internal.objects.annotations.ScriptClass;
|
||||
import jdk.nashorn.internal.runtime.ConsString;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ECMAErrors;
|
||||
import jdk.nashorn.internal.runtime.GlobalConstants;
|
||||
import jdk.nashorn.internal.runtime.GlobalFunctions;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.NativeJavaPackage;
|
||||
@ -69,6 +73,7 @@ import jdk.nashorn.internal.runtime.Specialization;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayData;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
import jdk.nashorn.internal.runtime.linker.InvokeByName;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
import jdk.nashorn.internal.runtime.regexp.RegExpResult;
|
||||
import jdk.nashorn.internal.scripts.JO;
|
||||
|
||||
@ -410,13 +415,14 @@ public final class Global extends ScriptObject implements Scope {
|
||||
// Used to store the last RegExp result to support deprecated RegExp constructor properties
|
||||
private RegExpResult lastRegExpResult;
|
||||
|
||||
private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
|
||||
private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
|
||||
private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
|
||||
|
||||
// initialized by nasgen
|
||||
private static PropertyMap $nasgenmap$;
|
||||
@ -429,6 +435,12 @@ public final class Global extends ScriptObject implements Scope {
|
||||
// current ScriptEngine associated - can be null.
|
||||
private ScriptEngine engine;
|
||||
|
||||
// ES6 global lexical scope.
|
||||
private final LexicalScope lexicalScope;
|
||||
|
||||
// Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
|
||||
private SwitchPoint lexicalScopeSwitchPoint;
|
||||
|
||||
/**
|
||||
* Set the current script context
|
||||
* @param scontext script context
|
||||
@ -466,6 +478,7 @@ public final class Global extends ScriptObject implements Scope {
|
||||
super(checkAndGetMap(context));
|
||||
this.context = context;
|
||||
this.setIsScope();
|
||||
this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1693,6 +1706,133 @@ public final class Global extends ScriptObject implements Scope {
|
||||
splitState = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ES6 global scope for lexically declared bindings.
|
||||
* @return the ES6 lexical global scope.
|
||||
*/
|
||||
public final ScriptObject getLexicalScope() {
|
||||
assert context.getEnv()._es6;
|
||||
return lexicalScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
|
||||
PropertyMap ownMap = getMap();
|
||||
LexicalScope lexicalScope = null;
|
||||
PropertyMap lexicalMap = null;
|
||||
boolean hasLexicalDefinitions = false;
|
||||
|
||||
if (context.getEnv()._es6) {
|
||||
lexicalScope = (LexicalScope) getLexicalScope();
|
||||
lexicalMap = lexicalScope.getMap();
|
||||
|
||||
for (final jdk.nashorn.internal.runtime.Property property : properties) {
|
||||
if (property.isLexicalBinding()) {
|
||||
hasLexicalDefinitions = true;
|
||||
}
|
||||
// ES6 15.1.8 steps 6. and 7.
|
||||
final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
|
||||
if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
|
||||
throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
|
||||
}
|
||||
final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
|
||||
if (lexicalProperty != null && !property.isConfigurable()) {
|
||||
throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final jdk.nashorn.internal.runtime.Property property : properties) {
|
||||
if (property.isLexicalBinding()) {
|
||||
assert lexicalScope != null;
|
||||
lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
|
||||
|
||||
if (ownMap.findProperty(property.getKey()) != null) {
|
||||
// If property exists in the global object invalidate any global constant call sites.
|
||||
invalidateGlobalConstant(property.getKey());
|
||||
}
|
||||
} else {
|
||||
ownMap = addBoundProperty(ownMap, source, property);
|
||||
}
|
||||
}
|
||||
|
||||
setMap(ownMap);
|
||||
|
||||
if (hasLexicalDefinitions) {
|
||||
lexicalScope.setMap(lexicalMap);
|
||||
invalidateLexicalSwitchPoint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
|
||||
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
|
||||
final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
|
||||
|
||||
if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
|
||||
if (lexicalScope.hasOwnProperty(name)) {
|
||||
return lexicalScope.findGetMethod(desc, request, operator);
|
||||
}
|
||||
}
|
||||
|
||||
final GuardedInvocation invocation = super.findGetMethod(desc, request, operator);
|
||||
|
||||
// We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
|
||||
// because those are invalidated per-key in the addBoundProperties method above.
|
||||
// We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
|
||||
// assuming this only applies to global constants. If other non-inherited properties will
|
||||
// start using switchpoints some time in the future we'll have to revisit this.
|
||||
if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
|
||||
return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
|
||||
}
|
||||
|
||||
return invocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
|
||||
final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
|
||||
|
||||
if (lexicalScope != null && isScope) {
|
||||
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
|
||||
if (lexicalScope.hasOwnProperty(name)) {
|
||||
return lexicalScope.findSetMethod(desc, request);
|
||||
}
|
||||
}
|
||||
|
||||
final GuardedInvocation invocation = super.findSetMethod(desc, request);
|
||||
|
||||
if (isScope && context.getEnv()._es6) {
|
||||
return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
|
||||
}
|
||||
|
||||
return invocation;
|
||||
}
|
||||
|
||||
private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
|
||||
SwitchPoint switchPoint = lexicalScopeSwitchPoint;
|
||||
if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
|
||||
switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
|
||||
}
|
||||
return switchPoint;
|
||||
}
|
||||
|
||||
private synchronized void invalidateLexicalSwitchPoint() {
|
||||
if (lexicalScopeSwitchPoint != null) {
|
||||
context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
|
||||
SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static Object lexicalScopeFilter(final Object self) {
|
||||
if (self instanceof Global) {
|
||||
return ((Global) self).getLexicalScope();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
|
||||
final T func = initConstructor(name, clazz);
|
||||
tagBuiltinProperties(name, func);
|
||||
@ -1737,7 +1877,7 @@ public final class Global extends ScriptObject implements Scope {
|
||||
this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
|
||||
this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
|
||||
this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
|
||||
this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
|
||||
this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
|
||||
this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
|
||||
this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
|
||||
|
||||
@ -2203,4 +2343,36 @@ public final class Global extends ScriptObject implements Scope {
|
||||
protected boolean isGlobal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class representing the ES6 global lexical scope.
|
||||
*/
|
||||
private static class LexicalScope extends ScriptObject {
|
||||
|
||||
LexicalScope(final ScriptObject proto) {
|
||||
super(proto, PropertyMap.newMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
|
||||
return filterInvocation(super.findGetMethod(desc, request, operator));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
|
||||
return filterInvocation(super.findSetMethod(desc, request));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
|
||||
// We override this method just to make it callable by Global
|
||||
return super.addBoundProperty(propMap, source, property);
|
||||
}
|
||||
|
||||
private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
|
||||
final MethodType type = invocation.getInvocation().type();
|
||||
return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -105,10 +105,10 @@ public class NativeDataView extends ScriptObject {
|
||||
|
||||
private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset, final int length) {
|
||||
super(Global.instance().getDataViewPrototype(), $nasgenmap$);
|
||||
this.buffer = arrBuf;
|
||||
this.buffer = arrBuf;
|
||||
this.byteOffset = offset;
|
||||
this.byteLength = length;
|
||||
this.buf = buf;
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,14 +135,14 @@ public class NativeDataView extends ScriptObject {
|
||||
throw typeError("not.an.arraybuffer.in.dataview");
|
||||
}
|
||||
|
||||
final NativeArrayBuffer arrBuf = (NativeArrayBuffer) args[0];
|
||||
final NativeArrayBuffer arrBuf = (NativeArrayBuffer)args[0];
|
||||
switch (args.length) {
|
||||
case 1:
|
||||
return new NativeDataView(arrBuf);
|
||||
case 2:
|
||||
return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
|
||||
default:
|
||||
return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
|
||||
case 1:
|
||||
return new NativeDataView(arrBuf);
|
||||
case 2:
|
||||
return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
|
||||
default:
|
||||
return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,7 +995,7 @@ public class NativeDataView extends ScriptObject {
|
||||
|
||||
private static NativeDataView checkSelf(final Object self) {
|
||||
if (!(self instanceof NativeDataView)) {
|
||||
throw typeError("not.an.arraybuffer", ScriptRuntime.safeToString(self));
|
||||
throw typeError("not.an.arraybuffer.in.dataview", ScriptRuntime.safeToString(self));
|
||||
}
|
||||
return (NativeDataView)self;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ import jdk.nashorn.internal.runtime.ScriptEnvironment;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
|
||||
/**
|
||||
* ECMA 15.3 Function Objects
|
||||
@ -204,11 +205,7 @@ public final class NativeFunction {
|
||||
* @return function with bound arguments
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
|
||||
public static ScriptFunction bind(final Object self, final Object... args) {
|
||||
if (!(self instanceof ScriptFunction)) {
|
||||
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
|
||||
}
|
||||
|
||||
public static Object bind(final Object self, final Object... args) {
|
||||
final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
|
||||
|
||||
Object[] arguments;
|
||||
@ -219,7 +216,7 @@ public final class NativeFunction {
|
||||
arguments = ScriptRuntime.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
return ((ScriptFunctionImpl)self).makeBoundFunction(thiz, arguments);
|
||||
return Bootstrap.bindCallable(self, thiz, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -28,6 +28,7 @@ package jdk.nashorn.internal.objects;
|
||||
import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
@ -498,7 +499,7 @@ public final class NativeObject {
|
||||
final Object obj = JSType.toScriptObject(self);
|
||||
if (obj instanceof ScriptObject) {
|
||||
final InvokeByName toStringInvoker = getTO_STRING();
|
||||
final ScriptObject sobj = (ScriptObject)self;
|
||||
final ScriptObject sobj = (ScriptObject)obj;
|
||||
try {
|
||||
final Object toString = toStringInvoker.getGetter().invokeExact(sobj);
|
||||
|
||||
@ -804,7 +805,7 @@ public final class NativeObject {
|
||||
// name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is
|
||||
// constant for any given method name and object's class.)
|
||||
return MethodHandles.dropArguments(MethodHandles.constant(Object.class,
|
||||
Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class);
|
||||
Bootstrap.bindCallable(methodGetter.invoke(source), source, null)), 0, Object.class);
|
||||
} catch(RuntimeException|Error e) {
|
||||
throw e;
|
||||
} catch(final Throwable t) {
|
||||
|
||||
@ -30,7 +30,6 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jdk.nashorn.internal.runtime.AccessorProperty;
|
||||
import jdk.nashorn.internal.runtime.GlobalFunctions;
|
||||
import jdk.nashorn.internal.runtime.Property;
|
||||
@ -237,13 +236,13 @@ public class ScriptFunctionImpl extends ScriptFunction {
|
||||
|
||||
/**
|
||||
* Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we
|
||||
* can expose it to methods in this package.
|
||||
* can expose it.
|
||||
* @param self the self to bind to this function. Can be null (in which case, null is bound as this).
|
||||
* @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
|
||||
* @return a function with the specified self and parameters bound.
|
||||
*/
|
||||
@Override
|
||||
protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
|
||||
public ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
|
||||
return super.makeBoundFunction(self, args);
|
||||
}
|
||||
|
||||
|
||||
@ -554,7 +554,7 @@ loop:
|
||||
// Set up new block. Captures first token.
|
||||
final ParserContextBlockNode newBlock = newBlock();
|
||||
try {
|
||||
statement();
|
||||
statement(false, false, true);
|
||||
} finally {
|
||||
restoreBlock(newBlock);
|
||||
}
|
||||
@ -703,26 +703,12 @@ loop:
|
||||
Collections.<IdentNode>emptyList());
|
||||
lc.push(script);
|
||||
final ParserContextBlockNode body = newBlock();
|
||||
// If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations.
|
||||
final int startLine = start;
|
||||
final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
|
||||
functionDeclarations = new ArrayList<>();
|
||||
|
||||
try {
|
||||
sourceElements(allowPropertyFunction);
|
||||
addFunctionDeclarations(script);
|
||||
} finally {
|
||||
if (outer != null) {
|
||||
restoreBlock(outer);
|
||||
appendStatement(new BlockStatement(
|
||||
startLine,
|
||||
new Block(
|
||||
functionToken,
|
||||
startLine, outer.getFlags(),
|
||||
outer.getStatements())));
|
||||
}
|
||||
}
|
||||
functionDeclarations = new ArrayList<>();
|
||||
sourceElements(allowPropertyFunction);
|
||||
addFunctionDeclarations(script);
|
||||
functionDeclarations = null;
|
||||
|
||||
restoreBlock(body);
|
||||
body.setFlag(Block.NEEDS_SCOPE);
|
||||
final Block programBody = new Block(functionToken, functionLine, body.getFlags(), body.getStatements());
|
||||
@ -784,7 +770,7 @@ loop:
|
||||
|
||||
try {
|
||||
// Get the next element.
|
||||
statement(true, allowPropertyFunction);
|
||||
statement(true, allowPropertyFunction, false);
|
||||
allowPropertyFunction = false;
|
||||
|
||||
// check for directive prologues
|
||||
@ -874,13 +860,15 @@ loop:
|
||||
* Parse any of the basic statement types.
|
||||
*/
|
||||
private void statement() {
|
||||
statement(false, false);
|
||||
statement(false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param topLevel does this statement occur at the "top level" of a script or a function?
|
||||
* @param allowPropertyFunction allow property "get" and "set" functions?
|
||||
* @param singleStatement are we in a single statement context?
|
||||
*/
|
||||
private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
|
||||
private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
|
||||
if (type == FUNCTION) {
|
||||
// As per spec (ECMA section 12), function declarations as arbitrary statement
|
||||
// is not "portable". Implementation can issue a warning or disallow the same.
|
||||
@ -944,6 +932,9 @@ loop:
|
||||
break;
|
||||
default:
|
||||
if (useBlockScope() && (type == LET || type == CONST)) {
|
||||
if (singleStatement) {
|
||||
throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
|
||||
}
|
||||
variableStatement(type, true);
|
||||
break;
|
||||
}
|
||||
@ -1069,7 +1060,7 @@ loop:
|
||||
next();
|
||||
|
||||
final List<VarNode> vars = new ArrayList<>();
|
||||
int varFlags = VarNode.IS_STATEMENT;
|
||||
int varFlags = 0;
|
||||
if (varType == LET) {
|
||||
varFlags |= VarNode.IS_LET;
|
||||
} else if (varType == CONST) {
|
||||
@ -1214,7 +1205,6 @@ loop:
|
||||
final int startLine = start;
|
||||
final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
|
||||
|
||||
|
||||
// Create FOR node, capturing FOR token.
|
||||
final ParserContextLoopNode forNode = new ParserContextLoopNode();
|
||||
lc.push(forNode);
|
||||
@ -1242,19 +1232,22 @@ loop:
|
||||
|
||||
switch (type) {
|
||||
case VAR:
|
||||
// Var statements captured in for outer block.
|
||||
// Var declaration captured in for outer block.
|
||||
vars = variableStatement(type, false);
|
||||
break;
|
||||
case SEMICOLON:
|
||||
break;
|
||||
default:
|
||||
if (useBlockScope() && (type == LET || type == CONST)) {
|
||||
// LET/CONST captured in container block created above.
|
||||
if (type == LET) {
|
||||
flags |= ForNode.PER_ITERATION_SCOPE;
|
||||
}
|
||||
// LET/CONST declaration captured in container block created above.
|
||||
vars = variableStatement(type, false);
|
||||
break;
|
||||
}
|
||||
if (env._const_as_var && type == CONST) {
|
||||
// Var statements captured in for outer block.
|
||||
// Var declaration captured in for outer block.
|
||||
vars = variableStatement(TokenType.VAR, false);
|
||||
break;
|
||||
}
|
||||
@ -1330,22 +1323,23 @@ loop:
|
||||
body = getStatement();
|
||||
} finally {
|
||||
lc.pop(forNode);
|
||||
if (vars != null) {
|
||||
for (final VarNode var : vars) {
|
||||
appendStatement(var);
|
||||
}
|
||||
}
|
||||
if (body != null) {
|
||||
appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
|
||||
}
|
||||
if (outer != null) {
|
||||
restoreBlock(outer);
|
||||
appendStatement(new BlockStatement(startLine, new Block(
|
||||
outer.getToken(),
|
||||
body.getFinish(),
|
||||
outer.getStatements())));
|
||||
}
|
||||
|
||||
if (vars != null) {
|
||||
for (final VarNode var : vars) {
|
||||
appendStatement(var);
|
||||
}
|
||||
}
|
||||
if (body != null) {
|
||||
appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
|
||||
}
|
||||
if (outer != null) {
|
||||
restoreBlock(outer);
|
||||
appendStatement(new BlockStatement(startLine, new Block(
|
||||
outer.getToken(),
|
||||
body.getFinish(),
|
||||
outer.getStatements())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1378,9 +1372,10 @@ loop:
|
||||
body = getStatement();
|
||||
} finally {
|
||||
lc.pop(whileNode);
|
||||
if (body != null){
|
||||
appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
|
||||
}
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1422,8 +1417,9 @@ loop:
|
||||
}
|
||||
} finally {
|
||||
lc.pop(doWhileNode);
|
||||
appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
|
||||
}
|
||||
|
||||
appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1621,17 +1617,12 @@ loop:
|
||||
throw error(AbstractParser.message("strict.no.with"), withToken);
|
||||
}
|
||||
|
||||
Expression expression = null;
|
||||
Block body = null;
|
||||
try {
|
||||
expect(LPAREN);
|
||||
expression = expression();
|
||||
expect(RPAREN);
|
||||
body = getStatement();
|
||||
} finally {
|
||||
appendStatement(new WithNode(withLine, withToken, finish, expression, body));
|
||||
}
|
||||
expect(LPAREN);
|
||||
final Expression expression = expression();
|
||||
expect(RPAREN);
|
||||
final Block body = getStatement();
|
||||
|
||||
appendStatement(new WithNode(withLine, withToken, finish, expression, body));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1720,8 +1711,9 @@ loop:
|
||||
next();
|
||||
} finally {
|
||||
lc.pop(switchNode);
|
||||
appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
|
||||
}
|
||||
|
||||
appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1752,10 +1744,9 @@ loop:
|
||||
} finally {
|
||||
assert lc.peek() instanceof ParserContextLabelNode;
|
||||
lc.pop(labelNode);
|
||||
if (ident != null){
|
||||
appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
|
||||
}
|
||||
}
|
||||
|
||||
appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2300,9 +2291,14 @@ loop:
|
||||
final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
|
||||
lc.push(functionNode);
|
||||
|
||||
final Block functionBody = functionBody(functionNode);
|
||||
Block functionBody;
|
||||
|
||||
lc.pop(functionNode);
|
||||
|
||||
try {
|
||||
functionBody = functionBody(functionNode);
|
||||
} finally {
|
||||
lc.pop(functionNode);
|
||||
}
|
||||
|
||||
final FunctionNode function = createFunctionNode(
|
||||
functionNode,
|
||||
@ -2340,9 +2336,13 @@ loop:
|
||||
final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
|
||||
lc.push(functionNode);
|
||||
|
||||
final Block functionBody = functionBody(functionNode);
|
||||
Block functionBody;
|
||||
try {
|
||||
functionBody = functionBody(functionNode);
|
||||
} finally {
|
||||
lc.pop(functionNode);
|
||||
}
|
||||
|
||||
lc.pop(functionNode);
|
||||
|
||||
final FunctionNode function = createFunctionNode(
|
||||
functionNode,
|
||||
@ -2739,12 +2739,9 @@ loop:
|
||||
functionBody);
|
||||
|
||||
if (isStatement) {
|
||||
int varFlags = VarNode.IS_STATEMENT;
|
||||
if (!topLevel && useBlockScope()) {
|
||||
// mark ES6 block functions as lexically scoped
|
||||
varFlags |= VarNode.IS_LET;
|
||||
}
|
||||
final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
|
||||
// mark ES6 block functions as lexically scoped
|
||||
final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
|
||||
final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
|
||||
if (topLevel) {
|
||||
functionDeclarations.add(varNode);
|
||||
} else if (useBlockScope()) {
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
package jdk.nashorn.internal.parser;
|
||||
|
||||
/**
|
||||
* A ParserContextNode that represents a SwithcNode that is currently being parsed
|
||||
* A ParserContextNode that represents a SwitchNode that is currently being parsed
|
||||
*/
|
||||
class ParserContextSwitchNode extends ParserContextBaseNode implements ParserContextBreakableNode {
|
||||
|
||||
|
||||
@ -714,6 +714,9 @@ public enum JSType {
|
||||
* @return a number
|
||||
*/
|
||||
public static double toNumber(final Object obj) {
|
||||
if (obj instanceof Double) {
|
||||
return (Double)obj;
|
||||
}
|
||||
if (obj instanceof Number) {
|
||||
return ((Number)obj).doubleValue();
|
||||
}
|
||||
|
||||
@ -84,14 +84,17 @@ public abstract class Property implements Serializable {
|
||||
public static final int IS_NASGEN_PRIMITIVE = 1 << 6;
|
||||
|
||||
/** Is this a builtin property, e.g. Function.prototype.apply */
|
||||
public static final int IS_BUILTIN = 1 << 7;
|
||||
public static final int IS_BUILTIN = 1 << 7;
|
||||
|
||||
/** Is this property bound to a receiver? This means get/set operations will be delegated to
|
||||
* a statically defined object instead of the object passed as callsite parameter. */
|
||||
public static final int IS_BOUND = 1 << 7;
|
||||
public static final int IS_BOUND = 1 << 8;
|
||||
|
||||
/** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */
|
||||
public static final int NEEDS_DECLARATION = 1 << 8;
|
||||
public static final int NEEDS_DECLARATION = 1 << 9;
|
||||
|
||||
/** Is this property an ES6 lexical binding? */
|
||||
public static final int IS_LEXICAL_BINDING = 1 << 10;
|
||||
|
||||
/** Property key. */
|
||||
private final String key;
|
||||
@ -714,4 +717,12 @@ public abstract class Property implements Serializable {
|
||||
public boolean isFunctionDeclaration() {
|
||||
return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a property defined by ES6 let or const?
|
||||
* @return true if this property represents a lexical binding.
|
||||
*/
|
||||
public boolean isLexicalBinding() {
|
||||
return (flags & IS_LEXICAL_BINDING) == IS_LEXICAL_BINDING;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +46,8 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_
|
||||
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
|
||||
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
|
||||
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
|
||||
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
|
||||
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
|
||||
import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
@ -98,7 +100,7 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards;
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
public abstract class ScriptObject implements PropertyAccess {
|
||||
public abstract class ScriptObject implements PropertyAccess, Cloneable {
|
||||
/** __proto__ special property name inside object literals. ES6 draft. */
|
||||
public static final String PROTO_PROPERTY_NAME = "__proto__";
|
||||
|
||||
@ -304,31 +306,46 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
PropertyMap newMap = this.getMap();
|
||||
|
||||
for (final Property property : properties) {
|
||||
final String key = property.getKey();
|
||||
final Property oldProp = newMap.findProperty(key);
|
||||
if (oldProp == null) {
|
||||
if (property instanceof UserAccessorProperty) {
|
||||
// Note: we copy accessor functions to this object which is semantically different from binding.
|
||||
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
|
||||
newMap = newMap.addPropertyNoHistory(prop);
|
||||
} else {
|
||||
newMap = newMap.addPropertyBind((AccessorProperty)property, source);
|
||||
}
|
||||
} else {
|
||||
// See ECMA section 10.5 Declaration Binding Instantiation
|
||||
// step 5 processing each function declaration.
|
||||
if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
|
||||
if (oldProp instanceof UserAccessorProperty ||
|
||||
!(oldProp.isWritable() && oldProp.isEnumerable())) {
|
||||
throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
newMap = addBoundProperty(newMap, source, property);
|
||||
}
|
||||
|
||||
this.setMap(newMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a bound property from {@code source}, using the interim property map {@code propMap}, and return the
|
||||
* new interim property map.
|
||||
*
|
||||
* @param propMap the property map
|
||||
* @param source the source object
|
||||
* @param property the property to be added
|
||||
* @return the new property map
|
||||
*/
|
||||
protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
|
||||
PropertyMap newMap = propMap;
|
||||
final String key = property.getKey();
|
||||
final Property oldProp = newMap.findProperty(key);
|
||||
if (oldProp == null) {
|
||||
if (property instanceof UserAccessorProperty) {
|
||||
// Note: we copy accessor functions to this object which is semantically different from binding.
|
||||
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
|
||||
newMap = newMap.addPropertyNoHistory(prop);
|
||||
} else {
|
||||
newMap = newMap.addPropertyBind((AccessorProperty)property, source);
|
||||
}
|
||||
} else {
|
||||
// See ECMA section 10.5 Declaration Binding Instantiation
|
||||
// step 5 processing each function declaration.
|
||||
if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
|
||||
if (oldProp instanceof UserAccessorProperty ||
|
||||
!(oldProp.isWritable() && oldProp.isEnumerable())) {
|
||||
throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
return newMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all properties from the array with their receiver bound to the source.
|
||||
*
|
||||
@ -510,7 +527,11 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateGlobalConstant(final String key) {
|
||||
/**
|
||||
* Invalidate any existing global constant method handles that may exist for {@code key}.
|
||||
* @param key the property name
|
||||
*/
|
||||
protected void invalidateGlobalConstant(final String key) {
|
||||
final GlobalConstants globalConstants = getGlobalConstants();
|
||||
if (globalConstants != null) {
|
||||
globalConstants.delete(key);
|
||||
@ -2183,6 +2204,9 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
|
||||
if (find != null) {
|
||||
if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) {
|
||||
if (NashornCallSiteDescriptor.isScope(desc) && find.getProperty().isLexicalBinding()) {
|
||||
throw typeError("assign.constant", name); // Overwriting ES6 const should throw also in non-strict mode.
|
||||
}
|
||||
// Existing, non-writable property
|
||||
return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
|
||||
}
|
||||
@ -3084,7 +3108,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
|
||||
if (longIndex >= oldLength) {
|
||||
if (!isExtensible()) {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
if (isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return true;
|
||||
@ -3108,7 +3132,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
final long oldLength = getArray().length();
|
||||
final long longIndex = ArrayIndex.toLongIndex(index);
|
||||
if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
|
||||
final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
|
||||
final boolean strict = isStrictFlag(callSiteFlags);
|
||||
setArray(getArray().set(index, value, strict));
|
||||
doesNotHaveEnsureDelete(longIndex, oldLength, strict);
|
||||
}
|
||||
@ -3118,7 +3142,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
final long oldLength = getArray().length();
|
||||
final long longIndex = ArrayIndex.toLongIndex(index);
|
||||
if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
|
||||
final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
|
||||
final boolean strict = isStrictFlag(callSiteFlags);
|
||||
setArray(getArray().set(index, value, strict));
|
||||
doesNotHaveEnsureDelete(longIndex, oldLength, strict);
|
||||
}
|
||||
@ -3128,7 +3152,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
final long oldLength = getArray().length();
|
||||
final long longIndex = ArrayIndex.toLongIndex(index);
|
||||
if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
|
||||
final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
|
||||
final boolean strict = isStrictFlag(callSiteFlags);
|
||||
setArray(getArray().set(index, value, strict));
|
||||
doesNotHaveEnsureDelete(longIndex, oldLength, strict);
|
||||
}
|
||||
@ -3138,7 +3162,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
final long oldLength = getArray().length();
|
||||
final long longIndex = ArrayIndex.toLongIndex(index);
|
||||
if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
|
||||
final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
|
||||
final boolean strict = isStrictFlag(callSiteFlags);
|
||||
setArray(getArray().set(index, value, strict));
|
||||
doesNotHaveEnsureDelete(longIndex, oldLength, strict);
|
||||
}
|
||||
@ -3159,7 +3183,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
invalidateGlobalConstant(key);
|
||||
|
||||
if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
|
||||
final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags);
|
||||
final boolean isScope = isScopeFlag(callSiteFlags);
|
||||
// If the start object of the find is not this object it means the property was found inside a
|
||||
// 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set'
|
||||
// to the 'with' object.
|
||||
@ -3180,16 +3204,19 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
|
||||
if (f != null) {
|
||||
if (!f.getProperty().isWritable()) {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
if (isScopeFlag(callSiteFlags) && f.getProperty().isLexicalBinding()) {
|
||||
throw typeError("assign.constant", key); // Overwriting ES6 const should throw also in non-strict mode.
|
||||
}
|
||||
if (isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
f.setValue(value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags));
|
||||
f.setValue(value, isStrictFlag(callSiteFlags));
|
||||
|
||||
} else if (!isExtensible()) {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
if (isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
} else {
|
||||
@ -3216,7 +3243,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3236,7 +3263,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3256,7 +3283,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3276,7 +3303,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3295,7 +3322,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3314,7 +3341,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3333,7 +3360,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3352,7 +3379,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3371,7 +3398,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3390,7 +3417,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3409,7 +3436,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3428,7 +3455,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3446,7 +3473,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
final ArrayData data = getArray();
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3464,7 +3491,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3483,7 +3510,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3502,7 +3529,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
final ArrayData data = getArray();
|
||||
if (data.has(index)) {
|
||||
setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
@ -3666,6 +3693,29 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a shallow copy of this ScriptObject.
|
||||
* @return a shallow copy.
|
||||
*/
|
||||
public final ScriptObject copy() {
|
||||
try {
|
||||
return clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScriptObject clone() throws CloneNotSupportedException {
|
||||
final ScriptObject clone = (ScriptObject) super.clone();
|
||||
if (objectSpill != null) {
|
||||
clone.objectSpill = objectSpill.clone();
|
||||
clone.primitiveSpill = primitiveSpill.clone();
|
||||
}
|
||||
clone.arrayData = arrayData.copy();
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new UserAccessorProperty property. getter and setter functions are stored in
|
||||
* this ScriptObject and slot values are used in property object.
|
||||
|
||||
@ -61,9 +61,9 @@ public abstract class ArrayData {
|
||||
/**
|
||||
* Length of the array data. Not necessarily length of the wrapped array.
|
||||
* This is private to ensure that no one in a subclass is able to touch the length
|
||||
* without going through {@link setLength}. This is used to implement
|
||||
* without going through {@link #setLength}. This is used to implement
|
||||
* {@link LengthNotWritableFilter}s, ensuring that there are no ways past
|
||||
* a {@link setLength} function replaced by a nop
|
||||
* a {@link #setLength} function replaced by a nop
|
||||
*/
|
||||
private long length;
|
||||
|
||||
@ -79,11 +79,7 @@ public abstract class ArrayData {
|
||||
*/
|
||||
private static class UntouchedArrayData extends ContinuousArrayData {
|
||||
private UntouchedArrayData() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
private UntouchedArrayData(final int length) {
|
||||
super(length);
|
||||
super(0);
|
||||
}
|
||||
|
||||
private ArrayData toRealArrayData() {
|
||||
@ -100,7 +96,8 @@ public abstract class ArrayData {
|
||||
|
||||
@Override
|
||||
public ContinuousArrayData copy() {
|
||||
return new UntouchedArrayData((int)length());
|
||||
assert length() == 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -246,7 +243,7 @@ public abstract class ArrayData {
|
||||
public Class<?> getBoxedElementType() {
|
||||
return Integer.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
||||
@ -25,11 +25,7 @@
|
||||
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
|
||||
import jdk.nashorn.api.scripting.JSObject;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
|
||||
@ -98,17 +94,7 @@ public abstract class IteratorAction<T> {
|
||||
* @return result of apply
|
||||
*/
|
||||
public final T apply() {
|
||||
final boolean strict;
|
||||
if (callbackfn instanceof ScriptFunction) {
|
||||
strict = ((ScriptFunction)callbackfn).isStrict();
|
||||
} else if (callbackfn instanceof JSObject &&
|
||||
((JSObject)callbackfn).isFunction()) {
|
||||
strict = ((JSObject)callbackfn).isStrictFunction();
|
||||
} else if (Bootstrap.isDynamicMethod(callbackfn) || Bootstrap.isFunctionalInterfaceObject(callbackfn)) {
|
||||
strict = false;
|
||||
} else {
|
||||
throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn));
|
||||
}
|
||||
final boolean strict = Bootstrap.isStrictCallable(callbackfn);
|
||||
|
||||
// for non-strict callback, need to translate undefined thisArg to be global object
|
||||
thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.ConstantCallSite;
|
||||
@ -50,6 +51,8 @@ import jdk.nashorn.internal.codegen.ObjectClassGenerator;
|
||||
import jdk.nashorn.internal.codegen.RuntimeCallSite;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
|
||||
import jdk.nashorn.internal.objects.ScriptFunctionImpl;
|
||||
import jdk.nashorn.internal.runtime.ECMAException;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
@ -94,7 +97,7 @@ public final class Bootstrap {
|
||||
new NashornLinker(),
|
||||
new NashornPrimitiveLinker(),
|
||||
new NashornStaticClassLinker(),
|
||||
new BoundDynamicMethodLinker(),
|
||||
new BoundCallableLinker(),
|
||||
new JavaSuperAdapterLinker(),
|
||||
new JSObjectLinker(nashornBeansLinker),
|
||||
new BrowserJSObjectLinker(nashornBeansLinker),
|
||||
@ -136,19 +139,47 @@ public final class Bootstrap {
|
||||
}
|
||||
|
||||
return obj instanceof ScriptFunction ||
|
||||
((obj instanceof JSObject) && ((JSObject)obj).isFunction()) ||
|
||||
isDynamicMethod(obj) ||
|
||||
isJSObjectFunction(obj) ||
|
||||
BeansLinker.isDynamicMethod(obj) ||
|
||||
obj instanceof BoundCallable ||
|
||||
isFunctionalInterfaceObject(obj) ||
|
||||
obj instanceof StaticClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given object is a strict callable
|
||||
* @param callable the callable object to be checked for strictness
|
||||
* @return true if the obj is a strict callable, false if it is a non-strict callable.
|
||||
* @throws ECMAException with {@code TypeError} if the object is not a callable.
|
||||
*/
|
||||
public static boolean isStrictCallable(final Object callable) {
|
||||
if (callable instanceof ScriptFunction) {
|
||||
return ((ScriptFunction)callable).isStrict();
|
||||
} else if (isJSObjectFunction(callable)) {
|
||||
return ((JSObject)callable).isStrictFunction();
|
||||
} else if (callable instanceof BoundCallable) {
|
||||
return isStrictCallable(((BoundCallable)callable).getCallable());
|
||||
} else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) {
|
||||
return false;
|
||||
}
|
||||
throw notFunction(callable);
|
||||
}
|
||||
|
||||
private static ECMAException notFunction(final Object obj) {
|
||||
return typeError("not.a.function", ScriptRuntime.safeToString(obj));
|
||||
}
|
||||
|
||||
private static boolean isJSObjectFunction(final Object obj) {
|
||||
return obj instanceof JSObject && ((JSObject)obj).isFunction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the given object is a dynalink Dynamic method
|
||||
* @param obj object to be checked
|
||||
* @return true if the obj is a dynamic method
|
||||
*/
|
||||
public static boolean isDynamicMethod(final Object obj) {
|
||||
return obj instanceof BoundDynamicMethod || BeansLinker.isDynamicMethod(obj);
|
||||
return BeansLinker.isDynamicMethod(obj instanceof BoundCallable ? ((BoundCallable)obj).getCallable() : obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -370,14 +401,22 @@ public final class Bootstrap {
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a bean dynamic method (returned by invoking {@code dyn:getMethod} on an object linked with
|
||||
* {@code BeansLinker} to a receiver.
|
||||
* @param dynamicMethod the dynamic method to bind
|
||||
* Binds any object Nashorn can use as a [[Callable]] to a receiver and optionally arguments.
|
||||
* @param callable the callable to bind
|
||||
* @param boundThis the bound "this" value.
|
||||
* @return a bound dynamic method.
|
||||
* @param boundArgs the bound arguments. Can be either null or empty array to signify no arguments are bound.
|
||||
* @return a bound callable.
|
||||
* @throws ECMAException with {@code TypeError} if the object is not a callable.
|
||||
*/
|
||||
public static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
|
||||
return new BoundDynamicMethod(dynamicMethod, boundThis);
|
||||
public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
|
||||
if (callable instanceof ScriptFunctionImpl) {
|
||||
return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs);
|
||||
} else if (callable instanceof BoundCallable) {
|
||||
return ((BoundCallable)callable).bind(boundArgs);
|
||||
} else if (isCallable(callable)) {
|
||||
return new BoundCallable(callable, boundThis, boundArgs);
|
||||
}
|
||||
throw notFunction(callable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import java.util.Arrays;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
|
||||
/**
|
||||
* Represents a Nashorn callable bound to a receiver and optionally arguments. Note that objects of this class
|
||||
* are just the tuples of a callable and a bound this and arguments, without any behavior. All the behavior is
|
||||
* defined in the {@code BoundCallableLinker}.
|
||||
*/
|
||||
public final class BoundCallable {
|
||||
private final Object callable;
|
||||
private final Object boundThis;
|
||||
private final Object[] boundArgs;
|
||||
|
||||
BoundCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
|
||||
this.callable = callable;
|
||||
this.boundThis = boundThis;
|
||||
this.boundArgs = isEmptyArray(boundArgs) ? ScriptRuntime.EMPTY_ARRAY : boundArgs.clone();
|
||||
}
|
||||
|
||||
private BoundCallable(final BoundCallable original, final Object[] extraBoundArgs) {
|
||||
this.callable = original.callable;
|
||||
this.boundThis = original.boundThis;
|
||||
this.boundArgs = original.concatenateBoundArgs(extraBoundArgs);
|
||||
}
|
||||
|
||||
Object getCallable() {
|
||||
return callable;
|
||||
}
|
||||
|
||||
Object getBoundThis() {
|
||||
return boundThis;
|
||||
}
|
||||
|
||||
Object[] getBoundArgs() {
|
||||
return boundArgs;
|
||||
}
|
||||
|
||||
BoundCallable bind(final Object[] extraBoundArgs) {
|
||||
if (isEmptyArray(extraBoundArgs)) {
|
||||
return this;
|
||||
}
|
||||
return new BoundCallable(this, extraBoundArgs);
|
||||
}
|
||||
|
||||
private Object[] concatenateBoundArgs(final Object[] extraBoundArgs) {
|
||||
if (boundArgs.length == 0) {
|
||||
return extraBoundArgs.clone();
|
||||
}
|
||||
final int origBoundArgsLen = boundArgs.length;
|
||||
final int extraBoundArgsLen = extraBoundArgs.length;
|
||||
final Object[] newBoundArgs = new Object[origBoundArgsLen + extraBoundArgsLen];
|
||||
System.arraycopy(boundArgs, 0, newBoundArgs, 0, origBoundArgsLen);
|
||||
System.arraycopy(extraBoundArgs, 0, newBoundArgs, origBoundArgsLen, extraBoundArgsLen);
|
||||
return newBoundArgs;
|
||||
}
|
||||
|
||||
private static boolean isEmptyArray(final Object[] a) {
|
||||
return a == null || a.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder b = new StringBuilder(callable.toString()).append(" on ").append(boundThis);
|
||||
if (boundArgs.length != 0) {
|
||||
b.append(" with ").append(Arrays.toString(boundArgs));
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Arrays;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
|
||||
/**
|
||||
* Links {@link BoundCallable} objects. Passes through to linker services for linking a callable (for either
|
||||
* "dyn:call" or "dyn:new"), and modifies the returned invocation to deal with the receiver and argument binding.
|
||||
*/
|
||||
final class BoundCallableLinker implements TypeBasedGuardingDynamicLinker {
|
||||
@Override
|
||||
public boolean canLinkType(final Class<?> type) {
|
||||
return type == BoundCallable.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
|
||||
final Object objBoundCallable = linkRequest.getReceiver();
|
||||
if(!(objBoundCallable instanceof BoundCallable)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
|
||||
if (descriptor.getNameTokenCount() < 2 || !"dyn".equals(descriptor.getNameToken(CallSiteDescriptor.SCHEME))) {
|
||||
return null;
|
||||
}
|
||||
final String operation = descriptor.getNameToken(CallSiteDescriptor.OPERATOR);
|
||||
// We need to distinguish "dyn:new" from "dyn:call" because "dyn:call" sites have parameter list of the form
|
||||
// "callee, this, args", while "dyn:call" sites have "callee, args" -- they lack the "this" parameter.
|
||||
final boolean isCall;
|
||||
if ("new".equals(operation)) {
|
||||
isCall = false;
|
||||
} else if ("call".equals(operation)) {
|
||||
isCall = true;
|
||||
} else {
|
||||
// Only dyn:call and dyn:new are supported.
|
||||
return null;
|
||||
}
|
||||
final BoundCallable boundCallable = (BoundCallable)objBoundCallable;
|
||||
final Object callable = boundCallable.getCallable();
|
||||
final Object boundThis = boundCallable.getBoundThis();
|
||||
|
||||
// We need to ask the linker services for a delegate invocation on the target callable.
|
||||
|
||||
// Replace arguments (boundCallable[, this], args) => (callable[, boundThis], boundArgs, args) when delegating
|
||||
final Object[] args = linkRequest.getArguments();
|
||||
final Object[] boundArgs = boundCallable.getBoundArgs();
|
||||
final int argsLen = args.length;
|
||||
final int boundArgsLen = boundArgs.length;
|
||||
final Object[] newArgs = new Object[argsLen + boundArgsLen];
|
||||
newArgs[0] = callable;
|
||||
final int firstArgIndex;
|
||||
if (isCall) {
|
||||
newArgs[1] = boundThis;
|
||||
firstArgIndex = 2;
|
||||
} else {
|
||||
firstArgIndex = 1;
|
||||
}
|
||||
System.arraycopy(boundArgs, 0, newArgs, firstArgIndex, boundArgsLen);
|
||||
System.arraycopy(args, firstArgIndex, newArgs, firstArgIndex + boundArgsLen, argsLen - firstArgIndex);
|
||||
|
||||
// Use R(T0, T1, T2, ...) => R(callable.class, boundThis.class, boundArg0.class, ..., boundArgn.class, T2, ...)
|
||||
// call site type when delegating to underlying linker (for dyn:new, there's no this).
|
||||
final MethodType type = descriptor.getMethodType();
|
||||
// Use R(T0, ...) => R(callable.class, ...)
|
||||
MethodType newMethodType = descriptor.getMethodType().changeParameterType(0, callable.getClass());
|
||||
if (isCall) {
|
||||
// R(callable.class, T1, ...) => R(callable.class, boundThis.class, ...)
|
||||
newMethodType = newMethodType.changeParameterType(1, boundThis.getClass());
|
||||
}
|
||||
// R(callable.class[, boundThis.class], T2, ...) => R(callable.class[, boundThis.class], boundArg0.class, ..., boundArgn.class, T2, ...)
|
||||
for(int i = boundArgs.length; i-- > 0;) {
|
||||
newMethodType = newMethodType.insertParameterTypes(firstArgIndex, boundArgs[i] == null ? Object.class : boundArgs[i].getClass());
|
||||
}
|
||||
final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(newMethodType);
|
||||
|
||||
// Delegate to target's linker
|
||||
final GuardedInvocation inv = linkerServices.getGuardedInvocation(linkRequest.replaceArguments(newDescriptor, newArgs));
|
||||
if(inv == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Bind (callable[, boundThis], boundArgs) to the delegate handle
|
||||
final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0,
|
||||
Arrays.copyOf(newArgs, firstArgIndex + boundArgs.length));
|
||||
final Class<?> p0Type = type.parameterType(0);
|
||||
final MethodHandle droppingHandle;
|
||||
if (isCall) {
|
||||
// Ignore incoming boundCallable and this
|
||||
droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
|
||||
} else {
|
||||
// Ignore incoming boundCallable
|
||||
droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type);
|
||||
}
|
||||
// Identity guard on boundCallable object
|
||||
final MethodHandle newGuard = Guards.getIdentityGuard(boundCallable);
|
||||
return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import java.util.Objects;
|
||||
import jdk.internal.dynalink.beans.BeansLinker;
|
||||
|
||||
/**
|
||||
* Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of
|
||||
* a method and a bound this, without any behavior. All the behavior is defined in the {@code BoundDynamicMethodLinker}.
|
||||
*/
|
||||
final class BoundDynamicMethod {
|
||||
private final Object dynamicMethod;
|
||||
private final Object boundThis;
|
||||
|
||||
BoundDynamicMethod(final Object dynamicMethod, final Object boundThis) {
|
||||
assert BeansLinker.isDynamicMethod(dynamicMethod);
|
||||
this.dynamicMethod = dynamicMethod;
|
||||
this.boundThis = boundThis;
|
||||
}
|
||||
|
||||
Object getDynamicMethod() {
|
||||
return dynamicMethod;
|
||||
}
|
||||
|
||||
Object getBoundThis() {
|
||||
return boundThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return dynamicMethod.toString() + " on " + Objects.toString(boundThis);
|
||||
}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.beans.BeansLinker;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
|
||||
/**
|
||||
* Links {@code BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method
|
||||
* (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding.
|
||||
*/
|
||||
final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
|
||||
@Override
|
||||
public boolean canLinkType(final Class<?> type) {
|
||||
return type == BoundDynamicMethod.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
|
||||
final Object objBoundDynamicMethod = linkRequest.getReceiver();
|
||||
if(!(objBoundDynamicMethod instanceof BoundDynamicMethod)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final BoundDynamicMethod boundDynamicMethod = (BoundDynamicMethod)objBoundDynamicMethod;
|
||||
final Object dynamicMethod = boundDynamicMethod.getDynamicMethod();
|
||||
final Object boundThis = boundDynamicMethod.getBoundThis();
|
||||
|
||||
// Replace arguments (boundDynamicMethod, this, ...) => (dynamicMethod, boundThis, ...) when delegating to
|
||||
// BeansLinker
|
||||
final Object[] args = linkRequest.getArguments();
|
||||
args[0] = dynamicMethod;
|
||||
args[1] = boundThis;
|
||||
|
||||
// Use R(T0, T1, ...) => R(dynamicMethod.class, boundThis.class, ...) call site type when delegating to
|
||||
// BeansLinker.
|
||||
final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
|
||||
final MethodType type = descriptor.getMethodType();
|
||||
final Class<?> dynamicMethodClass = dynamicMethod.getClass();
|
||||
final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(
|
||||
type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass()));
|
||||
|
||||
// Delegate to BeansLinker
|
||||
final GuardedInvocation inv = NashornBeansLinker.getGuardedInvocation(BeansLinker.getLinkerForClass(dynamicMethodClass),
|
||||
linkRequest.replaceArguments(newDescriptor, args), linkerServices);
|
||||
if(inv == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Bind (dynamicMethod, boundThis) to the handle
|
||||
final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0, dynamicMethod, boundThis);
|
||||
final Class<?> p0Type = type.parameterType(0);
|
||||
// Ignore incoming (boundDynamicMethod, this)
|
||||
final MethodHandle droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
|
||||
// Identity guard on boundDynamicMethod object
|
||||
final MethodHandle newGuard = Guards.getIdentityGuard(boundDynamicMethod);
|
||||
|
||||
return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
|
||||
}
|
||||
}
|
||||
@ -165,7 +165,7 @@ final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
|
||||
return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindDynamicMethod(dynamicMethod, boundThis);
|
||||
return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindCallable(dynamicMethod, boundThis, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -82,7 +82,7 @@ type.error.not.a.constructor={0} is not a constructor function
|
||||
type.error.not.a.file={0} is not a File
|
||||
type.error.not.a.numeric.array={0} is not a numeric array
|
||||
type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer
|
||||
type.error.not.an.arraybuffer.in.dataview=First arg to DataView constructor must be an ArrayBuffer
|
||||
type.error.not.an.arraybuffer.in.dataview=First argument to DataView constructor must be an ArrayBuffer
|
||||
type.error.no.reflection.with.classfilter=Java reflection not supported when class filter is present
|
||||
|
||||
# operations not permitted on undefined
|
||||
@ -116,6 +116,7 @@ type.error.instanceof.on.non.object=instanceof must be called with a javascript
|
||||
type.error.cannot.convert.to.interface=object {0} cannot be converted to {1} due to "{2}"
|
||||
type.error.array.reduce.invalid.init=invalid initialValue for Array.prototype.reduce
|
||||
type.error.array.reduceright.invalid.init=invalid initialValue for Array.prototype.reduceRight
|
||||
type.error.assign.constant=Assignment to constant "{0}"
|
||||
type.error.cannot.get.default.string=Cannot get default string value
|
||||
type.error.cannot.get.default.number=Cannot get default number value
|
||||
type.error.cant.apply.with.to.null=Cannot apply "with" to null
|
||||
@ -166,6 +167,7 @@ syntax.error.invalid.json=Invalid JSON: {0}
|
||||
syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
|
||||
syntax.error.redeclare.variable=Variable "{0}" has already been declared
|
||||
syntax.error.assign.constant=Assignment to constant "{0}"
|
||||
syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
|
||||
|
||||
io.error.cant.write=cannot write "{0}"
|
||||
config.error.no.dest=no destination directory supplied
|
||||
|
||||
33
nashorn/test/script/basic/JDK-8049407-big-endian.js
Normal file
33
nashorn/test/script/basic/JDK-8049407-big-endian.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Verify DataView behavior with little/big endian
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @bigendian
|
||||
*/
|
||||
|
||||
var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
|
||||
load(dir + "JDK-8049407-payload.js");
|
||||
@ -0,0 +1 @@
|
||||
false
|
||||
37
nashorn/test/script/basic/JDK-8049407-payload.js
Normal file
37
nashorn/test/script/basic/JDK-8049407-payload.js
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Verify DataView behavior with little/big endian
|
||||
*
|
||||
* @subtest
|
||||
* @run
|
||||
*/
|
||||
|
||||
var littleEndian = (function() {
|
||||
var buffer = new ArrayBuffer(2);
|
||||
new DataView(buffer).setInt16(0, 256, true);
|
||||
return new Int16Array(buffer)[0] === 256;
|
||||
})();
|
||||
|
||||
print(littleEndian);
|
||||
33
nashorn/test/script/basic/JDK-8049407.js
Normal file
33
nashorn/test/script/basic/JDK-8049407.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Verify DataView behavior with little/big endian
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @littleendian
|
||||
*/
|
||||
|
||||
var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
|
||||
load(dir + "JDK-8049407-payload.js");
|
||||
1
nashorn/test/script/basic/JDK-8049407.js.EXPECTED
Normal file
1
nashorn/test/script/basic/JDK-8049407.js.EXPECTED
Normal file
@ -0,0 +1 @@
|
||||
true
|
||||
83
nashorn/test/script/basic/JDK-8051778.js
Normal file
83
nashorn/test/script/basic/JDK-8051778.js
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8051778: support bind on all Nashorn callables
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var bind = Function.prototype.bind;
|
||||
|
||||
// Bind a POJO method
|
||||
var l = new java.util.ArrayList();
|
||||
var l_add_foo = bind.call(l.add, l, "foo");
|
||||
l_add_foo();
|
||||
print("l=" + l);
|
||||
|
||||
// Bind a BoundCallable
|
||||
var l_add = bind.call(l.add, l);
|
||||
var l_add_foo2 = bind.call(l_add, null, "foo2");
|
||||
l_add_foo2();
|
||||
print("l=" + l);
|
||||
|
||||
// Bind a POJO method retrieved from one instance to a different but
|
||||
// compatible instance.
|
||||
var l2 = new java.util.ArrayList();
|
||||
var l2_size = bind.call(l.size, l2);
|
||||
print("l2_size()=" + l2_size());
|
||||
|
||||
// Bind a Java type object (used as a constructor).
|
||||
var construct_two = bind.call(java.lang.Integer, null, 2);
|
||||
print("Bound Integer(2) constructor: " + new construct_two())
|
||||
|
||||
// Bind a @FunctionalInterface proxying to an object literal. NOTE: the
|
||||
// expected value of this.a is always "original" and never "bound". This
|
||||
// might seem counterintuitive, but we are not binding the apply()
|
||||
// function of the object literal that defines the BiFunction behaviour,
|
||||
// we are binding the SAM proxy object instead, and it is always
|
||||
// forwarding to the apply() function with "this" set to the object
|
||||
// literal. Basically, binding "this" for SAM proxies is useless; only
|
||||
// binding arguments makes sense.
|
||||
var f1 = new java.util.function.BiFunction() {
|
||||
apply: function(x, y) {
|
||||
return "BiFunction with literal: " + this.a + ", " + x + ", " + y;
|
||||
},
|
||||
a: "unbound"
|
||||
};
|
||||
print((bind.call(f1, {a: "bound"}))(1, 2))
|
||||
print((bind.call(f1, {a: "bound"}, 3))(4))
|
||||
print((bind.call(f1, {a: "bound"}, 5, 6))())
|
||||
|
||||
// Bind a @FunctionalInterface proxying to a function. With the same
|
||||
// reasoning as above (binding the proxy vs. binding the JS function),
|
||||
// the value of this.a will always be undefined, and never "bound".
|
||||
var f2 = new java.util.function.BiFunction(
|
||||
function(x, y) {
|
||||
return "BiFunction with function: " + this.a + ", " + x + ", " + y;
|
||||
}
|
||||
);
|
||||
print((bind.call(f2, {a: "bound"}))(7, 8))
|
||||
print((bind.call(f2, {a: "bound"}, 9))(10))
|
||||
print((bind.call(f2, {a: "bound"}, 11, 12))())
|
||||
10
nashorn/test/script/basic/JDK-8051778.js.EXPECTED
Normal file
10
nashorn/test/script/basic/JDK-8051778.js.EXPECTED
Normal file
@ -0,0 +1,10 @@
|
||||
l=[foo]
|
||||
l=[foo, foo2]
|
||||
l2_size()=0
|
||||
Bound Integer(2) constructor: 2
|
||||
BiFunction with literal: unbound, 1, 2
|
||||
BiFunction with literal: unbound, 3, 4
|
||||
BiFunction with literal: unbound, 5, 6
|
||||
BiFunction with function: undefined, 7, 8
|
||||
BiFunction with function: undefined, 9, 10
|
||||
BiFunction with function: undefined, 11, 12
|
||||
49
nashorn/test/script/basic/JDK-8066214.js
Normal file
49
nashorn/test/script/basic/JDK-8066214.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8066214: Fuzzing bug: Object.prototype.toLocaleString(0)
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
function test(func) {
|
||||
print(func.call(0));
|
||||
print(func.call("abc"));
|
||||
print(func.call(true));
|
||||
try {
|
||||
print(func.call(undefined));
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
try {
|
||||
print(func.call(null));
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
test(Object.prototype.toLocaleString);
|
||||
test(Object.prototype.toString);
|
||||
test(Object.prototype.valueOf);
|
||||
15
nashorn/test/script/basic/JDK-8066214.js.EXPECTED
Normal file
15
nashorn/test/script/basic/JDK-8066214.js.EXPECTED
Normal file
@ -0,0 +1,15 @@
|
||||
0
|
||||
abc
|
||||
true
|
||||
TypeError: undefined is not an Object
|
||||
TypeError: null is not an Object
|
||||
[object Number]
|
||||
[object String]
|
||||
[object Boolean]
|
||||
[object Undefined]
|
||||
[object Null]
|
||||
0
|
||||
abc
|
||||
true
|
||||
TypeError: undefined is not an Object
|
||||
TypeError: null is not an Object
|
||||
35
nashorn/test/script/basic/JDK-8066222.js
Normal file
35
nashorn/test/script/basic/JDK-8066222.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8066222: too strong assertion on function expression names
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
// Has to print "SUCCESS"
|
||||
(function x (x){print(x)})("SUCCESS");
|
||||
|
||||
// Has to print "undefined" and "1", not the function source in any case.
|
||||
(function x(){print(x); var x=1; print(x)})();
|
||||
3
nashorn/test/script/basic/JDK-8066222.js.EXPECTED
Normal file
3
nashorn/test/script/basic/JDK-8066222.js.EXPECTED
Normal file
@ -0,0 +1,3 @@
|
||||
SUCCESS
|
||||
undefined
|
||||
1
|
||||
36
nashorn/test/script/basic/JDK-8066232.js
Normal file
36
nashorn/test/script/basic/JDK-8066232.js
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8066232: problem with conditional catch compilation
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
(function () {
|
||||
try {
|
||||
x;
|
||||
} catch(e if 1) {
|
||||
}
|
||||
})()
|
||||
1
nashorn/test/script/basic/JDK-8066232.js.EXPECTED
Normal file
1
nashorn/test/script/basic/JDK-8066232.js.EXPECTED
Normal file
@ -0,0 +1 @@
|
||||
SUCCESS
|
||||
43
nashorn/test/script/basic/JDK-8066238.js
Normal file
43
nashorn/test/script/basic/JDK-8066238.js
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parser should not crash on invalid property function bodies.
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
try {
|
||||
eval("function f() { L: ({ set prop(){0 = null} }); }");
|
||||
} catch (e) {
|
||||
if (!(e instanceof ReferenceError)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
try {
|
||||
eval("function g() { do ; while({ get x()1-- }); }");
|
||||
} catch (e) {
|
||||
if (!(e instanceof ReferenceError)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
33
nashorn/test/script/basic/NASHORN-377-big-endian.js
Normal file
33
nashorn/test/script/basic/NASHORN-377-big-endian.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NASHORN-377: Typed arrays.
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @bigendian
|
||||
*/
|
||||
|
||||
var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
|
||||
load(dir + "NASHORN-377-payload.js");
|
||||
34
nashorn/test/script/basic/NASHORN-377-big-endian.js.EXPECTED
Normal file
34
nashorn/test/script/basic/NASHORN-377-big-endian.js.EXPECTED
Normal file
@ -0,0 +1,34 @@
|
||||
8 8 true undefined
|
||||
[object ArrayBuffer] [object ArrayBuffer] [object Int8Array]
|
||||
0 8 8 1
|
||||
0 8 8 1
|
||||
0 8 8 1
|
||||
0 8 4 2
|
||||
0 8 4 2
|
||||
0 8 2 4
|
||||
0 8 2 4
|
||||
0 8 2 4
|
||||
0 8 1 8
|
||||
7071727374-807677 7071727374807677
|
||||
727374-807677 2 6
|
||||
72737480 2 4
|
||||
71727374 1 4
|
||||
717273748076
|
||||
7071727374807677 1886483059 1954575991
|
||||
70717273-1020305 1886483059 -16909061
|
||||
70717273fefdfcfb 1886483059 4278058235
|
||||
40490fdafefdfcfb 2
|
||||
400921fb4d12d84a 1
|
||||
400921fb4d12d84a 1074340347 1293080650
|
||||
00000000400921fb4d12d84a
|
||||
400921fb4d12-27b6 400921fb4d12d84a
|
||||
00-100804d12-27b6 ffff00804d12d84a
|
||||
0 1 2 3 4 5 6 7
|
||||
0102030405060708
|
||||
subarray(2,4)=0304 subarray(-6,-4)=0304
|
||||
010203040506
|
||||
03040506 0405
|
||||
0102030405060708090a0b0c0d0e0f10
|
||||
slice(4,8)=05060708 slice(-8,-4)=090a0b0c
|
||||
0102030405060708090a0b0c
|
||||
060708090a0b
|
||||
226
nashorn/test/script/basic/NASHORN-377-payload.js
Normal file
226
nashorn/test/script/basic/NASHORN-377-payload.js
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NASHORN-377: Typed arrays. Payload for litte and big endian platforms.
|
||||
*
|
||||
* @subtest
|
||||
* @run
|
||||
*/
|
||||
|
||||
var types = [Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// utility functions
|
||||
//---------------------------------------------------------------------------
|
||||
function tohex(d, w) {
|
||||
var hex = Number(d).toString(16);
|
||||
var pad = (w ? w : 8) - hex.length;
|
||||
hex = "00000000".substr(0, pad) + hex;
|
||||
return hex;
|
||||
}
|
||||
|
||||
function arrstr(a, n, w) {
|
||||
var s = "";
|
||||
if (typeof n == "undefined") n = a.length;
|
||||
if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
|
||||
for (var i = 0; i < n; i++) {
|
||||
s += tohex(a[i], w);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function bufstr(b) {
|
||||
if (b.buffer !== undefined) {
|
||||
b = b.buffer;
|
||||
}
|
||||
return arrstr(new Uint8Array(b));
|
||||
}
|
||||
|
||||
function assertFail(f) {
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
//print(e);
|
||||
return;
|
||||
}
|
||||
throw "assertion failed: expected exception";
|
||||
}
|
||||
|
||||
function assertTrue(f) {
|
||||
if (f() !== true) throw "assertion failed: " + f;
|
||||
}
|
||||
|
||||
function isUndefined(x) {
|
||||
return typeof x === "undefined";
|
||||
}
|
||||
|
||||
function fillArray(a, start) {
|
||||
if (typeof start == "undefined") start = 1;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
a[i] = i + start;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// tests
|
||||
//---------------------------------------------------------------------------
|
||||
(function() {
|
||||
var b = new ArrayBuffer(8);
|
||||
var i8 = new Int8Array(b);
|
||||
print(i8.buffer.byteLength, b.byteLength, i8.buffer === b, b.length);
|
||||
print(b, i8.buffer, i8);
|
||||
})();
|
||||
|
||||
(function test_attributes() {
|
||||
var b = new ArrayBuffer(8);
|
||||
for (var i in types) {
|
||||
var x = new types[i](b);
|
||||
print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
|
||||
assertTrue(function(){ return x.constructor === types[i] });
|
||||
}
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var b = new ArrayBuffer(8);
|
||||
var i8 = new Int8Array(b);
|
||||
fillArray(i8, 0x70);
|
||||
|
||||
var i8_2 = new Int8Array(b, 2);
|
||||
var i8_2_4 = new Uint8Array(b, 2, 4);
|
||||
|
||||
i8_2_4[3] = 0x80;
|
||||
|
||||
print(arrstr(i8, 8, 2) + " " + bufstr(i8));
|
||||
print(arrstr(i8_2, 6) + " " + i8_2.byteOffset + " " + i8_2.byteLength);
|
||||
print(arrstr(i8_2_4, 4) + " " + i8_2_4.byteOffset + " " + i8_2_4.byteLength);
|
||||
|
||||
var i8_1_5 = i8.subarray(1, 5);
|
||||
i8_2_4.subarray(1, 5);
|
||||
print(arrstr(i8_1_5, 4) + " " + i8_1_5.byteOffset + " " + i8_1_5.byteLength);
|
||||
|
||||
print(bufstr(b.slice(1,7)));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var b = new ArrayBuffer(8);
|
||||
fillArray(new Int8Array(b), 0x70);
|
||||
new Int8Array(b)[5] = 0x80;
|
||||
|
||||
var i32 = new Int32Array(b);
|
||||
var u32 = new Uint32Array(b);
|
||||
print(arrstr(i32), i32[0], i32[1]);
|
||||
i32[1] = 0xfefdfcfb;
|
||||
print(arrstr(i32), i32[0], i32[1]);
|
||||
print(arrstr(u32), u32[0], u32[1]);
|
||||
|
||||
var pi = 3.1415926;
|
||||
var f32 = new Float32Array(b);
|
||||
var f64 = new Float64Array(b);
|
||||
f32[0] = pi;
|
||||
print(bufstr(b), f32.length);
|
||||
f64[0] = pi;
|
||||
print(bufstr(b), f64.length);
|
||||
print(arrstr(u32), u32[0], u32[1]);
|
||||
|
||||
var d = new Int32Array(3);
|
||||
d.set(i32,1);
|
||||
print(bufstr(d));
|
||||
|
||||
var s = new Int16Array(b);
|
||||
var t = new Uint16Array(b);
|
||||
print(arrstr(s), arrstr(t));
|
||||
s[0] = -1; s[1] = 0x80;
|
||||
print(arrstr(s), arrstr(t));
|
||||
})();
|
||||
|
||||
(function enumerate_properties() {
|
||||
var i8 = new Int8Array(new ArrayBuffer(8));
|
||||
var s = ""; for (var i in i8) { s += i + " "; } print(s.trim());
|
||||
})();
|
||||
|
||||
// check that ScriptObject fallback is still working
|
||||
// DISABLED because correct behavior is unclear
|
||||
(function() {
|
||||
// NB: firefox will never set any out-of-bounds or non-array values although it does get both from prototype.
|
||||
var z = new Uint8Array(4);
|
||||
z["asdf"] = "asdf"; print(z["asdf"]);
|
||||
z[0x100000000] = "asdf"; print(z[0x100000000]);
|
||||
z[-1] = "asdf"; print(z[-1]);
|
||||
|
||||
// v8 and nashorn disagree on out-of-bounds uint32 indices: v8 won't go to the prototype.
|
||||
z[0xf0000000] = "asdf"; print(z[0xf0000000]);
|
||||
z[0xffffffff] = "asdf"; print(z[0xffffffff]);
|
||||
z[0x70000000] = "asdf"; print(z[0x70000000]);
|
||||
|
||||
// this will work in firefox and nashorn (not in v8).
|
||||
Uint8Array.prototype[4] = "asdf"; print(z[4]);
|
||||
});
|
||||
|
||||
(function test_exceptions() {
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(7)); });
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(8), 0, 4); });
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(8),-1, 2); });
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(8), 0,-1); });
|
||||
})();
|
||||
|
||||
(function test_subarray() {
|
||||
var x = fillArray(new Int8Array(8));
|
||||
print(arrstr(x));
|
||||
print("subarray(2,4)=" + arrstr(x.subarray(2, 4)), "subarray(-6,-4)=" + arrstr(x.subarray(-6, -4))); // negative index refers from the end of the array
|
||||
print(arrstr(x.subarray(-10, -2))); // negative index clamped to 0
|
||||
assertTrue(function(){ return arrstr(x.subarray(6, 4)) === ""; }); // negative length clamped to 0
|
||||
print(arrstr(x.subarray(1,-1).subarray(1,-1)), arrstr(x.subarray(1,-1).subarray(1,-1).subarray(1,-1))); // subarray of subarray
|
||||
})();
|
||||
|
||||
(function test_slice() {
|
||||
var b = new ArrayBuffer(16);
|
||||
fillArray(new Int8Array(b));
|
||||
print(bufstr(b));
|
||||
print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
|
||||
print(bufstr(b.slice(-20, -4))); // negative index clamped to 0
|
||||
assertTrue(function(){ return bufstr(b.slice(8, 4)) === ""; }); // negative length clamped to 0
|
||||
print(arrstr(new Int16Array(b.slice(1,-1).slice(2,-1).slice(1,-2).slice(1,-1)))); // slice of slice
|
||||
})();
|
||||
|
||||
(function test_clamped() {
|
||||
var a = new Uint8ClampedArray(10);
|
||||
a[0] = -17; // clamped to 0
|
||||
a[1] = 4711; // clamped to 255
|
||||
a[2] = 17.5; // clamped to 18
|
||||
a[3] = 16.5; // clamped to 16
|
||||
a[4] = 255.9; // clamped to 255
|
||||
a[5] = Infinity; // clamped to 255
|
||||
a[6] = -Infinity; // clamped to 0
|
||||
a[7] = NaN; // 0
|
||||
assertTrue(function(){ return a[0] === 0 && a[1] === 255 && a[2] === 18 && a[3] === 16 && a[4] === 255 && a[5] === 255 && a[6] === 0 && a[7] === 0; });
|
||||
})();
|
||||
|
||||
(function test_out_of_bounds() {
|
||||
var a = new Int32Array(10);
|
||||
a[10] = 10;
|
||||
a[100] = 100;
|
||||
a[1000] = 1000;
|
||||
assertTrue(function(){ return isUndefined(a[10]) && isUndefined(a[11]) && isUndefined(a[100]) && isUndefined(a[123]) && isUndefined(a[1000]); });
|
||||
})();
|
||||
|
||||
@ -26,201 +26,8 @@
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @littleendian
|
||||
*/
|
||||
|
||||
var types = [Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// utility functions
|
||||
//---------------------------------------------------------------------------
|
||||
function tohex(d, w) {
|
||||
var hex = Number(d).toString(16);
|
||||
var pad = (w ? w : 8) - hex.length;
|
||||
hex = "00000000".substr(0, pad) + hex;
|
||||
return hex;
|
||||
}
|
||||
|
||||
function arrstr(a, n, w) {
|
||||
var s = "";
|
||||
if (typeof n == "undefined") n = a.length;
|
||||
if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
|
||||
for (var i = 0; i < n; i++) {
|
||||
s += tohex(a[i], w);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function bufstr(b) {
|
||||
if (b.buffer !== undefined) {
|
||||
b = b.buffer;
|
||||
}
|
||||
return arrstr(new Uint8Array(b));
|
||||
}
|
||||
|
||||
function assertFail(f) {
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
//print(e);
|
||||
return;
|
||||
}
|
||||
throw "assertion failed: expected exception";
|
||||
}
|
||||
|
||||
function assertTrue(f) {
|
||||
if (f() !== true) throw "assertion failed: " + f;
|
||||
}
|
||||
|
||||
function isUndefined(x) {
|
||||
return typeof x === "undefined";
|
||||
}
|
||||
|
||||
function fillArray(a, start) {
|
||||
if (typeof start == "undefined") start = 1;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
a[i] = i + start;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// tests
|
||||
//---------------------------------------------------------------------------
|
||||
(function() {
|
||||
var b = new ArrayBuffer(8);
|
||||
var i8 = new Int8Array(b);
|
||||
print(i8.buffer.byteLength, b.byteLength, i8.buffer === b, b.length);
|
||||
print(b, i8.buffer, i8);
|
||||
})();
|
||||
|
||||
(function test_attributes() {
|
||||
var b = new ArrayBuffer(8);
|
||||
for (var i in types) {
|
||||
var x = new types[i](b);
|
||||
print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
|
||||
assertTrue(function(){ return x.constructor === types[i] });
|
||||
}
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var b = new ArrayBuffer(8);
|
||||
var i8 = new Int8Array(b);
|
||||
fillArray(i8, 0x70);
|
||||
|
||||
var i8_2 = new Int8Array(b, 2);
|
||||
var i8_2_4 = new Uint8Array(b, 2, 4);
|
||||
|
||||
i8_2_4[3] = 0x80;
|
||||
|
||||
print(arrstr(i8, 8, 2) + " " + bufstr(i8));
|
||||
print(arrstr(i8_2, 6) + " " + i8_2.byteOffset + " " + i8_2.byteLength);
|
||||
print(arrstr(i8_2_4, 4) + " " + i8_2_4.byteOffset + " " + i8_2_4.byteLength);
|
||||
|
||||
var i8_1_5 = i8.subarray(1, 5);
|
||||
i8_2_4.subarray(1, 5);
|
||||
print(arrstr(i8_1_5, 4) + " " + i8_1_5.byteOffset + " " + i8_1_5.byteLength);
|
||||
|
||||
print(bufstr(b.slice(1,7)));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var b = new ArrayBuffer(8);
|
||||
fillArray(new Int8Array(b), 0x70);
|
||||
new Int8Array(b)[5] = 0x80;
|
||||
|
||||
var i32 = new Int32Array(b);
|
||||
var u32 = new Uint32Array(b);
|
||||
print(arrstr(i32), i32[0], i32[1]);
|
||||
i32[1] = 0xfefdfcfb;
|
||||
print(arrstr(i32), i32[0], i32[1]);
|
||||
print(arrstr(u32), u32[0], u32[1]);
|
||||
|
||||
var pi = 3.1415926;
|
||||
var f32 = new Float32Array(b);
|
||||
var f64 = new Float64Array(b);
|
||||
f32[0] = pi;
|
||||
print(bufstr(b), f32.length);
|
||||
f64[0] = pi;
|
||||
print(bufstr(b), f64.length);
|
||||
print(arrstr(u32), u32[0], u32[1]);
|
||||
|
||||
var d = new Int32Array(3);
|
||||
d.set(i32,1);
|
||||
print(bufstr(d));
|
||||
|
||||
var s = new Int16Array(b);
|
||||
var t = new Uint16Array(b);
|
||||
print(arrstr(s), arrstr(t));
|
||||
s[0] = -1; s[1] = 0x80;
|
||||
print(arrstr(s), arrstr(t));
|
||||
})();
|
||||
|
||||
(function enumerate_properties() {
|
||||
var i8 = new Int8Array(new ArrayBuffer(8));
|
||||
var s = ""; for (var i in i8) { s += i + " "; } print(s.trim());
|
||||
})();
|
||||
|
||||
// check that ScriptObject fallback is still working
|
||||
// DISABLED because correct behavior is unclear
|
||||
(function() {
|
||||
// NB: firefox will never set any out-of-bounds or non-array values although it does get both from prototype.
|
||||
var z = new Uint8Array(4);
|
||||
z["asdf"] = "asdf"; print(z["asdf"]);
|
||||
z[0x100000000] = "asdf"; print(z[0x100000000]);
|
||||
z[-1] = "asdf"; print(z[-1]);
|
||||
|
||||
// v8 and nashorn disagree on out-of-bounds uint32 indices: v8 won't go to the prototype.
|
||||
z[0xf0000000] = "asdf"; print(z[0xf0000000]);
|
||||
z[0xffffffff] = "asdf"; print(z[0xffffffff]);
|
||||
z[0x70000000] = "asdf"; print(z[0x70000000]);
|
||||
|
||||
// this will work in firefox and nashorn (not in v8).
|
||||
Uint8Array.prototype[4] = "asdf"; print(z[4]);
|
||||
});
|
||||
|
||||
(function test_exceptions() {
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(7)); });
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(8), 0, 4); });
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(8),-1, 2); });
|
||||
assertFail(function() { new Int32Array(new ArrayBuffer(8), 0,-1); });
|
||||
})();
|
||||
|
||||
(function test_subarray() {
|
||||
var x = fillArray(new Int8Array(8));
|
||||
print(arrstr(x));
|
||||
print("subarray(2,4)=" + arrstr(x.subarray(2, 4)), "subarray(-6,-4)=" + arrstr(x.subarray(-6, -4))); // negative index refers from the end of the array
|
||||
print(arrstr(x.subarray(-10, -2))); // negative index clamped to 0
|
||||
assertTrue(function(){ return arrstr(x.subarray(6, 4)) === ""; }); // negative length clamped to 0
|
||||
print(arrstr(x.subarray(1,-1).subarray(1,-1)), arrstr(x.subarray(1,-1).subarray(1,-1).subarray(1,-1))); // subarray of subarray
|
||||
})();
|
||||
|
||||
(function test_slice() {
|
||||
var b = new ArrayBuffer(16);
|
||||
fillArray(new Int8Array(b));
|
||||
print(bufstr(b));
|
||||
print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
|
||||
print(bufstr(b.slice(-20, -4))); // negative index clamped to 0
|
||||
assertTrue(function(){ return bufstr(b.slice(8, 4)) === ""; }); // negative length clamped to 0
|
||||
print(arrstr(new Int16Array(b.slice(1,-1).slice(2,-1).slice(1,-2).slice(1,-1)))); // slice of slice
|
||||
})();
|
||||
|
||||
(function test_clamped() {
|
||||
var a = new Uint8ClampedArray(10);
|
||||
a[0] = -17; // clamped to 0
|
||||
a[1] = 4711; // clamped to 255
|
||||
a[2] = 17.5; // clamped to 18
|
||||
a[3] = 16.5; // clamped to 16
|
||||
a[4] = 255.9; // clamped to 255
|
||||
a[5] = Infinity; // clamped to 255
|
||||
a[6] = -Infinity; // clamped to 0
|
||||
a[7] = NaN; // 0
|
||||
assertTrue(function(){ return a[0] === 0 && a[1] === 255 && a[2] === 18 && a[3] === 16 && a[4] === 255 && a[5] === 255 && a[6] === 0 && a[7] === 0; });
|
||||
})();
|
||||
|
||||
(function test_out_of_bounds() {
|
||||
var a = new Int32Array(10);
|
||||
a[10] = 10;
|
||||
a[100] = 100;
|
||||
a[1000] = 1000;
|
||||
assertTrue(function(){ return isUndefined(a[10]) && isUndefined(a[11]) && isUndefined(a[100]) && isUndefined(a[123]) && isUndefined(a[1000]); });
|
||||
})();
|
||||
|
||||
var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
|
||||
load(dir + "NASHORN-377-payload.js");
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared
|
||||
var x = {};
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:8 Variable "x" has already been declared
|
||||
var x = 2;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:13 Variable "x" has already been declared
|
||||
function x () {}
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
|
||||
const x = {};
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
|
||||
const x = 5;
|
||||
^
|
||||
|
||||
@ -39,3 +39,40 @@ try {
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
let a = [];
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
a.push(function() { print(i); });
|
||||
}
|
||||
|
||||
a.forEach(function(f) { f(); });
|
||||
|
||||
a = [];
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (i == 5) {
|
||||
i = "foo";
|
||||
}
|
||||
a.push(function() { print(i); });
|
||||
}
|
||||
|
||||
a.forEach(function(f) { f(); });
|
||||
|
||||
try {
|
||||
print(i);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
a = [];
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
if (i % 2 == 1) {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
a.push(function() { print(i); });
|
||||
}
|
||||
|
||||
a.forEach(function(f) { f(); });
|
||||
|
||||
@ -9,3 +9,25 @@
|
||||
8
|
||||
9
|
||||
ReferenceError: "i" is not defined
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
foo
|
||||
ReferenceError: "i" is not defined
|
||||
0
|
||||
4
|
||||
8
|
||||
12
|
||||
16
|
||||
|
||||
49
nashorn/test/script/basic/es6/let-const-statement-context.js
Normal file
49
nashorn/test/script/basic/es6/let-const-statement-context.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057980: let & const: remaining issues with lexical scoping
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @option --language=es6
|
||||
*/
|
||||
|
||||
function tryEval(s) {
|
||||
try {
|
||||
eval(s);
|
||||
} catch (e) {
|
||||
print(String(e).replace(/\\/g, "/"));
|
||||
}
|
||||
}
|
||||
|
||||
tryEval('if (true) let x = 1;');
|
||||
tryEval('if (true) const x = 1;');
|
||||
tryEval('while (true) let x = 1;');
|
||||
tryEval('while (true) const x = 1;');
|
||||
tryEval('for (;;) let x = 1;');
|
||||
tryEval('for (;;) const x = 1;');
|
||||
tryEval('do let x = 1; while (true);');
|
||||
tryEval('do const x = 1; while (true);');
|
||||
tryEval('with (y) const x = 1;');
|
||||
tryEval('with (y) let x = 1;');
|
||||
@ -0,0 +1,30 @@
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:10 Expected statement but found let declaration
|
||||
if (true) let x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:10 Expected statement but found const declaration
|
||||
if (true) const x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:13 Expected statement but found let declaration
|
||||
while (true) let x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:13 Expected statement but found const declaration
|
||||
while (true) const x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found let declaration
|
||||
for (;;) let x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found const declaration
|
||||
for (;;) const x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:3 Expected statement but found let declaration
|
||||
do let x = 1; while (true);
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:3 Expected statement but found const declaration
|
||||
do const x = 1; while (true);
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found const declaration
|
||||
with (y) const x = 1;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found let declaration
|
||||
with (y) let x = 1;
|
||||
^
|
||||
45
nashorn/test/script/basic/es6/let-const-switch.js
Normal file
45
nashorn/test/script/basic/es6/let-const-switch.js
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057980: let & const: remaining issues with lexical scoping
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @option --language=es6
|
||||
*/
|
||||
|
||||
function tryEval(s) {
|
||||
try {
|
||||
eval(s);
|
||||
} catch (e) {
|
||||
print(String(e).replace(/\\/g, "/"));
|
||||
}
|
||||
}
|
||||
|
||||
tryEval('var x = 0; switch (x) { case 0: { let x = 1; print(x); } case 1: { let x = 2; print(x); }} print(x);');
|
||||
tryEval('var x = 0; switch (x) { case 0: { const x = 1; print(x); } case 1: { const x = 2; print(x); }} print(x);');
|
||||
|
||||
// TODO: the following should not throw
|
||||
tryEval('switch (x) { case 0: let x = 1; }');
|
||||
tryEval('switch (x) { case 0: const x = 1; }');
|
||||
12
nashorn/test/script/basic/es6/let-const-switch.js.EXPECTED
Normal file
12
nashorn/test/script/basic/es6/let-const-switch.js.EXPECTED
Normal file
@ -0,0 +1,12 @@
|
||||
1
|
||||
2
|
||||
0
|
||||
1
|
||||
2
|
||||
0
|
||||
SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:25 Unsupported let declaration in unprotected switch statement
|
||||
switch (x) { case 0: let x = 1; }
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:27 Unsupported const declaration in unprotected switch statement
|
||||
switch (x) { case 0: const x = 1; }
|
||||
^
|
||||
@ -26,7 +26,8 @@
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @option --language=es6 */
|
||||
* @option --language=es6
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -39,17 +40,8 @@ load(__DIR__ + "let-load-lib.js");
|
||||
}
|
||||
|
||||
print("imported var: " + a);
|
||||
try {
|
||||
print("imported let: " + b);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
try {
|
||||
print("imported const: " + c);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
print("imported let: " + b);
|
||||
print("imported const: " + c);
|
||||
|
||||
top();
|
||||
|
||||
@ -59,4 +51,10 @@ try {
|
||||
print(e);
|
||||
}
|
||||
|
||||
try {
|
||||
c = "foo";
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,8 @@ top level function
|
||||
block function
|
||||
print local defs: 20 30
|
||||
imported var: 1
|
||||
ReferenceError: "b" is not defined
|
||||
ReferenceError: "c" is not defined
|
||||
imported let: 2
|
||||
imported const: 3
|
||||
top level function
|
||||
ReferenceError: "block" is not defined
|
||||
TypeError: Assignment to constant "c"
|
||||
|
||||
@ -4,12 +4,12 @@ SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variabl
|
||||
SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
|
||||
var x = 2;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
|
||||
var x = 2;
|
||||
SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
|
||||
let x = undefined;
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared
|
||||
const x = function (){};
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:13 Variable "a" has already been declared
|
||||
function a () {};
|
||||
^
|
||||
SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "a" has already been declared
|
||||
let a = 2;
|
||||
^
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
test
|
||||
test
|
||||
test
|
||||
3
|
||||
3
|
||||
3
|
||||
0
|
||||
1
|
||||
2
|
||||
0
|
||||
1
|
||||
2
|
||||
|
||||
34
nashorn/test/script/basic/es6/lexical-toplevel-def.js
Normal file
34
nashorn/test/script/basic/es6/lexical-toplevel-def.js
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
var VAR = "VAR";
|
||||
let LET = "LET";
|
||||
const CONST = "CONST";
|
||||
function FUNC() {}
|
||||
this.GLOBAL = "GLOBAL";
|
||||
51
nashorn/test/script/basic/es6/lexical-toplevel-print.js
Normal file
51
nashorn/test/script/basic/es6/lexical-toplevel-print.js
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
print(VAR);
|
||||
print(LET);
|
||||
print(CONST);
|
||||
print(FUNC);
|
||||
print(GLOBAL);
|
||||
print(this.VAR);
|
||||
print(this.LET); // undefined
|
||||
print(this.CONST); // undefined
|
||||
print(this.FUNC);
|
||||
print(this.GLOBAL);
|
||||
print("VAR" in this);
|
||||
print("LET" in this); // false
|
||||
print("CONST" in this); // false
|
||||
print("FUNC" in this);
|
||||
print("GLOBAL" in this);
|
||||
|
||||
try {
|
||||
LET = LET + "LET";
|
||||
CONST = CONST + "CONST";
|
||||
} catch (e) {
|
||||
print(String(e).replace(/\\/g, "/"));
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
function LET() {}
|
||||
var SHOULD_NOT_EXIST = 10;
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
let Object = "LEXICAL BUILTIN";
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
let FUNC = 10;
|
||||
var SHOULD_NOT_EXIST = 10;
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
let GLOBAL = "LEXICAL GLOBAL";
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
let VAR = 10;
|
||||
var SHOULD_NOT_EXIST = 10;
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @subtest
|
||||
*/
|
||||
|
||||
var LET = 10;
|
||||
var SHOULD_NOT_EXIST = 10;
|
||||
78
nashorn/test/script/basic/es6/lexical-toplevel-redeclare.js
Normal file
78
nashorn/test/script/basic/es6/lexical-toplevel-redeclare.js
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @option -scripting
|
||||
* @option --language=es6
|
||||
*/
|
||||
|
||||
load(__DIR__ + "lexical-toplevel-def.js");
|
||||
|
||||
var global = this;
|
||||
|
||||
function tryIt (code) {
|
||||
try {
|
||||
eval(code)
|
||||
} catch (e) {
|
||||
print(String(e).replace(/\\/g, "/"))
|
||||
}
|
||||
}
|
||||
|
||||
function loadScript(script) {
|
||||
print(script);
|
||||
try {
|
||||
load(__DIR__ + script);
|
||||
} catch (e) {
|
||||
print(String(e).replace(/\\/g, "/"));
|
||||
}
|
||||
print(VAR);
|
||||
print(LET);
|
||||
print(CONST);
|
||||
print(FUNC);
|
||||
print(GLOBAL);
|
||||
print(global.VAR);
|
||||
print(global.LET);
|
||||
print(global.CONST);
|
||||
print(global.FUNC);
|
||||
print(global.GLOBAL);
|
||||
try {
|
||||
print(SHOULD_NOT_EXIST);
|
||||
} catch (e) {
|
||||
print(String(e).replace(/\\/g, "/"));
|
||||
}
|
||||
print(global.SHOULD_NOT_EXIST);
|
||||
print(Object);
|
||||
print(global.Object);
|
||||
print();
|
||||
}
|
||||
|
||||
loadScript("lexical-toplevel-redeclare-var-on-let.js");
|
||||
loadScript("lexical-toplevel-redeclare-func-on-let.js");
|
||||
loadScript("lexical-toplevel-redeclare-let-on-var.js");
|
||||
loadScript("lexical-toplevel-redeclare-let-on-func.js");
|
||||
loadScript("lexical-toplevel-redeclare-let-on-builtin.js");
|
||||
loadScript("lexical-toplevel-redeclare-let-on-global.js");
|
||||
@ -0,0 +1,100 @@
|
||||
lexical-toplevel-redeclare-var-on-let.js
|
||||
SyntaxError: Variable "LET" has already been declared
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
ReferenceError: "SHOULD_NOT_EXIST" is not defined
|
||||
undefined
|
||||
function Object() { [native code] }
|
||||
function Object() { [native code] }
|
||||
|
||||
lexical-toplevel-redeclare-func-on-let.js
|
||||
SyntaxError: Variable "LET" has already been declared
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
ReferenceError: "SHOULD_NOT_EXIST" is not defined
|
||||
undefined
|
||||
function Object() { [native code] }
|
||||
function Object() { [native code] }
|
||||
|
||||
lexical-toplevel-redeclare-let-on-var.js
|
||||
SyntaxError: Variable "VAR" has already been declared
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
ReferenceError: "SHOULD_NOT_EXIST" is not defined
|
||||
undefined
|
||||
function Object() { [native code] }
|
||||
function Object() { [native code] }
|
||||
|
||||
lexical-toplevel-redeclare-let-on-func.js
|
||||
SyntaxError: Variable "FUNC" has already been declared
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
ReferenceError: "SHOULD_NOT_EXIST" is not defined
|
||||
undefined
|
||||
function Object() { [native code] }
|
||||
function Object() { [native code] }
|
||||
|
||||
lexical-toplevel-redeclare-let-on-builtin.js
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
ReferenceError: "SHOULD_NOT_EXIST" is not defined
|
||||
undefined
|
||||
LEXICAL BUILTIN
|
||||
function Object() { [native code] }
|
||||
|
||||
lexical-toplevel-redeclare-let-on-global.js
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
LEXICAL GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
ReferenceError: "SHOULD_NOT_EXIST" is not defined
|
||||
undefined
|
||||
LEXICAL BUILTIN
|
||||
function Object() { [native code] }
|
||||
|
||||
35
nashorn/test/script/basic/es6/lexical-toplevel.js
Normal file
35
nashorn/test/script/basic/es6/lexical-toplevel.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8057691: Nashorn: let & const declarations are not shared between scripts
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @option --language=es6
|
||||
*/
|
||||
|
||||
load(__DIR__ + "lexical-toplevel-def.js");
|
||||
|
||||
load(__DIR__ + "lexical-toplevel-print.js");
|
||||
load(__DIR__ + "lexical-toplevel-print.js");
|
||||
32
nashorn/test/script/basic/es6/lexical-toplevel.js.EXPECTED
Normal file
32
nashorn/test/script/basic/es6/lexical-toplevel.js.EXPECTED
Normal file
@ -0,0 +1,32 @@
|
||||
VAR
|
||||
LET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
true
|
||||
TypeError: Assignment to constant "CONST"
|
||||
VAR
|
||||
LETLET
|
||||
CONST
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
VAR
|
||||
undefined
|
||||
undefined
|
||||
function FUNC() {}
|
||||
GLOBAL
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
true
|
||||
TypeError: Assignment to constant "CONST"
|
||||
@ -53,6 +53,7 @@ if (! new File(jdepsPath).isFile()) {
|
||||
}
|
||||
|
||||
// run jdep on nashorn.jar - only summary but print profile info
|
||||
$ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
|
||||
`${jdepsPath} -s -P ${nashornJar.absolutePath}`
|
||||
|
||||
// check for "(compact1)" in output from jdep tool
|
||||
|
||||
@ -54,6 +54,7 @@ if (! new File(jjsCmd).isFile()) {
|
||||
}
|
||||
jjsCmd += " -J-Xbootclasspath/a:" + nashornJarDir;
|
||||
|
||||
$ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
|
||||
$EXEC(jjsCmd, "var x = Object.create(null);\nx;\nprint('PASSED');\nexit(0)");
|
||||
|
||||
// $ERR has all interactions including prompts! Just check for error substring.
|
||||
|
||||
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
import javax.script.SimpleScriptContext;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Top-level lexical binding tests.
|
||||
*
|
||||
* @test
|
||||
* @run testng jdk.nashorn.internal.runtime.LexicalBindingTest
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public class LexicalBindingTest {
|
||||
|
||||
final static String LANGUAGE_ES6 = "--language=es6";
|
||||
final static int NUMBER_OF_CONTEXTS = 20;
|
||||
final static int MEGAMORPHIC_LOOP_COUNT = 20;
|
||||
|
||||
/**
|
||||
* Test access to global var-declared variables for shared script classes with multiple globals.
|
||||
*/
|
||||
@Test
|
||||
public static void megamorphicVarTest() throws ScriptException, InterruptedException {
|
||||
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
final ScriptEngine e = factory.getScriptEngine();
|
||||
final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
|
||||
final String sharedScript = "foo";
|
||||
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
|
||||
final ScriptContext context = contexts[i] = new SimpleScriptContext();
|
||||
final Bindings b = e.createBindings();
|
||||
context.setBindings(b, ScriptContext.ENGINE_SCOPE);
|
||||
assertEquals(e.eval("var foo = '" + i + "';", context), null);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
|
||||
final ScriptContext context = contexts[i];
|
||||
assertEquals(e.eval(sharedScript, context), String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test access to global lexically declared variables for shared script classes with multiple globals.
|
||||
*/
|
||||
@Test
|
||||
public static void megamorphicMultiGlobalLetTest() throws ScriptException, InterruptedException {
|
||||
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
|
||||
final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
|
||||
final String sharedScript = "foo";
|
||||
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
|
||||
final ScriptContext context = contexts[i] = new SimpleScriptContext();
|
||||
final Bindings b = e.createBindings();
|
||||
context.setBindings(b, ScriptContext.ENGINE_SCOPE);
|
||||
assertEquals(e.eval("let foo = '" + i + "';", context), null);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
|
||||
final ScriptContext context = contexts[i];
|
||||
assertEquals(e.eval(sharedScript, context), String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test access to global lexically declared variables for shared script classes with single global.
|
||||
*/
|
||||
@Test
|
||||
public static void megamorphicSingleGlobalLetTest() throws ScriptException, InterruptedException {
|
||||
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
|
||||
final String sharedGetterScript = "foo";
|
||||
final String sharedSetterScript = "foo = 1";
|
||||
|
||||
for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
|
||||
assertEquals(e.eval(sharedSetterScript), 1);
|
||||
assertEquals(e.eval(sharedGetterScript), 1);
|
||||
assertEquals(e.eval("delete foo; a" + i + " = 1; foo = " + i + ";"), i);
|
||||
assertEquals(e.eval(sharedGetterScript), i);
|
||||
}
|
||||
|
||||
assertEquals(e.eval("let foo = 'foo';"), null);
|
||||
assertEquals(e.eval(sharedGetterScript), "foo");
|
||||
assertEquals(e.eval(sharedSetterScript), 1);
|
||||
assertEquals(e.eval(sharedGetterScript), 1);
|
||||
assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test access to global lexically declared variables for shared script classes with single global.
|
||||
*/
|
||||
@Test
|
||||
public static void megamorphicInheritedGlobalLetTest() throws ScriptException, InterruptedException {
|
||||
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
|
||||
final String sharedGetterScript = "foo";
|
||||
final String sharedSetterScript = "foo = 1";
|
||||
|
||||
for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
|
||||
assertEquals(e.eval(sharedSetterScript), 1);
|
||||
assertEquals(e.eval(sharedGetterScript), 1);
|
||||
assertEquals(e.eval("delete foo; a" + i + " = 1; Object.prototype.foo = " + i + ";"), i);
|
||||
assertEquals(e.eval(sharedGetterScript), i);
|
||||
}
|
||||
|
||||
assertEquals(e.eval("let foo = 'foo';"), null);
|
||||
assertEquals(e.eval(sharedGetterScript), "foo");
|
||||
assertEquals(e.eval(sharedSetterScript), 1);
|
||||
assertEquals(e.eval(sharedGetterScript), 1);
|
||||
assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multi-threaded access to global lexically declared variables for shared script classes with multiple globals.
|
||||
*/
|
||||
@Test
|
||||
public static void multiThreadedLetTest() throws ScriptException, InterruptedException {
|
||||
final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
|
||||
final Bindings b = e.createBindings();
|
||||
final ScriptContext origContext = e.getContext();
|
||||
final ScriptContext newCtxt = new SimpleScriptContext();
|
||||
newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
|
||||
final String sharedScript = "foo";
|
||||
|
||||
assertEquals(e.eval("let foo = 'original context';", origContext), null);
|
||||
assertEquals(e.eval("let foo = 'new context';", newCtxt), null);
|
||||
|
||||
final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
|
||||
final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
|
||||
t1.start();
|
||||
t2.start();
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
assertEquals(e.eval("foo = 'newer context';", newCtxt), "newer context");
|
||||
final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
|
||||
final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
|
||||
|
||||
t3.start();
|
||||
t4.start();
|
||||
t3.join();
|
||||
t4.join();
|
||||
|
||||
assertEquals(e.eval(sharedScript), "original context");
|
||||
assertEquals(e.eval(sharedScript, newCtxt), "newer context");
|
||||
}
|
||||
|
||||
private static class ScriptRunner implements Runnable {
|
||||
|
||||
final ScriptEngine engine;
|
||||
final ScriptContext context;
|
||||
final String source;
|
||||
final Object expected;
|
||||
final int iterations;
|
||||
|
||||
ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
|
||||
this.engine = engine;
|
||||
this.context = context;
|
||||
this.source = source;
|
||||
this.expected = expected;
|
||||
this.iterations = iterations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
assertEquals(engine.eval(source, context), expected);
|
||||
}
|
||||
} catch (final ScriptException se) {
|
||||
throw new RuntimeException(se);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,7 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitOption;
|
||||
@ -264,6 +265,12 @@ public final class TestFinder {
|
||||
isTest = false;
|
||||
isNotTest = true;
|
||||
break;
|
||||
case "@bigendian":
|
||||
shouldRun = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||
break;
|
||||
case "@littleendian":
|
||||
shouldRun = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
|
||||
break;
|
||||
case "@runif": {
|
||||
final String prop = scanner.next();
|
||||
if (System.getProperty(prop) != null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user