Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(class-properties): replace new.target in static properties with undefined #13560

Merged
merged 7 commits into from Jul 16, 2021
14 changes: 14 additions & 0 deletions packages/babel-helper-create-class-features-plugin/src/fields.ts
@@ -1,4 +1,5 @@
import { template, traverse, types as t } from "@babel/core";
import type { NodePath } from "@babel/traverse";
import ReplaceSupers, {
environmentVisitor,
} from "@babel/helper-replace-supers";
Expand Down Expand Up @@ -665,6 +666,19 @@ const thisContextVisitor = traverse.visitors.merge([
state.needsClassRef = true;
path.replaceWith(t.cloneNode(state.classRef));
},
MetaProperty(path: NodePath<t.MetaProperty>) {
const meta = path.get("meta");
const property = path.get("property");
const { scope } = path;
// if there are `new.target` in static field
// we should replace it with `undefined`
if (
meta.isIdentifier({ name: "new" }) &&
property.isIdentifier({ name: "target" })
) {
path.replaceWith(scope.buildUndefinedNode());
}
},
},
environmentVisitor,
]);
Expand Down
Expand Up @@ -2,7 +2,6 @@ class Base {
constructor() {
this.Foo = class {
static {
// fixme: new.target should be undefined after transformed
this.foo = new.target;
}
}
Expand Down
@@ -0,0 +1,12 @@
class Base {
constructor() {
var _class, _temp;

this.Foo = (_temp = _class = class {}, (() => {
_class.foo = void 0;
})(), _temp);
}

}

expect(new Base().Foo.foo).toBe(undefined);
@@ -0,0 +1,9 @@
class Foo {
constructor() {
this.Bar = class {
static p = new.target
}
}
}

expect((new Foo).Bar.p).toBeUndefined()
@@ -0,0 +1,20 @@
class Foo {
constructor() {
this.Bar = class {
static p = new.target
static p1 = class { constructor() { new.target } } // should not replace
static p2 = new function () { new.target } // should not replace
static p3 = () => { new.target } // should replace
static p4 = function () { new.target } // should not replace
q = new.target // should not replace
}
}

test = function() {
new.target;
};

test2 = () => {
new.target;
}
}
@@ -0,0 +1,7 @@
{
"plugins": [
"transform-new-target",
"transform-arrow-functions",
["proposal-class-properties", { "loose": true }]
]
}
@@ -0,0 +1,35 @@
class Foo {
constructor() {
var _newtarget = this.constructor,
_class,
_temp;

this.test = function _target() {
this instanceof _target ? this.constructor : void 0;
};

this.test2 = function () {
_newtarget;
};

this.Bar = (_temp = _class = class _target2 {
constructor() {
this.q = this.constructor;
} // should not replace


}, _class.p = void 0, _class.p1 = class _target3 {
constructor() {
this.constructor;
}

}, _class.p2 = new function _target4() {
this instanceof _target4 ? this.constructor : void 0;
}(), _class.p3 = function () {
void 0;
}, _class.p4 = function _target5() {
this instanceof _target5 ? this.constructor : void 0;
}, _temp);
}

}
@@ -0,0 +1,9 @@
class Foo {
constructor() {
this.Bar = class {
static p = new.target
}
}
}

expect((new Foo).Bar.p).toBeUndefined()
@@ -1,4 +1,15 @@
class Foo {
constructor() {
this.Bar = class {
static p = new.target
static p1 = class { constructor() { new.target } } // should not replace
static p2 = new function () { new.target } // should not replace
static p3 = () => { new.target } // should replace
static p4 = function () { new.target } // should not replace
q = new.target // should not replace
}
}

test = function() {
new.target;
};
Expand Down
Expand Up @@ -2,6 +2,6 @@
"plugins": [
"transform-new-target",
"transform-arrow-functions",
["proposal-class-properties", { "loose": true }]
["proposal-class-properties", { "loose": false }]
colinaaa marked this conversation as resolved.
Show resolved Hide resolved
]
}
@@ -1,14 +1,33 @@
class Foo {
constructor() {
var _newtarget = this.constructor;
var _newtarget = this.constructor,
_class,
_temp;

this.test = function _target() {
babelHelpers.defineProperty(this, "test", function _target() {
this instanceof _target ? this.constructor : void 0;
};

this.test2 = function () {
});
babelHelpers.defineProperty(this, "test2", function () {
_newtarget;
};
});
this.Bar = (_temp = _class = class _target2 {
constructor() {
babelHelpers.defineProperty(this, "q", this.constructor);
} // should not replace


}, babelHelpers.defineProperty(_class, "p", void 0), babelHelpers.defineProperty(_class, "p1", class _target3 {
constructor() {
this.constructor;
}

}), babelHelpers.defineProperty(_class, "p2", new function _target4() {
this instanceof _target4 ? this.constructor : void 0;
}()), babelHelpers.defineProperty(_class, "p3", function () {
void 0;
}), babelHelpers.defineProperty(_class, "p4", function _target5() {
this instanceof _target5 ? this.constructor : void 0;
}), _temp);
}

}