--- a/nashorn/make/build.xml Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/make/build.xml Thu Dec 04 15:23:04 2014 -0800
@@ -36,9 +36,9 @@
<pathelement location="${dist.dir}"/>
</path>
<path id="nashorn.boot.prefix.path">
- <pathelement location="${dist.dir}"/>
+ <pathelement location="${dist.jar}"/>
</path>
- <property name="boot.class.path" value="-Xbootclasspath/a:="${toString:nashorn.boot.prefix.path}""/>
+ <property name="boot.class.path" value="-Xbootclasspath/p:"${toString:nashorn.boot.prefix.path}""/>
<condition property="svn.executable" value="/usr/local/bin/svn" else="svn">
<available file="/usr/local/bin/svn"/>
</condition>
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Dec 04 15:23:04 2014 -0800
@@ -135,15 +135,11 @@
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 @@
* @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 @@
@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 @@
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 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 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 @@
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);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java Thu Dec 04 15:23:04 2014 -0800
@@ -48,11 +48,13 @@
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();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Dec 04 15:23:04 2014 -0800
@@ -3080,6 +3080,7 @@
if (isConditionalCatch) {
loadExpressionAsBoolean(exceptionCondition);
nextCatch = new Label("next_catch");
+ nextCatch.markAsBreakTarget();
method.ifeq(nextCatch);
} else {
nextCatch = null;
@@ -3092,7 +3093,7 @@
method._goto(afterCatch);
}
if(nextCatch != null) {
- method.label(nextCatch);
+ method.breakLabel(nextCatch, lc.getUsedSlotCount());
}
}
@@ -3264,6 +3265,13 @@
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);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Thu Dec 04 15:23:04 2014 -0800
@@ -525,7 +525,7 @@
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;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MapCreator.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MapCreator.java Thu Dec 04 15:23:04 2014 -0800
@@ -152,6 +152,10 @@
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;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Thu Dec 04 15:23:04 2014 -0800
@@ -45,14 +45,14 @@
/** 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 @@
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;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Thu Dec 04 15:23:04 2014 -0800
@@ -1091,6 +1091,15 @@
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;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java Thu Dec 04 15:23:04 2014 -0800
@@ -597,6 +597,20 @@
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();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java Thu Dec 04 15:23:04 2014 -0800
@@ -177,4 +177,10 @@
* @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();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java Thu Dec 04 15:23:04 2014 -0800
@@ -45,19 +45,16 @@
/** 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 @@
* @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) {
@@ -260,14 +257,6 @@
}
/**
- * 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.
*/
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java Thu Dec 04 15:23:04 2014 -0800
@@ -150,4 +150,9 @@
}
return test == null;
}
+
+ @Override
+ public boolean hasPerIterationScope() {
+ return false;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Thu Dec 04 15:23:04 2014 -0800
@@ -34,6 +34,7 @@
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.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.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.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 @@
// 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 @@
// 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 @@
super(checkAndGetMap(context));
this.context = context;
this.setIsScope();
+ this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
}
/**
@@ -1693,6 +1706,133 @@
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 @@
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 @@
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);
+ }
+ }
+
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDataView.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDataView.java Thu Dec 04 15:23:04 2014 -0800
@@ -105,10 +105,10 @@
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 @@
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 @@
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;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java Thu Dec 04 15:23:04 2014 -0800
@@ -48,6 +48,7 @@
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 @@
* @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 @@
arguments = ScriptRuntime.EMPTY_ARRAY;
}
- return ((ScriptFunctionImpl)self).makeBoundFunction(thiz, arguments);
+ return Bootstrap.bindCallable(self, thiz, arguments);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Thu Dec 04 15:23:04 2014 -0800
@@ -28,6 +28,7 @@
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 @@
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 @@
// 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) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Dec 04 15:23:04 2014 -0800
@@ -30,7 +30,6 @@
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 @@
/**
* 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);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Thu Dec 04 15:23:04 2014 -0800
@@ -554,7 +554,7 @@
// Set up new block. Captures first token.
final ParserContextBlockNode newBlock = newBlock();
try {
- statement();
+ statement(false, false, true);
} finally {
restoreBlock(newBlock);
}
@@ -703,26 +703,12 @@
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())));
- }
- }
+ 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 @@
try {
// Get the next element.
- statement(true, allowPropertyFunction);
+ statement(true, allowPropertyFunction, false);
allowPropertyFunction = false;
// check for directive prologues
@@ -874,13 +860,15 @@
* 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 @@
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 @@
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 @@
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 @@
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,21 +1323,22 @@
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 (vars != null) {
+ for (final VarNode var : vars) {
+ appendStatement(var);
}
- if (outer != null) {
- restoreBlock(outer);
- appendStatement(new BlockStatement(startLine, new Block(
- outer.getToken(),
- body.getFinish(),
- outer.getStatements())));
- }
+ }
+ 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 @@
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 @@
}
} 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 @@
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 @@
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 @@
} 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 @@
final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
lc.push(functionNode);
- final Block functionBody = functionBody(functionNode);
-
- lc.pop(functionNode);
+ Block functionBody;
+
+
+ try {
+ functionBody = functionBody(functionNode);
+ } finally {
+ lc.pop(functionNode);
+ }
final FunctionNode function = createFunctionNode(
functionNode,
@@ -2340,9 +2336,13 @@
final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
lc.push(functionNode);
- final Block functionBody = functionBody(functionNode);
-
- lc.pop(functionNode);
+ Block functionBody;
+ try {
+ functionBody = functionBody(functionNode);
+ } finally {
+ lc.pop(functionNode);
+ }
+
final FunctionNode function = createFunctionNode(
functionNode,
@@ -2739,12 +2739,9 @@
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()) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java Thu Dec 04 15:23:04 2014 -0800
@@ -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 {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstDeserializer.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstDeserializer.java Thu Dec 04 15:23:04 2014 -0800
@@ -27,6 +27,8 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.zip.InflaterInputStream;
import jdk.nashorn.internal.ir.FunctionNode;
@@ -36,12 +38,18 @@
*/
final class AstDeserializer {
static FunctionNode deserialize(final byte[] serializedAst) {
- try {
- return (FunctionNode)new ObjectInputStream(new InflaterInputStream(new ByteArrayInputStream(
- serializedAst))).readObject();
- } catch (final ClassNotFoundException | IOException e) {
- // This is internal, can't happen
- throw new AssertionError("Unexpected exception deserializing function", e);
- }
+ // FIXME: do we need this doPrivileged block at all?
+ return AccessController.doPrivileged(new PrivilegedAction<FunctionNode>() {
+ @Override
+ public FunctionNode run() {
+ try {
+ return (FunctionNode)new ObjectInputStream(new InflaterInputStream(
+ new ByteArrayInputStream(serializedAst))).readObject();
+ } catch (final ClassNotFoundException | IOException e) {
+ // This is internal, can't happen
+ throw new AssertionError("Unexpected exception deserializing function", e);
+ }
+ }
+ });
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Thu Dec 04 15:23:04 2014 -0800
@@ -714,6 +714,9 @@
* @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();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Thu Dec 04 15:23:04 2014 -0800
@@ -84,14 +84,17 @@
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 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;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Thu Dec 04 15:23:04 2014 -0800
@@ -46,6 +46,8 @@
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 @@
* </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,29 +306,44 @@
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);
- }
+ 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 {
- // 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 = 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));
}
}
}
-
- this.setMap(newMap);
+ return newMap;
}
/**
@@ -510,7 +527,11 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
@@ -3667,6 +3694,29 @@
}
/**
+ * 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.
*
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Dec 04 15:23:04 2014 -0800
@@ -61,9 +61,9 @@
/**
* 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 @@
*/
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 @@
@Override
public ContinuousArrayData copy() {
- return new UntouchedArrayData((int)length());
+ assert length() == 0;
+ return this;
}
@Override
@@ -246,7 +243,7 @@
public Class<?> getBoxedElementType() {
return Integer.class;
}
- };
+ }
/**
* Constructor
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Thu Dec 04 15:23:04 2014 -0800
@@ -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 @@
* @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;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Dec 04 15:23:04 2014 -0800
@@ -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.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 @@
new NashornLinker(),
new NashornPrimitiveLinker(),
new NashornStaticClassLinker(),
- new BoundDynamicMethodLinker(),
+ new BoundCallableLinker(),
new JavaSuperAdapterLinker(),
new JSObjectLinker(nashornBeansLinker),
new BrowserJSObjectLinker(nashornBeansLinker),
@@ -136,19 +139,47 @@
}
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 @@
}
/**
- * 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);
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallable.java Thu Dec 04 15:23:04 2014 -0800
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java Thu Dec 04 15:23:04 2014 -0800
@@ -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)));
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java Thu Dec 04 12:58:22 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java Thu Dec 04 12:58:22 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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)));
- }
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Thu Dec 04 15:23:04 2014 -0800
@@ -45,7 +45,15 @@
* A Dynalink linker to handle web browser built-in JS (DOM etc.) objects.
*/
final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
- private static final ClassLoader myLoader = BrowserJSObjectLinker.class.getClassLoader();
+ private static ClassLoader extLoader;
+ static {
+ extLoader = BrowserJSObjectLinker.class.getClassLoader();
+ // in case nashorn is loaded as bootstrap!
+ if (extLoader == null) {
+ extLoader = ClassLoader.getSystemClassLoader().getParent();
+ }
+ }
+
private static final String JSOBJECT_CLASS = "netscape.javascript.JSObject";
// not final because this is lazily initialized
// when we hit a subclass for the first time.
@@ -69,7 +77,7 @@
// check if this class is a subclass of JSObject
Class<?> clazz = type;
while (clazz != null) {
- if (clazz.getClassLoader() == myLoader &&
+ if (clazz.getClassLoader() == extLoader &&
clazz.getName().equals(JSOBJECT_CLASS)) {
jsObjectClass = clazz;
return true;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu Dec 04 15:23:04 2014 -0800
@@ -104,7 +104,7 @@
// SecurityException for nashorn's classes!. For adapter's to work, we
// should be able to refer to the few classes it needs in its implementation.
if(VISIBLE_INTERNAL_CLASS_NAMES.contains(name)) {
- return myLoader.loadClass(name);
+ return myLoader != null? myLoader.loadClass(name) : Class.forName(name, false, myLoader);
}
throw se;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Thu Dec 04 15:23:04 2014 -0800
@@ -165,7 +165,7 @@
*/
@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);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Dec 04 15:23:04 2014 -0800
@@ -82,7 +82,7 @@
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.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.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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049407-big-endian.js Thu Dec 04 15:23:04 2014 -0800
@@ -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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049407-big-endian.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -0,0 +1,1 @@
+false
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049407-payload.js Thu Dec 04 15:23:04 2014 -0800
@@ -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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049407.js Thu Dec 04 15:23:04 2014 -0800
@@ -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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049407.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -0,0 +1,1 @@
+true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8051778.js Thu Dec 04 15:23:04 2014 -0800
@@ -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))())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8051778.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066214.js Thu Dec 04 15:23:04 2014 -0800
@@ -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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066214.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066222.js Thu Dec 04 15:23:04 2014 -0800
@@ -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)})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066222.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -0,0 +1,3 @@
+SUCCESS
+undefined
+1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066232.js Thu Dec 04 15:23:04 2014 -0800
@@ -0,0 +1,38 @@
+/*
+ * 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) {
+ }
+})()
+
+print("SUCCESS");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066232.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -0,0 +1,1 @@
+SUCCESS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066238.js Thu Dec 04 15:23:04 2014 -0800
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/NASHORN-377-big-endian.js Thu Dec 04 15:23:04 2014 -0800
@@ -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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/NASHORN-377-big-endian.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/NASHORN-377-payload.js Thu Dec 04 15:23:04 2014 -0800
@@ -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]); });
+})();
+
--- a/nashorn/test/script/basic/NASHORN-377.js Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/NASHORN-377.js Thu Dec 04 15:23:04 2014 -0800
@@ -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");
--- a/nashorn/test/script/basic/es6/const-redeclare-extra.js.EXPECTED Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/const-redeclare-extra.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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;
+ ^
--- a/nashorn/test/script/basic/es6/for-let.js Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/for-let.js Thu Dec 04 15:23:04 2014 -0800
@@ -39,3 +39,40 @@
} 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(); });
--- a/nashorn/test/script/basic/es6/for-let.js.EXPECTED Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/for-let.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let-const-statement-context.js Thu Dec 04 15:23:04 2014 -0800
@@ -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;');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let-const-statement-context.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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;
+ ^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let-const-switch.js Thu Dec 04 15:23:04 2014 -0800
@@ -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; }');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/let-const-switch.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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; }
+ ^
--- a/nashorn/test/script/basic/es6/let-load.js Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/let-load.js Thu Dec 04 15:23:04 2014 -0800
@@ -26,7 +26,8 @@
*
* @test
* @run
- * @option --language=es6 */
+ * @option --language=es6
+ */
"use strict";
@@ -39,17 +40,8 @@
}
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 @@
print(e);
}
+try {
+ c = "foo";
+} catch (e) {
+ print(e);
+}
+
--- a/nashorn/test/script/basic/es6/let-load.js.EXPECTED Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/let-load.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -2,7 +2,8 @@
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"
--- a/nashorn/test/script/basic/es6/let-redeclare-extra.js.EXPECTED Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/let-redeclare-extra.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -4,12 +4,12 @@
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;
+ ^
--- a/nashorn/test/script/basic/es6/let_const_closure.js.EXPECTED Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/basic/es6/let_const_closure.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -5,9 +5,9 @@
test
test
test
-3
-3
-3
0
1
2
+0
+1
+2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-def.js Thu Dec 04 15:23:04 2014 -0800
@@ -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";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-print.js Thu Dec 04 15:23:04 2014 -0800
@@ -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, "/"));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js Thu Dec 04 15:23:04 2014 -0800
@@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js Thu Dec 04 15:23:04 2014 -0800
@@ -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";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js Thu Dec 04 15:23:04 2014 -0800
@@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js Thu Dec 04 15:23:04 2014 -0800
@@ -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";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js Thu Dec 04 15:23:04 2014 -0800
@@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js Thu Dec 04 15:23:04 2014 -0800
@@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare.js Thu Dec 04 15:23:04 2014 -0800
@@ -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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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] }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel.js Thu Dec 04 15:23:04 2014 -0800
@@ -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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/lexical-toplevel.js.EXPECTED Thu Dec 04 15:23:04 2014 -0800
@@ -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"
--- a/nashorn/test/script/nosecurity/JDK-8050964.js Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/nosecurity/JDK-8050964.js Thu Dec 04 15:23:04 2014 -0800
@@ -53,6 +53,7 @@
}
// 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
--- a/nashorn/test/script/nosecurity/JDK-8055034.js Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/script/nosecurity/JDK-8055034.js Thu Dec 04 15:23:04 2014 -0800
@@ -43,7 +43,6 @@
if (! nashornJar.isAbsolute()) {
nashornJar = new File(".", nashornJar);
}
-var nashornJarDir = nashornJar.parentFile.absolutePath;
// we want to use nashorn.jar passed and not the one that comes with JRE
var jjsCmd = javahome + "/../bin/jjs";
@@ -52,8 +51,9 @@
jjsCmd = javahome + "/bin/jjs";
jjsCmd = jjsCmd.toString().replaceAll(/\//g, File.separater);
}
-jjsCmd += " -J-Xbootclasspath/a:" + nashornJarDir;
+jjsCmd += " -J-Xbootclasspath/p:" + nashornJar;
+$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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java Thu Dec 04 15:23:04 2014 -0800
@@ -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);
+ }
+ }
+ }
+}
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Thu Dec 04 12:58:22 2014 -0800
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Thu Dec 04 15:23:04 2014 -0800
@@ -46,6 +46,7 @@
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 @@
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) {