Thu, 04 Sep 2014 18:47:18 +0200
8051889: Implement block scoping in symbol assignment and scope computation
Reviewed-by: attila, lagergren
1.1 --- a/make/build.xml Wed Sep 03 14:33:34 2014 +0200 1.2 +++ b/make/build.xml Thu Sep 04 18:47:18 2014 +0200 1.3 @@ -340,6 +340,13 @@ 1.4 permission java.util.PropertyPermission "nashorn.test.*", "read"; 1.5 }; 1.6 1.7 +grant codeBase "file:/${basedir}/test/script/basic/es6/*" { 1.8 + permission java.io.FilePermission "${basedir}/test/script/-", "read"; 1.9 + permission java.io.FilePermission "$${user.dir}", "read"; 1.10 + permission java.util.PropertyPermission "user.dir", "read"; 1.11 + permission java.util.PropertyPermission "nashorn.test.*", "read"; 1.12 +}; 1.13 + 1.14 grant codeBase "file:/${basedir}/test/script/basic/JDK-8010946-privileged.js" { 1.15 permission java.util.PropertyPermission "java.security.policy", "read"; 1.16 };
2.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java Wed Sep 03 14:33:34 2014 +0200 2.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Sep 04 18:47:18 2014 +0200 2.3 @@ -36,6 +36,7 @@ 2.4 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; 2.5 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; 2.6 import static jdk.nashorn.internal.ir.Symbol.HAS_OBJECT_VALUE; 2.7 +import static jdk.nashorn.internal.ir.Symbol.IS_CONST; 2.8 import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF; 2.9 import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL; 2.10 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; 2.11 @@ -83,11 +84,13 @@ 2.12 import jdk.nashorn.internal.ir.UnaryNode; 2.13 import jdk.nashorn.internal.ir.VarNode; 2.14 import jdk.nashorn.internal.ir.WithNode; 2.15 -import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; 2.16 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 2.17 import jdk.nashorn.internal.runtime.Context; 2.18 -import jdk.nashorn.internal.runtime.Property; 2.19 -import jdk.nashorn.internal.runtime.PropertyMap; 2.20 +import jdk.nashorn.internal.runtime.ECMAErrors; 2.21 +import jdk.nashorn.internal.runtime.ErrorManager; 2.22 +import jdk.nashorn.internal.runtime.JSErrorType; 2.23 +import jdk.nashorn.internal.runtime.ParserException; 2.24 +import jdk.nashorn.internal.runtime.Source; 2.25 import jdk.nashorn.internal.runtime.logging.DebugLogger; 2.26 import jdk.nashorn.internal.runtime.logging.Loggable; 2.27 import jdk.nashorn.internal.runtime.logging.Logger; 2.28 @@ -101,7 +104,7 @@ 2.29 * visitor. 2.30 */ 2.31 @Logger(name="symbols") 2.32 -final class AssignSymbols extends NodeOperatorVisitor<LexicalContext> implements Loggable { 2.33 +final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable { 2.34 private final DebugLogger log; 2.35 private final boolean debug; 2.36 2.37 @@ -190,8 +193,7 @@ 2.38 * @param body the body of the FunctionNode we are entering 2.39 */ 2.40 private void acceptDeclarations(final FunctionNode functionNode, final Block body) { 2.41 - // This visitor will assign symbol to all declared variables, except function declarations (which are taken care 2.42 - // in a separate step above) and "var" declarations in for loop initializers. 2.43 + // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers. 2.44 // 2.45 body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 2.46 @Override 2.47 @@ -204,8 +206,8 @@ 2.48 public Node leaveVarNode(final VarNode varNode) { 2.49 if (varNode.isStatement()) { 2.50 final IdentNode ident = varNode.getName(); 2.51 - final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR); 2.52 - functionNode.addDeclaredSymbol(symbol); 2.53 + final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body; 2.54 + final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags()); 2.55 if (varNode.isFunctionDeclaration()) { 2.56 symbol.setIsFunctionDeclaration(); 2.57 } 2.58 @@ -303,23 +305,31 @@ 2.59 return functionNode.setBody(lc, body.setStatements(lc, newStatements)); 2.60 } 2.61 2.62 - private Symbol defineGlobalSymbol(final Block block, final String name) { 2.63 - return defineSymbol(block, name, IS_GLOBAL); 2.64 - } 2.65 - 2.66 /** 2.67 * Defines a new symbol in the given block. 2.68 * 2.69 * @param block the block in which to define the symbol 2.70 * @param name name of symbol. 2.71 + * @param origin origin node 2.72 * @param symbolFlags Symbol flags. 2.73 * 2.74 * @return Symbol for given name or null for redefinition. 2.75 */ 2.76 - private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) { 2.77 + private Symbol defineSymbol(final Block block, final String name, final Node origin, final int symbolFlags) { 2.78 int flags = symbolFlags; 2.79 - Symbol symbol = findSymbol(block, name); // Locate symbol. 2.80 - final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; 2.81 + final boolean isBlockScope = (flags & IS_LET) != 0 || (flags & IS_CONST) != 0; 2.82 + final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; 2.83 + 2.84 + Symbol symbol; 2.85 + final FunctionNode function; 2.86 + if (isBlockScope) { 2.87 + // block scoped variables always live in current block, no need to look for existing symbols in parent blocks. 2.88 + symbol = block.getExistingSymbol(name); 2.89 + function = lc.getCurrentFunction(); 2.90 + } else { 2.91 + symbol = findSymbol(block, name); 2.92 + function = lc.getFunction(block); 2.93 + } 2.94 2.95 // Global variables are implicitly always scope variables too. 2.96 if (isGlobal) { 2.97 @@ -333,7 +343,6 @@ 2.98 final boolean isParam = (flags & KINDMASK) == IS_PARAM; 2.99 final boolean isVar = (flags & KINDMASK) == IS_VAR; 2.100 2.101 - final FunctionNode function = lc.getFunction(block); 2.102 if (symbol != null) { 2.103 // Symbol was already defined. Check if it needs to be redefined. 2.104 if (isParam) { 2.105 @@ -345,10 +354,21 @@ 2.106 throw new AssertionError("duplicate parameter"); 2.107 } 2.108 } else if (isVar) { 2.109 - if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) { 2.110 + if (isBlockScope) { 2.111 + // Check redeclaration in same block 2.112 + if (symbol.hasBeenDeclared()) { 2.113 + throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin); 2.114 + } else { 2.115 + symbol.setHasBeenDeclared(); 2.116 + } 2.117 + } else if ((flags & IS_INTERNAL) != 0) { 2.118 // Always create a new definition. 2.119 symbol = null; 2.120 } else { 2.121 + // Found LET or CONST in parent scope of same function - s SyntaxError 2.122 + if (symbol.isBlockScoped() && isLocal(lc.getCurrentFunction(), symbol)) { 2.123 + throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin); 2.124 + } 2.125 // Not defined in this function. Create a new definition. 2.126 if (!isLocal(function, symbol) || symbol.less(IS_VAR)) { 2.127 symbol = null; 2.128 @@ -359,10 +379,10 @@ 2.129 2.130 if (symbol == null) { 2.131 // If not found, then create a new one. 2.132 - Block symbolBlock; 2.133 + final Block symbolBlock; 2.134 2.135 // Determine where to create it. 2.136 - if (isVar && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { 2.137 + if (isVar && ((flags & IS_INTERNAL) != 0 || isBlockScope)) { 2.138 symbolBlock = block; //internal vars are always defined in the block closest to them 2.139 } else if (isGlobal) { 2.140 symbolBlock = lc.getOutermostFunction().getBody(); 2.141 @@ -420,9 +440,9 @@ 2.142 @Override 2.143 public boolean enterBlock(final Block block) { 2.144 start(block); 2.145 - block.clearSymbols(); 2.146 2.147 if (lc.isFunctionBody()) { 2.148 + block.clearSymbols(); 2.149 enterFunctionBody(); 2.150 } 2.151 2.152 @@ -441,7 +461,10 @@ 2.153 // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its 2.154 // symbol is naturally internal, and should be treated as such. 2.155 final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName()); 2.156 - defineSymbol(block, exname, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE); 2.157 + // IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to 2.158 + // clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block. 2.159 + final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE); 2.160 + symbol.clearFlag(IS_LET); 2.161 2.162 return true; 2.163 } 2.164 @@ -452,15 +475,13 @@ 2.165 2.166 initFunctionWideVariables(functionNode, body); 2.167 2.168 - if (functionNode.isProgram()) { 2.169 - initGlobalSymbols(body); 2.170 - } else if (!functionNode.isDeclared() && !functionNode.isAnonymous()) { 2.171 + if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) { 2.172 // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's 2.173 // anonymous. 2.174 final String name = functionNode.getIdent().getName(); 2.175 assert name != null; 2.176 assert body.getExistingSymbol(name) == null; 2.177 - defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE); 2.178 + defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE); 2.179 if(functionNode.allVarsInScope()) { // basically, has deep eval 2.180 lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL); 2.181 } 2.182 @@ -485,7 +506,8 @@ 2.183 if (functionNode.isDeclared()) { 2.184 final Iterator<Block> blocks = lc.getBlocks(); 2.185 if (blocks.hasNext()) { 2.186 - defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0)); 2.187 + final IdentNode ident = functionNode.getIdent(); 2.188 + defineSymbol(blocks.next(), ident.getName(), ident, IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0)); 2.189 } 2.190 } 2.191 2.192 @@ -495,10 +517,16 @@ 2.193 @Override 2.194 public boolean enterVarNode(final VarNode varNode) { 2.195 start(varNode); 2.196 - defineSymbol(lc.getCurrentBlock(), varNode.getName().getName(), IS_VAR | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0)); 2.197 return true; 2.198 } 2.199 2.200 + @Override 2.201 + public Node leaveVarNode(final VarNode varNode) { 2.202 + final IdentNode ident = varNode.getName(); 2.203 + defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0)); 2.204 + return super.leaveVarNode(varNode); 2.205 + } 2.206 + 2.207 private Symbol exceptionSymbol() { 2.208 return newObjectInternal(EXCEPTION_PREFIX); 2.209 } 2.210 @@ -597,7 +625,7 @@ 2.211 } 2.212 2.213 private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) { 2.214 - defineSymbol(block, cc.symbolName(), flags).setNeedsSlot(true); 2.215 + defineSymbol(block, cc.symbolName(), null, flags).setNeedsSlot(true); 2.216 } 2.217 2.218 private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) { 2.219 @@ -608,7 +636,7 @@ 2.220 initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE); 2.221 if (functionNode.needsArguments()) { 2.222 initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE); 2.223 - defineSymbol(body, ARGUMENTS_VAR.symbolName(), IS_VAR | HAS_OBJECT_VALUE); 2.224 + defineSymbol(body, ARGUMENTS_VAR.symbolName(), null, IS_VAR | HAS_OBJECT_VALUE); 2.225 } 2.226 } 2.227 2.228 @@ -617,20 +645,6 @@ 2.229 initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL); 2.230 } 2.231 2.232 - 2.233 - /** 2.234 - * Move any properties from the global map into the scope of this function (which must be a program function). 2.235 - * @param block the function node body for which to init scope vars 2.236 - */ 2.237 - private void initGlobalSymbols(final Block block) { 2.238 - final PropertyMap map = Context.getGlobalMap(); 2.239 - 2.240 - for (final Property property : map.getProperties()) { 2.241 - final Symbol symbol = defineGlobalSymbol(block, property.getKey()); 2.242 - log.info("Added global symbol from property map ", symbol); 2.243 - } 2.244 - } 2.245 - 2.246 /** 2.247 * Initialize parameters for function node. 2.248 * @param functionNode the function node 2.249 @@ -639,7 +653,7 @@ 2.250 final boolean isVarArg = functionNode.isVarArg(); 2.251 final boolean scopeParams = functionNode.allVarsInScope() || isVarArg; 2.252 for (final IdentNode param : functionNode.getParameters()) { 2.253 - final Symbol symbol = defineSymbol(body, param.getName(), IS_PARAM); 2.254 + final Symbol symbol = defineSymbol(body, param.getName(), param, IS_PARAM); 2.255 if(scopeParams) { 2.256 // NOTE: this "set is scope" is a poor substitute for clear expression of where the symbol is stored. 2.257 // It will force creation of scopes where they would otherwise not necessarily be needed (functions 2.258 @@ -665,10 +679,29 @@ 2.259 return definingFn == function; 2.260 } 2.261 2.262 + private void checkConstAssignment(final IdentNode ident) { 2.263 + // Check for reassignment of constant 2.264 + final Symbol symbol = ident.getSymbol(); 2.265 + if (symbol.isConst()) { 2.266 + throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident); 2.267 + } 2.268 + } 2.269 + 2.270 @Override 2.271 - public Node leaveASSIGN(final BinaryNode binaryNode) { 2.272 + public Node leaveBinaryNode(final BinaryNode binaryNode) { 2.273 + if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) { 2.274 + checkConstAssignment((IdentNode) binaryNode.lhs()); 2.275 + } 2.276 + switch (binaryNode.tokenType()) { 2.277 + case ASSIGN: 2.278 + return leaveASSIGN(binaryNode); 2.279 + default: 2.280 + return super.leaveBinaryNode(binaryNode); 2.281 + } 2.282 + } 2.283 + 2.284 + private Node leaveASSIGN(final BinaryNode binaryNode) { 2.285 // If we're assigning a property of the this object ("this.foo = ..."), record it. 2.286 - 2.287 final Expression lhs = binaryNode.lhs(); 2.288 if (lhs instanceof AccessNode) { 2.289 final AccessNode accessNode = (AccessNode) lhs; 2.290 @@ -684,6 +717,21 @@ 2.291 } 2.292 2.293 @Override 2.294 + public Node leaveUnaryNode(final UnaryNode unaryNode) { 2.295 + if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) { 2.296 + checkConstAssignment((IdentNode) unaryNode.getExpression()); 2.297 + } 2.298 + switch (unaryNode.tokenType()) { 2.299 + case DELETE: 2.300 + return leaveDELETE(unaryNode); 2.301 + case TYPEOF: 2.302 + return leaveTYPEOF(unaryNode); 2.303 + default: 2.304 + return super.leaveUnaryNode(unaryNode); 2.305 + } 2.306 + } 2.307 + 2.308 + @Override 2.309 public Node leaveBlock(final Block block) { 2.310 // It's not necessary to guard the marking of symbols as locals with this "if"condition for correctness, it's 2.311 // just an optimization -- runtime type calculation is not used when the compilation is not an on-demand 2.312 @@ -699,8 +747,7 @@ 2.313 return block; 2.314 } 2.315 2.316 - @Override 2.317 - public Node leaveDELETE(final UnaryNode unaryNode) { 2.318 + private Node leaveDELETE(final UnaryNode unaryNode) { 2.319 final FunctionNode currentFunctionNode = lc.getCurrentFunction(); 2.320 final boolean strictMode = currentFunctionNode.isStrict(); 2.321 final Expression rhs = unaryNode.getExpression(); 2.322 @@ -799,9 +846,8 @@ 2.323 // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already) 2.324 maybeForceScope(symbol); 2.325 } else { 2.326 - log.info("No symbol exists. Declare as global: ", symbol); 2.327 - symbol = defineGlobalSymbol(block, name); 2.328 - Symbol.setSymbolIsScope(lc, symbol); 2.329 + log.info("No symbol exists. Declare as global: ", name); 2.330 + symbol = defineSymbol(block, name, identNode, IS_GLOBAL | IS_SCOPE); 2.331 } 2.332 2.333 functionUsesSymbol(symbol); 2.334 @@ -810,7 +856,15 @@ 2.335 symbol.increaseUseCount(); 2.336 } 2.337 2.338 - return end(identNode.setSymbol(symbol)); 2.339 + IdentNode newIdentNode = identNode.setSymbol(symbol); 2.340 + 2.341 + // If a block-scoped var is used before its declaration mark it as dead. 2.342 + // We can only statically detect this for local vars, cross-function symbols require runtime checks. 2.343 + if (symbol.isBlockScoped() && !symbol.hasBeenDeclared() && !identNode.isDeclaredHere() && isLocal(lc.getCurrentFunction(), symbol)) { 2.344 + newIdentNode = newIdentNode.markDead(); 2.345 + } 2.346 + 2.347 + return end(newIdentNode); 2.348 } 2.349 2.350 @Override 2.351 @@ -834,8 +888,7 @@ 2.352 return tryNode; 2.353 } 2.354 2.355 - @Override 2.356 - public Node leaveTYPEOF(final UnaryNode unaryNode) { 2.357 + private Node leaveTYPEOF(final UnaryNode unaryNode) { 2.358 final Expression rhs = unaryNode.getExpression(); 2.359 2.360 final List<Expression> args = new ArrayList<>(); 2.361 @@ -875,7 +928,7 @@ 2.362 } 2.363 2.364 private Symbol newInternal(final CompilerConstants cc, final int flags) { 2.365 - return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), IS_VAR | IS_INTERNAL | flags); //NASHORN-73 2.366 + return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), null, IS_VAR | IS_INTERNAL | flags); //NASHORN-73 2.367 } 2.368 2.369 private Symbol newObjectInternal(final CompilerConstants cc) { 2.370 @@ -915,7 +968,8 @@ 2.371 return false; 2.372 } 2.373 2.374 - if (lc.getCurrentFunction().allVarsInScope()) { 2.375 + final FunctionNode func = lc.getCurrentFunction(); 2.376 + if ( func.allVarsInScope() || (!symbol.isBlockScoped() && func.isProgram())) { 2.377 return true; 2.378 } 2.379 2.380 @@ -955,4 +1009,16 @@ 2.381 final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits(); 2.382 return !(units == null || units.isEmpty()); 2.383 } 2.384 + 2.385 + private void throwParserException(final String message, final Node origin) { 2.386 + if (origin == null) { 2.387 + throw new ParserException(message); 2.388 + } 2.389 + final Source source = compiler.getSource(); 2.390 + final long token = origin.getToken(); 2.391 + final int line = source.getLine(origin.getStart()); 2.392 + final int column = source.getColumn(origin.getStart()); 2.393 + final String formatted = ErrorManager.format(message, source, line, column, token); 2.394 + throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token); 2.395 + } 2.396 }
3.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 03 14:33:34 2014 +0200 3.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Sep 04 18:47:18 2014 +0200 3.3 @@ -52,6 +52,7 @@ 3.4 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; 3.5 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 3.6 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL; 3.7 +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE; 3.8 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE; 3.9 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; 3.10 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; 3.11 @@ -302,6 +303,7 @@ 3.12 * @return the method generator used 3.13 */ 3.14 private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) { 3.15 + checkTemporalDeadZone(identNode); 3.16 final Symbol symbol = identNode.getSymbol(); 3.17 3.18 if (!symbol.isScope()) { 3.19 @@ -334,6 +336,15 @@ 3.20 return method; 3.21 } 3.22 3.23 + // Any access to LET and CONST variables before their declaration must throw ReferenceError. 3.24 + // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a 3.25 + private void checkTemporalDeadZone(final IdentNode identNode) { 3.26 + if (identNode.isDead()) { 3.27 + method.load(identNode.getSymbol().getName()); 3.28 + method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR); 3.29 + } 3.30 + } 3.31 + 3.32 private boolean isRestOf() { 3.33 return continuationEntryPoints != null; 3.34 } 3.35 @@ -3216,27 +3227,34 @@ 3.36 return false; 3.37 } 3.38 final Expression init = varNode.getInit(); 3.39 - 3.40 - if (init == null) { 3.41 - return false; 3.42 - } 3.43 - 3.44 - enterStatement(varNode); 3.45 - 3.46 final IdentNode identNode = varNode.getName(); 3.47 final Symbol identSymbol = identNode.getSymbol(); 3.48 assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol"; 3.49 - 3.50 + final boolean needsScope = identSymbol.isScope(); 3.51 + 3.52 + if (init == null) { 3.53 + if (needsScope && varNode.isBlockScoped()) { 3.54 + // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ) 3.55 + method.loadCompilerConstant(SCOPE); 3.56 + method.loadUndefined(Type.OBJECT); 3.57 + final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0); 3.58 + assert isFastScope(identSymbol); 3.59 + storeFastScopeVar(identSymbol, flags); 3.60 + } 3.61 + return false; 3.62 + } 3.63 + 3.64 + enterStatement(varNode); 3.65 assert method != null; 3.66 3.67 - final boolean needsScope = identSymbol.isScope(); 3.68 if (needsScope) { 3.69 method.loadCompilerConstant(SCOPE); 3.70 } 3.71 3.72 if (needsScope) { 3.73 loadExpressionUnbounded(init); 3.74 - final int flags = CALLSITE_SCOPE | getCallSiteFlags(); 3.75 + // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ) 3.76 + final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0); 3.77 if (isFastScope(identSymbol)) { 3.78 storeFastScopeVar(identSymbol, flags); 3.79 } else { 3.80 @@ -4343,6 +4361,9 @@ 3.81 protected abstract void evaluate(); 3.82 3.83 void store() { 3.84 + if (target instanceof IdentNode) { 3.85 + checkTemporalDeadZone((IdentNode)target); 3.86 + } 3.87 prologue(); 3.88 evaluate(); // leaves an operation of whatever the operationType was on the stack 3.89 storeNonDiscard();
4.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Wed Sep 03 14:33:34 2014 +0200 4.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Thu Sep 04 18:47:18 2014 +0200 4.3 @@ -59,7 +59,9 @@ 4.4 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator; 4.5 import jdk.nashorn.internal.runtime.CodeInstaller; 4.6 import jdk.nashorn.internal.runtime.Context; 4.7 +import jdk.nashorn.internal.runtime.ErrorManager; 4.8 import jdk.nashorn.internal.runtime.FunctionInitializer; 4.9 +import jdk.nashorn.internal.runtime.ParserException; 4.10 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 4.11 import jdk.nashorn.internal.runtime.ScriptEnvironment; 4.12 import jdk.nashorn.internal.runtime.ScriptObject; 4.13 @@ -89,6 +91,8 @@ 4.14 4.15 private final String sourceName; 4.16 4.17 + private final ErrorManager errors; 4.18 + 4.19 private final boolean optimistic; 4.20 4.21 private final Map<String, byte[]> bytecode; 4.22 @@ -311,6 +315,7 @@ 4.23 * @param env script environment 4.24 * @param installer code installer 4.25 * @param source source to compile 4.26 + * @param errors error manager 4.27 * @param isStrict is this a strict compilation 4.28 */ 4.29 public Compiler( 4.30 @@ -318,8 +323,9 @@ 4.31 final ScriptEnvironment env, 4.32 final CodeInstaller<ScriptEnvironment> installer, 4.33 final Source source, 4.34 + final ErrorManager errors, 4.35 final boolean isStrict) { 4.36 - this(context, env, installer, source, isStrict, false, null, null, null, null, null, null); 4.37 + this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null); 4.38 } 4.39 4.40 /** 4.41 @@ -329,6 +335,7 @@ 4.42 * @param env script environment 4.43 * @param installer code installer 4.44 * @param source source to compile 4.45 + * @param errors error manager 4.46 * @param isStrict is this a strict compilation 4.47 * @param isOnDemand is this an on demand compilation 4.48 * @param compiledFunction compiled function, if any 4.49 @@ -343,6 +350,7 @@ 4.50 final ScriptEnvironment env, 4.51 final CodeInstaller<ScriptEnvironment> installer, 4.52 final Source source, 4.53 + final ErrorManager errors, 4.54 final boolean isStrict, 4.55 final boolean isOnDemand, 4.56 final RecompilableScriptFunctionData compiledFunction, 4.57 @@ -359,6 +367,7 @@ 4.58 this.bytecode = new LinkedHashMap<>(); 4.59 this.log = initLogger(context); 4.60 this.source = source; 4.61 + this.errors = errors; 4.62 this.sourceName = FunctionNode.getSourceName(source); 4.63 this.onDemand = isOnDemand; 4.64 this.compiledFunction = compiledFunction; 4.65 @@ -524,7 +533,17 @@ 4.66 4.67 for (final CompilationPhase phase : phases) { 4.68 log.fine(phase, " starting for ", quote(name)); 4.69 - newFunctionNode = phase.apply(this, phases, newFunctionNode); 4.70 + 4.71 + try { 4.72 + newFunctionNode = phase.apply(this, phases, newFunctionNode); 4.73 + } catch (final ParserException error) { 4.74 + errors.error(error); 4.75 + if (env._dump_on_error) { 4.76 + error.printStackTrace(env.getErr()); 4.77 + } 4.78 + return null; 4.79 + } 4.80 + 4.81 log.fine(phase, " done for function ", quote(name)); 4.82 4.83 if (env._print_mem_usage) {
5.1 --- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java Wed Sep 03 14:33:34 2014 +0200 5.2 +++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java Thu Sep 04 18:47:18 2014 +0200 5.3 @@ -69,9 +69,7 @@ 5.4 * Constructor 5.5 * 5.6 * @param codegen code generator 5.7 - * @param keys keys for fields in object 5.8 - * @param symbols symbols for fields in object 5.9 - * @param values list of values corresponding to keys 5.10 + * @param tuples tuples for fields in object 5.11 */ 5.12 FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples) { 5.13 this(codegen, tuples, false, false); 5.14 @@ -81,9 +79,7 @@ 5.15 * Constructor 5.16 * 5.17 * @param codegen code generator 5.18 - * @param keys keys for fields in object 5.19 - * @param symbols symbols for fields in object 5.20 - * @param values values (or null where no value) to be written to the fields 5.21 + * @param tuples tuples for fields in object 5.22 * @param isScope is this a scope object 5.23 * @param hasArguments does the created object have an "arguments" property 5.24 */ 5.25 @@ -165,7 +161,7 @@ 5.26 * @param method Script method. 5.27 * @param key Property key. 5.28 * @param fieldIndex Field number. 5.29 - * @param value Value to store. 5.30 + * @param tuple Tuple to store. 5.31 */ 5.32 private void putField(final MethodEmitter method, final String key, final int fieldIndex, final MapTuple<T> tuple) { 5.33 method.dup(); 5.34 @@ -188,7 +184,7 @@ 5.35 * 5.36 * @param method Script method. 5.37 * @param index Slot index. 5.38 - * @param value Value to store. 5.39 + * @param tuple Tuple to store. 5.40 */ 5.41 private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) { 5.42 method.dup();
6.1 --- a/src/jdk/nashorn/internal/codegen/MapCreator.java Wed Sep 03 14:33:34 2014 +0200 6.2 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Thu Sep 04 18:47:18 2014 +0200 6.3 @@ -52,8 +52,7 @@ 6.4 * Constructor 6.5 * 6.6 * @param structure structure to generate map for (a JO subclass) 6.7 - * @param keys list of keys for map 6.8 - * @param symbols list of symbols for map 6.9 + * @param tuples list of tuples for map 6.10 */ 6.11 MapCreator(final Class<? extends ScriptObject> structure, final List<MapTuple<T>> tuples) { 6.12 this.structure = structure; 6.13 @@ -149,6 +148,15 @@ 6.14 flags |= Property.IS_FUNCTION_DECLARATION; 6.15 } 6.16 6.17 + if (symbol.isConst()) { 6.18 + flags |= Property.NOT_WRITABLE; 6.19 + } 6.20 + 6.21 + // Mark symbol as needing declaration. Access before declaration will throw a ReferenceError. 6.22 + if (symbol.isBlockScoped() && symbol.isScope()) { 6.23 + flags |= Property.NEEDS_DECLARATION; 6.24 + } 6.25 + 6.26 return flags; 6.27 } 6.28 }
7.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Sep 03 14:33:34 2014 +0200 7.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Sep 04 18:47:18 2014 +0200 7.3 @@ -2233,9 +2233,8 @@ 7.4 /** 7.5 * Generate dynamic setter. Pop receiver and property from stack. 7.6 * 7.7 - * @param valueType the type of the value to set 7.8 - * @param name name of property 7.9 - * @param flags call site flags 7.10 + * @param name name of property 7.11 + * @param flags call site flags 7.12 */ 7.13 void dynamicSet(final String name, final int flags) { 7.14 assert !isOptimistic(flags); 7.15 @@ -2462,7 +2461,6 @@ 7.16 * Register line number at a label 7.17 * 7.18 * @param line line number 7.19 - * @param label label 7.20 */ 7.21 void lineNumber(final int line) { 7.22 if (context.getEnv()._debug_lines) {
8.1 --- a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java Wed Sep 03 14:33:34 2014 +0200 8.2 +++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java Thu Sep 04 18:47:18 2014 +0200 8.3 @@ -108,7 +108,7 @@ 8.4 8.5 // Safely evaluate the property, and return the narrowest type for the actual value (e.g. Type.INT for a boxed 8.6 // integer). 8.7 - final Object value = property.getObjectValue(owner, owner); 8.8 + final Object value = property.needsDeclaration() ? ScriptRuntime.UNDEFINED : property.getObjectValue(owner, owner); 8.9 if (value == ScriptRuntime.UNDEFINED) { 8.10 return null; 8.11 }
9.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Wed Sep 03 14:33:34 2014 +0200 9.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Sep 04 18:47:18 2014 +0200 9.3 @@ -138,10 +138,6 @@ 9.4 /** Last token of function. **/ 9.5 private final long lastToken; 9.6 9.7 - /** Declared symbols in this function node */ 9.8 - @Ignore 9.9 - private final Set<Symbol> declaredSymbols; 9.10 - 9.11 /** Method's namespace. */ 9.12 private final Namespace namespace; 9.13 9.14 @@ -330,7 +326,6 @@ 9.15 this.lastToken = token; 9.16 this.namespace = namespace; 9.17 this.compilationState = EnumSet.of(CompilationState.INITIALIZED); 9.18 - this.declaredSymbols = new HashSet<>(); 9.19 this.flags = flags; 9.20 this.compileUnit = null; 9.21 this.body = null; 9.22 @@ -369,7 +364,6 @@ 9.23 this.id = functionNode.id; 9.24 this.ident = functionNode.ident; 9.25 this.namespace = functionNode.namespace; 9.26 - this.declaredSymbols = functionNode.declaredSymbols; 9.27 this.kind = functionNode.kind; 9.28 this.firstToken = functionNode.firstToken; 9.29 } 9.30 @@ -724,24 +718,6 @@ 9.31 } 9.32 9.33 /** 9.34 - * Return a set of symbols declared in this function node. This 9.35 - * is only relevant after Attr, otherwise it will be an empty 9.36 - * set as no symbols have been introduced 9.37 - * @return set of declared symbols in function 9.38 - */ 9.39 - public Set<Symbol> getDeclaredSymbols() { 9.40 - return Collections.unmodifiableSet(declaredSymbols); 9.41 - } 9.42 - 9.43 - /** 9.44 - * Add a declared symbol to this function node 9.45 - * @param symbol symbol that is declared 9.46 - */ 9.47 - public void addDeclaredSymbol(final Symbol symbol) { 9.48 - declaredSymbols.add(symbol); 9.49 - } 9.50 - 9.51 - /** 9.52 * Get the function body 9.53 * @return the function body 9.54 */ 9.55 @@ -970,13 +946,13 @@ 9.56 } 9.57 9.58 /** 9.59 - * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and 9.60 + * Check if this function should have all its variables in its own scope. Split sub-functions, and 9.61 * functions having with and/or eval blocks are such. 9.62 * 9.63 * @return true if all variables should be in scope 9.64 */ 9.65 public boolean allVarsInScope() { 9.66 - return isProgram() || getFlag(HAS_ALL_VARS_IN_SCOPE); 9.67 + return getFlag(HAS_ALL_VARS_IN_SCOPE); 9.68 } 9.69 9.70 /**
10.1 --- a/src/jdk/nashorn/internal/ir/IdentNode.java Wed Sep 03 14:33:34 2014 +0200 10.2 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Thu Sep 04 18:47:18 2014 +0200 10.3 @@ -46,6 +46,8 @@ 10.4 private static final int INITIALIZED_HERE = 1 << 1; 10.5 private static final int FUNCTION = 1 << 2; 10.6 private static final int FUTURESTRICT_NAME = 1 << 3; 10.7 + private static final int IS_DECLARED_HERE = 1 << 4; 10.8 + private static final int IS_DEAD = 1 << 5; 10.9 10.10 /** Identifier. */ 10.11 private final String name; 10.12 @@ -247,6 +249,45 @@ 10.13 } 10.14 10.15 /** 10.16 + * Is this a LET or CONST identifier used before its declaration? 10.17 + * 10.18 + * @return true if identifier is dead 10.19 + */ 10.20 + public boolean isDead() { 10.21 + return (flags & IS_DEAD) != 0; 10.22 + } 10.23 + 10.24 + /** 10.25 + * Flag this IdentNode as a LET or CONST identifier used before its declaration. 10.26 + * 10.27 + * @return a new IdentNode equivalent to this but marked as dead. 10.28 + */ 10.29 + public IdentNode markDead() { 10.30 + return new IdentNode(this, name, type, flags | IS_DEAD, programPoint, conversion); 10.31 + } 10.32 + 10.33 + /** 10.34 + * Is this IdentNode declared here? 10.35 + * 10.36 + * @return true if identifier is declared here 10.37 + */ 10.38 + public boolean isDeclaredHere() { 10.39 + return (flags & IS_DECLARED_HERE) != 0; 10.40 + } 10.41 + 10.42 + /** 10.43 + * Flag this IdentNode as being declared here. 10.44 + * 10.45 + * @return a new IdentNode equivalent to this but marked as declared here. 10.46 + */ 10.47 + public IdentNode setIsDeclaredHere() { 10.48 + if (isDeclaredHere()) { 10.49 + return this; 10.50 + } 10.51 + return new IdentNode(this, name, type, flags | IS_DECLARED_HERE, programPoint, conversion); 10.52 + } 10.53 + 10.54 + /** 10.55 * Check if the name of this IdentNode is same as that of a compile-time property (currently __DIR__, __FILE__, and 10.56 * __LINE__). 10.57 *
11.1 --- a/src/jdk/nashorn/internal/ir/Symbol.java Wed Sep 03 14:33:34 2014 +0200 11.2 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Thu Sep 04 18:47:18 2014 +0200 11.3 @@ -54,17 +54,17 @@ 11.4 public static final int IS_VAR = 2; 11.5 /** Is this a parameter */ 11.6 public static final int IS_PARAM = 3; 11.7 - /** Is this a constant */ 11.8 - public static final int IS_CONSTANT = 4; 11.9 /** Mask for kind flags */ 11.10 - public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits 11.11 + public static final int KINDMASK = (1 << 2) - 1; // Kinds are represented by lower two bits 11.12 11.13 /** Is this symbol in scope */ 11.14 - public static final int IS_SCOPE = 1 << 3; 11.15 + public static final int IS_SCOPE = 1 << 2; 11.16 /** Is this a this symbol */ 11.17 - public static final int IS_THIS = 1 << 4; 11.18 + public static final int IS_THIS = 1 << 3; 11.19 /** Is this a let */ 11.20 - public static final int IS_LET = 1 << 5; 11.21 + public static final int IS_LET = 1 << 4; 11.22 + /** Is this a const */ 11.23 + public static final int IS_CONST = 1 << 5; 11.24 /** Is this an internal symbol, never represented explicitly in source code */ 11.25 public static final int IS_INTERNAL = 1 << 6; 11.26 /** Is this a function self-reference symbol */ 11.27 @@ -83,6 +83,8 @@ 11.28 public static final int HAS_DOUBLE_VALUE = 1 << 13; 11.29 /** Is this symbol known to store an object value ? */ 11.30 public static final int HAS_OBJECT_VALUE = 1 << 14; 11.31 + /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */ 11.32 + public static final int HAS_BEEN_DECLARED = 1 << 15; 11.33 11.34 /** Null or name identifying symbol. */ 11.35 private final String name; 11.36 @@ -184,14 +186,17 @@ 11.37 sb.append(" global"); 11.38 break; 11.39 case IS_VAR: 11.40 - sb.append(" var"); 11.41 + if (isConst()) { 11.42 + sb.append(" const"); 11.43 + } else if (isLet()) { 11.44 + sb.append(" let"); 11.45 + } else { 11.46 + sb.append(" var"); 11.47 + } 11.48 break; 11.49 case IS_PARAM: 11.50 sb.append(" param"); 11.51 break; 11.52 - case IS_CONSTANT: 11.53 - sb.append(" const"); 11.54 - break; 11.55 default: 11.56 break; 11.57 } 11.58 @@ -204,10 +209,6 @@ 11.59 sb.append(" internal"); 11.60 } 11.61 11.62 - if (isLet()) { 11.63 - sb.append(" let"); 11.64 - } 11.65 - 11.66 if (isThis()) { 11.67 sb.append(" this"); 11.68 } 11.69 @@ -410,8 +411,8 @@ 11.70 * Check if this symbol is a constant 11.71 * @return true if a constant 11.72 */ 11.73 - public boolean isConstant() { 11.74 - return (flags & KINDMASK) == IS_CONSTANT; 11.75 + public boolean isConst() { 11.76 + return (flags & IS_CONST) != 0; 11.77 } 11.78 11.79 /** 11.80 @@ -440,15 +441,6 @@ 11.81 } 11.82 11.83 /** 11.84 - * Flag this symbol as a let 11.85 - */ 11.86 - public void setIsLet() { 11.87 - if (!isLet()) { 11.88 - flags |= IS_LET; 11.89 - } 11.90 - } 11.91 - 11.92 - /** 11.93 * Flag this symbol as a function's self-referencing symbol. 11.94 * @return true if this symbol as a function's self-referencing symbol. 11.95 */ 11.96 @@ -456,6 +448,20 @@ 11.97 return (flags & IS_FUNCTION_SELF) != 0; 11.98 } 11.99 11.100 + public boolean isBlockScoped() { 11.101 + return isLet() || isConst(); 11.102 + } 11.103 + 11.104 + public boolean hasBeenDeclared() { 11.105 + return (flags & HAS_BEEN_DECLARED) != 0; 11.106 + } 11.107 + 11.108 + public void setHasBeenDeclared() { 11.109 + if (!hasBeenDeclared()) { 11.110 + flags |= HAS_BEEN_DECLARED; 11.111 + } 11.112 + } 11.113 + 11.114 /** 11.115 * Get the index of the field used to store this symbol, should it be an AccessorProperty 11.116 * and get allocated in a JO-prefixed ScriptObject subclass.
12.1 --- a/src/jdk/nashorn/internal/ir/VarNode.java Wed Sep 03 14:33:34 2014 +0200 12.2 +++ b/src/jdk/nashorn/internal/ir/VarNode.java Thu Sep 04 18:47:18 2014 +0200 12.3 @@ -27,6 +27,7 @@ 12.4 12.5 import jdk.nashorn.internal.ir.annotations.Immutable; 12.6 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 12.7 +import jdk.nashorn.internal.parser.Token; 12.8 12.9 /** 12.10 * Node represents a var/let declaration. 12.11 @@ -43,12 +44,18 @@ 12.12 private final int flags; 12.13 12.14 /** Flag that determines if this function node is a statement */ 12.15 - public static final int IS_STATEMENT = 1 << 0; 12.16 + public static final int IS_STATEMENT = 1 << 0; 12.17 + 12.18 + /** Flag for ES6 LET declaration */ 12.19 + public static final int IS_LET = 1 << 1; 12.20 + 12.21 + /** Flag for ES6 CONST declaration */ 12.22 + public static final int IS_CONST = 1 << 2; 12.23 12.24 /** Flag that determines if this is the last function declaration in a function 12.25 * This is used to micro optimize the placement of return value assignments for 12.26 * a program node */ 12.27 - public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 1; 12.28 + public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 3; 12.29 12.30 /** 12.31 * Constructor 12.32 @@ -109,6 +116,43 @@ 12.33 } 12.34 12.35 /** 12.36 + * Is this a VAR node block scoped? This returns true for ECMAScript 6 LET and CONST nodes. 12.37 + * @return true if an ES6 LET or CONST node 12.38 + */ 12.39 + public boolean isBlockScoped() { 12.40 + return getFlag(IS_LET) || getFlag(IS_CONST); 12.41 + } 12.42 + 12.43 + /** 12.44 + * Is this an ECMAScript 6 LET node? 12.45 + * @return true if LET node 12.46 + */ 12.47 + public boolean isLet() { 12.48 + return getFlag(IS_LET); 12.49 + } 12.50 + 12.51 + /** 12.52 + * Is this an ECMAScript 6 CONST node? 12.53 + * @return true if CONST node 12.54 + */ 12.55 + public boolean isConst() { 12.56 + return getFlag(IS_CONST); 12.57 + } 12.58 + 12.59 + /** 12.60 + * Return the flags to use for symbols for this declaration. 12.61 + * @return the symbol flags 12.62 + */ 12.63 + public int getSymbolFlags() { 12.64 + if (isLet()) { 12.65 + return Symbol.IS_VAR | Symbol.IS_LET; 12.66 + } else if (isConst()) { 12.67 + return Symbol.IS_VAR | Symbol.IS_CONST; 12.68 + } 12.69 + return Symbol.IS_VAR; 12.70 + } 12.71 + 12.72 + /** 12.73 * Does this variable declaration have an init value 12.74 * @return true if an init exists, false otherwise 12.75 */ 12.76 @@ -139,7 +183,7 @@ 12.77 12.78 @Override 12.79 public void toString(final StringBuilder sb, final boolean printType) { 12.80 - sb.append("var "); 12.81 + sb.append(Token.descType(getToken()).getName()).append(' '); 12.82 name.toString(sb, printType); 12.83 12.84 if (init != null) {
13.1 --- a/src/jdk/nashorn/internal/parser/Parser.java Wed Sep 03 14:33:34 2014 +0200 13.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java Thu Sep 04 18:47:18 2014 +0200 13.3 @@ -45,6 +45,7 @@ 13.4 import static jdk.nashorn.internal.parser.TokenType.IF; 13.5 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX; 13.6 import static jdk.nashorn.internal.parser.TokenType.LBRACE; 13.7 +import static jdk.nashorn.internal.parser.TokenType.LET; 13.8 import static jdk.nashorn.internal.parser.TokenType.LPAREN; 13.9 import static jdk.nashorn.internal.parser.TokenType.RBRACE; 13.10 import static jdk.nashorn.internal.parser.TokenType.RBRACKET; 13.11 @@ -579,6 +580,10 @@ 13.12 } 13.13 } 13.14 13.15 + private boolean useBlockScope() { 13.16 + return env._es6; 13.17 + } 13.18 + 13.19 private static boolean isArguments(final String name) { 13.20 return ARGUMENTS_NAME.equals(name); 13.21 } 13.22 @@ -694,9 +699,20 @@ 13.23 FunctionNode.Kind.SCRIPT, 13.24 functionLine); 13.25 13.26 + // If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations. 13.27 + final int startLine = start; 13.28 + Block outer = useBlockScope() ? newBlock() : null; 13.29 functionDeclarations = new ArrayList<>(); 13.30 - sourceElements(allowPropertyFunction); 13.31 - addFunctionDeclarations(script); 13.32 + 13.33 + try { 13.34 + sourceElements(allowPropertyFunction); 13.35 + addFunctionDeclarations(script); 13.36 + } finally { 13.37 + if (outer != null) { 13.38 + outer = restoreBlock(outer); 13.39 + appendStatement(new BlockStatement(startLine, outer)); 13.40 + } 13.41 + } 13.42 functionDeclarations = null; 13.43 13.44 expect(EOF); 13.45 @@ -868,7 +884,7 @@ 13.46 block(); 13.47 break; 13.48 case VAR: 13.49 - variableStatement(true); 13.50 + variableStatement(type, true); 13.51 break; 13.52 case SEMICOLON: 13.53 emptyStatement(); 13.54 @@ -918,8 +934,12 @@ 13.55 expect(SEMICOLON); 13.56 break; 13.57 default: 13.58 + if (useBlockScope() && (type == LET || type == CONST)) { 13.59 + variableStatement(type, true); 13.60 + break; 13.61 + } 13.62 if (env._const_as_var && type == CONST) { 13.63 - variableStatement(true); 13.64 + variableStatement(TokenType.VAR, true); 13.65 break; 13.66 } 13.67 13.68 @@ -1035,11 +1055,17 @@ 13.69 * Parse a VAR statement. 13.70 * @param isStatement True if a statement (not used in a FOR.) 13.71 */ 13.72 - private List<VarNode> variableStatement(final boolean isStatement) { 13.73 + private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) { 13.74 // VAR tested in caller. 13.75 next(); 13.76 13.77 final List<VarNode> vars = new ArrayList<>(); 13.78 + int varFlags = VarNode.IS_STATEMENT; 13.79 + if (varType == LET) { 13.80 + varFlags |= VarNode.IS_LET; 13.81 + } else if (varType == CONST) { 13.82 + varFlags |= VarNode.IS_CONST; 13.83 + } 13.84 13.85 while (true) { 13.86 // Get starting token. 13.87 @@ -1063,10 +1089,12 @@ 13.88 } finally { 13.89 defaultNames.pop(); 13.90 } 13.91 + } else if (varType == CONST) { 13.92 + throw error(AbstractParser.message("missing.const.assignment", name.getName())); 13.93 } 13.94 13.95 // Allocate var node. 13.96 - final VarNode var = new VarNode(varLine, varToken, finish, name, init); 13.97 + final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags); 13.98 vars.add(var); 13.99 appendStatement(var); 13.100 13.101 @@ -1180,9 +1208,12 @@ 13.102 * Parse a FOR statement. 13.103 */ 13.104 private void forStatement() { 13.105 + // When ES6 for-let is enabled we create a container block to capture the LET. 13.106 + final int startLine = start; 13.107 + Block outer = useBlockScope() ? newBlock() : null; 13.108 + 13.109 // Create FOR node, capturing FOR token. 13.110 ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR); 13.111 - 13.112 lc.push(forNode); 13.113 13.114 try { 13.115 @@ -1203,14 +1234,19 @@ 13.116 switch (type) { 13.117 case VAR: 13.118 // Var statements captured in for outer block. 13.119 - vars = variableStatement(false); 13.120 + vars = variableStatement(type, false); 13.121 break; 13.122 case SEMICOLON: 13.123 break; 13.124 default: 13.125 + if (useBlockScope() && (type == LET || type == CONST)) { 13.126 + // LET/CONST captured in container block created above. 13.127 + vars = variableStatement(type, false); 13.128 + break; 13.129 + } 13.130 if (env._const_as_var && type == CONST) { 13.131 // Var statements captured in for outer block. 13.132 - vars = variableStatement(false); 13.133 + vars = variableStatement(TokenType.VAR, false); 13.134 break; 13.135 } 13.136 13.137 @@ -1290,8 +1326,13 @@ 13.138 appendStatement(forNode); 13.139 } finally { 13.140 lc.pop(forNode); 13.141 + if (outer != null) { 13.142 + outer.setFinish(forNode.getFinish()); 13.143 + outer = restoreBlock(outer); 13.144 + appendStatement(new BlockStatement(startLine, outer)); 13.145 + } 13.146 } 13.147 - } 13.148 + } 13.149 13.150 /** 13.151 * ... IterationStatement : 13.152 @@ -1722,7 +1763,7 @@ 13.153 } 13.154 } 13.155 13.156 - /** 13.157 + /** 13.158 * ThrowStatement : 13.159 * throw Expression ; // [no LineTerminator here] 13.160 * 13.161 @@ -2609,7 +2650,7 @@ 13.162 FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine); 13.163 13.164 if (isStatement) { 13.165 - if (topLevel) { 13.166 + if (topLevel || useBlockScope()) { 13.167 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED); 13.168 } else if (isStrictMode) { 13.169 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); 13.170 @@ -2661,9 +2702,16 @@ 13.171 } 13.172 13.173 if (isStatement) { 13.174 - final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, VarNode.IS_STATEMENT); 13.175 + int varFlags = VarNode.IS_STATEMENT; 13.176 + if (!topLevel && useBlockScope()) { 13.177 + // mark ES6 block functions as lexically scoped 13.178 + varFlags |= VarNode.IS_LET; 13.179 + } 13.180 + final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags); 13.181 if (topLevel) { 13.182 functionDeclarations.add(varNode); 13.183 + } else if (useBlockScope()) { 13.184 + prependStatement(varNode); // Hoist to beginning of current block 13.185 } else { 13.186 appendStatement(varNode); 13.187 } 13.188 @@ -2838,7 +2886,6 @@ 13.189 } 13.190 13.191 private void addFunctionDeclarations(final FunctionNode functionNode) { 13.192 - assert lc.peek() == lc.getFunctionBody(functionNode); 13.193 VarNode lastDecl = null; 13.194 for (int i = functionDeclarations.size() - 1; i >= 0; i--) { 13.195 Statement decl = functionDeclarations.get(i);
14.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Sep 03 14:33:34 2014 +0200 14.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Thu Sep 04 18:47:18 2014 +0200 14.3 @@ -549,6 +549,8 @@ 14.4 type == Object.class : 14.5 "invalid getter type " + type + " for " + getKey(); 14.6 14.7 + checkUndeclared(); 14.8 + 14.9 //all this does is add a return value filter for object fields only 14.10 final MethodHandle[] getterCache = GETTER_CACHE; 14.11 final MethodHandle cachedGetter = getterCache[i]; 14.12 @@ -579,6 +581,8 @@ 14.13 return getOptimisticPrimitiveGetter(type, programPoint); 14.14 } 14.15 14.16 + checkUndeclared(); 14.17 + 14.18 return debug( 14.19 createGetter( 14.20 getCurrentType(), 14.21 @@ -608,6 +612,13 @@ 14.22 return newMap; 14.23 } 14.24 14.25 + private void checkUndeclared() { 14.26 + if ((getFlags() & NEEDS_DECLARATION) != 0) { 14.27 + // a lexically defined variable that hasn't seen its declaration - throw ReferenceError 14.28 + throw ECMAErrors.referenceError("not.defined", getKey()); 14.29 + } 14.30 + } 14.31 + 14.32 // the final three arguments are for debug printout purposes only 14.33 @SuppressWarnings("unused") 14.34 private static Object replaceMap(final Object sobj, final PropertyMap newMap) { 14.35 @@ -635,13 +646,14 @@ 14.36 14.37 @Override 14.38 public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) { 14.39 - final int i = getAccessorTypeIndex(type); 14.40 - final int ci = isUndefined() ? -1 : getAccessorTypeIndex(getCurrentType()); 14.41 - final Class<?> forType = isUndefined() ? type : getCurrentType(); 14.42 + checkUndeclared(); 14.43 + 14.44 + final int typeIndex = getAccessorTypeIndex(type); 14.45 + final int currentTypeIndex = getAccessorTypeIndex(getCurrentType()); 14.46 14.47 //if we are asking for an object setter, but are still a primitive type, we might try to box it 14.48 MethodHandle mh; 14.49 - if (needsInvalidator(i, ci)) { 14.50 + if (needsInvalidator(typeIndex, currentTypeIndex)) { 14.51 final Property newProperty = getWiderProperty(type); 14.52 final PropertyMap newMap = getWiderMap(currentMap, newProperty); 14.53 14.54 @@ -652,6 +664,7 @@ 14.55 mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh); 14.56 } 14.57 } else { 14.58 + final Class<?> forType = isUndefined() ? type : getCurrentType(); 14.59 mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type); 14.60 } 14.61 14.62 @@ -692,11 +705,12 @@ 14.63 if (OBJECT_FIELDS_ONLY) { 14.64 return false; 14.65 } 14.66 - return getCurrentType() != Object.class && (isConfigurable() || isWritable()); 14.67 + // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST. 14.68 + return getCurrentType() == null || (getCurrentType() != Object.class && (isConfigurable() || isWritable())); 14.69 } 14.70 14.71 - private boolean needsInvalidator(final int ti, final int fti) { 14.72 - return canChangeType() && ti > fti; 14.73 + private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) { 14.74 + return canChangeType() && typeIndex > currentTypeIndex; 14.75 } 14.76 14.77 @Override
15.1 --- a/src/jdk/nashorn/internal/runtime/Context.java Wed Sep 03 14:33:34 2014 +0200 15.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 04 18:47:18 2014 +0200 15.3 @@ -1132,7 +1132,7 @@ 15.4 if (storedScript == null) { 15.5 functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse(); 15.6 15.7 - if (errors.hasErrors()) { 15.8 + if (errMan.hasErrors()) { 15.9 return null; 15.10 } 15.11 15.12 @@ -1162,9 +1162,13 @@ 15.13 env, 15.14 installer, 15.15 source, 15.16 + errMan, 15.17 strict | functionNode.isStrict()); 15.18 15.19 final FunctionNode compiledFunction = compiler.compile(functionNode, phases); 15.20 + if (errMan.hasErrors()) { 15.21 + return null; 15.22 + } 15.23 script = compiledFunction.getRootClass(); 15.24 compiler.persistClassInfo(cacheKey, compiledFunction); 15.25 } else {
16.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java Wed Sep 03 14:33:34 2014 +0200 16.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Thu Sep 04 18:47:18 2014 +0200 16.3 @@ -58,6 +58,18 @@ 16.4 } 16.5 16.6 /** 16.7 + * Return a copy of this FindProperty with a different property. 16.8 + * 16.9 + * @param newProperty the new property 16.10 + * @return the new FindProperty instance 16.11 + */ 16.12 + public FindProperty replaceProperty(final Property newProperty) { 16.13 + assert this.property.getKey().equals(newProperty.getKey()); 16.14 + assert this.property.getSlot() == newProperty.getSlot(); 16.15 + return new FindProperty(self, prototype, newProperty); 16.16 + } 16.17 + 16.18 + /** 16.19 * Ask for a getter that returns the given type. The type has nothing to do with the 16.20 * internal representation of the property. It may be an Object (boxing primitives) or 16.21 * a primitive (primitive fields with -Dnashorn.fields.dual=true)
17.1 --- a/src/jdk/nashorn/internal/runtime/Property.java Wed Sep 03 14:33:34 2014 +0200 17.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java Thu Sep 04 18:47:18 2014 +0200 17.3 @@ -82,11 +82,14 @@ 17.4 * is narrower than object, e.g. Math.PI which is declared 17.5 * as a double 17.6 */ 17.7 - public static final int IS_NASGEN_PRIMITIVE = 1 << 6; 17.8 + public static final int IS_NASGEN_PRIMITIVE = 1 << 6; 17.9 17.10 /** Is this property bound to a receiver? This means get/set operations will be delegated to 17.11 * a statically defined object instead of the object passed as callsite parameter. */ 17.12 - public static final int IS_BOUND = 1 << 8; 17.13 + public static final int IS_BOUND = 1 << 7; 17.14 + 17.15 + /** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */ 17.16 + public static final int NEEDS_DECLARATION = 1 << 8; 17.17 17.18 /** Property key. */ 17.19 private final String key; 17.20 @@ -287,6 +290,15 @@ 17.21 } 17.22 17.23 /** 17.24 + * Is this a LET or CONST property that needs to see its declaration before being usable? 17.25 + * 17.26 + * @return true if this is a block-scoped variable 17.27 + */ 17.28 + public boolean needsDeclaration() { 17.29 + return (flags & NEEDS_DECLARATION) == NEEDS_DECLARATION; 17.30 + } 17.31 + 17.32 + /** 17.33 * Add more property flags to the property. Properties are immutable here, 17.34 * so any property change that results in a larger flag set results in the 17.35 * property being cloned. Use only the return value
18.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Sep 03 14:33:34 2014 +0200 18.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Sep 04 18:47:18 2014 +0200 18.3 @@ -394,6 +394,7 @@ 18.4 context.getEnv(), 18.5 installer, 18.6 functionNode.getSource(), // source 18.7 + context.getErrorManager(), 18.8 isStrict() | functionNode.isStrict(), // is strict 18.9 true, // is on demand 18.10 this, // compiledFunction, i.e. this RecompilableScriptFunctionData
19.1 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed Sep 03 14:33:34 2014 +0200 19.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Thu Sep 04 18:47:18 2014 +0200 19.3 @@ -94,6 +94,9 @@ 19.4 /** Use single Global instance per jsr223 engine instance. */ 19.5 public final boolean _global_per_engine; 19.6 19.7 + /** Enable experimental ECMAScript 6 features. */ 19.8 + public final boolean _es6; 19.9 + 19.10 /** Argument passed to compile only if optimistic compilation should take place */ 19.11 public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic"; 19.12 19.13 @@ -258,6 +261,15 @@ 19.14 _version = options.getBoolean("version"); 19.15 _verify_code = options.getBoolean("verify.code"); 19.16 19.17 + final String language = options.getString("language"); 19.18 + if (language == null || language.equals("es5")) { 19.19 + _es6 = false; 19.20 + } else if (language.equals("es6")) { 19.21 + _es6 = true; 19.22 + } else { 19.23 + throw new RuntimeException("Unsupported language: " + language); 19.24 + } 19.25 + 19.26 String dir = null; 19.27 String func = null; 19.28 final String pc = options.getString("print.code");
20.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Sep 03 14:33:34 2014 +0200 20.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Sep 04 18:47:18 2014 +0200 20.3 @@ -158,6 +158,7 @@ 20.4 20.5 static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class); 20.6 static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class); 20.7 + static final MethodHandle DECLARE_AND_SET = findOwnMH_V("declareAndSet", void.class, String.class, Object.class); 20.8 20.9 private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class); 20.10 private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class); 20.11 @@ -2027,6 +2028,22 @@ 20.12 return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT); 20.13 } 20.14 20.15 + // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST 20.16 + @SuppressWarnings("unused") 20.17 + private void declareAndSet(final String key, final Object value) { 20.18 + final PropertyMap map = getMap(); 20.19 + final FindProperty find = findProperty(key, false); 20.20 + assert find != null; 20.21 + 20.22 + final Property property = find.getProperty(); 20.23 + assert property != null; 20.24 + assert property.needsDeclaration(); 20.25 + 20.26 + final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION)); 20.27 + setMap(newMap); 20.28 + set(key, value, true); 20.29 + } 20.30 + 20.31 /** 20.32 * Find the appropriate GETINDEX method for an invoke dynamic call. 20.33 * 20.34 @@ -2140,7 +2157,7 @@ 20.35 } 20.36 20.37 if (find != null) { 20.38 - if (!find.getProperty().isWritable()) { 20.39 + if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) { 20.40 // Existing, non-writable property 20.41 return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true); 20.42 }
21.1 --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Sep 03 14:33:34 2014 +0200 21.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Sep 04 18:47:18 2014 +0200 21.3 @@ -108,6 +108,11 @@ 21.4 public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class); 21.5 21.6 /** 21.7 + * Throws a reference error for an undefined variable. 21.8 + */ 21.9 + public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class); 21.10 + 21.11 + /** 21.12 * Converts a switch tag value to a simple integer. deflt value if it can't. 21.13 * 21.14 * @param tag Switch statement tag value. 21.15 @@ -382,6 +387,15 @@ 21.16 } 21.17 21.18 /** 21.19 + * Throws a reference error for an undefined variable. 21.20 + * 21.21 + * @param name the variable name 21.22 + */ 21.23 + public static void throwReferenceError(final String name) { 21.24 + throw referenceError("not.defined", name); 21.25 + } 21.26 + 21.27 + /** 21.28 * Call a script function as a constructor with given args. 21.29 * 21.30 * @param target ScriptFunction object.
22.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Sep 03 14:33:34 2014 +0200 22.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Thu Sep 04 18:47:18 2014 +0200 22.3 @@ -140,7 +140,29 @@ 22.4 22.5 private SetMethod createExistingPropertySetter() { 22.6 final Property property = find.getProperty(); 22.7 - final MethodHandle methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc)); 22.8 + final MethodHandle methodHandle; 22.9 + 22.10 + if (NashornCallSiteDescriptor.isDeclaration(desc)) { 22.11 + assert property.needsDeclaration(); 22.12 + // This is a LET or CONST being declared. The property is already there but flagged as needing declaration. 22.13 + // We create a new PropertyMap with the flag removed. The map is installed with a fast compare-and-set 22.14 + // method if the pre-callsite map is stable (which should be the case for function scopes except for 22.15 + // non-strict functions containing eval() with var). Otherwise we have to use a slow setter that creates 22.16 + // a new PropertyMap on the fly. 22.17 + final PropertyMap oldMap = getMap(); 22.18 + final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION); 22.19 + final PropertyMap newMap = oldMap.replaceProperty(property, newProperty); 22.20 + final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, NashornCallSiteDescriptor.isStrict(desc)); 22.21 + final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type()); 22.22 + 22.23 + // cas map used as guard, if true that means we can do the set fast 22.24 + MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap); 22.25 + casMap = MH.dropArguments(casMap, 1, type); 22.26 + casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class)); 22.27 + methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter); 22.28 + } else { 22.29 + methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc)); 22.30 + } 22.31 22.32 assert methodHandle != null; 22.33 assert property != null;
23.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Sep 03 14:33:34 2014 +0200 23.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Sep 04 18:47:18 2014 +0200 23.3 @@ -54,23 +54,25 @@ 23.4 public static final int CALLSITE_OPTIMISTIC = 1 << 3; 23.5 /** Is this really an apply that we try to call as a call? */ 23.6 public static final int CALLSITE_APPLY_TO_CALL = 1 << 4; 23.7 + /** Does this a callsite for a variable declaration? */ 23.8 + public static final int CALLSITE_DECLARE = 1 << 5; 23.9 23.10 /** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit 23.11 * code where call sites have this flag set. */ 23.12 - public static final int CALLSITE_PROFILE = 1 << 5; 23.13 + public static final int CALLSITE_PROFILE = 1 << 6; 23.14 /** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where 23.15 * call sites have this flag set. */ 23.16 - public static final int CALLSITE_TRACE = 1 << 6; 23.17 + public static final int CALLSITE_TRACE = 1 << 7; 23.18 /** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword 23.19 * {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */ 23.20 - public static final int CALLSITE_TRACE_MISSES = 1 << 7; 23.21 + public static final int CALLSITE_TRACE_MISSES = 1 << 8; 23.22 /** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword 23.23 * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */ 23.24 - public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 8; 23.25 + public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 9; 23.26 /** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts 23.27 * that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites 23.28 * have this flag set. */ 23.29 - public static final int CALLSITE_TRACE_VALUES = 1 << 9; 23.30 + public static final int CALLSITE_TRACE_VALUES = 1 << 10; 23.31 23.32 //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious 23.33 //right now given the program points 23.34 @@ -82,10 +84,10 @@ 23.35 * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its 23.36 * trace/profile settings. 23.37 */ 23.38 - public static final int CALLSITE_PROGRAM_POINT_SHIFT = 10; 23.39 + public static final int CALLSITE_PROGRAM_POINT_SHIFT = 11; 23.40 23.41 /** 23.42 - * Maximum program point value. 22 bits should be enough for anyone 23.43 + * Maximum program point value. 21 bits should be enough for anyone 23.44 */ 23.45 public static final int MAX_PROGRAM_POINT_VALUE = (1 << 32 - CALLSITE_PROGRAM_POINT_SHIFT) - 1; 23.46 23.47 @@ -123,6 +125,9 @@ 23.48 assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope"; 23.49 sb.append("scope "); 23.50 } 23.51 + if ((flags & CALLSITE_DECLARE) != 0) { 23.52 + sb.append("declare "); 23.53 + } 23.54 } 23.55 if ((flags & CALLSITE_APPLY_TO_CALL) != 0) { 23.56 sb.append("apply2call "); 23.57 @@ -329,6 +334,15 @@ 23.58 } 23.59 23.60 /** 23.61 + * Does this callsite contain a declaration for its target? 23.62 + * @param desc descriptor 23.63 + * @return true if contains declaration 23.64 + */ 23.65 + public static boolean isDeclaration(final CallSiteDescriptor desc) { 23.66 + return isFlag(desc, CALLSITE_DECLARE); 23.67 + } 23.68 + 23.69 + /** 23.70 * Get a program point from a descriptor (must be optimistic) 23.71 * @param desc descriptor 23.72 * @return program point
24.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties Wed Sep 03 14:33:34 2014 +0200 24.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties Thu Sep 04 18:47:18 2014 +0200 24.3 @@ -58,6 +58,7 @@ 24.4 parser.error.regex.repeated.flag=Repeated RegExp flag: {0} 24.5 parser.error.regex.syntax={0} 24.6 parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON 24.7 +parser.error.missing.const.assignment=Missing assignment to constant "{0}" 24.8 24.9 # strict mode error messages 24.10 parser.error.strict.no.with="with" statement cannot be used in strict mode 24.11 @@ -162,6 +163,8 @@ 24.12 24.13 syntax.error.invalid.json=Invalid JSON: {0} 24.14 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode 24.15 +syntax.error.redeclare.variable=Variable "{0}" has already been declared 24.16 +syntax.error.assign.constant=Assignment to constant "{0}" 24.17 24.18 io.error.cant.write=cannot write "{0}" 24.19 config.error.no.dest=no destination directory supplied
25.1 --- a/src/jdk/nashorn/internal/runtime/resources/Options.properties Wed Sep 03 14:33:34 2014 +0200 25.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties Thu Sep 04 18:47:18 2014 +0200 25.3 @@ -329,6 +329,14 @@ 25.4 desc="Enable scripting features." \ 25.5 } 25.6 25.7 +nashorn.option.language = { \ 25.8 + name="--language", \ 25.9 + type=String, \ 25.10 + params=[es5|es6], \ 25.11 + default=es5, \ 25.12 + desc="Specify ECMAScript language version." \ 25.13 +} 25.14 + 25.15 nashorn.option.stdout = { \ 25.16 name="--stdout", \ 25.17 is_undocumented=true, \
26.1 --- a/src/jdk/nashorn/tools/Shell.java Wed Sep 03 14:33:34 2014 +0200 26.2 +++ b/src/jdk/nashorn/tools/Shell.java Thu Sep 04 18:47:18 2014 +0200 26.3 @@ -252,6 +252,15 @@ 26.4 return COMPILATION_ERROR; 26.5 } 26.6 26.7 + new Compiler( 26.8 + context, 26.9 + env, 26.10 + null, //null - pass no code installer - this is compile only 26.11 + functionNode.getSource(), 26.12 + context.getErrorManager(), 26.13 + env._strict | functionNode.isStrict()). 26.14 + compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL); 26.15 + 26.16 if (env._print_ast) { 26.17 context.getErr().println(new ASTWriter(functionNode)); 26.18 } 26.19 @@ -260,14 +269,9 @@ 26.20 context.getErr().println(new PrintVisitor(functionNode)); 26.21 } 26.22 26.23 - //null - pass no code installer - this is compile only 26.24 - new Compiler( 26.25 - context, 26.26 - env, 26.27 - null, 26.28 - functionNode.getSource(), 26.29 - env._strict | functionNode.isStrict()). 26.30 - compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL); 26.31 + if (errors.getNumberOfErrors() != 0) { 26.32 + return COMPILATION_ERROR; 26.33 + } 26.34 } 26.35 } finally { 26.36 env.getOut().flush();
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/test/script/basic/es6/block-function-decl.js Thu Sep 04 18:47:18 2014 +0200 27.3 @@ -0,0 +1,51 @@ 27.4 +/* 27.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 27.7 + * 27.8 + * This code is free software; you can redistribute it and/or modify it 27.9 + * under the terms of the GNU General Public License version 2 only, as 27.10 + * published by the Free Software Foundation. 27.11 + * 27.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 27.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 27.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 27.15 + * version 2 for more details (a copy is included in the LICENSE file that 27.16 + * accompanied this code). 27.17 + * 27.18 + * You should have received a copy of the GNU General Public License version 27.19 + * 2 along with this work; if not, write to the Free Software Foundation, 27.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 27.21 + * 27.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 27.23 + * or visit www.oracle.com if you need additional information or have any 27.24 + * questions. 27.25 + */ 27.26 + 27.27 +/** 27.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 27.29 + * 27.30 + * @test 27.31 + * @run 27.32 + * @option --language=es6 27.33 + */ 27.34 + 27.35 +"use strict"; 27.36 + 27.37 +{ 27.38 + // f is defined on block level 27.39 + print(f); 27.40 + f(); 27.41 + function f() { 27.42 + print("in f"); 27.43 + } 27.44 + print(f); 27.45 + f(); 27.46 +} 27.47 + 27.48 +try { 27.49 + print(typeof f); 27.50 + f(); 27.51 +} catch (e) { 27.52 + print(e); 27.53 +} 27.54 +
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/test/script/basic/es6/block-function-decl.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 28.3 @@ -0,0 +1,10 @@ 28.4 +function f() { 28.5 + print("in f"); 28.6 + } 28.7 +in f 28.8 +function f() { 28.9 + print("in f"); 28.10 + } 28.11 +in f 28.12 +undefined 28.13 +ReferenceError: "f" is not defined
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/test/script/basic/es6/const-empty.js Thu Sep 04 18:47:18 2014 +0200 29.3 @@ -0,0 +1,37 @@ 29.4 +/* 29.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 29.7 + * 29.8 + * This code is free software; you can redistribute it and/or modify it 29.9 + * under the terms of the GNU General Public License version 2 only, as 29.10 + * published by the Free Software Foundation. 29.11 + * 29.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 29.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 29.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29.15 + * version 2 for more details (a copy is included in the LICENSE file that 29.16 + * accompanied this code). 29.17 + * 29.18 + * You should have received a copy of the GNU General Public License version 29.19 + * 2 along with this work; if not, write to the Free Software Foundation, 29.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 29.21 + * 29.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 29.23 + * or visit www.oracle.com if you need additional information or have any 29.24 + * questions. 29.25 + */ 29.26 + 29.27 +/** 29.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 29.29 + * 29.30 + * @test 29.31 + * @run 29.32 + * @option --language=es6 29.33 + */ 29.34 + 29.35 +try { 29.36 + eval('"use strict";\n' + 29.37 + 'const x;\n'); 29.38 +} catch (e) { 29.39 + print(e); 29.40 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/test/script/basic/es6/const-empty.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 30.3 @@ -0,0 +1,3 @@ 30.4 +SyntaxError: test/script/basic/es6/const-empty.js#33:4<eval>@1:2:7 Missing assignment to constant "x" 30.5 +const x; 30.6 + ^
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/test/script/basic/es6/const-reassign.js Thu Sep 04 18:47:18 2014 +0200 31.3 @@ -0,0 +1,174 @@ 31.4 +/* 31.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 31.7 + * 31.8 + * This code is free software; you can redistribute it and/or modify it 31.9 + * under the terms of the GNU General Public License version 2 only, as 31.10 + * published by the Free Software Foundation. 31.11 + * 31.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 31.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 31.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 31.15 + * version 2 for more details (a copy is included in the LICENSE file that 31.16 + * accompanied this code). 31.17 + * 31.18 + * You should have received a copy of the GNU General Public License version 31.19 + * 2 along with this work; if not, write to the Free Software Foundation, 31.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 31.21 + * 31.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 31.23 + * or visit www.oracle.com if you need additional information or have any 31.24 + * questions. 31.25 + */ 31.26 + 31.27 +/** 31.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 31.29 + * 31.30 + * @test 31.31 + * @run 31.32 + * @option --language=es6 */ 31.33 + 31.34 +"use strict"; 31.35 + 31.36 +try { 31.37 + eval('"use strict";\n' + 31.38 + 'const x = 2;\n' + 31.39 + 'x = 1;\n'); 31.40 +} catch (e) { 31.41 + print(e.name); 31.42 +} 31.43 + 31.44 +try { 31.45 + eval('"use strict";\n' + 31.46 + 'const x = 2;\n' + 31.47 + 'x++;\n'); 31.48 + fail("const assignment didn't throw"); 31.49 +} catch (e) { 31.50 + print(e.name); 31.51 +} 31.52 + 31.53 +try { 31.54 + eval('"use strict";\n' + 31.55 + 'const x = 2;\n' + 31.56 + 'x--;\n'); 31.57 + fail("const assignment didn't throw"); 31.58 +} catch (e) { 31.59 + print(e.name); 31.60 +} 31.61 + 31.62 +try { 31.63 + eval('"use strict";\n' + 31.64 + 'const x = 2;\n' + 31.65 + '++x;\n'); 31.66 + fail("const assignment didn't throw"); 31.67 +} catch (e) { 31.68 + print(e.name); 31.69 +} 31.70 + 31.71 +try { 31.72 + eval('"use strict";\n' + 31.73 + 'const x = 2;\n' + 31.74 + '--x;\n'); 31.75 + fail("const assignment didn't throw"); 31.76 +} catch (e) { 31.77 + print(e.name); 31.78 +} 31.79 + 31.80 +try { 31.81 + eval('"use strict";\n' + 31.82 + 'const x = 2;\n' + 31.83 + 'x += 1;\n'); 31.84 + fail("const assignment didn't throw"); 31.85 +} catch (e) { 31.86 + print(e.name); 31.87 +} 31.88 + 31.89 +try { 31.90 + eval('"use strict";\n' + 31.91 + 'const x = 2;\n' + 31.92 + 'x *= 1;\n'); 31.93 + fail("const assignment didn't throw"); 31.94 +} catch (e) { 31.95 + print(e.name); 31.96 +} 31.97 + 31.98 +try { 31.99 + eval('"use strict";\n' + 31.100 + 'const x = 2;\n' + 31.101 + 'x /= 1;\n'); 31.102 + fail("const assignment didn't throw"); 31.103 +} catch (e) { 31.104 + print(e.name); 31.105 +} 31.106 + 31.107 +try { 31.108 + eval('"use strict";\n' + 31.109 + 'const x = 2;\n' + 31.110 + 'x %= 1;\n'); 31.111 + fail("const assignment didn't throw"); 31.112 +} catch (e) { 31.113 + print(e.name); 31.114 +} 31.115 + 31.116 +try { 31.117 + eval('"use strict";\n' + 31.118 + 'const x = 2;\n' + 31.119 + 'x |= 1;\n'); 31.120 + fail("const assignment didn't throw"); 31.121 +} catch (e) { 31.122 + print(e.name); 31.123 +} 31.124 + 31.125 +try { 31.126 + eval('"use strict";\n' + 31.127 + 'const x = 2;\n' + 31.128 + 'x &= 1;\n'); 31.129 + fail("const assignment didn't throw"); 31.130 +} catch (e) { 31.131 + print(e.name); 31.132 +} 31.133 + 31.134 +try { 31.135 + eval('"use strict";\n' + 31.136 + 'const x = 2;\n' + 31.137 + 'x ^= 1;\n'); 31.138 + fail("const assignment didn't throw"); 31.139 +} catch (e) { 31.140 + print(e.name); 31.141 +} 31.142 + 31.143 +try { 31.144 + eval('"use strict";\n' + 31.145 + 'const x = 2;\n' + 31.146 + 'x <<= 1;\n'); 31.147 + fail("const assignment didn't throw"); 31.148 +} catch (e) { 31.149 + print(e.name); 31.150 +} 31.151 + 31.152 +try { 31.153 + eval('"use strict";\n' + 31.154 + 'const x = 2;\n' + 31.155 + 'x >>= 1;\n'); 31.156 + fail("const assignment didn't throw"); 31.157 +} catch (e) { 31.158 + print(e.name); 31.159 +} 31.160 + 31.161 +try { 31.162 + eval('"use strict";\n' + 31.163 + 'const x = 2;\n' + 31.164 + 'x >>>= 1;\n'); 31.165 + fail("const assignment didn't throw"); 31.166 +} catch (e) { 31.167 + print(e.name); 31.168 +} 31.169 + 31.170 +try { 31.171 + eval('"use strict";\n' + 31.172 + 'const x = 2;\n' + 31.173 + 'delete x;\n'); 31.174 + fail("const assignment didn't throw"); 31.175 +} catch (e) { 31.176 + print(e.name); 31.177 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/test/script/basic/es6/const-reassign.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 32.3 @@ -0,0 +1,16 @@ 32.4 +SyntaxError 32.5 +SyntaxError 32.6 +SyntaxError 32.7 +SyntaxError 32.8 +SyntaxError 32.9 +SyntaxError 32.10 +SyntaxError 32.11 +SyntaxError 32.12 +SyntaxError 32.13 +SyntaxError 32.14 +SyntaxError 32.15 +SyntaxError 32.16 +SyntaxError 32.17 +SyntaxError 32.18 +SyntaxError 32.19 +SyntaxError
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/test/script/basic/es6/const-redeclare.js Thu Sep 04 18:47:18 2014 +0200 33.3 @@ -0,0 +1,38 @@ 33.4 +/* 33.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 33.7 + * 33.8 + * This code is free software; you can redistribute it and/or modify it 33.9 + * under the terms of the GNU General Public License version 2 only, as 33.10 + * published by the Free Software Foundation. 33.11 + * 33.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 33.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 33.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 33.15 + * version 2 for more details (a copy is included in the LICENSE file that 33.16 + * accompanied this code). 33.17 + * 33.18 + * You should have received a copy of the GNU General Public License version 33.19 + * 2 along with this work; if not, write to the Free Software Foundation, 33.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 33.21 + * 33.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 33.23 + * or visit www.oracle.com if you need additional information or have any 33.24 + * questions. 33.25 + */ 33.26 + 33.27 +/** 33.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 33.29 + * 33.30 + * @test 33.31 + * @run 33.32 + * @option --language=es6 33.33 + */ 33.34 + 33.35 +try { 33.36 + eval('"use strict";\n' + 33.37 + 'const x = 2;\n' + 33.38 + 'const x = 2;\n'); 33.39 +} catch (e) { 33.40 + print(e); 33.41 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/test/script/basic/es6/const-redeclare.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 34.3 @@ -0,0 +1,3 @@ 34.4 +SyntaxError: test/script/basic/es6/const-redeclare.js#33:4<eval>@1:2:6 Variable "x" has already been declared 34.5 +const x = 2; 34.6 + ^
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/test/script/basic/es6/const-self.js Thu Sep 04 18:47:18 2014 +0200 35.3 @@ -0,0 +1,42 @@ 35.4 +/* 35.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 35.7 + * 35.8 + * This code is free software; you can redistribute it and/or modify it 35.9 + * under the terms of the GNU General Public License version 2 only, as 35.10 + * published by the Free Software Foundation. 35.11 + * 35.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 35.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 35.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 35.15 + * version 2 for more details (a copy is included in the LICENSE file that 35.16 + * accompanied this code). 35.17 + * 35.18 + * You should have received a copy of the GNU General Public License version 35.19 + * 2 along with this work; if not, write to the Free Software Foundation, 35.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 35.21 + * 35.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 35.23 + * or visit www.oracle.com if you need additional information or have any 35.24 + * questions. 35.25 + */ 35.26 + 35.27 +/** 35.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 35.29 + * 35.30 + * @test 35.31 + * @run 35.32 + * @option --language=es6 */ 35.33 + 35.34 +"use strict"; 35.35 + 35.36 +const a = 1, b = a; 35.37 + 35.38 +print(a, b); 35.39 + 35.40 +try { 35.41 + eval('"use strict";\n' + 35.42 + 'const a = a;\n'); 35.43 +} catch (e) { 35.44 + print(e); 35.45 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/test/script/basic/es6/const-self.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 36.3 @@ -0,0 +1,2 @@ 36.4 +1 1 36.5 +ReferenceError: "a" is not defined
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/test/script/basic/es6/const-tdz.js Thu Sep 04 18:47:18 2014 +0200 37.3 @@ -0,0 +1,81 @@ 37.4 +/* 37.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 37.7 + * 37.8 + * This code is free software; you can redistribute it and/or modify it 37.9 + * under the terms of the GNU General Public License version 2 only, as 37.10 + * published by the Free Software Foundation. 37.11 + * 37.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 37.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 37.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 37.15 + * version 2 for more details (a copy is included in the LICENSE file that 37.16 + * accompanied this code). 37.17 + * 37.18 + * You should have received a copy of the GNU General Public License version 37.19 + * 2 along with this work; if not, write to the Free Software Foundation, 37.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 37.21 + * 37.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 37.23 + * or visit www.oracle.com if you need additional information or have any 37.24 + * questions. 37.25 + */ 37.26 + 37.27 +/** 37.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 37.29 + * 37.30 + * @test 37.31 + * @run 37.32 + * @option --language=es6 */ 37.33 + 37.34 +"use strict"; 37.35 + 37.36 +{ 37.37 + print("test 1"); 37.38 + 37.39 + function f() { 37.40 + try { 37.41 + print(a); 37.42 + } catch (a) { 37.43 + print(a); 37.44 + } 37.45 + } 37.46 + 37.47 + f(); 37.48 + const a = 1; 37.49 + f(); 37.50 +} 37.51 + 37.52 +{ 37.53 + print("test 2"); 37.54 + 37.55 + function f() { 37.56 + try { 37.57 + print(a); 37.58 + } catch (a) { 37.59 + print(a); 37.60 + } 37.61 + } 37.62 + 37.63 + f(); 37.64 + const a = 2; 37.65 + f(); 37.66 +} 37.67 + 37.68 +{ 37.69 + print("test 3"); 37.70 + { 37.71 + try { 37.72 + print(a); 37.73 + } catch (a) { 37.74 + print(a); 37.75 + } 37.76 + } 37.77 + 37.78 + const a = 3; 37.79 + 37.80 + { 37.81 + print(a); 37.82 + } 37.83 +} 37.84 +
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/test/script/basic/es6/const-tdz.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 38.3 @@ -0,0 +1,9 @@ 38.4 +test 1 38.5 +ReferenceError: "a" is not defined 38.6 +1 38.7 +test 2 38.8 +ReferenceError: "a" is not defined 38.9 +2 38.10 +test 3 38.11 +ReferenceError: "a" is not defined 38.12 +3
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/test/script/basic/es6/const.js Thu Sep 04 18:47:18 2014 +0200 39.3 @@ -0,0 +1,69 @@ 39.4 +/* 39.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 39.7 + * 39.8 + * This code is free software; you can redistribute it and/or modify it 39.9 + * under the terms of the GNU General Public License version 2 only, as 39.10 + * published by the Free Software Foundation. 39.11 + * 39.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 39.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 39.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 39.15 + * version 2 for more details (a copy is included in the LICENSE file that 39.16 + * accompanied this code). 39.17 + * 39.18 + * You should have received a copy of the GNU General Public License version 39.19 + * 2 along with this work; if not, write to the Free Software Foundation, 39.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 39.21 + * 39.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 39.23 + * or visit www.oracle.com if you need additional information or have any 39.24 + * questions. 39.25 + */ 39.26 + 39.27 +/** 39.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 39.29 + * 39.30 + * @test 39.31 + * @run 39.32 + * @option --language=es6 39.33 + */ 39.34 + 39.35 +"use strict"; 39.36 + 39.37 +const a = 2; 39.38 +const c = 2; 39.39 +print(a, c); 39.40 + 39.41 +function f(x) { 39.42 + const a = 5; 39.43 + const c = 10; 39.44 + print(a, c); 39.45 + if (x) { 39.46 + const a = 42; 39.47 + const c = 43; 39.48 + print(a, c); 39.49 + } 39.50 + print(a, c); 39.51 + 39.52 + function inner() { 39.53 + (function() { 39.54 + print(a, c); 39.55 + })(); 39.56 + } 39.57 + inner(); 39.58 +} 39.59 + 39.60 +f(true); 39.61 +f(false); 39.62 + 39.63 +(function() { 39.64 + (function() { 39.65 + print(a, c); 39.66 + })(); 39.67 +})(); 39.68 + 39.69 +function outer() { 39.70 + print(a, c); 39.71 +} 39.72 +outer();
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/test/script/basic/es6/const.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 40.3 @@ -0,0 +1,10 @@ 40.4 +2 2 40.5 +5 10 40.6 +42 43 40.7 +5 10 40.8 +5 10 40.9 +5 10 40.10 +5 10 40.11 +5 10 40.12 +2 2 40.13 +2 2
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/test/script/basic/es6/for-let.js Thu Sep 04 18:47:18 2014 +0200 41.3 @@ -0,0 +1,41 @@ 41.4 +/* 41.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 41.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41.7 + * 41.8 + * This code is free software; you can redistribute it and/or modify it 41.9 + * under the terms of the GNU General Public License version 2 only, as 41.10 + * published by the Free Software Foundation. 41.11 + * 41.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 41.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 41.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 41.15 + * version 2 for more details (a copy is included in the LICENSE file that 41.16 + * accompanied this code). 41.17 + * 41.18 + * You should have received a copy of the GNU General Public License version 41.19 + * 2 along with this work; if not, write to the Free Software Foundation, 41.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 41.21 + * 41.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 41.23 + * or visit www.oracle.com if you need additional information or have any 41.24 + * questions. 41.25 + */ 41.26 + 41.27 +/** 41.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 41.29 + * 41.30 + * @test 41.31 + * @run 41.32 + * @option --language=es6 */ 41.33 + 41.34 +"use strict"; 41.35 + 41.36 +for (let i = 0; i < 10; i++) { 41.37 + print(i); 41.38 +} 41.39 + 41.40 +try { 41.41 + print(i); 41.42 +} catch (e) { 41.43 + print(e); 41.44 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/test/script/basic/es6/for-let.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 42.3 @@ -0,0 +1,11 @@ 42.4 +0 42.5 +1 42.6 +2 42.7 +3 42.8 +4 42.9 +5 42.10 +6 42.11 +7 42.12 +8 42.13 +9 42.14 +ReferenceError: "i" is not defined
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/test/script/basic/es6/let-eval.js Thu Sep 04 18:47:18 2014 +0200 43.3 @@ -0,0 +1,98 @@ 43.4 +/* 43.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 43.7 + * 43.8 + * This code is free software; you can redistribute it and/or modify it 43.9 + * under the terms of the GNU General Public License version 2 only, as 43.10 + * published by the Free Software Foundation. 43.11 + * 43.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 43.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 43.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 43.15 + * version 2 for more details (a copy is included in the LICENSE file that 43.16 + * accompanied this code). 43.17 + * 43.18 + * You should have received a copy of the GNU General Public License version 43.19 + * 2 along with this work; if not, write to the Free Software Foundation, 43.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 43.21 + * 43.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 43.23 + * or visit www.oracle.com if you need additional information or have any 43.24 + * questions. 43.25 + */ 43.26 + 43.27 +/** 43.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 43.29 + * 43.30 + * @test 43.31 + * @run 43.32 + * @option --language=es6 */ 43.33 + 43.34 +"use strict"; 43.35 + 43.36 +function f() { 43.37 + var a; 43.38 + let b; 43.39 + const c = 0; 43.40 + 43.41 + print(a, b, c); 43.42 + 43.43 + try { 43.44 + eval("x = 1; print('x: ' + x);"); 43.45 + print("assignment to x succeeded"); 43.46 + } catch (e) { 43.47 + print(e); 43.48 + } 43.49 + try { 43.50 + eval("'use strict'; let z = 1; print('z: ' + z);"); 43.51 + print("assignment to z succeeded"); 43.52 + eval("print('z: ' + z);"); 43.53 + } catch (e) { 43.54 + print(e); 43.55 + } 43.56 + 43.57 + try { 43.58 + eval("a = 1; print(a);"); 43.59 + print("assignment to a succeeded"); 43.60 + } catch (e) { 43.61 + print(e); 43.62 + } 43.63 + print("a: " + a); 43.64 + 43.65 + try { 43.66 + eval("b = 1; print('b: ' + b);"); 43.67 + print("assignment to b succeeded"); 43.68 + } catch (e) { 43.69 + print(e); 43.70 + } 43.71 + print("b: " + b); 43.72 + 43.73 + try { 43.74 + eval("c = 1; print('c: ' + c);"); 43.75 + print("assignment to c succeeded"); 43.76 + } catch (e) { 43.77 + print(e); 43.78 + } 43.79 + print("c: " + c); 43.80 + 43.81 + eval("a = 2; let b = 3;"); 43.82 + 43.83 + try { 43.84 + print(a, b, c); 43.85 + } catch (e) { 43.86 + print(e); 43.87 + } 43.88 + 43.89 + let x; 43.90 + 43.91 + try { 43.92 + print(a, b, c, x); 43.93 + } catch (e) { 43.94 + print(e); 43.95 + } 43.96 + 43.97 +} 43.98 + 43.99 +f(); 43.100 + 43.101 +print(typeof a, typeof b, typeof c, typeof x, typeof z);
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/test/script/basic/es6/let-eval.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 44.3 @@ -0,0 +1,16 @@ 44.4 +undefined undefined 0 44.5 +ReferenceError: "x" is not defined 44.6 +z: 1 44.7 +assignment to z succeeded 44.8 +ReferenceError: "z" is not defined 44.9 +1 44.10 +assignment to a succeeded 44.11 +a: 1 44.12 +b: 1 44.13 +assignment to b succeeded 44.14 +b: 1 44.15 +TypeError: "c" is not a writable property of [object Object] 44.16 +c: 0 44.17 +2 1 0 44.18 +2 1 0 undefined 44.19 +undefined undefined undefined undefined undefined
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/test/script/basic/es6/let-load-lib.js Thu Sep 04 18:47:18 2014 +0200 45.3 @@ -0,0 +1,48 @@ 45.4 +/* 45.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 45.7 + * 45.8 + * This code is free software; you can redistribute it and/or modify it 45.9 + * under the terms of the GNU General Public License version 2 only, as 45.10 + * published by the Free Software Foundation. 45.11 + * 45.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 45.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 45.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 45.15 + * version 2 for more details (a copy is included in the LICENSE file that 45.16 + * accompanied this code). 45.17 + * 45.18 + * You should have received a copy of the GNU General Public License version 45.19 + * 2 along with this work; if not, write to the Free Software Foundation, 45.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 45.21 + * 45.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 45.23 + * or visit www.oracle.com if you need additional information or have any 45.24 + * questions. 45.25 + */ 45.26 + 45.27 +/** 45.28 + * @subtest 45.29 + */ 45.30 + 45.31 +"use strict"; 45.32 + 45.33 +// var should be visible in other script, let and const not 45.34 +var a = 1; 45.35 +let b = 2; 45.36 +const c = 3; 45.37 + 45.38 +// top level function should be visible 45.39 +function top() { 45.40 + print("top level function"); 45.41 +} 45.42 + 45.43 +// block level function not visible outside script 45.44 +{ 45.45 + function block() { 45.46 + print("block function"); 45.47 + } 45.48 + 45.49 + top(); 45.50 + block(); 45.51 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/test/script/basic/es6/let-load.js Thu Sep 04 18:47:18 2014 +0200 46.3 @@ -0,0 +1,62 @@ 46.4 +/* 46.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 46.7 + * 46.8 + * This code is free software; you can redistribute it and/or modify it 46.9 + * under the terms of the GNU General Public License version 2 only, as 46.10 + * published by the Free Software Foundation. 46.11 + * 46.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 46.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 46.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 46.15 + * version 2 for more details (a copy is included in the LICENSE file that 46.16 + * accompanied this code). 46.17 + * 46.18 + * You should have received a copy of the GNU General Public License version 46.19 + * 2 along with this work; if not, write to the Free Software Foundation, 46.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 46.21 + * 46.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 46.23 + * or visit www.oracle.com if you need additional information or have any 46.24 + * questions. 46.25 + */ 46.26 + 46.27 +/** 46.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 46.29 + * 46.30 + * @test 46.31 + * @run 46.32 + * @option --language=es6 */ 46.33 + 46.34 +"use strict"; 46.35 + 46.36 +load(__DIR__ + "let-load-lib.js"); 46.37 + 46.38 +{ 46.39 + let a = 20; 46.40 + const c = 30; 46.41 + print("print local defs: " + a, c); 46.42 +} 46.43 + 46.44 +print("imported var: " + a); 46.45 +try { 46.46 + print("imported let: " + b); 46.47 +} catch (e) { 46.48 + print(e); 46.49 +} 46.50 + 46.51 +try { 46.52 + print("imported const: " + c); 46.53 +} catch (e) { 46.54 + print(e); 46.55 +} 46.56 + 46.57 +top(); 46.58 + 46.59 +try { 46.60 + block(); 46.61 +} catch (e) { 46.62 + print(e); 46.63 +} 46.64 + 46.65 +
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/test/script/basic/es6/let-load.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 47.3 @@ -0,0 +1,8 @@ 47.4 +top level function 47.5 +block function 47.6 +print local defs: 20 30 47.7 +imported var: 1 47.8 +ReferenceError: "b" is not defined 47.9 +ReferenceError: "c" is not defined 47.10 +top level function 47.11 +ReferenceError: "block" is not defined
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/test/script/basic/es6/let-nodeclare.js Thu Sep 04 18:47:18 2014 +0200 48.3 @@ -0,0 +1,52 @@ 48.4 +/* 48.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 48.7 + * 48.8 + * This code is free software; you can redistribute it and/or modify it 48.9 + * under the terms of the GNU General Public License version 2 only, as 48.10 + * published by the Free Software Foundation. 48.11 + * 48.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 48.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 48.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 48.15 + * version 2 for more details (a copy is included in the LICENSE file that 48.16 + * accompanied this code). 48.17 + * 48.18 + * You should have received a copy of the GNU General Public License version 48.19 + * 2 along with this work; if not, write to the Free Software Foundation, 48.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 48.21 + * 48.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 48.23 + * or visit www.oracle.com if you need additional information or have any 48.24 + * questions. 48.25 + */ 48.26 + 48.27 +/** 48.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 48.29 + * 48.30 + * @test 48.31 + * @run 48.32 + * @option --language=es6 */ 48.33 + 48.34 +"use strict"; 48.35 + 48.36 +try { 48.37 + if (true) { 48.38 + let x = 2; 48.39 + print(x); 48.40 + } 48.41 + print(x); 48.42 +} catch (e) { 48.43 + print(e); 48.44 +} 48.45 + 48.46 + 48.47 +try { 48.48 + if (true) { 48.49 + const x = 2; 48.50 + print(x); 48.51 + } 48.52 + print(x); 48.53 +} catch (e) { 48.54 + print(e); 48.55 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/test/script/basic/es6/let-nodeclare.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 49.3 @@ -0,0 +1,4 @@ 49.4 +2 49.5 +ReferenceError: "x" is not defined 49.6 +2 49.7 +ReferenceError: "x" is not defined
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/test/script/basic/es6/let-redeclare.js Thu Sep 04 18:47:18 2014 +0200 50.3 @@ -0,0 +1,38 @@ 50.4 +/* 50.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 50.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 50.7 + * 50.8 + * This code is free software; you can redistribute it and/or modify it 50.9 + * under the terms of the GNU General Public License version 2 only, as 50.10 + * published by the Free Software Foundation. 50.11 + * 50.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 50.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 50.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 50.15 + * version 2 for more details (a copy is included in the LICENSE file that 50.16 + * accompanied this code). 50.17 + * 50.18 + * You should have received a copy of the GNU General Public License version 50.19 + * 2 along with this work; if not, write to the Free Software Foundation, 50.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 50.21 + * 50.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 50.23 + * or visit www.oracle.com if you need additional information or have any 50.24 + * questions. 50.25 + */ 50.26 + 50.27 +/** 50.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 50.29 + * 50.30 + * @test 50.31 + * @run 50.32 + * @option --language=es6 50.33 + */ 50.34 + 50.35 +try { 50.36 + eval('"use strict";\n' + 50.37 + 'let x = 2;\n' + 50.38 + 'let x = 2;\n'); 50.39 +} catch (e) { 50.40 + print(e); 50.41 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/test/script/basic/es6/let-redeclare.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 51.3 @@ -0,0 +1,3 @@ 51.4 +SyntaxError: test/script/basic/es6/let-redeclare.js#33:4<eval>@1:2:4 Variable "x" has already been declared 51.5 +let x = 2; 51.6 + ^
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/test/script/basic/es6/let-self.js Thu Sep 04 18:47:18 2014 +0200 52.3 @@ -0,0 +1,42 @@ 52.4 +/* 52.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 52.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 52.7 + * 52.8 + * This code is free software; you can redistribute it and/or modify it 52.9 + * under the terms of the GNU General Public License version 2 only, as 52.10 + * published by the Free Software Foundation. 52.11 + * 52.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 52.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 52.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 52.15 + * version 2 for more details (a copy is included in the LICENSE file that 52.16 + * accompanied this code). 52.17 + * 52.18 + * You should have received a copy of the GNU General Public License version 52.19 + * 2 along with this work; if not, write to the Free Software Foundation, 52.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 52.21 + * 52.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 52.23 + * or visit www.oracle.com if you need additional information or have any 52.24 + * questions. 52.25 + */ 52.26 + 52.27 +/** 52.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 52.29 + * 52.30 + * @test 52.31 + * @run 52.32 + * @option --language=es6 */ 52.33 + 52.34 +"use strict"; 52.35 + 52.36 +let a, b = a; 52.37 + 52.38 +print(a, b); 52.39 + 52.40 +try { 52.41 + eval('"use strict";\n' + 52.42 + 'let a = a;\n'); 52.43 +} catch (e) { 52.44 + print(e); 52.45 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/test/script/basic/es6/let-self.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 53.3 @@ -0,0 +1,2 @@ 53.4 +undefined undefined 53.5 +ReferenceError: "a" is not defined
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/test/script/basic/es6/let-tdz.js Thu Sep 04 18:47:18 2014 +0200 54.3 @@ -0,0 +1,97 @@ 54.4 +/* 54.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 54.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 54.7 + * 54.8 + * This code is free software; you can redistribute it and/or modify it 54.9 + * under the terms of the GNU General Public License version 2 only, as 54.10 + * published by the Free Software Foundation. 54.11 + * 54.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 54.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 54.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 54.15 + * version 2 for more details (a copy is included in the LICENSE file that 54.16 + * accompanied this code). 54.17 + * 54.18 + * You should have received a copy of the GNU General Public License version 54.19 + * 2 along with this work; if not, write to the Free Software Foundation, 54.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 54.21 + * 54.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 54.23 + * or visit www.oracle.com if you need additional information or have any 54.24 + * questions. 54.25 + */ 54.26 + 54.27 +/** 54.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 54.29 + * 54.30 + * @test 54.31 + * @run 54.32 + * @option --language=es6 */ 54.33 + 54.34 +"use strict"; 54.35 + 54.36 +{ 54.37 + print("test 1"); 54.38 + 54.39 + function f() { 54.40 + try { 54.41 + print(a); 54.42 + } catch (a) { 54.43 + print(a); 54.44 + } 54.45 + } 54.46 + 54.47 + f(); 54.48 + let a = 1; 54.49 + f(); 54.50 +} 54.51 + 54.52 +{ 54.53 + print("test 2"); 54.54 + 54.55 + function f() { 54.56 + try { 54.57 + print(a); 54.58 + } catch (a) { 54.59 + print(a); 54.60 + } 54.61 + } 54.62 + 54.63 + f(); 54.64 + let a = 2; 54.65 + f(); 54.66 +} 54.67 + 54.68 +{ 54.69 + print("test 3"); 54.70 + 54.71 + { 54.72 + try { 54.73 + print(a); 54.74 + } catch (a) { 54.75 + print(a); 54.76 + } 54.77 + } 54.78 + 54.79 + let a = 3; 54.80 + 54.81 + { 54.82 + print(a); 54.83 + } 54.84 +} 54.85 + 54.86 +{ 54.87 + print("test 4"); 54.88 + let a; 54.89 + 54.90 + { 54.91 + print(a); 54.92 + } 54.93 + 54.94 + a = 4; 54.95 + 54.96 + { 54.97 + print(a); 54.98 + } 54.99 +} 54.100 +
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/test/script/basic/es6/let-tdz.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 55.3 @@ -0,0 +1,12 @@ 55.4 +test 1 55.5 +ReferenceError: "a" is not defined 55.6 +1 55.7 +test 2 55.8 +ReferenceError: "a" is not defined 55.9 +2 55.10 +test 3 55.11 +ReferenceError: "a" is not defined 55.12 +3 55.13 +test 4 55.14 +undefined 55.15 +4
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/test/script/basic/es6/let.js Thu Sep 04 18:47:18 2014 +0200 56.3 @@ -0,0 +1,69 @@ 56.4 +/* 56.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 56.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 56.7 + * 56.8 + * This code is free software; you can redistribute it and/or modify it 56.9 + * under the terms of the GNU General Public License version 2 only, as 56.10 + * published by the Free Software Foundation. 56.11 + * 56.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 56.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 56.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 56.15 + * version 2 for more details (a copy is included in the LICENSE file that 56.16 + * accompanied this code). 56.17 + * 56.18 + * You should have received a copy of the GNU General Public License version 56.19 + * 2 along with this work; if not, write to the Free Software Foundation, 56.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 56.21 + * 56.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 56.23 + * or visit www.oracle.com if you need additional information or have any 56.24 + * questions. 56.25 + */ 56.26 + 56.27 +/** 56.28 + * JDK-8051889: Implement block scoping in symbol assignment and scope computation 56.29 + * 56.30 + * @test 56.31 + * @run 56.32 + * @option --language=es6 */ 56.33 + 56.34 +"use strict"; 56.35 + 56.36 +let a = 2; 56.37 +let c = 2; 56.38 +print(a, c); 56.39 + 56.40 +function f(x) { 56.41 + let a = 5; 56.42 + const c = 10; 56.43 + print(a, c); 56.44 + if (x) { 56.45 + let a = 42; 56.46 + const c = 43; 56.47 + print(a, c); 56.48 + } 56.49 + print(a, c); 56.50 + 56.51 + function inner() { 56.52 + (function() { 56.53 + print(a, c); 56.54 + })(); 56.55 + } 56.56 + inner(); 56.57 +} 56.58 + 56.59 +f(true); 56.60 +f(false); 56.61 + 56.62 +(function() { 56.63 + (function() { 56.64 + print(a, c); 56.65 + })(); 56.66 +})(); 56.67 + 56.68 +function outer() { 56.69 + print(a, c); 56.70 +} 56.71 +outer(); 56.72 +
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/test/script/basic/es6/let.js.EXPECTED Thu Sep 04 18:47:18 2014 +0200 57.3 @@ -0,0 +1,10 @@ 57.4 +2 2 57.5 +5 10 57.6 +42 43 57.7 +5 10 57.8 +5 10 57.9 +5 10 57.10 +5 10 57.11 +5 10 57.12 +2 2 57.13 +2 2
58.1 --- a/test/script/trusted/JDK-8006529.js Wed Sep 03 14:33:34 2014 +0200 58.2 +++ b/test/script/trusted/JDK-8006529.js Thu Sep 04 18:47:18 2014 +0200 58.3 @@ -120,7 +120,7 @@ 58.4 58.5 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class) 58.6 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class) 58.7 -var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, boolean.class); 58.8 +var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, ErrorManager.class, boolean.class); 58.9 58.10 // compile(script) -- compiles a script specified as a string with its 58.11 // source code, returns a jdk.nashorn.internal.ir.FunctionNode object 58.12 @@ -134,7 +134,7 @@ 58.13 var parser = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance()); 58.14 var func = parseMethod.invoke(parser); 58.15 58.16 - var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, false); 58.17 + var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, null, false); 58.18 58.19 return compileMethod.invoke(compiler, func, phases); 58.20 };
59.1 --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed Sep 03 14:33:34 2014 +0200 59.2 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Thu Sep 04 18:47:18 2014 +0200 59.3 @@ -98,11 +98,16 @@ 59.4 compileTestSet(new File(TEST262_SUITE_DIR), new TestFilter() { 59.5 @Override 59.6 public boolean exclude(final File file, final String content) { 59.7 - return content.indexOf("@negative") != -1; 59.8 + return content != null && content.contains("@negative"); 59.9 } 59.10 }); 59.11 } 59.12 - compileTestSet(new File(TEST_BASIC_DIR), null); 59.13 + compileTestSet(new File(TEST_BASIC_DIR), new TestFilter() { 59.14 + @Override 59.15 + public boolean exclude(final File file, final String content) { 59.16 + return file.getName().equals("es6"); 59.17 + } 59.18 + }); 59.19 compileTestSet(new File(TEST_NODE_DIR, "node"), null); 59.20 compileTestSet(new File(TEST_NODE_DIR, "src"), null); 59.21 } 59.22 @@ -136,6 +141,9 @@ 59.23 private int skipped; 59.24 59.25 private void compileJSDirectory(final File dir, final TestFilter filter) { 59.26 + if (filter != null && filter.exclude(dir, null)) { 59.27 + return; 59.28 + } 59.29 for (final File f : dir.listFiles()) { 59.30 if (f.isDirectory()) { 59.31 compileJSDirectory(f, filter);
60.1 --- a/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed Sep 03 14:33:34 2014 +0200 60.2 +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java Thu Sep 04 18:47:18 2014 +0200 60.3 @@ -82,11 +82,16 @@ 60.4 parseTestSet(TEST262_SUITE_DIR, new TestFilter() { 60.5 @Override 60.6 public boolean exclude(final File file, final String content) { 60.7 - return content.indexOf("@negative") != -1; 60.8 + return content != null && content.contains("@negative"); 60.9 } 60.10 }); 60.11 } 60.12 - parseTestSet(TEST_BASIC_DIR, null); 60.13 + parseTestSet(TEST_BASIC_DIR, new TestFilter() { 60.14 + @Override 60.15 + public boolean exclude(final File file, final String content) { 60.16 + return file.getName().equals("es6"); 60.17 + } 60.18 + }); 60.19 } 60.20 60.21 private void parseTestSet(final String testSet, final TestFilter filter) { 60.22 @@ -120,6 +125,9 @@ 60.23 private int skipped; 60.24 60.25 private void parseJSDirectory(final File dir, final TestFilter filter) { 60.26 + if (filter != null && filter.exclude(dir, null)) { 60.27 + return; 60.28 + } 60.29 for (final File f : dir.listFiles()) { 60.30 if (f.isDirectory()) { 60.31 parseJSDirectory(f, filter);