src/jdk/nashorn/internal/parser/Parser.java
Print this page
@@ -557,11 +557,11 @@
return getBlock(true);
}
// Set up new block. Captures first token.
Block newBlock = newBlock();
try {
- statement();
+ statement(false, false, true);
} finally {
newBlock = restoreBlock(newBlock);
}
return newBlock;
}
@@ -770,11 +770,11 @@
break;
}
try {
// Get the next element.
- statement(true, allowPropertyFunction);
+ statement(true, allowPropertyFunction, false);
allowPropertyFunction = false;
// check for directive prologues
if (checkDirective) {
// skip any debug statement like line number to get actual first line
@@ -860,17 +860,19 @@
* see 12
*
* Parse any of the basic statement types.
*/
private void statement() {
- statement(false, false);
+ statement(false, false, false);
}
/**
* @param topLevel does this statement occur at the "top level" of a script or a function?
+ * @param allowPropertyFunction allow property "get" and "set" functions?
+ * @param singleStatement are we in a single statement context?
*/
- private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
+ private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
if (type == FUNCTION) {
// As per spec (ECMA section 12), function declarations as arbitrary statement
// is not "portable". Implementation can issue a warning or disallow the same.
functionExpression(true, topLevel);
return;
@@ -930,10 +932,13 @@
case EOF:
expect(SEMICOLON);
break;
default:
if (useBlockScope() && (type == LET || type == CONST)) {
+ if (singleStatement) {
+ throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
+ }
variableStatement(type, true);
break;
}
if (env._const_as_var && type == CONST) {
variableStatement(TokenType.VAR, true);
@@ -1055,11 +1060,11 @@
private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
// VAR tested in caller.
next();
final List<VarNode> vars = new ArrayList<>();
- int varFlags = VarNode.IS_STATEMENT;
+ int varFlags = 0;
if (varType == LET) {
varFlags |= VarNode.IS_LET;
} else if (varType == CONST) {
varFlags |= VarNode.IS_CONST;
}
@@ -1208,11 +1213,11 @@
// When ES6 for-let is enabled we create a container block to capture the LET.
final int startLine = start;
Block outer = useBlockScope() ? newBlock() : null;
// Create FOR node, capturing FOR token.
- ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR);
+ ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, 0);
lc.push(forNode);
try {
// FOR tested in caller.
next();
@@ -1228,23 +1233,26 @@
List<VarNode> vars = null;
switch (type) {
case VAR:
- // Var statements captured in for outer block.
+ // Var declaration captured in for outer block.
vars = variableStatement(type, false);
break;
case SEMICOLON:
break;
default:
if (useBlockScope() && (type == LET || type == CONST)) {
- // LET/CONST captured in container block created above.
+ if (type == LET) {
+ forNode = forNode.setPerIterationScope(lc);
+ }
+ // LET/CONST declaration captured in container block created above.
vars = variableStatement(type, false);
break;
}
if (env._const_as_var && type == CONST) {
- // Var statements captured in for outer block.
+ // Var declaration captured in for outer block.
vars = variableStatement(TokenType.VAR, false);
break;
}
final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
@@ -1321,17 +1329,18 @@
forNode.setFinish(body.getFinish());
appendStatement(forNode);
} finally {
lc.pop(forNode);
+ }
+
if (outer != null) {
outer.setFinish(forNode.getFinish());
outer = restoreBlock(outer);
appendStatement(new BlockStatement(startLine, outer));
}
}
- }
/**
* ... IterationStatement :
* ...
* Expression[NoIn]?; Expression? ; Expression?
@@ -2697,15 +2706,11 @@
functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
}
}
if (isStatement) {
- int varFlags = VarNode.IS_STATEMENT;
- if (!topLevel && useBlockScope()) {
- // mark ES6 block functions as lexically scoped
- varFlags |= VarNode.IS_LET;
- }
+ final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
if (topLevel) {
functionDeclarations.add(varNode);
} else if (useBlockScope()) {
prependStatement(varNode); // Hoist to beginning of current block