feat(transformer/optional-chaining): change parent scope for expression when it wrapped with an arrow function (#8511)

This commit is contained in:
Dunqing 2025-01-16 12:21:44 +00:00
parent 8dd0013e72
commit f413bb5c64
3 changed files with 15 additions and 325 deletions

View file

@ -51,6 +51,7 @@ use std::mem;
use oxc_allocator::CloneIn;
use oxc_ast::{ast::*, NONE};
use oxc_semantic::ScopeFlags;
use oxc_span::SPAN;
use oxc_traverse::{Ancestor, BoundIdentifier, MaybeBoundIdentifier, Traverse, TraverseCtx};
@ -244,14 +245,19 @@ impl<'a> OptionalChaining<'a, '_> {
/// Wrap the expression with an arrow function
///
/// `expr` -> `() => { return expr; }`
fn wrap_arrow_function(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
/// `expr` -> `(() => { return expr; })()`
fn wrap_arrow_function_iife(
expr: &mut Expression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let scope_id =
ctx.insert_scope_below_expression(expr, ScopeFlags::Arrow | ScopeFlags::Function);
let kind = FormalParameterKind::ArrowFormalParameters;
let params = ctx.ast.formal_parameters(SPAN, kind, ctx.ast.vec(), NONE);
let statements =
ctx.ast.vec1(ctx.ast.statement_return(SPAN, Some(ctx.ast.move_expression(expr))));
let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), statements);
let scope_id = ctx.current_scope_id();
let arrow = ctx.ast.alloc_arrow_function_expression_with_scope_id(
SPAN, false, false, NONE, params, NONE, body, scope_id,
);
@ -306,7 +312,7 @@ impl<'a> OptionalChaining<'a, '_> {
// To insert the temp binding in the correct scope, we wrap the expression with
// an arrow function. During the chain expression transformation, the temp binding
// will be inserted into the arrow function's body.
Self::wrap_arrow_function(expr, ctx)
Self::wrap_arrow_function_iife(expr, ctx)
} else {
self.transform_chain_expression_impl(false, expr, ctx)
}
@ -320,7 +326,7 @@ impl<'a> OptionalChaining<'a, '_> {
) {
*expr = if self.is_inside_function_parameter {
// Same as the above `transform_chain_expression` explanation
Self::wrap_arrow_function(expr, ctx)
Self::wrap_arrow_function_iife(expr, ctx)
} else {
// Unfortunately no way to get compiler to see that this branch is provably unreachable.
// We don't want to inline this function, to keep `enter_expression` as small as possible.
@ -659,7 +665,6 @@ impl<'a> OptionalChaining<'a, '_> {
let assignment_expression =
Self::create_assignment_expression(temp_binding.create_write_target(ctx), expr, ctx);
let reference = temp_binding.create_read_expression(ctx);
// `left || (binding = expr) === null`
let left = Self::create_logical_expression(
left,
@ -670,6 +675,7 @@ impl<'a> OptionalChaining<'a, '_> {
if self.ctx.assumptions.no_document_all {
left
} else {
let reference = temp_binding.create_read_expression(ctx);
// `left || (binding = expr) === null || binding === void 0`
Self::create_logical_expression(left, Self::wrap_void0_check(reference, ctx), ctx)
}

View file

@ -2,7 +2,7 @@ commit: d85767ab
semantic_typescript Summary:
AST Parsed : 6503/6503 (100.00%)
Positive Passed: 2923/6503 (44.95%)
Positive Passed: 2925/6503 (44.98%)
tasks/coverage/typescript/tests/cases/compiler/2dArrays.ts
semantic error: Symbol reference IDs mismatch for "Cell":
after transform: SymbolId(0): [ReferenceId(1)]
@ -36429,34 +36429,6 @@ Unresolved references mismatch:
after transform: []
rebuilt : ["o1", "o2", "o3", "o4", "o5", "o6"]
tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts
semantic error: Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
Bindings mismatch:
after transform: ScopeId(2): ["_a", "c"]
rebuilt : ScopeId(3): ["_a"]
Scope parent mismatch:
after transform: ScopeId(2): Some(ScopeId(0))
rebuilt : ScopeId(3): Some(ScopeId(2))
Symbol scope ID mismatch for "c":
after transform: SymbolId(1): ScopeId(2)
rebuilt : SymbolId(1): ScopeId(2)
tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts
semantic error: Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
Bindings mismatch:
after transform: ScopeId(2): ["_a", "b"]
rebuilt : ScopeId(3): ["_a"]
Scope parent mismatch:
after transform: ScopeId(2): Some(ScopeId(0))
rebuilt : ScopeId(3): Some(ScopeId(2))
Symbol scope ID mismatch for "b":
after transform: SymbolId(1): ScopeId(2)
rebuilt : SymbolId(1): ScopeId(2)
tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInference.ts
semantic error: Bindings mismatch:
after transform: ScopeId(0): ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "fnu", "ofnu", "osu", "su", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"]

View file

@ -1,6 +1,6 @@
commit: acbc09a8
Passed: 692/1168
Passed: 698/1168
# All Passed:
* babel-plugin-transform-logical-assignment-operators
@ -962,295 +962,7 @@ x Output mismatch
x Output mismatch
# babel-plugin-transform-optional-chaining (36/45)
* assumption-noDocumentAll/assignment/input.js
Symbol reference IDs mismatch for "_obj$a":
after transform: SymbolId(5): [ReferenceId(7), ReferenceId(8), ReferenceId(9)]
rebuilt : SymbolId(0): [ReferenceId(3), ReferenceId(5)]
Symbol reference IDs mismatch for "_obj$b":
after transform: SymbolId(6): [ReferenceId(11), ReferenceId(12), ReferenceId(13)]
rebuilt : SymbolId(1): [ReferenceId(7), ReferenceId(9)]
Symbol reference IDs mismatch for "_obj$a2":
after transform: SymbolId(7): [ReferenceId(15), ReferenceId(16), ReferenceId(17)]
rebuilt : SymbolId(2): [ReferenceId(12), ReferenceId(14)]
* assumption-noDocumentAll/in-function-params/input.js
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(3), ScopeId(5), ScopeId(7), ScopeId(9)]
Bindings mismatch:
after transform: ScopeId(1): ["_x", "a"]
rebuilt : ScopeId(2): ["_x"]
Scope flags mismatch:
after transform: ScopeId(1): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(1): Some(ScopeId(0))
rebuilt : ScopeId(2): Some(ScopeId(1))
Bindings mismatch:
after transform: ScopeId(2): ["a", "b"]
rebuilt : ScopeId(4): []
Scope flags mismatch:
after transform: ScopeId(2): ScopeFlags(Function)
rebuilt : ScopeId(4): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(2): Some(ScopeId(0))
rebuilt : ScopeId(4): Some(ScopeId(3))
Bindings mismatch:
after transform: ScopeId(3): ["_a$b", "a", "b"]
rebuilt : ScopeId(6): ["_a$b"]
Scope flags mismatch:
after transform: ScopeId(3): ScopeFlags(Function)
rebuilt : ScopeId(6): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(3): Some(ScopeId(0))
rebuilt : ScopeId(6): Some(ScopeId(5))
Bindings mismatch:
after transform: ScopeId(4): ["_a$b2", "a", "b"]
rebuilt : ScopeId(8): ["_a$b2"]
Scope flags mismatch:
after transform: ScopeId(4): ScopeFlags(Function)
rebuilt : ScopeId(8): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(4): Some(ScopeId(0))
rebuilt : ScopeId(8): Some(ScopeId(7))
Bindings mismatch:
after transform: ScopeId(5): ["_a$b3", "a", "b"]
rebuilt : ScopeId(10): ["_a$b3"]
Scope flags mismatch:
after transform: ScopeId(5): ScopeFlags(Function)
rebuilt : ScopeId(10): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(5): Some(ScopeId(0))
rebuilt : ScopeId(10): Some(ScopeId(9))
Symbol scope ID mismatch for "a":
after transform: SymbolId(1): ScopeId(1)
rebuilt : SymbolId(1): ScopeId(1)
Symbol scope ID mismatch for "a":
after transform: SymbolId(3): ScopeId(2)
rebuilt : SymbolId(4): ScopeId(3)
Symbol scope ID mismatch for "b":
after transform: SymbolId(4): ScopeId(2)
rebuilt : SymbolId(5): ScopeId(3)
Symbol scope ID mismatch for "a":
after transform: SymbolId(6): ScopeId(3)
rebuilt : SymbolId(7): ScopeId(5)
Symbol scope ID mismatch for "b":
after transform: SymbolId(7): ScopeId(3)
rebuilt : SymbolId(8): ScopeId(5)
Symbol reference IDs mismatch for "_a$b":
after transform: SymbolId(15): [ReferenceId(8), ReferenceId(9), ReferenceId(10), ReferenceId(11), ReferenceId(12)]
rebuilt : SymbolId(9): [ReferenceId(5), ReferenceId(7), ReferenceId(8), ReferenceId(9)]
Symbol scope ID mismatch for "a":
after transform: SymbolId(9): ScopeId(4)
rebuilt : SymbolId(11): ScopeId(7)
Symbol scope ID mismatch for "b":
after transform: SymbolId(10): ScopeId(4)
rebuilt : SymbolId(12): ScopeId(7)
Symbol reference IDs mismatch for "_a$b2":
after transform: SymbolId(16): [ReferenceId(13), ReferenceId(14), ReferenceId(15), ReferenceId(16), ReferenceId(17)]
rebuilt : SymbolId(13): [ReferenceId(10), ReferenceId(12), ReferenceId(13), ReferenceId(14)]
Symbol scope ID mismatch for "a":
after transform: SymbolId(12): ScopeId(5)
rebuilt : SymbolId(15): ScopeId(9)
Symbol scope ID mismatch for "b":
after transform: SymbolId(13): ScopeId(5)
rebuilt : SymbolId(16): ScopeId(9)
Symbol reference IDs mismatch for "_a$b3":
after transform: SymbolId(17): [ReferenceId(19), ReferenceId(20), ReferenceId(21)]
rebuilt : SymbolId(17): [ReferenceId(16), ReferenceId(18)]
* assumption-noDocumentAll/memoize/input.js
Symbol reference IDs mismatch for "_foo$bar":
after transform: SymbolId(2): [ReferenceId(27), ReferenceId(28), ReferenceId(29)]
rebuilt : SymbolId(2): [ReferenceId(3), ReferenceId(5)]
Symbol reference IDs mismatch for "_foo$bar5":
after transform: SymbolId(9): [ReferenceId(46), ReferenceId(47), ReferenceId(48)]
rebuilt : SymbolId(9): [ReferenceId(35), ReferenceId(37)]
Symbol reference IDs mismatch for "_foo$bar7":
after transform: SymbolId(11): [ReferenceId(53), ReferenceId(54), ReferenceId(55)]
rebuilt : SymbolId(11): [ReferenceId(45), ReferenceId(47)]
Symbol reference IDs mismatch for "_foo$bar8$baz":
after transform: SymbolId(13): [ReferenceId(58), ReferenceId(59), ReferenceId(60)]
rebuilt : SymbolId(13): [ReferenceId(51), ReferenceId(53)]
Symbol reference IDs mismatch for "_foo$bar9":
after transform: SymbolId(14): [ReferenceId(63), ReferenceId(64), ReferenceId(65), ReferenceId(69)]
rebuilt : SymbolId(14): [ReferenceId(57), ReferenceId(60), ReferenceId(62)]
Symbol reference IDs mismatch for "_foo$bar9$baz":
after transform: SymbolId(15): [ReferenceId(66), ReferenceId(67), ReferenceId(68)]
rebuilt : SymbolId(15): [ReferenceId(59), ReferenceId(61)]
* general/delete-in-function-params/input.js
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1)]
rebuilt : ScopeId(0): [ScopeId(1)]
Bindings mismatch:
after transform: ScopeId(1): ["_a", "x"]
rebuilt : ScopeId(2): ["_a"]
Scope flags mismatch:
after transform: ScopeId(1): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(1): Some(ScopeId(0))
rebuilt : ScopeId(2): Some(ScopeId(1))
Symbol scope ID mismatch for "x":
after transform: SymbolId(1): ScopeId(1)
rebuilt : SymbolId(1): ScopeId(1)
* general/in-function-params/input.js
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(3), ScopeId(5), ScopeId(7), ScopeId(9)]
Bindings mismatch:
after transform: ScopeId(1): ["_x", "a"]
rebuilt : ScopeId(2): ["_x"]
Scope flags mismatch:
after transform: ScopeId(1): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(1): Some(ScopeId(0))
rebuilt : ScopeId(2): Some(ScopeId(1))
Bindings mismatch:
after transform: ScopeId(2): ["a", "b"]
rebuilt : ScopeId(4): []
Scope flags mismatch:
after transform: ScopeId(2): ScopeFlags(Function)
rebuilt : ScopeId(4): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(2): Some(ScopeId(0))
rebuilt : ScopeId(4): Some(ScopeId(3))
Bindings mismatch:
after transform: ScopeId(3): ["_a$b", "a", "b"]
rebuilt : ScopeId(6): ["_a$b"]
Scope flags mismatch:
after transform: ScopeId(3): ScopeFlags(Function)
rebuilt : ScopeId(6): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(3): Some(ScopeId(0))
rebuilt : ScopeId(6): Some(ScopeId(5))
Bindings mismatch:
after transform: ScopeId(4): ["_a$b2", "a", "b"]
rebuilt : ScopeId(8): ["_a$b2"]
Scope flags mismatch:
after transform: ScopeId(4): ScopeFlags(Function)
rebuilt : ScopeId(8): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(4): Some(ScopeId(0))
rebuilt : ScopeId(8): Some(ScopeId(7))
Bindings mismatch:
after transform: ScopeId(5): ["_a$b3", "a", "b"]
rebuilt : ScopeId(10): ["_a$b3"]
Scope flags mismatch:
after transform: ScopeId(5): ScopeFlags(Function)
rebuilt : ScopeId(10): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(5): Some(ScopeId(0))
rebuilt : ScopeId(10): Some(ScopeId(9))
Symbol scope ID mismatch for "a":
after transform: SymbolId(1): ScopeId(1)
rebuilt : SymbolId(1): ScopeId(1)
Symbol scope ID mismatch for "a":
after transform: SymbolId(3): ScopeId(2)
rebuilt : SymbolId(4): ScopeId(3)
Symbol scope ID mismatch for "b":
after transform: SymbolId(4): ScopeId(2)
rebuilt : SymbolId(5): ScopeId(3)
Symbol scope ID mismatch for "a":
after transform: SymbolId(6): ScopeId(3)
rebuilt : SymbolId(7): ScopeId(5)
Symbol scope ID mismatch for "b":
after transform: SymbolId(7): ScopeId(3)
rebuilt : SymbolId(8): ScopeId(5)
Symbol scope ID mismatch for "a":
after transform: SymbolId(9): ScopeId(4)
rebuilt : SymbolId(11): ScopeId(7)
Symbol scope ID mismatch for "b":
after transform: SymbolId(10): ScopeId(4)
rebuilt : SymbolId(12): ScopeId(7)
Symbol scope ID mismatch for "a":
after transform: SymbolId(12): ScopeId(5)
rebuilt : SymbolId(15): ScopeId(9)
Symbol scope ID mismatch for "b":
after transform: SymbolId(13): ScopeId(5)
rebuilt : SymbolId(16): ScopeId(9)
* general/in-function-params-loose/input.js
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5)]
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(3), ScopeId(5), ScopeId(7), ScopeId(9)]
Bindings mismatch:
after transform: ScopeId(1): ["_x", "a"]
rebuilt : ScopeId(2): ["_x"]
Scope flags mismatch:
after transform: ScopeId(1): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(1): Some(ScopeId(0))
rebuilt : ScopeId(2): Some(ScopeId(1))
Bindings mismatch:
after transform: ScopeId(2): ["a", "b"]
rebuilt : ScopeId(4): []
Scope flags mismatch:
after transform: ScopeId(2): ScopeFlags(Function)
rebuilt : ScopeId(4): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(2): Some(ScopeId(0))
rebuilt : ScopeId(4): Some(ScopeId(3))
Bindings mismatch:
after transform: ScopeId(3): ["_a$b", "a", "b"]
rebuilt : ScopeId(6): ["_a$b"]
Scope flags mismatch:
after transform: ScopeId(3): ScopeFlags(Function)
rebuilt : ScopeId(6): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(3): Some(ScopeId(0))
rebuilt : ScopeId(6): Some(ScopeId(5))
Bindings mismatch:
after transform: ScopeId(4): ["_a$b2", "a", "b"]
rebuilt : ScopeId(8): ["_a$b2"]
Scope flags mismatch:
after transform: ScopeId(4): ScopeFlags(Function)
rebuilt : ScopeId(8): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(4): Some(ScopeId(0))
rebuilt : ScopeId(8): Some(ScopeId(7))
Bindings mismatch:
after transform: ScopeId(5): ["_a$b3", "a", "b"]
rebuilt : ScopeId(10): ["_a$b3"]
Scope flags mismatch:
after transform: ScopeId(5): ScopeFlags(Function)
rebuilt : ScopeId(10): ScopeFlags(Function | Arrow)
Scope parent mismatch:
after transform: ScopeId(5): Some(ScopeId(0))
rebuilt : ScopeId(10): Some(ScopeId(9))
Symbol scope ID mismatch for "a":
after transform: SymbolId(1): ScopeId(1)
rebuilt : SymbolId(1): ScopeId(1)
Symbol scope ID mismatch for "a":
after transform: SymbolId(3): ScopeId(2)
rebuilt : SymbolId(4): ScopeId(3)
Symbol scope ID mismatch for "b":
after transform: SymbolId(4): ScopeId(2)
rebuilt : SymbolId(5): ScopeId(3)
Symbol scope ID mismatch for "a":
after transform: SymbolId(6): ScopeId(3)
rebuilt : SymbolId(7): ScopeId(5)
Symbol scope ID mismatch for "b":
after transform: SymbolId(7): ScopeId(3)
rebuilt : SymbolId(8): ScopeId(5)
Symbol scope ID mismatch for "a":
after transform: SymbolId(9): ScopeId(4)
rebuilt : SymbolId(11): ScopeId(7)
Symbol scope ID mismatch for "b":
after transform: SymbolId(10): ScopeId(4)
rebuilt : SymbolId(12): ScopeId(7)
Symbol scope ID mismatch for "a":
after transform: SymbolId(12): ScopeId(5)
rebuilt : SymbolId(15): ScopeId(9)
Symbol scope ID mismatch for "b":
after transform: SymbolId(13): ScopeId(5)
rebuilt : SymbolId(16): ScopeId(9)
# babel-plugin-transform-optional-chaining (42/45)
* transparent-expr-wrappers/ts-as-function-call-loose/input.ts
Unresolved references mismatch:
after transform: ["A", "B", "foo"]