Skip to content

Commit ef20d75

Browse files
committed
feat(transformer/optional-chaining): change parent scope for expression when it wrapped with an arrow function
1 parent 92e44cb commit ef20d75

File tree

3 files changed

+15
-325
lines changed

3 files changed

+15
-325
lines changed

crates/oxc_transformer/src/es2020/optional_chaining.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use std::mem;
5151

5252
use oxc_allocator::CloneIn;
5353
use oxc_ast::{ast::*, NONE};
54+
use oxc_semantic::ScopeFlags;
5455
use oxc_span::SPAN;
5556
use oxc_traverse::{Ancestor, BoundIdentifier, MaybeBoundIdentifier, Traverse, TraverseCtx};
5657

@@ -244,14 +245,19 @@ 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+
let scope_id =
254+
ctx.insert_scope_below_expression(expr, ScopeFlags::Arrow | ScopeFlags::Function);
255+
249256
let kind = FormalParameterKind::ArrowFormalParameters;
250257
let params = ctx.ast.formal_parameters(SPAN, kind, ctx.ast.vec(), NONE);
251258
let statements =
252259
ctx.ast.vec1(ctx.ast.statement_return(SPAN, Some(ctx.ast.move_expression(expr))));
253260
let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), statements);
254-
let scope_id = ctx.current_scope_id();
255261
let arrow = ctx.ast.alloc_arrow_function_expression_with_scope_id(
256262
SPAN, false, false, NONE, params, NONE, body, scope_id,
257263
);
@@ -306,7 +312,7 @@ impl<'a> OptionalChaining<'a, '_> {
306312
// To insert the temp binding in the correct scope, we wrap the expression with
307313
// an arrow function. During the chain expression transformation, the temp binding
308314
// will be inserted into the arrow function's body.
309-
Self::wrap_arrow_function(expr, ctx)
315+
Self::wrap_arrow_function_iife(expr, ctx)
310316
} else {
311317
self.transform_chain_expression_impl(false, expr, ctx)
312318
}
@@ -320,7 +326,7 @@ impl<'a> OptionalChaining<'a, '_> {
320326
) {
321327
*expr = if self.is_inside_function_parameter {
322328
// Same as the above `transform_chain_expression` explanation
323-
Self::wrap_arrow_function(expr, ctx)
329+
Self::wrap_arrow_function_iife(expr, ctx)
324330
} else {
325331
// Unfortunately no way to get compiler to see that this branch is provably unreachable.
326332
// We don't want to inline this function, to keep `enter_expression` as small as possible.
@@ -659,7 +665,6 @@ impl<'a> OptionalChaining<'a, '_> {
659665
let assignment_expression =
660666
Self::create_assignment_expression(temp_binding.create_write_target(ctx), expr, ctx);
661667

662-
let reference = temp_binding.create_read_expression(ctx);
663668
// `left || (binding = expr) === null`
664669
let left = Self::create_logical_expression(
665670
left,
@@ -670,6 +675,7 @@ impl<'a> OptionalChaining<'a, '_> {
670675
if self.ctx.assumptions.no_document_all {
671676
left
672677
} else {
678+
let reference = temp_binding.create_read_expression(ctx);
673679
// `left || (binding = expr) === null || binding === void 0`
674680
Self::create_logical_expression(left, Self::wrap_void0_check(reference, ctx), ctx)
675681
}

tasks/coverage/snapshots/semantic_typescript.snap

+1-29
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ commit: d85767ab
22

33
semantic_typescript Summary:
44
AST Parsed : 6503/6503 (100.00%)
5-
Positive Passed: 2923/6503 (44.95%)
5+
Positive Passed: 2925/6503 (44.98%)
66
tasks/coverage/typescript/tests/cases/compiler/2dArrays.ts
77
semantic error: Symbol reference IDs mismatch for "Cell":
88
after transform: SymbolId(0): [ReferenceId(1)]
@@ -36429,34 +36429,6 @@ Unresolved references mismatch:
3642936429
after transform: []
3643036430
rebuilt : ["o1", "o2", "o3", "o4", "o5", "o6"]
3643136431

36432-
tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts
36433-
semantic error: Scope children mismatch:
36434-
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
36435-
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
36436-
Bindings mismatch:
36437-
after transform: ScopeId(2): ["_a", "c"]
36438-
rebuilt : ScopeId(3): ["_a"]
36439-
Scope parent mismatch:
36440-
after transform: ScopeId(2): Some(ScopeId(0))
36441-
rebuilt : ScopeId(3): Some(ScopeId(2))
36442-
Symbol scope ID mismatch for "c":
36443-
after transform: SymbolId(1): ScopeId(2)
36444-
rebuilt : SymbolId(1): ScopeId(2)
36445-
36446-
tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts
36447-
semantic error: Scope children mismatch:
36448-
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
36449-
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
36450-
Bindings mismatch:
36451-
after transform: ScopeId(2): ["_a", "b"]
36452-
rebuilt : ScopeId(3): ["_a"]
36453-
Scope parent mismatch:
36454-
after transform: ScopeId(2): Some(ScopeId(0))
36455-
rebuilt : ScopeId(3): Some(ScopeId(2))
36456-
Symbol scope ID mismatch for "b":
36457-
after transform: SymbolId(1): ScopeId(2)
36458-
rebuilt : SymbolId(1): ScopeId(2)
36459-
3646036432
tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInference.ts
3646136433
semantic error: Bindings mismatch:
3646236434
after transform: ScopeId(0): ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "fnu", "ofnu", "osu", "su", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"]

0 commit comments

Comments
 (0)