fix(class-properties): replace new.target in static properties with undefined (#13560)
* fix(class-properties): replace `new.target` in static properties with `undefined` non-static prop is not affected fix #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>
This commit is contained in:
parent
6e57617138
commit
aa18da08cd
@ -1,4 +1,5 @@
|
|||||||
import { template, traverse, types as t } from "@babel/core";
|
import { template, traverse, types as t } from "@babel/core";
|
||||||
|
import type { NodePath } from "@babel/traverse";
|
||||||
import ReplaceSupers, {
|
import ReplaceSupers, {
|
||||||
environmentVisitor,
|
environmentVisitor,
|
||||||
} from "@babel/helper-replace-supers";
|
} from "@babel/helper-replace-supers";
|
||||||
@ -665,6 +666,19 @@ const thisContextVisitor = traverse.visitors.merge([
|
|||||||
state.needsClassRef = true;
|
state.needsClassRef = true;
|
||||||
path.replaceWith(t.cloneNode(state.classRef));
|
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,
|
environmentVisitor,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -2,7 +2,6 @@ class Base {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.Foo = class {
|
this.Foo = class {
|
||||||
static {
|
static {
|
||||||
// fixme: new.target should be undefined after transformed
|
|
||||||
this.foo = new.target;
|
this.foo = new.target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
12
packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/output.js
vendored
Normal file
12
packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/output.js
vendored
Normal file
@ -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()
|
||||||
20
packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/input.js
vendored
Normal file
20
packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/input.js
vendored
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/exec.js
vendored
Normal file
9
packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/exec.js
vendored
Normal file
@ -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 {
|
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() {
|
test = function() {
|
||||||
new.target;
|
new.target;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,6 +2,6 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
"transform-new-target",
|
"transform-new-target",
|
||||||
"transform-arrow-functions",
|
"transform-arrow-functions",
|
||||||
["proposal-class-properties", { "loose": true }]
|
["proposal-class-properties", { "loose": false }]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,33 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
constructor() {
|
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 instanceof _target ? this.constructor : void 0;
|
||||||
};
|
});
|
||||||
|
babelHelpers.defineProperty(this, "test2", function () {
|
||||||
this.test2 = function () {
|
|
||||||
_newtarget;
|
_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user