mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(transformer/class-properties): use UID for args in created class constructor (#7866)
When creating class constructor for a class which has super class, use UID `_args` for temp var (rather than `args`). This avoids shadowing a var called `args` used in an instance property initializer. This diverges from Babel. Babel uses `args` unless it finds a var called `args` in an instance property initializer. But searching the AST of initializers can be fairly expensive, so it's better to skip it. The overrides for test fixtures included in this PR are just to account for that difference.
This commit is contained in:
parent
0b67b37584
commit
c0576faf80
14 changed files with 125 additions and 19 deletions
|
|
@ -228,17 +228,12 @@ impl<'a, 'ctx> ClassProperties<'a, 'ctx> {
|
|||
let has_super_class = class.super_class.is_some();
|
||||
let mut stmts = ctx.ast.vec_with_capacity(inits.len() + usize::from(has_super_class));
|
||||
|
||||
// Add `super(...args);` statement and `...args` param if class has a super class.
|
||||
// `constructor(...args) { super(...args); /* prop initialization */ }`
|
||||
// TODO: One of initializers could access a var called `args` from outer scope.
|
||||
// Use a UID `_args` instead of `args` here.
|
||||
// Add `super(..._args);` statement and `..._args` param if class has a super class.
|
||||
// `constructor(..._args) { super(..._args); /* prop initialization */ }`
|
||||
let mut params_rest = None;
|
||||
if has_super_class {
|
||||
let args_binding = ctx.generate_binding(
|
||||
Atom::from("args"),
|
||||
constructor_scope_id,
|
||||
SymbolFlags::FunctionScopedVariable,
|
||||
);
|
||||
let args_binding =
|
||||
ctx.generate_uid("args", constructor_scope_id, SymbolFlags::FunctionScopedVariable);
|
||||
params_rest = Some(
|
||||
ctx.ast.alloc_binding_rest_element(SPAN, args_binding.create_binding_pattern(ctx)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
class A extends B {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
babelHelpers.defineProperty(this, "foo", super.bar);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class Foo extends Bar {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
this.bar = "foo";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class A {
|
||||
foo() {
|
||||
return "bar";
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
this.foo = super.foo();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
var _prop = babelHelpers.classPrivateFieldLooseKey("prop");
|
||||
class Foo {
|
||||
constructor() {
|
||||
Object.defineProperty(this, _prop, {
|
||||
writable: true,
|
||||
value: "foo"
|
||||
});
|
||||
}
|
||||
}
|
||||
var _prop2 = babelHelpers.classPrivateFieldLooseKey("prop");
|
||||
class Bar extends Foo {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
Object.defineProperty(this, _prop2, {
|
||||
writable: true,
|
||||
value: "bar"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
var _foo = /*#__PURE__*/babelHelpers.classPrivateFieldLooseKey("foo");
|
||||
var _foo = babelHelpers.classPrivateFieldLooseKey("foo");
|
||||
class Foo {
|
||||
constructor() {
|
||||
Object.defineProperty(this, _foo, {
|
||||
|
|
@ -9,8 +9,8 @@ class Foo {
|
|||
test() {
|
||||
var _foo3;
|
||||
let _this$foo;
|
||||
var _foo2 = /*#__PURE__*/babelHelpers.classPrivateFieldLooseKey("foo");
|
||||
class Nested extends (_foo3 = /*#__PURE__*/babelHelpers.classPrivateFieldLooseKey("foo"), _this$foo = babelHelpers.classPrivateFieldLooseBase(this, _foo3)[_foo3], class {
|
||||
var _foo2 = babelHelpers.classPrivateFieldLooseKey("foo");
|
||||
class Nested extends (_foo3 = babelHelpers.classPrivateFieldLooseKey("foo"), _this$foo = babelHelpers.classPrivateFieldLooseBase(this, _foo3)[_foo3], class {
|
||||
constructor() {
|
||||
Object.defineProperty(this, _foo3, {
|
||||
writable: true,
|
||||
|
|
@ -19,8 +19,8 @@ class Foo {
|
|||
this[_this$foo] = 2;
|
||||
}
|
||||
}) {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
Object.defineProperty(this, _foo2, {
|
||||
writable: true,
|
||||
value: 3
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
var _prop = new WeakMap();
|
||||
class Foo {
|
||||
constructor() {
|
||||
babelHelpers.classPrivateFieldInitSpec(this, _prop, "foo");
|
||||
}
|
||||
}
|
||||
var _prop2 = new WeakMap();
|
||||
class Bar extends Foo {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
babelHelpers.classPrivateFieldInitSpec(this, _prop2, "bar");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
class A {
|
||||
foo() {
|
||||
return "bar";
|
||||
}
|
||||
}
|
||||
var _foo = new WeakMap();
|
||||
class B extends A {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
babelHelpers.classPrivateFieldInitSpec(this, _foo, super.foo());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class Foo extends Bar {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
this.bar = "foo";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class A {
|
||||
foo() {
|
||||
return "bar";
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
this.foo = super.foo();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class Foo extends Bar {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
babelHelpers.defineProperty(this, "bar", "foo");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class A {
|
||||
foo() {
|
||||
return "bar";
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
babelHelpers.defineProperty(this, "foo", super.foo());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
class Test {
|
||||
constructor() {
|
||||
var _Other;
|
||||
class Other extends Test {
|
||||
constructor(..._args) {
|
||||
super(..._args);
|
||||
babelHelpers.defineProperty(this, "a", () => super.test);
|
||||
}
|
||||
}
|
||||
_Other = Other;
|
||||
babelHelpers.defineProperty(Other, "a", () => babelHelpers.superPropGet(_Other, "test", _Other));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
commit: 54a8389f
|
||||
|
||||
Passed: 581/927
|
||||
Passed: 582/927
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-class-static-block
|
||||
|
|
@ -276,7 +276,7 @@ x Output mismatch
|
|||
x Output mismatch
|
||||
|
||||
|
||||
# babel-plugin-transform-class-properties (193/264)
|
||||
# babel-plugin-transform-class-properties (194/264)
|
||||
* assumption-constantSuper/complex-super-class/input.js
|
||||
x Output mismatch
|
||||
|
||||
|
|
@ -499,9 +499,6 @@ x Output mismatch
|
|||
* regression/6153/input.js
|
||||
x Output mismatch
|
||||
|
||||
* regression/7951/input.mjs
|
||||
x Output mismatch
|
||||
|
||||
|
||||
# babel-plugin-transform-nullish-coalescing-operator (5/12)
|
||||
* assumption-noDocumentAll/transform/input.js
|
||||
|
|
|
|||
Loading…
Reference in a new issue