Skip to content

Commit aa18da0

Browse files
fix(class-properties): replace new.target in static properties with undefined (babel#13560)
* fix(class-properties): replace `new.target` in static properties with `undefined` non-static prop is not affected fix babel#12737 * Update packages/babel-helper-create-class-features-plugin/src/fields.ts fix typo Co-authored-by: Brian Ng <bng412@gmail.com> * fix: add loose test case and fix replace condition * test: add new.target tests for static block * feat: move new-target replace into thisContextVisitor defaults to replace new.target, do not replace within function * feat: simplify thisContextVisitor remove function visitor since environmentVisitor is skipping arrow function * test: remove unused fixme comments Co-authored-by: Brian Ng <bng412@gmail.com>
1 parent 6e57617 commit aa18da0

12 files changed

Lines changed: 143 additions & 8 deletions

File tree

packages/babel-helper-create-class-features-plugin/src/fields.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { template, traverse, types as t } from "@babel/core";
2+
import type { NodePath } from "@babel/traverse";
23
import ReplaceSupers, {
34
environmentVisitor,
45
} from "@babel/helper-replace-supers";
@@ -665,6 +666,19 @@ const thisContextVisitor = traverse.visitors.merge([
665666
state.needsClassRef = true;
666667
path.replaceWith(t.cloneNode(state.classRef));
667668
},
669+
MetaProperty(path: NodePath<t.MetaProperty>) {
670+
const meta = path.get("meta");
671+
const property = path.get("property");
672+
const { scope } = path;
673+
// if there are `new.target` in static field
674+
// we should replace it with `undefined`
675+
if (
676+
meta.isIdentifier({ name: "new" }) &&
677+
property.isIdentifier({ name: "target" })
678+
) {
679+
path.replaceWith(scope.buildUndefinedNode());
680+
}
681+
},
668682
},
669683
environmentVisitor,
670684
]);

packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/exec.js renamed to packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/exec.js

File renamed without changes.

packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/input.js renamed to packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/input.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ class Base {
22
constructor() {
33
this.Foo = class {
44
static {
5-
// fixme: new.target should be undefined after transformed
65
this.foo = new.target;
76
}
87
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Base {
2+
constructor() {
3+
var _class, _temp;
4+
5+
this.Foo = (_temp = _class = class {}, (() => {
6+
_class.foo = void 0;
7+
})(), _temp);
8+
}
9+
10+
}
11+
12+
expect(new Base().Foo.foo).toBe(undefined);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Foo {
2+
constructor() {
3+
this.Bar = class {
4+
static p = new.target
5+
}
6+
}
7+
}
8+
9+
expect((new Foo).Bar.p).toBeUndefined()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Foo {
2+
constructor() {
3+
this.Bar = class {
4+
static p = new.target
5+
static p1 = class { constructor() { new.target } } // should not replace
6+
static p2 = new function () { new.target } // should not replace
7+
static p3 = () => { new.target } // should replace
8+
static p4 = function () { new.target } // should not replace
9+
q = new.target // should not replace
10+
}
11+
}
12+
13+
test = function() {
14+
new.target;
15+
};
16+
17+
test2 = () => {
18+
new.target;
19+
}
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"plugins": [
3+
"transform-new-target",
4+
"transform-arrow-functions",
5+
["proposal-class-properties", { "loose": true }]
6+
]
7+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class Foo {
2+
constructor() {
3+
var _newtarget = this.constructor,
4+
_class,
5+
_temp;
6+
7+
this.test = function _target() {
8+
this instanceof _target ? this.constructor : void 0;
9+
};
10+
11+
this.test2 = function () {
12+
_newtarget;
13+
};
14+
15+
this.Bar = (_temp = _class = class _target2 {
16+
constructor() {
17+
this.q = this.constructor;
18+
} // should not replace
19+
20+
21+
}, _class.p = void 0, _class.p1 = class _target3 {
22+
constructor() {
23+
this.constructor;
24+
}
25+
26+
}, _class.p2 = new function _target4() {
27+
this instanceof _target4 ? this.constructor : void 0;
28+
}(), _class.p3 = function () {
29+
void 0;
30+
}, _class.p4 = function _target5() {
31+
this instanceof _target5 ? this.constructor : void 0;
32+
}, _temp);
33+
}
34+
35+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Foo {
2+
constructor() {
3+
this.Bar = class {
4+
static p = new.target
5+
}
6+
}
7+
}
8+
9+
expect((new Foo).Bar.p).toBeUndefined()

packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/input.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
class Foo {
2+
constructor() {
3+
this.Bar = class {
4+
static p = new.target
5+
static p1 = class { constructor() { new.target } } // should not replace
6+
static p2 = new function () { new.target } // should not replace
7+
static p3 = () => { new.target } // should replace
8+
static p4 = function () { new.target } // should not replace
9+
q = new.target // should not replace
10+
}
11+
}
12+
213
test = function() {
314
new.target;
415
};

0 commit comments

Comments
 (0)