1
1
/*
2
- * Copyright (c) 2010, 2023 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2010, 2024 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* The Universal Permissive License (UPL), Version 1.0
@@ -3612,12 +3612,36 @@ private void switchStatement(boolean yield, boolean await) {
3612
3612
ParserContextBlockNode switchBlock ;
3613
3613
SwitchNode switchStatement ;
3614
3614
try {
3615
+ assert type == TokenType .SWITCH ; // tested in caller.
3616
+ next ();
3617
+
3618
+ /*
3619
+ * Note: Identifier references in the switch expression need to be resolved in the scope
3620
+ * of the outer block, so we must parse the expression before pushing the switch scope.
3621
+ */
3622
+ expect (LPAREN );
3623
+ int expressionLine = line ;
3624
+ Expression expression = expression (yield , await );
3625
+ expect (RPAREN );
3626
+
3627
+ // Desugar expression to a synthetic let variable assignment in the outer block.
3628
+ // This simplifies lexical scope analysis (the expression is outside the switch
3629
+ // block).
3630
+ // e.g.: let x = 1; switch (x) { case 0: let x = 2; } =>
3631
+ // let x = 1; { let :switch = x; { let x; switch (:switch) { case 0: x = 2; } } }
3632
+ if (useBlockScope ()) {
3633
+ IdentNode switchExprName = new IdentNode (Token .recast (expression .getToken (), IDENT ), expression .getFinish (), lexer .stringIntern (SWITCH_BINDING_NAME ));
3634
+ VarNode varNode = new VarNode (expressionLine , Token .recast (expression .getToken (), LET ), expression .getFinish (), switchExprName , expression , VarNode .IS_LET );
3635
+ outerBlock .appendStatement (varNode );
3636
+ declareVar (outerBlock .getScope (), varNode );
3637
+ expression = switchExprName ;
3638
+ }
3639
+
3615
3640
// Block to capture variables declared inside the switch statement.
3616
3641
switchBlock = newBlock (Scope .createSwitchBlock (lc .getCurrentScope ()));
3617
3642
switchBlock .setFlag (Block .IS_SYNTHETIC | Block .IS_SWITCH_BLOCK );
3618
3643
3619
- // SWITCH tested in caller.
3620
- next ();
3644
+ expect (LBRACE );
3621
3645
3622
3646
// Create and add switch statement.
3623
3647
final ParserContextSwitchNode switchNode = new ParserContextSwitchNode ();
@@ -3628,26 +3652,6 @@ private void switchStatement(boolean yield, boolean await) {
3628
3652
final ArrayList <CaseNode > cases = new ArrayList <>();
3629
3653
3630
3654
try {
3631
- expect (LPAREN );
3632
- int expressionLine = line ;
3633
- Expression expression = expression (yield , await );
3634
- expect (RPAREN );
3635
-
3636
- expect (LBRACE );
3637
-
3638
- // Desugar expression to a synthetic let variable assignment in the outer block.
3639
- // This simplifies lexical scope analysis (the expression is outside the switch
3640
- // block).
3641
- // e.g.: let x = 1; switch (x) { case 0: let x = 2; } =>
3642
- // let x = 1; { let :switch = x; { let x; switch (:switch) { case 0: x = 2; } } }
3643
- if (useBlockScope ()) {
3644
- IdentNode switchExprName = new IdentNode (Token .recast (expression .getToken (), IDENT ), expression .getFinish (), lexer .stringIntern (SWITCH_BINDING_NAME ));
3645
- VarNode varNode = new VarNode (expressionLine , Token .recast (expression .getToken (), LET ), expression .getFinish (), switchExprName , expression , VarNode .IS_LET );
3646
- outerBlock .appendStatement (varNode );
3647
- declareVar (outerBlock .getScope (), varNode );
3648
- expression = switchExprName ;
3649
- }
3650
-
3651
3655
while (type != RBRACE ) {
3652
3656
// Prepare for next case.
3653
3657
Expression caseExpression = null ;
@@ -3686,6 +3690,7 @@ private void switchStatement(boolean yield, boolean await) {
3686
3690
cases .add (caseNode );
3687
3691
}
3688
3692
3693
+ assert type == RBRACE ;
3689
3694
next ();
3690
3695
3691
3696
switchStatement = new SwitchNode (switchLine , switchToken , finish , expression , cases , defaultCaseIndex );
0 commit comments