src/jdk/nashorn/internal/codegen/AssignSymbols.java
Print this page
*** 187,218 ****
*
* @param functionNode the FunctionNode we are entering
* @param body the body of the FunctionNode we are entering
*/
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
! // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers.
body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
protected boolean enterDefault(final Node node) {
// Don't bother visiting expressions; var is a statement, it can't be inside an expression.
// This will also prevent visiting nested functions (as FunctionNode is an expression).
return !(node instanceof Expression);
}
@Override
public Node leaveVarNode(final VarNode varNode) {
- if (varNode.isStatement()) {
final IdentNode ident = varNode.getName();
! final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body;
final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
if (varNode.isFunctionDeclaration()) {
symbol.setIsFunctionDeclaration();
}
return varNode.setName(ident.setSymbol(symbol));
}
- return varNode;
- }
});
}
private IdentNode compilerConstantIdentifier(final CompilerConstants cc) {
return createImplicitIdentifier(cc.symbolName()).setSymbol(lc.getCurrentFunction().compilerConstant(cc));
--- 187,219 ----
*
* @param functionNode the FunctionNode we are entering
* @param body the body of the FunctionNode we are entering
*/
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
! // This visitor will assign symbol to all declared variables.
body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
protected boolean enterDefault(final Node node) {
// Don't bother visiting expressions; var is a statement, it can't be inside an expression.
// This will also prevent visiting nested functions (as FunctionNode is an expression).
return !(node instanceof Expression);
}
@Override
public Node leaveVarNode(final VarNode varNode) {
final IdentNode ident = varNode.getName();
! final boolean blockScoped = varNode.isBlockScoped();
! if (blockScoped && lc.inUnprotectedSwitchContext()) {
! throwUnprotectedSwitchError(varNode);
! }
! final Block block = blockScoped ? lc.getCurrentBlock() : body;
final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
if (varNode.isFunctionDeclaration()) {
symbol.setIsFunctionDeclaration();
}
return varNode.setName(ident.setSymbol(symbol));
}
});
}
private IdentNode compilerConstantIdentifier(final CompilerConstants cc) {
return createImplicitIdentifier(cc.symbolName()).setSymbol(lc.getCurrentFunction().compilerConstant(cc));
*** 1046,1055 ****
--- 1047,1065 ----
}
final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
return !(units == null || units.isEmpty());
}
+ private void throwUnprotectedSwitchError(final VarNode varNode) {
+ // Block scoped declarations in switch statements without explicit blocks should be declared
+ // in a common block that contains all the case clauses. We cannot support this without a
+ // fundamental rewrite of how switch statements are handled (case nodes contain blocks and are
+ // directly contained by switch node). As a temporary solution we throw a reference error here.
+ final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const");
+ throwParserException(msg, varNode);
+ }
+
private void throwParserException(final String message, final Node origin) {
if (origin == null) {
throw new ParserException(message);
}
final Source source = compiler.getSource();