11/*
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.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * The Universal Permissive License (UPL), Version 1.0
@@ -3612,12 +3612,36 @@ private void switchStatement(boolean yield, boolean await) {
36123612 ParserContextBlockNode switchBlock ;
36133613 SwitchNode switchStatement ;
36143614 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+
36153640 // Block to capture variables declared inside the switch statement.
36163641 switchBlock = newBlock (Scope .createSwitchBlock (lc .getCurrentScope ()));
36173642 switchBlock .setFlag (Block .IS_SYNTHETIC | Block .IS_SWITCH_BLOCK );
36183643
3619- // SWITCH tested in caller.
3620- next ();
3644+ expect (LBRACE );
36213645
36223646 // Create and add switch statement.
36233647 final ParserContextSwitchNode switchNode = new ParserContextSwitchNode ();
@@ -3628,26 +3652,6 @@ private void switchStatement(boolean yield, boolean await) {
36283652 final ArrayList <CaseNode > cases = new ArrayList <>();
36293653
36303654 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-
36513655 while (type != RBRACE ) {
36523656 // Prepare for next case.
36533657 Expression caseExpression = null ;
@@ -3686,6 +3690,7 @@ private void switchStatement(boolean yield, boolean await) {
36863690 cases .add (caseNode );
36873691 }
36883692
3693+ assert type == RBRACE ;
36893694 next ();
36903695
36913696 switchStatement = new SwitchNode (switchLine , switchToken , finish , expression , cases , defaultCaseIndex );
0 commit comments