diff --git a/crates/oxc_transformer/src/es2022/class_properties/constructor.rs b/crates/oxc_transformer/src/es2022/class_properties/constructor.rs index 1b7dfafc0641a..c4cdca20da24a 100644 --- a/crates/oxc_transformer/src/es2022/class_properties/constructor.rs +++ b/crates/oxc_transformer/src/es2022/class_properties/constructor.rs @@ -87,6 +87,7 @@ //! Oxc output: //! ```js //! let _super = function() { +//! "use strict"; //! this.prop = foo(); //! return this; //! }; @@ -95,7 +96,7 @@ //! } //! ``` //! -//! ESBuild does not `super()` in constructor params correctly: +//! ESBuild does not handle `super()` in constructor params correctly: //! [ESBuild REPL](https://esbuild.github.io/try/#dAAwLjI0LjAALS10YXJnZXQ9ZXMyMDIwAGNsYXNzIEMgZXh0ZW5kcyBTIHsKICBwcm9wID0gZm9vKCk7CiAgY29uc3RydWN0b3IoeCA9IHN1cGVyKCksIHkgPSBzdXBlcigpKSB7fQp9Cg) use oxc_allocator::Vec as ArenaVec; @@ -407,8 +408,20 @@ impl<'a, 'c> ConstructorParamsSuperReplacer<'a, 'c> { let super_func_scope_id = ctx.scopes_mut().add_scope( Some(outer_scope_id), NodeId::DUMMY, - ScopeFlags::Function | ScopeFlags::Arrow | ScopeFlags::StrictMode, + ScopeFlags::Function | ScopeFlags::StrictMode, ); + + // Add `"use strict"` directive if outer scope is not strict mode + let directives = if ctx.scopes().get_flags(outer_scope_id).is_strict_mode() { + ctx.ast.vec() + } else { + ctx.ast.vec1(ctx.ast.directive( + SPAN, + ctx.ast.string_literal(SPAN, Atom::from("use strict"), None), + Atom::from("use strict"), + )) + }; + // `return this;` let return_stmt = ctx.ast.statement_return(SPAN, Some(ctx.ast.expression_this(SPAN))); // `; return this;` @@ -430,7 +443,7 @@ impl<'a, 'c> ConstructorParamsSuperReplacer<'a, 'c> { NONE, ), NONE, - Some(ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), body_stmts)), + Some(ctx.ast.alloc_function_body(SPAN, directives, body_stmts)), super_func_scope_id, )) } diff --git a/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-complex/output.js b/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-complex/output.js index 9c789497f69fd..81b3631788f12 100644 --- a/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-complex/output.js +++ b/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-complex/output.js @@ -1,4 +1,5 @@ let _super = function() { + "use strict"; babelHelpers.defineProperty(this, "bar", "foo"); return this; }; diff --git a/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-in-arrow/output.js b/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-in-arrow/output.js index 48b8e56378f94..5a4f1154f4463 100644 --- a/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-in-arrow/output.js +++ b/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params-in-arrow/output.js @@ -1,4 +1,5 @@ let _super = function() { + "use strict"; babelHelpers.defineProperty(this, "bar", "foo"); return this; }; diff --git a/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params/output.js b/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params/output.js index 985fbb012ab07..a78c74e145944 100644 --- a/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params/output.js +++ b/tasks/transform_conformance/overrides/babel-plugin-transform-class-properties/test/fixtures/public/derived-super-in-default-params/output.js @@ -1,4 +1,5 @@ let _super = function() { + "use strict"; babelHelpers.defineProperty(this, "bar", "foo"); return this; }; diff --git a/tasks/transform_conformance/snapshots/babel.snap.md b/tasks/transform_conformance/snapshots/babel.snap.md index 73697f9a71a30..d032130e08c84 100644 --- a/tasks/transform_conformance/snapshots/babel.snap.md +++ b/tasks/transform_conformance/snapshots/babel.snap.md @@ -822,25 +822,16 @@ x Output mismatch x Output mismatch * public/derived-super-in-default-params/input.js -Scope flags mismatch: -after transform: ScopeId(3): ScopeFlags(StrictMode | Function | Arrow) -rebuilt : ScopeId(1): ScopeFlags(Function) Symbol flags mismatch for "_super": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) * public/derived-super-in-default-params-complex/input.js -Scope flags mismatch: -after transform: ScopeId(3): ScopeFlags(StrictMode | Function | Arrow) -rebuilt : ScopeId(1): ScopeFlags(Function) Symbol flags mismatch for "_super": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) * public/derived-super-in-default-params-in-arrow/input.js -Scope flags mismatch: -after transform: ScopeId(4): ScopeFlags(StrictMode | Function | Arrow) -rebuilt : ScopeId(1): ScopeFlags(Function) Symbol flags mismatch for "_super": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index 28790404a475c..057c5cafb8614 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -1,9 +1,8 @@ commit: 54a8389f -Passed: 94/105 +Passed: 94/106 # All Passed: -* babel-plugin-transform-class-properties * babel-plugin-transform-class-static-block * babel-plugin-transform-nullish-coalescing-operator * babel-plugin-transform-optional-catch-binding @@ -16,6 +15,16 @@ Passed: 94/105 * regexp +# babel-plugin-transform-class-properties (1/2) +* super-in-constructor-strict/input.js +Symbol flags mismatch for "_super": +after transform: SymbolId(6): SymbolFlags(FunctionScopedVariable) +rebuilt : SymbolId(1): SymbolFlags(BlockScopedVariable) +Symbol flags mismatch for "_super2": +after transform: SymbolId(7): SymbolFlags(FunctionScopedVariable) +rebuilt : SymbolId(5): SymbolFlags(BlockScopedVariable) + + # babel-plugin-transform-async-to-generator (14/15) * super/nested/input.js x Output mismatch diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-class-properties/test/fixtures/super-in-constructor-strict/input.js b/tasks/transform_conformance/tests/babel-plugin-transform-class-properties/test/fixtures/super-in-constructor-strict/input.js new file mode 100644 index 0000000000000..c10afb85cbdc4 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-class-properties/test/fixtures/super-in-constructor-strict/input.js @@ -0,0 +1,14 @@ +function sloppy() { + class C extends S { + prop = 1; + constructor(x = super()) {} + } +} + +function strict() { + "use strict"; + class C extends S { + prop = 1; + constructor(x = super()) {} + } +} diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-class-properties/test/fixtures/super-in-constructor-strict/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-class-properties/test/fixtures/super-in-constructor-strict/output.js new file mode 100644 index 0000000000000..0788916eddfe9 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-class-properties/test/fixtures/super-in-constructor-strict/output.js @@ -0,0 +1,21 @@ +function sloppy() { + let _super = function() { + "use strict"; + babelHelpers.defineProperty(this, "prop", 1); + return this; + }; + class C extends S { + constructor(x = _super.call(super())) {} + } +} + +function strict() { + "use strict"; + let _super2 = function() { + babelHelpers.defineProperty(this, "prop", 1); + return this; + }; + class C extends S { + constructor(x = _super2.call(super())) {} + } +}