@@ -51,6 +51,7 @@ use std::mem;
5151
5252use oxc_allocator:: CloneIn ;
5353use oxc_ast:: { ast:: * , NONE } ;
54+ use oxc_semantic:: ScopeFlags ;
5455use oxc_span:: SPAN ;
5556use oxc_traverse:: { Ancestor , BoundIdentifier , MaybeBoundIdentifier , Traverse , TraverseCtx } ;
5657
@@ -244,14 +245,20 @@ impl<'a> OptionalChaining<'a, '_> {
244245
245246 /// Wrap the expression with an arrow function
246247 ///
247- /// `expr` -> `() => { return expr; }`
248- fn wrap_arrow_function ( expr : & mut Expression < ' a > , ctx : & mut TraverseCtx < ' a > ) -> Expression < ' a > {
248+ /// `expr` -> `(() => { return expr; })()`
249+ fn wrap_arrow_function_iife (
250+ expr : & mut Expression < ' a > ,
251+ ctx : & mut TraverseCtx < ' a > ,
252+ ) -> Expression < ' a > {
253+ // Create a child scope for the outside arrow function and change the parent scope for the expression
254+ let scope_id = ctx. create_child_scope_of_current ( ScopeFlags :: Arrow | ScopeFlags :: Function ) ;
255+ ctx. change_parent_scope_for_expression ( scope_id, expr) ;
256+
249257 let kind = FormalParameterKind :: ArrowFormalParameters ;
250258 let params = ctx. ast . formal_parameters ( SPAN , kind, ctx. ast . vec ( ) , NONE ) ;
251259 let statements =
252260 ctx. ast . vec1 ( ctx. ast . statement_return ( SPAN , Some ( ctx. ast . move_expression ( expr) ) ) ) ;
253261 let body = ctx. ast . function_body ( SPAN , ctx. ast . vec ( ) , statements) ;
254- let scope_id = ctx. current_scope_id ( ) ;
255262 let arrow = ctx. ast . alloc_arrow_function_expression_with_scope_id (
256263 SPAN , false , false , NONE , params, NONE , body, scope_id,
257264 ) ;
@@ -306,7 +313,7 @@ impl<'a> OptionalChaining<'a, '_> {
306313 // To insert the temp binding in the correct scope, we wrap the expression with
307314 // an arrow function. During the chain expression transformation, the temp binding
308315 // will be inserted into the arrow function's body.
309- Self :: wrap_arrow_function ( expr, ctx)
316+ Self :: wrap_arrow_function_iife ( expr, ctx)
310317 } else {
311318 self . transform_chain_expression_impl ( false , expr, ctx)
312319 }
@@ -320,7 +327,7 @@ impl<'a> OptionalChaining<'a, '_> {
320327 ) {
321328 * expr = if self . is_inside_function_parameter {
322329 // Same as the above `transform_chain_expression` explanation
323- Self :: wrap_arrow_function ( expr, ctx)
330+ Self :: wrap_arrow_function_iife ( expr, ctx)
324331 } else {
325332 // Unfortunately no way to get compiler to see that this branch is provably unreachable.
326333 // We don't want to inline this function, to keep `enter_expression` as small as possible.
@@ -659,7 +666,6 @@ impl<'a> OptionalChaining<'a, '_> {
659666 let assignment_expression =
660667 Self :: create_assignment_expression ( temp_binding. create_write_target ( ctx) , expr, ctx) ;
661668
662- let reference = temp_binding. create_read_expression ( ctx) ;
663669 // `left || (binding = expr) === null`
664670 let left = Self :: create_logical_expression (
665671 left,
@@ -670,6 +676,7 @@ impl<'a> OptionalChaining<'a, '_> {
670676 if self . ctx . assumptions . no_document_all {
671677 left
672678 } else {
679+ let reference = temp_binding. create_read_expression ( ctx) ;
673680 // `left || (binding = expr) === null || binding === void 0`
674681 Self :: create_logical_expression ( left, Self :: wrap_void0_check ( reference, ctx) , ctx)
675682 }
0 commit comments