mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(transformer/private-method): clear inherited strict flags (#22508)
Fixes private method transforms so scopes inherited from a transformed private method are converted back to sloppy mode when the surrounding scope is sloppy. Previously we only cleared `StrictMode` on the private method function scope itself. That left child scopes, such as async/generator wrapper scopes, marked as strict even though the transformed output is no longer inside a class method. This caused semantic rebuild mismatches across Babel and Test262 coverage. Nested classes are still left strict, since class bodies are always strict mode.
This commit is contained in:
1 parent
a71fedd39c
commit
7baed9c4b7
5 files changed
+40
-10365
No files matched your search
@@ -1,10 +1,12 @@
|
||||
//! ES2022: Class Properties
|
||||
//! Transform of private method uses e.g. `this.#method()`.
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
use oxc_allocator::TakeIn;
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_ast_visit::{VisitMut, walk_mut};
|
||||
use oxc_semantic::ScopeFlags;
|
||||
use oxc_semantic::{ScopeFlags, ScopeId};
|
||||
use oxc_span::SPAN;
|
||||
|
||||
use crate::{Helper, common::helper_loader::helper_call_expr, context::TraverseCtx};
|
||||
@@ -64,16 +66,11 @@ impl<'a> ClassProperties<'a> {
|
||||
let scope_id = function.scope_id();
|
||||
let new_parent_id = ctx.current_scope_id();
|
||||
ctx.scoping_mut().change_scope_parent_id(scope_id, Some(new_parent_id));
|
||||
let is_strict_mode = ctx.current_scope_flags().is_strict_mode();
|
||||
let make_sloppy_mode = !ctx.current_scope_flags().is_strict_mode();
|
||||
let flags = ctx.scoping_mut().scope_flags_mut(scope_id);
|
||||
*flags -= ScopeFlags::GetAccessor | ScopeFlags::SetAccessor;
|
||||
if !is_strict_mode {
|
||||
// TODO: Needs to remove all child scopes' strict mode flag if child scope
|
||||
// is inherited from this scope.
|
||||
*flags -= ScopeFlags::StrictMode;
|
||||
}
|
||||
|
||||
PrivateMethodVisitor::new(*r#static, self, ctx)
|
||||
PrivateMethodVisitor::new(*r#static, make_sloppy_mode, self, ctx)
|
||||
.visit_function(&mut function, ScopeFlags::Function);
|
||||
|
||||
Some(Statement::FunctionDeclaration(function))
|
||||
@@ -102,6 +99,8 @@ impl<'a> ClassProperties<'a> {
|
||||
/// 2. Transform `super` expressions.
|
||||
struct PrivateMethodVisitor<'a, 'v> {
|
||||
super_converter: ClassPropertiesSuperConverter<'a, 'v>,
|
||||
make_sloppy_mode: bool,
|
||||
strict_scope_depth: u32,
|
||||
/// `TransCtx` object.
|
||||
ctx: &'v mut TraverseCtx<'a>,
|
||||
}
|
||||
@@ -109,6 +108,7 @@ struct PrivateMethodVisitor<'a, 'v> {
|
||||
impl<'a, 'v> PrivateMethodVisitor<'a, 'v> {
|
||||
fn new(
|
||||
is_static: bool,
|
||||
make_sloppy_mode: bool,
|
||||
class_properties: &'v mut ClassProperties<'a>,
|
||||
ctx: &'v mut TraverseCtx<'a>,
|
||||
) -> Self {
|
||||
@@ -117,7 +117,12 @@ impl<'a, 'v> PrivateMethodVisitor<'a, 'v> {
|
||||
} else {
|
||||
ClassPropertiesSuperConverterMode::PrivateMethod
|
||||
};
|
||||
Self { super_converter: ClassPropertiesSuperConverter::new(mode, class_properties), ctx }
|
||||
Self {
|
||||
super_converter: ClassPropertiesSuperConverter::new(mode, class_properties),
|
||||
make_sloppy_mode,
|
||||
strict_scope_depth: 0,
|
||||
ctx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +166,7 @@ impl<'a> VisitMut<'a> for PrivateMethodVisitor<'a, '_> {
|
||||
#[inline]
|
||||
fn visit_class(&mut self, _class: &mut Class<'a>) {
|
||||
// Ignore because we don't need to transform `super` for other classes.
|
||||
// Nested classes are strict mode, so keep their scopes' strict flags.
|
||||
|
||||
// TODO: Actually we do need to transform `super` in:
|
||||
// 1. Class decorators
|
||||
@@ -169,4 +175,23 @@ impl<'a> VisitMut<'a> for PrivateMethodVisitor<'a, '_> {
|
||||
// 4. Class property/method/accessor decorators
|
||||
// (or does `super` in a decorator refer to inner class?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enter_scope(&mut self, flags: ScopeFlags, scope_id: &Cell<Option<ScopeId>>) {
|
||||
if !self.make_sloppy_mode {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.strict_scope_depth > 0 || flags.is_strict_mode() {
|
||||
self.strict_scope_depth += 1;
|
||||
} else {
|
||||
*self.ctx.scoping_mut().scope_flags_mut(scope_id.get().unwrap()) -=
|
||||
ScopeFlags::StrictMode;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn leave_scope(&mut self) {
|
||||
self.strict_scope_depth = self.strict_scope_depth.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ commit: 3d34928e
|
||||
|
||||
semantic_babel Summary:
|
||||
AST Parsed : 2236/2236 (100.00%)
|
||||
Positive Passed: 2035/2236 (91.01%)
|
||||
Positive Passed: 2037/2236 (91.10%)
|
||||
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js
|
||||
Symbol span mismatch for "C":
|
||||
after transform: SymbolId(0): Span { start: 65, end: 66 }
|
||||
@@ -46,25 +46,6 @@ Bindings mismatch:
|
||||
after transform: ScopeId(0): ["Foo"]
|
||||
rebuilt : ScopeId(0): []
|
||||
|
||||
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-private-methods/async/input.js
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(2): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(4): ScopeFlags(Function)
|
||||
|
||||
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-private-methods/async-generator/input.js
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(2): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(4): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode)
|
||||
rebuilt : ScopeId(5): ScopeFlags(0x0)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(4): ScopeFlags(StrictMode)
|
||||
rebuilt : ScopeId(6): ScopeFlags(0x0)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(5): ScopeFlags(StrictMode)
|
||||
rebuilt : ScopeId(7): ScopeFlags(0x0)
|
||||
|
||||
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-private-properties/await-in-private-property-in-params-of-async-arrow/input.js
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["_asyncToGenerator", "_classPrivateFieldInitSpec"]
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,7 +2,7 @@ commit: f350b523
|
||||
|
||||
semantic_typescript Summary:
|
||||
AST Parsed : 4773/4773 (100.00%)
|
||||
Positive Passed: 2671/4773 (55.96%)
|
||||
Positive Passed: 2677/4773 (56.09%)
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/compiler/2dArrays.ts
|
||||
Symbol reference IDs mismatch for "Cell":
|
||||
after transform: SymbolId(0): [ReferenceId(1)]
|
||||
@@ -19430,14 +19430,6 @@ Unresolved references mismatch:
|
||||
after transform: ["require", "undefined"]
|
||||
rebuilt : ["B", "require", "undefined"]
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameAccessorsCallExpression.ts
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(6): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(5): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(8): ScopeFlags(Function)
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameClassExpressionLoop.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["_C_brand", "_classPrivateFieldInitSpec", "_classPrivateMethodInitSpec", "_myField", "array"]
|
||||
@@ -19481,48 +19473,11 @@ Symbol reference IDs mismatch for "Test":
|
||||
after transform: SymbolId(0): [ReferenceId(0)]
|
||||
rebuilt : SymbolId(5): []
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameMethodAsync.ts
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(2): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(6): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(5): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(9): ScopeFlags(Function)
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameStaticAccessorsCallExpression.ts
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(5): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(5): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(7): ScopeFlags(Function)
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameStaticFieldDestructuredBinding.ts
|
||||
Symbol reference IDs mismatch for "A":
|
||||
after transform: SymbolId(0): [ReferenceId(12), ReferenceId(0), ReferenceId(25), ReferenceId(28)]
|
||||
rebuilt : SymbolId(2): [ReferenceId(3), ReferenceId(16), ReferenceId(19)]
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameStaticsAndStaticMethods.ts
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(5): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(4): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(7): ScopeFlags(Function)
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNamesAndStaticMethods.ts
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(5): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(4): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(7): ScopeFlags(Function)
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNamesAssertion.ts
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(8): ScopeFlags(StrictMode)
|
||||
rebuilt : ScopeId(10): ScopeFlags(0x0)
|
||||
|
||||
semantic Error: tasks/coverage/typescript/tests/cases/conformance/classes/mixinAbstractClasses.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["AbstractBase", "ConcreteBase", "DerivedFromAbstract", "DerivedFromConcrete", "wasAbstract", "wasConcrete"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
commit: 3d34928e
|
||||
|
||||
Passed: 700/1165
|
||||
Passed: 703/1165
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-logical-assignment-operators
|
||||
@@ -192,7 +192,7 @@ x Output mismatch
|
||||
x Output mismatch
|
||||
|
||||
|
||||
# babel-plugin-transform-class-properties (212/269)
|
||||
# babel-plugin-transform-class-properties (213/269)
|
||||
* assumption-constantSuper/complex-super-class/input.js
|
||||
x Output mismatch
|
||||
|
||||
@@ -278,14 +278,6 @@ x Output mismatch
|
||||
* private/static-infer-name/input.js
|
||||
x Output mismatch
|
||||
|
||||
* private/static-self-method/input.js
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(4): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(4): ScopeFlags(Function)
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(6): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(6): ScopeFlags(Function)
|
||||
|
||||
* private/static-shadow/input.js
|
||||
x Output mismatch
|
||||
|
||||
@@ -415,12 +407,7 @@ x Output mismatch
|
||||
x Output mismatch
|
||||
|
||||
|
||||
# babel-plugin-transform-private-methods (46/148)
|
||||
* accessors/tagged-template/input.js
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode | Function | Arrow)
|
||||
rebuilt : ScopeId(4): ScopeFlags(Function | Arrow)
|
||||
|
||||
# babel-plugin-transform-private-methods (48/148)
|
||||
* accessors-loose/basic/input.js
|
||||
x Output mismatch
|
||||
|
||||
@@ -699,11 +686,6 @@ x Output mismatch
|
||||
* static-accessors/set-only-getter/input.js
|
||||
x Output mismatch
|
||||
|
||||
* static-accessors/tagged-template/input.js
|
||||
Scope flags mismatch:
|
||||
after transform: ScopeId(3): ScopeFlags(StrictMode | Function)
|
||||
rebuilt : ScopeId(4): ScopeFlags(Function)
|
||||
|
||||
* static-accessors-loose/basic/input.js
|
||||
x Output mismatch
|
||||
|
||||
|
||||
Reference in new issue
Block a user