Skip to content

Commit 9eacb3a

Browse files
andreabergiagbrail
authored andcommitted
Fix variable resolution in switch statements with let declarations
Fixed the regression introduced by 2ba6e57, which made `switch` a proper `Scope`. The issue was that `Scope.splitScope()` creates an outer block scope and moves the symbol table from the switch to the block, but doesn't update the switch's `parentScope` pointer. This breaks the scope chain used for variable resolution, causing it to skip the block where symbols are stored. Fixed by manually fixing the scope chain, and follow the same pattern as `transformForLoop()` for manually managing `currentScope` instead of using `pushScope`/`popScope`, since the scope hierarchy is modified after parsing.
1 parent ddf877c commit 9eacb3a

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

rhino/src/main/java/org/mozilla/javascript/IRFactory.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,8 +1179,15 @@ private Node transformSwitch(SwitchStatement node) {
11791179
Scope block = Scope.splitScope(node);
11801180
block.setLineColumnNumber(node.getLineno(), node.getColumn());
11811181
block.addChildToBack(node);
1182+
node.setParentScope(block);
11821183

1183-
parser.pushScope(node);
1184+
// Can't use pushScope/popScope here since splitScope moves the symbol table
1185+
// We set currentScope to 'node' (not 'block') so nested scopes can be pushed,
1186+
// since their parent pointers were set to 'node' during parsing. Variable resolution
1187+
// works correctly because it walks up the parentScope chain, where node.parentScope =
1188+
// block.
1189+
Scope savedScope = parser.currentScope;
1190+
parser.currentScope = node;
11841191
try {
11851192
Node switchExpr = transform(node.getExpression());
11861193
node.addChildToBack(switchExpr);
@@ -1205,7 +1212,7 @@ private Node transformSwitch(SwitchStatement node) {
12051212
closeSwitch(block);
12061213
return block;
12071214
} finally {
1208-
parser.popScope();
1215+
parser.currentScope = savedScope;
12091216
}
12101217
}
12111218

tests/src/test/java/org/mozilla/javascript/tests/es5/LetTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,35 @@ void letInsideBodyOfSwitchES6Strict() {
9494
+ "})()\n";
9595
Utils.assertWithAllModes_ES6(1, script);
9696
}
97+
98+
@Test
99+
void letInsideFunctionSwitchIf() {
100+
String script =
101+
"(function () {\n"
102+
+ " switch (0) {\n"
103+
+ " default:\n"
104+
+ " let a = 0;\n"
105+
+ " if (a == 0) {\n"
106+
+ " a++;\n"
107+
+ " }\n"
108+
+ " return a;\n"
109+
+ " }\n"
110+
+ "})();\n";
111+
Utils.assertWithAllModes_1_8(1, script);
112+
}
113+
114+
@Test
115+
void letInsideFunctionWhileIf() {
116+
String script =
117+
"(function () {\n"
118+
+ " while (true) {\n"
119+
+ " let a = 0;\n"
120+
+ " if (a == 0) {\n"
121+
+ " a++;\n"
122+
+ " }\n"
123+
+ " return a;\n"
124+
+ " }\n"
125+
+ "})();\n";
126+
Utils.assertWithAllModes_1_8(1, script);
127+
}
97128
}

0 commit comments

Comments
 (0)