diff --git a/packages/babel-plugin-transform-classes/src/transformClass.ts b/packages/babel-plugin-transform-classes/src/transformClass.ts index fcaaac5445bc..7597b6a556f6 100644 --- a/packages/babel-plugin-transform-classes/src/transformClass.ts +++ b/packages/babel-plugin-transform-classes/src/transformClass.ts @@ -62,6 +62,8 @@ export default function transformClass( protoAlias: null, isLoose: false, + dynamicKeys: new Map(), + methods: { // 'list' is in the same order as the elements appear in the class body. // if there aren't computed keys, we can safely reorder class elements @@ -600,8 +602,26 @@ export default function transformClass( ); } + function extractDynamicKeys() { + const { dynamicKeys, node, scope } = classState as { + dynamicKeys: Map; + node: t.Class; + scope: NodePath["scope"]; + }; + + node.body.body.forEach(elem => { + if (!t.isClassMethod(elem) || !elem.computed) return; + if (scope.isPure(elem.key, /* constatns only*/ true)) return; + + const id = path.scope.generateUidIdentifierBasedOnNode(elem.key); + dynamicKeys.set(id.name, elem.key); + + elem.key = id; + }); + } + function setupClosureParamsArgs() { - const { superName } = classState; + const { superName, dynamicKeys } = classState; const closureParams = []; const closureArgs = []; @@ -623,6 +643,11 @@ export default function transformClass( setState({ superName: t.cloneNode(param) }); } + for (const [name, value] of dynamicKeys) { + closureParams.push(t.identifier(name)); + closureArgs.push(value); + } + return { closureParams, closureArgs }; } @@ -668,6 +693,8 @@ export default function transformClass( construct: buildConstructor(classRef, constructorBody, node), }); + extractDynamicKeys(); + let { body } = classState; const { closureParams, closureArgs } = setupClosureParamsArgs(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/change-computed-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/change-computed-key/output.js index 8e5ae962c606..a08a170daf74 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/get-set/change-computed-key/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/change-computed-key/output.js @@ -1,4 +1,4 @@ -let A = /*#__PURE__*/function () { +let A = /*#__PURE__*/function (_x, _ref, _x2) { "use strict"; function A() { @@ -6,14 +6,14 @@ let A = /*#__PURE__*/function () { } babelHelpers.createClass(A, [{ - key: x, + key: _x, get: function () {} }, { - key: (x = 2, 3), + key: _ref, value: function () {} }, { - key: x, + key: _x2, set: function (_) {} }]); return A; -}(); +}(x, (x = 2, 3), x); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-key-class-tdz/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-key-class-tdz/exec.js new file mode 100644 index 000000000000..afb11a7419e7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-key-class-tdz/exec.js @@ -0,0 +1,5 @@ +expect(() => { + class A { + [A.name]() {} + } +}).toThrow(ReferenceError); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-key-class-tdz/options.json b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-key-class-tdz/options.json new file mode 100644 index 000000000000..2e14e9fc86cb --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-key-class-tdz/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["transform-classes"], + "minNodeVersion": "10.0.0" +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-call-order/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-call-order/exec.js new file mode 100644 index 000000000000..f1e7372457c8 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-call-order/exec.js @@ -0,0 +1,11 @@ +var log = []; + +class A { + [log.push(1)]() {} + static [log.push(2)]() {} + [log.push(3)]() {} + static [log.push(4)]() {} +} + +expect(log).toEqual([1, 2, 3, 4]); + diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-yield-await/input.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-yield-await/input.js new file mode 100644 index 000000000000..c7995163ed03 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-yield-await/input.js @@ -0,0 +1,9 @@ +async function* fn() { + class A { + [yield 1]() {} + } + + class B extends A { + [await 1]() {} + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-yield-await/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-yield-await/output.js new file mode 100644 index 000000000000..aec80d976bac --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-keys-yield-await/output.js @@ -0,0 +1,34 @@ +async function* fn() { + var A = /*#__PURE__*/function (_yield$) { + "use strict"; + + function A() { + babelHelpers.classCallCheck(this, A); + } + + babelHelpers.createClass(A, [{ + key: _yield$, + value: function value() {} + }]); + return A; + }(yield 1); + + var B = /*#__PURE__*/function (_A, _await$) { + "use strict"; + + babelHelpers.inherits(B, _A); + + var _super = babelHelpers.createSuper(B); + + function B() { + babelHelpers.classCallCheck(this, B); + return _super.apply(this, arguments); + } + + babelHelpers.createClass(B, [{ + key: _await$, + value: function value() {} + }]); + return B; + }(A, await 1); +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-methods/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-methods/output.js index ef64056212c7..bc107f1a1b90 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-methods/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/computed-methods/output.js @@ -1,4 +1,4 @@ -var Foo = /*#__PURE__*/function () { +var Foo = /*#__PURE__*/function (_bar, _ref) { "use strict"; function Foo() { @@ -11,11 +11,11 @@ var Foo = /*#__PURE__*/function () { "second"; } }, { - key: bar, + key: _bar, value: function value() {} }, { - key: bar + "foo", + key: _ref, value: function value() {} }]); return Foo; -}(); +}(bar, bar + "foo"); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/name-collisions-with-class-ref-in-computed-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/name-collisions-with-class-ref-in-computed-key/output.js index 71b59391fdeb..84bdf2ee075c 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/spec/name-collisions-with-class-ref-in-computed-key/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/name-collisions-with-class-ref-in-computed-key/output.js @@ -11,21 +11,21 @@ var Foo = /*#__PURE__*/function (_Bar) { babelHelpers.classCallCheck(this, Foo); _this = _super.call(this); - var X = /*#__PURE__*/function () { + var X = /*#__PURE__*/function (_ref) { function X() { babelHelpers.classCallCheck(this, X); } babelHelpers.createClass(X, [{ - key: (() => { - var _Foo; - - babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Foo.prototype)), "method", _thisSuper).call(_thisSuper); - })(), + key: _ref, value: function value() {} }]); return X; - }(); + }((() => { + var _Foo; + + babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Foo.prototype)), "method", _thisSuper).call(_thisSuper); + })()); return _this; } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js index fe4902958d94..b1e76457cf36 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js @@ -16,25 +16,23 @@ var Outer = /*#__PURE__*/function (_Hello) { var _super = babelHelpers.createSuper(Outer); function Outer() { - var _this2 = this; - var _this; babelHelpers.classCallCheck(this, Outer); - var Inner = /*#__PURE__*/function () { + var Inner = /*#__PURE__*/function (_this2) { function Inner() { babelHelpers.classCallCheck(this, Inner); } babelHelpers.createClass(Inner, [{ - key: _this = _super.call(_this2), + key: _this2, value: function value() { return 'hello'; } }]); return Inner; - }(); + }(_this = _super.call(this)); return babelHelpers.possibleConstructorReturn(_this, new Inner()); } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js index 9b3145d21416..bf1411294fe7 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js @@ -25,19 +25,19 @@ var Outer = /*#__PURE__*/function (_Hello) { babelHelpers.classCallCheck(this, Outer); _this = _super.call(this); - var Inner = /*#__PURE__*/function () { + var Inner = /*#__PURE__*/function (_babelHelpers$get$cal) { function Inner() { babelHelpers.classCallCheck(this, Inner); } babelHelpers.createClass(Inner, [{ - key: babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Outer.prototype)), "toString", _thisSuper).call(_thisSuper), + key: _babelHelpers$get$cal, value: function value() { return 'hello'; } }]); return Inner; - }(); + }(babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Outer.prototype)), "toString", _thisSuper).call(_thisSuper)); return babelHelpers.possibleConstructorReturn(_this, new Inner()); } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/relaxed-method-coercion/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/relaxed-method-coercion/output.js index 5d9a2b9a2e46..6379fd21f1c1 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/spec/relaxed-method-coercion/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/relaxed-method-coercion/output.js @@ -1,5 +1,5 @@ // #1649 -var Foo = /*#__PURE__*/function () { +var Foo = /*#__PURE__*/function (_Symbol, _Symbol2) { "use strict"; function Foo() { @@ -7,11 +7,11 @@ var Foo = /*#__PURE__*/function () { } babelHelpers.createClass(Foo, [{ - key: Symbol(), + key: _Symbol, value: function value() {} }, { - key: Symbol(), + key: _Symbol2, value: function value() {} }]); return Foo; -}(); +}(Symbol(), Symbol());