src/jdk/nashorn/internal/parser/Parser.java
Print this page
*** 557,567 ****
return getBlock(true);
}
// Set up new block. Captures first token.
Block newBlock = newBlock();
try {
! statement();
} finally {
newBlock = restoreBlock(newBlock);
}
return newBlock;
}
--- 557,567 ----
return getBlock(true);
}
// Set up new block. Captures first token.
Block newBlock = newBlock();
try {
! statement(false, false, true);
} finally {
newBlock = restoreBlock(newBlock);
}
return newBlock;
}
*** 770,780 ****
break;
}
try {
// Get the next element.
! statement(true, allowPropertyFunction);
allowPropertyFunction = false;
// check for directive prologues
if (checkDirective) {
// skip any debug statement like line number to get actual first line
--- 770,780 ----
break;
}
try {
// Get the next element.
! 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,876 ****
* see 12
*
* Parse any of the basic statement types.
*/
private void statement() {
! statement(false, false);
}
/**
* @param topLevel does this statement occur at the "top level" of a script or a function?
*/
! private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
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;
--- 860,878 ----
* see 12
*
* Parse any of the basic statement types.
*/
private void statement() {
! 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, 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,939 ****
--- 932,944 ----
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,1065 ****
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;
if (varType == LET) {
varFlags |= VarNode.IS_LET;
} else if (varType == CONST) {
varFlags |= VarNode.IS_CONST;
}
--- 1060,1070 ----
private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
// VAR tested in caller.
next();
final List<VarNode> vars = new ArrayList<>();
! int varFlags = 0;
if (varType == LET) {
varFlags |= VarNode.IS_LET;
} else if (varType == CONST) {
varFlags |= VarNode.IS_CONST;
}
*** 1208,1218 ****
// 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);
lc.push(forNode);
try {
// FOR tested in caller.
next();
--- 1213,1223 ----
// 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, 0);
lc.push(forNode);
try {
// FOR tested in caller.
next();
*** 1228,1250 ****
List<VarNode> vars = null;
switch (type) {
case VAR:
! // Var statements 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.
vars = variableStatement(type, false);
break;
}
if (env._const_as_var && type == CONST) {
! // Var statements captured in for outer block.
vars = variableStatement(TokenType.VAR, false);
break;
}
final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
--- 1233,1258 ----
List<VarNode> vars = null;
switch (type) {
case VAR:
! // Var declaration captured in for outer block.
vars = variableStatement(type, false);
break;
case SEMICOLON:
break;
default:
if (useBlockScope() && (type == LET || type == CONST)) {
! 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 declaration captured in for outer block.
vars = variableStatement(TokenType.VAR, false);
break;
}
final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
*** 1321,1337 ****
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?
--- 1329,1346 ----
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,2711 ****
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 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
--- 2706,2716 ----
functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
}
}
if (isStatement) {
! 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