Install static fields and private methods on the correct class
This commit is contained in:
parent
c78320d1a7
commit
00f94dc88a
@ -2052,3 +2052,9 @@ if (!process.env.BABEL_8_BREAKING) {
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
helpers.identity = helper("7.16.7")`
|
||||
export default function _identity(x) {
|
||||
return x;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { NodePath } from "@babel/traverse";
|
||||
import { types as t } from "@babel/core";
|
||||
import { types as t, template } from "@babel/core";
|
||||
import syntaxDecorators from "@babel/plugin-syntax-decorators";
|
||||
import ReplaceSupers from "@babel/helper-replace-supers";
|
||||
import * as charCodes from "charcodes";
|
||||
@ -447,6 +447,19 @@ function isClassDecoratableElementPath(
|
||||
);
|
||||
}
|
||||
|
||||
function staticBlockToIIFE(block: t.StaticBlock) {
|
||||
return t.callExpression(
|
||||
t.arrowFunctionExpression([], t.blockStatement(block.body)),
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
function maybeSequenceExpression(exprs: t.Expression[]) {
|
||||
if (exprs.length === 0) return t.unaryExpression("void", t.numericLiteral(0));
|
||||
if (exprs.length === 1) return exprs[0];
|
||||
return t.sequenceExpression(exprs);
|
||||
}
|
||||
|
||||
function transformClass(
|
||||
path: NodePath<t.ClassExpression | t.ClassDeclaration>,
|
||||
state: any,
|
||||
@ -836,38 +849,6 @@ function transformClass(
|
||||
locals.push(staticInitLocal);
|
||||
}
|
||||
|
||||
const staticBlock = t.staticBlock(
|
||||
[
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
t.arrayPattern(locals),
|
||||
t.callExpression(state.addHelper("applyDecs"), [
|
||||
t.thisExpression(),
|
||||
elementDecorations,
|
||||
classDecorations,
|
||||
]),
|
||||
),
|
||||
),
|
||||
requiresStaticInit &&
|
||||
t.expressionStatement(
|
||||
t.callExpression(t.cloneNode(staticInitLocal), [t.thisExpression()]),
|
||||
),
|
||||
].filter(v => v),
|
||||
);
|
||||
|
||||
path.node.body.body.unshift(staticBlock as unknown as ClassElement);
|
||||
|
||||
if (classInitLocal) {
|
||||
path.node.body.body.push(
|
||||
t.staticBlock([
|
||||
t.expressionStatement(
|
||||
t.callExpression(t.cloneNode(classInitLocal), []),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
if (decoratedPrivateMethods.size > 0) {
|
||||
path.traverse({
|
||||
PrivateName(path) {
|
||||
@ -902,6 +883,116 @@ function transformClass(
|
||||
});
|
||||
}
|
||||
|
||||
let classInitInjected = false;
|
||||
const classInitCall =
|
||||
classInitLocal && t.callExpression(t.cloneNode(classInitLocal), []);
|
||||
|
||||
const originalClass = path.node;
|
||||
|
||||
if (classDecorators) {
|
||||
const statics = [];
|
||||
let staticBlocks: t.StaticBlock[] = [];
|
||||
path.get("body.body").forEach(element => {
|
||||
// Static blocks cannot be compiled to "instance blocks", but we can inline
|
||||
// them as IIFEs in the next property.
|
||||
if (element.isStaticBlock()) {
|
||||
staticBlocks.push(element.node);
|
||||
element.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const isProperty =
|
||||
element.isClassProperty() || element.isClassPrivateProperty();
|
||||
|
||||
if (
|
||||
(isProperty || element.isClassPrivateMethod()) &&
|
||||
element.node.static
|
||||
) {
|
||||
if (isProperty && staticBlocks.length > 0) {
|
||||
const allValues: t.Expression[] = staticBlocks.map(staticBlockToIIFE);
|
||||
if (element.node.value) allValues.push(element.node.value);
|
||||
element.node.value = maybeSequenceExpression(allValues);
|
||||
staticBlocks = [];
|
||||
}
|
||||
|
||||
element.node.static = false;
|
||||
statics.push(element.node);
|
||||
element.remove();
|
||||
}
|
||||
});
|
||||
|
||||
if (statics.length > 0 || staticBlocks.length > 0) {
|
||||
const staticsClass = template.expression.ast`
|
||||
class extends ${state.addHelper("identity")} {}
|
||||
` as t.ClassExpression;
|
||||
staticsClass.body.body = [
|
||||
t.staticBlock([t.toStatement(path.node, false)]),
|
||||
...statics,
|
||||
];
|
||||
|
||||
const constructorBody: t.Expression[] = [];
|
||||
|
||||
const newExpr = t.newExpression(staticsClass, []);
|
||||
|
||||
if (staticBlocks.length > 0) {
|
||||
constructorBody.push(...staticBlocks.map(staticBlockToIIFE));
|
||||
}
|
||||
if (classInitCall) {
|
||||
classInitInjected = true;
|
||||
constructorBody.push(classInitCall);
|
||||
}
|
||||
if (constructorBody.length > 0) {
|
||||
constructorBody.unshift(
|
||||
t.callExpression(t.super(), [t.cloneNode(classLocal)]),
|
||||
);
|
||||
|
||||
staticsClass.body.body.push(
|
||||
t.classMethod(
|
||||
"constructor",
|
||||
t.identifier("constructor"),
|
||||
[],
|
||||
t.blockStatement([
|
||||
t.expressionStatement(t.sequenceExpression(constructorBody)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
newExpr.arguments.push(t.cloneNode(classLocal));
|
||||
}
|
||||
|
||||
path.replaceWith(newExpr);
|
||||
}
|
||||
}
|
||||
if (!classInitInjected && classInitCall) {
|
||||
path.node.body.body.push(
|
||||
t.staticBlock([t.expressionStatement(classInitCall)]),
|
||||
);
|
||||
}
|
||||
|
||||
originalClass.body.body.unshift(
|
||||
t.staticBlock(
|
||||
[
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
t.arrayPattern(locals),
|
||||
t.callExpression(state.addHelper("applyDecs"), [
|
||||
t.thisExpression(),
|
||||
elementDecorations,
|
||||
classDecorations,
|
||||
]),
|
||||
),
|
||||
),
|
||||
requiresStaticInit &&
|
||||
t.expressionStatement(
|
||||
t.callExpression(t.cloneNode(staticInitLocal), [
|
||||
t.thisExpression(),
|
||||
]),
|
||||
),
|
||||
].filter(Boolean),
|
||||
),
|
||||
);
|
||||
|
||||
// Recrawl the scope to make sure new identifiers are properly synced
|
||||
path.scope.crawl();
|
||||
|
||||
|
||||
@ -1,33 +1,37 @@
|
||||
var _initClass, _initClass2;
|
||||
var _initClass, _temp2, _initClass2, _temp4;
|
||||
|
||||
let _Foo;
|
||||
|
||||
class Foo {}
|
||||
new (_temp2 = class extends babelHelpers.identity {
|
||||
constructor() {
|
||||
var _temp;
|
||||
|
||||
(() => {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(Foo, [], [dec]);
|
||||
})();
|
||||
(_temp = super(_Foo), babelHelpers.defineProperty(this, "field", 123), _temp), _initClass();
|
||||
}
|
||||
|
||||
babelHelpers.defineProperty(Foo, "field", 123);
|
||||
}, (() => {
|
||||
class Foo {}
|
||||
|
||||
(() => {
|
||||
_initClass();
|
||||
})();
|
||||
(() => {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(Foo, [], [dec]);
|
||||
})();
|
||||
})(), _temp2)();
|
||||
|
||||
let _Bar;
|
||||
|
||||
class Bar extends _Foo {}
|
||||
new (_temp4 = class extends babelHelpers.identity {
|
||||
constructor() {
|
||||
var _temp3;
|
||||
|
||||
(() => {
|
||||
[_Bar, _initClass2] = babelHelpers.applyDecs(Bar, [], [dec]);
|
||||
})();
|
||||
(_temp3 = super(_Bar), babelHelpers.defineProperty(this, "field", ((() => {
|
||||
this.otherField = 456;
|
||||
})(), 123)), _temp3), _initClass2();
|
||||
}
|
||||
|
||||
(() => {
|
||||
Bar.otherField = 456;
|
||||
})();
|
||||
}, (() => {
|
||||
class Bar extends _Foo {}
|
||||
|
||||
babelHelpers.defineProperty(Bar, "field", 123);
|
||||
|
||||
(() => {
|
||||
_initClass2();
|
||||
})();
|
||||
(() => {
|
||||
[_Bar, _initClass2] = babelHelpers.applyDecs(Bar, [], [dec]);
|
||||
})();
|
||||
})(), _temp4)();
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
let hasX, hasM, OriginalFoo;
|
||||
|
||||
class Bar {}
|
||||
|
||||
function dec(Foo) {
|
||||
OriginalFoo = Foo;
|
||||
return Bar;
|
||||
}
|
||||
|
||||
@dec
|
||||
class Foo {
|
||||
static #x;
|
||||
static #m() {}
|
||||
|
||||
static x;
|
||||
static m() {}
|
||||
|
||||
static {
|
||||
hasX = o => #x in o;
|
||||
hasM = o => #m in o;
|
||||
}
|
||||
}
|
||||
|
||||
expect(hasX(Bar)).toBe(true);
|
||||
expect(hasM(Bar)).toBe(true);
|
||||
expect(hasX(OriginalFoo)).toBe(false);
|
||||
expect(hasM(OriginalFoo)).toBe(false);
|
||||
|
||||
expect(Bar.hasOwnProperty("x")).toBe(true);
|
||||
expect(OriginalFoo.hasOwnProperty("x")).toBe(false);
|
||||
|
||||
expect(Bar.hasOwnProperty("m")).toBe(false);
|
||||
expect(OriginalFoo.hasOwnProperty("m")).toBe(true);
|
||||
@ -0,0 +1,15 @@
|
||||
let hasX, hasM;
|
||||
|
||||
@dec
|
||||
class Foo {
|
||||
static #x;
|
||||
static #m() {}
|
||||
|
||||
static x;
|
||||
static m() {}
|
||||
|
||||
static {
|
||||
hasX = o => #x in o;
|
||||
hasM = o => #m in o;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
var _initClass, _x, _m, _temp2;
|
||||
|
||||
let hasX, hasM;
|
||||
|
||||
let _Foo;
|
||||
|
||||
new (_temp2 = (_x = /*#__PURE__*/new WeakMap(), _m = /*#__PURE__*/new WeakSet(), class extends babelHelpers.identity {
|
||||
constructor() {
|
||||
var _temp;
|
||||
|
||||
(_temp = super(_Foo), babelHelpers.classPrivateMethodInitSpec(this, _m), babelHelpers.classPrivateFieldInitSpec(this, _x, {
|
||||
writable: true,
|
||||
value: void 0
|
||||
}), babelHelpers.defineProperty(this, "x", void 0), _temp), (() => {
|
||||
hasX = o => _x.has(o);
|
||||
|
||||
hasM = o => _m.has(o);
|
||||
})(), _initClass();
|
||||
}
|
||||
|
||||
}), (() => {
|
||||
class Foo {
|
||||
static m() {}
|
||||
|
||||
}
|
||||
|
||||
(() => {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(Foo, [], [dec]);
|
||||
})();
|
||||
})(), _temp2)();
|
||||
|
||||
function _m2() {}
|
||||
@ -0,0 +1,19 @@
|
||||
|
||||
class Bar {}
|
||||
|
||||
let _this, _this2, _this3;
|
||||
|
||||
@(() => Bar)
|
||||
class Foo {
|
||||
static {
|
||||
_this = this;
|
||||
}
|
||||
static field = (_this2 = this);
|
||||
static {
|
||||
_this3 = this;
|
||||
}
|
||||
}
|
||||
|
||||
expect(_this).toBe(Bar);
|
||||
expect(_this2).toBe(Bar);
|
||||
expect(_this3).toBe(Bar);
|
||||
@ -0,0 +1,10 @@
|
||||
@dec
|
||||
class Foo {
|
||||
static {
|
||||
this
|
||||
}
|
||||
static field = this;
|
||||
static {
|
||||
this
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
var _initClass, _temp2;
|
||||
|
||||
let _Foo;
|
||||
|
||||
new (_temp2 = class extends babelHelpers.identity {
|
||||
constructor() {
|
||||
var _temp;
|
||||
|
||||
(_temp = super(_Foo), babelHelpers.defineProperty(this, "field", ((() => {
|
||||
this;
|
||||
})(), this)), _temp), (() => {
|
||||
this;
|
||||
})(), _initClass();
|
||||
}
|
||||
|
||||
}, (() => {
|
||||
class Foo {}
|
||||
|
||||
(() => {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(Foo, [], [dec]);
|
||||
})();
|
||||
})(), _temp2)();
|
||||
@ -1,17 +1,19 @@
|
||||
var _initClass;
|
||||
var _initClass, _temp2;
|
||||
|
||||
let _Foo;
|
||||
|
||||
class Foo {}
|
||||
new (_temp2 = class extends babelHelpers.identity {
|
||||
constructor() {
|
||||
var _temp;
|
||||
|
||||
(() => {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(Foo, [], [dec]);
|
||||
})();
|
||||
(_temp = super(_Foo), babelHelpers.defineProperty(this, "foo", new _Foo()), _temp), _initClass();
|
||||
}
|
||||
|
||||
babelHelpers.defineProperty(Foo, "foo", new _Foo());
|
||||
|
||||
(() => {
|
||||
_initClass();
|
||||
})();
|
||||
}, (() => {
|
||||
class Foo {}
|
||||
|
||||
(() => {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(Foo, [], [dec]);
|
||||
})();
|
||||
})(), _temp2)();
|
||||
const foo = new _Foo();
|
||||
|
||||
@ -2,29 +2,40 @@ var _initClass, _initClass2;
|
||||
|
||||
let _Foo;
|
||||
|
||||
class Foo {
|
||||
new class extends babelHelpers.identity {
|
||||
static {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
static field = 123;
|
||||
static {
|
||||
_initClass();
|
||||
class Foo {
|
||||
static {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
field = 123;
|
||||
|
||||
constructor() {
|
||||
super(_Foo), _initClass();
|
||||
}
|
||||
|
||||
}();
|
||||
|
||||
let _Bar;
|
||||
|
||||
class Bar extends _Foo {
|
||||
new class extends babelHelpers.identity {
|
||||
static {
|
||||
[_Bar, _initClass2] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
static {
|
||||
this.otherField = 456;
|
||||
}
|
||||
static field = 123;
|
||||
static {
|
||||
_initClass2();
|
||||
class Bar extends _Foo {
|
||||
static {
|
||||
[_Bar, _initClass2] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
field = ((() => {
|
||||
this.otherField = 456;
|
||||
})(), 123);
|
||||
|
||||
constructor() {
|
||||
super(_Bar), _initClass2();
|
||||
}
|
||||
|
||||
}();
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
let hasX, hasM;
|
||||
|
||||
@dec
|
||||
class Foo {
|
||||
static #x;
|
||||
static #m() {}
|
||||
|
||||
static x;
|
||||
static m() {}
|
||||
|
||||
static {
|
||||
hasX = o => #x in o;
|
||||
hasM = o => #m in o;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
var _initClass;
|
||||
|
||||
let hasX, hasM;
|
||||
|
||||
let _Foo;
|
||||
|
||||
new class extends babelHelpers.identity {
|
||||
static {
|
||||
class Foo {
|
||||
static {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
|
||||
static m() {}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#x;
|
||||
|
||||
#m() {}
|
||||
|
||||
x;
|
||||
|
||||
constructor() {
|
||||
super(_Foo), (() => {
|
||||
hasX = o => #x in o;
|
||||
|
||||
hasM = o => #m in o;
|
||||
})(), _initClass();
|
||||
}
|
||||
|
||||
}();
|
||||
@ -0,0 +1,10 @@
|
||||
@dec
|
||||
class Foo {
|
||||
static {
|
||||
this
|
||||
}
|
||||
static field = this;
|
||||
static {
|
||||
this
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
var _initClass;
|
||||
|
||||
let _Foo;
|
||||
|
||||
new class extends babelHelpers.identity {
|
||||
static {
|
||||
class Foo {
|
||||
static {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
field = ((() => {
|
||||
this;
|
||||
})(), this);
|
||||
|
||||
constructor() {
|
||||
super(_Foo), (() => {
|
||||
this;
|
||||
})(), _initClass();
|
||||
}
|
||||
|
||||
}();
|
||||
@ -2,15 +2,20 @@ var _initClass;
|
||||
|
||||
let _Foo;
|
||||
|
||||
class Foo {
|
||||
new class extends babelHelpers.identity {
|
||||
static {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
static foo = new _Foo();
|
||||
static {
|
||||
_initClass();
|
||||
class Foo {
|
||||
static {
|
||||
[_Foo, _initClass] = babelHelpers.applyDecs(this, [], [dec]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
foo = new _Foo();
|
||||
|
||||
constructor() {
|
||||
super(_Foo), _initClass();
|
||||
}
|
||||
|
||||
}();
|
||||
const foo = new _Foo();
|
||||
|
||||
@ -846,6 +846,15 @@
|
||||
"./helpers/classPrivateMethodSet.js"
|
||||
],
|
||||
"./helpers/esm/classPrivateMethodSet": "./helpers/esm/classPrivateMethodSet.js",
|
||||
"./helpers/identity": [
|
||||
{
|
||||
"node": "./helpers/identity.js",
|
||||
"import": "./helpers/esm/identity.js",
|
||||
"default": "./helpers/identity.js"
|
||||
},
|
||||
"./helpers/identity.js"
|
||||
],
|
||||
"./helpers/esm/identity": "./helpers/esm/identity.js",
|
||||
"./package": "./package.json",
|
||||
"./package.json": "./package.json",
|
||||
"./regenerator": "./regenerator/index.js",
|
||||
|
||||
@ -845,6 +845,15 @@
|
||||
"./helpers/classPrivateMethodSet.js"
|
||||
],
|
||||
"./helpers/esm/classPrivateMethodSet": "./helpers/esm/classPrivateMethodSet.js",
|
||||
"./helpers/identity": [
|
||||
{
|
||||
"node": "./helpers/identity.js",
|
||||
"import": "./helpers/esm/identity.js",
|
||||
"default": "./helpers/identity.js"
|
||||
},
|
||||
"./helpers/identity.js"
|
||||
],
|
||||
"./helpers/esm/identity": "./helpers/esm/identity.js",
|
||||
"./package": "./package.json",
|
||||
"./package.json": "./package.json",
|
||||
"./regenerator": "./regenerator/index.js",
|
||||
|
||||
@ -845,6 +845,15 @@
|
||||
"./helpers/classPrivateMethodSet.js"
|
||||
],
|
||||
"./helpers/esm/classPrivateMethodSet": "./helpers/esm/classPrivateMethodSet.js",
|
||||
"./helpers/identity": [
|
||||
{
|
||||
"node": "./helpers/identity.js",
|
||||
"import": "./helpers/esm/identity.js",
|
||||
"default": "./helpers/identity.js"
|
||||
},
|
||||
"./helpers/identity.js"
|
||||
],
|
||||
"./helpers/esm/identity": "./helpers/esm/identity.js",
|
||||
"./package": "./package.json",
|
||||
"./package.json": "./package.json",
|
||||
"./regenerator": "./regenerator/index.js",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user