diff --git a/packages/babel-helper-create-class-features-plugin/src/fields.ts b/packages/babel-helper-create-class-features-plugin/src/fields.ts index 29e94d746ef9..34c99c678c79 100644 --- a/packages/babel-helper-create-class-features-plugin/src/fields.ts +++ b/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"; @@ -665,6 +666,19 @@ const thisContextVisitor = traverse.visitors.merge([ state.needsClassRef = true; path.replaceWith(t.cloneNode(state.classRef)); }, + MetaProperty(path: NodePath) { + 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, ]); diff --git a/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/exec.js b/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/exec.js similarity index 100% rename from packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/exec.js rename to packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/exec.js diff --git a/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/input.js b/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/input.js similarity index 70% rename from packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/input.js rename to packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/input.js index 2ad952ab6667..f7328ab49571 100644 --- a/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/.new-target/input.js +++ b/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/input.js @@ -2,7 +2,6 @@ class Base { constructor() { this.Foo = class { static { - // fixme: new.target should be undefined after transformed this.foo = new.target; } } diff --git a/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/output.js b/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/output.js new file mode 100644 index 000000000000..9d1f4c6b03cd --- /dev/null +++ b/packages/babel-plugin-proposal-class-static-block/test/fixtures/integration/new-target/output.js @@ -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); diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/exec.js b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/exec.js new file mode 100644 index 000000000000..396babafae95 --- /dev/null +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/exec.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + this.Bar = class { + static p = new.target + } + } +} + +expect((new Foo).Bar.p).toBeUndefined() diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/input.js b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/input.js new file mode 100644 index 000000000000..0045e3f3d0ae --- /dev/null +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/input.js @@ -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; + } +} diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/options.json b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/options.json new file mode 100644 index 000000000000..fafe51d4fbf0 --- /dev/null +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "transform-new-target", + "transform-arrow-functions", + ["proposal-class-properties", { "loose": true }] + ] +} diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/output.js b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/output.js new file mode 100644 index 000000000000..a64af0349e52 --- /dev/null +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties-loose/output.js @@ -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); + } + +} diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/exec.js b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/exec.js new file mode 100644 index 000000000000..396babafae95 --- /dev/null +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/exec.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + this.Bar = class { + static p = new.target + } + } +} + +expect((new Foo).Bar.p).toBeUndefined() diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/input.js b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/input.js index bdd27d7a4910..0045e3f3d0ae 100644 --- a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/input.js +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/input.js @@ -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; }; diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/options.json b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/options.json index fafe51d4fbf0..e82809c94180 100644 --- a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/options.json +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/options.json @@ -2,6 +2,6 @@ "plugins": [ "transform-new-target", "transform-arrow-functions", - ["proposal-class-properties", { "loose": true }] + ["proposal-class-properties", { "loose": false }] ] } diff --git a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/output.js b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/output.js index 4aa6b556b902..50c1d35350a6 100644 --- a/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/output.js +++ b/packages/babel-plugin-transform-new-target/test/fixtures/general/class-properties/output.js @@ -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); } }