Extract computed keys from the class closure (#13600)

This commit is contained in:
Nicolò Ribaudo 2021-07-26 23:31:45 +02:00 committed by GitHub
parent 224a35c5c6
commit 790c5180d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 142 additions and 58 deletions

View File

@ -20,7 +20,7 @@ var Foo = /*#__PURE__*/function () {
_babelHelpers$classPr = babelHelpers.classPrivateFieldLooseBase(this, _foo2)[_foo2]; _babelHelpers$classPr = babelHelpers.classPrivateFieldLooseBase(this, _foo2)[_foo2];
var Nested = /*#__PURE__*/function () { var Nested = /*#__PURE__*/function (_babelHelpers$classPr2) {
function Nested() { function Nested() {
babelHelpers.classCallCheck(this, Nested); babelHelpers.classCallCheck(this, Nested);
Object.defineProperty(this, _foo2, { Object.defineProperty(this, _foo2, {
@ -30,11 +30,11 @@ var Foo = /*#__PURE__*/function () {
} }
babelHelpers.createClass(Nested, [{ babelHelpers.createClass(Nested, [{
key: _babelHelpers$classPr, key: _babelHelpers$classPr2,
value: function () {} value: function () {}
}]); }]);
return Nested; return Nested;
}(); }(_babelHelpers$classPr);
babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo]; babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo];
} }

View File

@ -14,19 +14,17 @@ var Foo = /*#__PURE__*/function () {
babelHelpers.createClass(Foo, [{ babelHelpers.createClass(Foo, [{
key: "test", key: "test",
value: function test() { value: function test() {
var _this = this; var Nested = /*#__PURE__*/function (_babelHelpers$classPr) {
var Nested = /*#__PURE__*/function () {
function Nested() { function Nested() {
babelHelpers.classCallCheck(this, Nested); babelHelpers.classCallCheck(this, Nested);
} }
babelHelpers.createClass(Nested, [{ babelHelpers.createClass(Nested, [{
key: babelHelpers.classPrivateFieldLooseBase(_this, _foo)[_foo], key: _babelHelpers$classPr,
value: function () {} value: function () {}
}]); }]);
return Nested; return Nested;
}(); }(babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo]);
babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo]; babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo];
} }

View File

@ -21,7 +21,7 @@ var Foo = /*#__PURE__*/function () {
_babelHelpers$classPr = babelHelpers.classPrivateFieldGet(this, _foo2); _babelHelpers$classPr = babelHelpers.classPrivateFieldGet(this, _foo2);
var Nested = /*#__PURE__*/function () { var Nested = /*#__PURE__*/function (_babelHelpers$classPr2) {
function Nested() { function Nested() {
babelHelpers.classCallCheck(this, Nested); babelHelpers.classCallCheck(this, Nested);
@ -32,11 +32,11 @@ var Foo = /*#__PURE__*/function () {
} }
babelHelpers.createClass(Nested, [{ babelHelpers.createClass(Nested, [{
key: _babelHelpers$classPr, key: _babelHelpers$classPr2,
value: function () {} value: function () {}
}]); }]);
return Nested; return Nested;
}(); }(_babelHelpers$classPr);
babelHelpers.classPrivateFieldGet(this, _foo); babelHelpers.classPrivateFieldGet(this, _foo);
} }

View File

@ -15,19 +15,17 @@ var Foo = /*#__PURE__*/function () {
babelHelpers.createClass(Foo, [{ babelHelpers.createClass(Foo, [{
key: "test", key: "test",
value: function test() { value: function test() {
var _this = this; var Nested = /*#__PURE__*/function (_babelHelpers$classPr) {
var Nested = /*#__PURE__*/function () {
function Nested() { function Nested() {
babelHelpers.classCallCheck(this, Nested); babelHelpers.classCallCheck(this, Nested);
} }
babelHelpers.createClass(Nested, [{ babelHelpers.createClass(Nested, [{
key: babelHelpers.classPrivateFieldGet(_this, _foo), key: _babelHelpers$classPr,
value: function () {} value: function () {}
}]); }]);
return Nested; return Nested;
}(); }(babelHelpers.classPrivateFieldGet(this, _foo));
babelHelpers.classPrivateFieldGet(this, _foo); babelHelpers.classPrivateFieldGet(this, _foo);
} }

View File

@ -15,7 +15,7 @@ _ref3 = /regex/;
_baz = baz; _baz = baz;
_ref4 = `template${expression}`; _ref4 = `template${expression}`;
var MyClass = /*#__PURE__*/function () { var MyClass = /*#__PURE__*/function (_computed3, _computed4, _ref5) {
"use strict"; "use strict";
function MyClass() { function MyClass() {
@ -36,20 +36,20 @@ var MyClass = /*#__PURE__*/function () {
get: function () {}, get: function () {},
set: function (value) {} set: function (value) {}
}, { }, {
key: _computed, key: _computed3,
get: function () {} get: function () {}
}, { }, {
key: _computed2, key: _computed4,
set: function (value) {} set: function (value) {}
}, { }, {
key: _ref2, key: _ref5,
value: function () {} value: function () {}
}], [{ }], [{
key: "10", key: "10",
value: function _() {} value: function _() {}
}]); }]);
return MyClass; return MyClass;
}(); }(_computed, _computed2, _ref2);
MyClass[_one] = "test"; MyClass[_one] = "test";
MyClass[2 * 4 + 7] = "247"; MyClass[2 * 4 + 7] = "247";

View File

@ -15,7 +15,7 @@ _ref3 = /regex/;
_baz = baz; _baz = baz;
_ref4 = `template${expression}`; _ref4 = `template${expression}`;
var MyClass = /*#__PURE__*/function () { var MyClass = /*#__PURE__*/function (_computed3, _computed4, _ref5) {
"use strict"; "use strict";
function MyClass() { function MyClass() {
@ -36,20 +36,20 @@ var MyClass = /*#__PURE__*/function () {
get: function () {}, get: function () {},
set: function (value) {} set: function (value) {}
}, { }, {
key: _computed, key: _computed3,
get: function () {} get: function () {}
}, { }, {
key: _computed2, key: _computed4,
set: function (value) {} set: function (value) {}
}, { }, {
key: _ref2, key: _ref5,
value: function () {} value: function () {}
}], [{ }], [{
key: "10", key: "10",
value: function _() {} value: function _() {}
}]); }]);
return MyClass; return MyClass;
}(); }(_computed, _computed2, _ref2);
babelHelpers.defineProperty(MyClass, _one, "test"); babelHelpers.defineProperty(MyClass, _one, "test");
babelHelpers.defineProperty(MyClass, 2 * 4 + 7, "247"); babelHelpers.defineProperty(MyClass, 2 * 4 + 7, "247");

View File

@ -4,7 +4,7 @@ var _class, _descriptor;
function dec() {} function dec() {}
let A = (_class = (_Symbol$search = Symbol.search, /*#__PURE__*/function () { let A = (_class = (_Symbol$search = Symbol.search, /*#__PURE__*/function (_Symbol$search2) {
"use strict"; "use strict";
function A() { function A() {
@ -13,11 +13,11 @@ let A = (_class = (_Symbol$search = Symbol.search, /*#__PURE__*/function () {
} }
babelHelpers.createClass(A, [{ babelHelpers.createClass(A, [{
key: _Symbol$search, key: _Symbol$search2,
value: function () {} value: function () {}
}]); }]);
return A; return A;
}()), (_descriptor = babelHelpers.applyDecoratedDescriptor(_class.prototype, "a", [dec], { }(_Symbol$search)), (_descriptor = babelHelpers.applyDecoratedDescriptor(_class.prototype, "a", [dec], {
configurable: true, configurable: true,
enumerable: true, enumerable: true,
writable: true, writable: true,

View File

@ -62,6 +62,8 @@ export default function transformClass(
protoAlias: null, protoAlias: null,
isLoose: false, isLoose: false,
dynamicKeys: new Map(),
methods: { methods: {
// 'list' is in the same order as the elements appear in the class body. // '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 // 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<string, t.Expression>;
node: t.Class;
scope: NodePath["scope"];
};
for (const elem of node.body.body) {
if (!t.isClassMethod(elem) || !elem.computed) continue;
if (scope.isPure(elem.key, /* constatns only*/ true)) continue;
const id = scope.generateUidIdentifierBasedOnNode(elem.key);
dynamicKeys.set(id.name, elem.key);
elem.key = id;
}
}
function setupClosureParamsArgs() { function setupClosureParamsArgs() {
const { superName } = classState; const { superName, dynamicKeys } = classState;
const closureParams = []; const closureParams = [];
const closureArgs = []; const closureArgs = [];
@ -623,6 +643,11 @@ export default function transformClass(
setState({ superName: t.cloneNode(param) }); setState({ superName: t.cloneNode(param) });
} }
for (const [name, value] of dynamicKeys) {
closureParams.push(t.identifier(name));
closureArgs.push(value);
}
return { closureParams, closureArgs }; return { closureParams, closureArgs };
} }
@ -668,6 +693,8 @@ export default function transformClass(
construct: buildConstructor(classRef, constructorBody, node), construct: buildConstructor(classRef, constructorBody, node),
}); });
extractDynamicKeys();
let { body } = classState; let { body } = classState;
const { closureParams, closureArgs } = setupClosureParamsArgs(); const { closureParams, closureArgs } = setupClosureParamsArgs();

View File

@ -1,4 +1,4 @@
let A = /*#__PURE__*/function () { let A = /*#__PURE__*/function (_x, _ref, _x2) {
"use strict"; "use strict";
function A() { function A() {
@ -6,14 +6,14 @@ let A = /*#__PURE__*/function () {
} }
babelHelpers.createClass(A, [{ babelHelpers.createClass(A, [{
key: x, key: _x,
get: function () {} get: function () {}
}, { }, {
key: (x = 2, 3), key: _ref,
value: function () {} value: function () {}
}, { }, {
key: x, key: _x2,
set: function (_) {} set: function (_) {}
}]); }]);
return A; return A;
}(); }(x, (x = 2, 3), x);

View File

@ -0,0 +1,5 @@
expect(() => {
class A {
[A.name]() {}
}
}).toThrow(ReferenceError);

View File

@ -0,0 +1,4 @@
{
"plugins": ["transform-classes"],
"minNodeVersion": "10.0.0"
}

View File

@ -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]);

View File

@ -0,0 +1,9 @@
async function* fn() {
class A {
[yield 1]() {}
}
class B extends A {
[await 1]() {}
}
}

View File

@ -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);
}

View File

@ -1,4 +1,4 @@
var Foo = /*#__PURE__*/function () { var Foo = /*#__PURE__*/function (_bar, _ref) {
"use strict"; "use strict";
function Foo() { function Foo() {
@ -11,11 +11,11 @@ var Foo = /*#__PURE__*/function () {
"second"; "second";
} }
}, { }, {
key: bar, key: _bar,
value: function value() {} value: function value() {}
}, { }, {
key: bar + "foo", key: _ref,
value: function value() {} value: function value() {}
}]); }]);
return Foo; return Foo;
}(); }(bar, bar + "foo");

View File

@ -11,21 +11,21 @@ var Foo = /*#__PURE__*/function (_Bar) {
babelHelpers.classCallCheck(this, Foo); babelHelpers.classCallCheck(this, Foo);
_this = _super.call(this); _this = _super.call(this);
var X = /*#__PURE__*/function () { var X = /*#__PURE__*/function (_ref) {
function X() { function X() {
babelHelpers.classCallCheck(this, X); babelHelpers.classCallCheck(this, X);
} }
babelHelpers.createClass(X, [{ babelHelpers.createClass(X, [{
key: (() => { key: _ref,
var _Foo;
babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Foo.prototype)), "method", _thisSuper).call(_thisSuper);
})(),
value: function value() {} value: function value() {}
}]); }]);
return X; return X;
}(); }((() => {
var _Foo;
babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Foo.prototype)), "method", _thisSuper).call(_thisSuper);
})());
return _this; return _this;
} }

View File

@ -16,25 +16,23 @@ var Outer = /*#__PURE__*/function (_Hello) {
var _super = babelHelpers.createSuper(Outer); var _super = babelHelpers.createSuper(Outer);
function Outer() { function Outer() {
var _this2 = this;
var _this; var _this;
babelHelpers.classCallCheck(this, Outer); babelHelpers.classCallCheck(this, Outer);
var Inner = /*#__PURE__*/function () { var Inner = /*#__PURE__*/function (_this2) {
function Inner() { function Inner() {
babelHelpers.classCallCheck(this, Inner); babelHelpers.classCallCheck(this, Inner);
} }
babelHelpers.createClass(Inner, [{ babelHelpers.createClass(Inner, [{
key: _this = _super.call(_this2), key: _this2,
value: function value() { value: function value() {
return 'hello'; return 'hello';
} }
}]); }]);
return Inner; return Inner;
}(); }(_this = _super.call(this));
return babelHelpers.possibleConstructorReturn(_this, new Inner()); return babelHelpers.possibleConstructorReturn(_this, new Inner());
} }

View File

@ -25,19 +25,19 @@ var Outer = /*#__PURE__*/function (_Hello) {
babelHelpers.classCallCheck(this, Outer); babelHelpers.classCallCheck(this, Outer);
_this = _super.call(this); _this = _super.call(this);
var Inner = /*#__PURE__*/function () { var Inner = /*#__PURE__*/function (_babelHelpers$get$cal) {
function Inner() { function Inner() {
babelHelpers.classCallCheck(this, Inner); babelHelpers.classCallCheck(this, Inner);
} }
babelHelpers.createClass(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() { value: function value() {
return 'hello'; return 'hello';
} }
}]); }]);
return Inner; return Inner;
}(); }(babelHelpers.get((_thisSuper = babelHelpers.assertThisInitialized(_this), babelHelpers.getPrototypeOf(Outer.prototype)), "toString", _thisSuper).call(_thisSuper));
return babelHelpers.possibleConstructorReturn(_this, new Inner()); return babelHelpers.possibleConstructorReturn(_this, new Inner());
} }

View File

@ -1,5 +1,5 @@
// #1649 // #1649
var Foo = /*#__PURE__*/function () { var Foo = /*#__PURE__*/function (_Symbol, _Symbol2) {
"use strict"; "use strict";
function Foo() { function Foo() {
@ -7,11 +7,11 @@ var Foo = /*#__PURE__*/function () {
} }
babelHelpers.createClass(Foo, [{ babelHelpers.createClass(Foo, [{
key: Symbol(), key: _Symbol,
value: function value() {} value: function value() {}
}, { }, {
key: Symbol(), key: _Symbol2,
value: function value() {} value: function value() {}
}]); }]);
return Foo; return Foo;
}(); }(Symbol(), Symbol());