Skip to content

Commit

Permalink
Improve temporary variables for decorators (#16218)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed Jan 18, 2024
1 parent dde84f0 commit 87a67bf
Show file tree
Hide file tree
Showing 440 changed files with 1,984 additions and 1,998 deletions.
115 changes: 68 additions & 47 deletions packages/babel-helper-create-class-features-plugin/src/decorators.ts
Expand Up @@ -562,7 +562,7 @@ function transformClass(
continue;
}

if (element.node.decorators && element.node.decorators.length > 0) {
if (element.node.decorators?.length) {
switch (element.node.type) {
case "ClassProperty":
// @ts-expect-error todo: propertyVisitor.ClassProperty should be callable. Improve typings.
Expand Down Expand Up @@ -646,38 +646,72 @@ function transformClass(
classIdLocal: t.Identifier;

const decoratorsThis = new Map<t.Decorator, t.Expression>();
const maybeExtractDecorator = (decorator: t.Decorator) => {
const { expression } = decorator;
if (version === "2023-05" && t.isMemberExpression(expression)) {
let object;
if (
t.isSuper(expression.object) ||
t.isThisExpression(expression.object)
) {
object = memoiseExpression(t.thisExpression(), "obj");
} else if (!scopeParent.isStatic(expression.object)) {
object = memoiseExpression(expression.object, "obj");
expression.object = object;
} else {
object = expression.object;
const maybeExtractDecorators = (
decorators: t.Decorator[],
memoiseInPlace: boolean,
) => {
let needMemoise = false;
for (const decorator of decorators) {
const { expression } = decorator;
if (version === "2023-05" && t.isMemberExpression(expression)) {
let object;
if (
t.isSuper(expression.object) ||
t.isThisExpression(expression.object)
) {
needMemoise = true;
if (memoiseInPlace) {
object = memoiseExpression(t.thisExpression(), "obj");
} else {
object = t.thisExpression();
}
} else {
if (!scopeParent.isStatic(expression.object)) {
needMemoise = true;
if (memoiseInPlace) {
expression.object = memoiseExpression(expression.object, "obj");
}
}
object = t.cloneNode(expression.object);
}
decoratorsThis.set(decorator, object);
}
if (!scopeParent.isStatic(expression)) {
needMemoise = true;
if (memoiseInPlace) {
decorator.expression = memoiseExpression(expression, "dec");
}
}
decoratorsThis.set(decorator, t.cloneNode(object));
}
if (!scopeParent.isStatic(expression)) {
decorator.expression = memoiseExpression(expression, "dec");
}
return needMemoise && !memoiseInPlace;
};

let needsDeclaraionForClassBinding = false;
let classDecorationsFlag = 0;
let classDecorations: t.Expression[] = [];
let classDecorationsId: t.Identifier;
if (classDecorators) {
classInitLocal = scopeParent.generateDeclaredUidIdentifier("initClass");
needsDeclaraionForClassBinding = path.isClassDeclaration();
({ id: classIdLocal, path } = replaceClassWithVar(path, className));

path.node.decorators = null;

for (const classDecorator of classDecorators) {
maybeExtractDecorator(classDecorator);
const needMemoise = maybeExtractDecorators(classDecorators, false);

const { hasThis, decs } = generateDecorationList(
classDecorators.map(el => el.expression),
classDecorators.map(dec => decoratorsThis.get(dec)),
version,
);
classDecorationsFlag = hasThis ? 1 : 0;
classDecorations = decs;

if (needMemoise) {
classDecorationsId = memoiseExpression(
t.arrayExpression(classDecorations),
"classDecs",
);
}
} else {
if (!path.node.id) {
Expand All @@ -696,18 +730,15 @@ function transformClass(
}

const { node } = element;
const decorators = element.get("decorators");
const decorators = element.node.decorators;

const hasDecorators = Array.isArray(decorators) && decorators.length > 0;
const hasDecorators = !!decorators?.length;

if (hasDecorators) {
for (const decoratorPath of decorators) {
maybeExtractDecorator(decoratorPath.node);
}
maybeExtractDecorators(decorators, true);
}

const isComputed =
"computed" in element.node && element.node.computed === true;
const isComputed = "computed" in element.node && element.node.computed;
if (isComputed) {
if (!element.get("key").isConstantExpression()) {
node.key = memoiseExpression(
Expand All @@ -722,7 +753,7 @@ function transformClass(

const isPrivate = key.type === "PrivateName";

const isStatic = !!element.node.static;
const isStatic = element.node.static;

let name = "computedKey";

Expand Down Expand Up @@ -881,8 +912,8 @@ function transformClass(

elementDecoratorInfo.push({
kind,
decorators: decorators.map(d => d.node.expression),
decoratorsThis: decorators.map(d => decoratorsThis.get(d.node)),
decorators: decorators.map(d => d.expression),
decoratorsThis: decorators.map(d => decoratorsThis.get(d)),
name: nameExpr,
isStatic,
privateMethods,
Expand Down Expand Up @@ -918,17 +949,6 @@ function transformClass(
elementDecoratorInfo,
version,
);
let classDecorationsFlag = 0;
let classDecorations: t.Expression[] = [];
if (classDecorators) {
const { hasThis, decs } = generateDecorationList(
classDecorators.map(el => el.expression),
classDecorators.map(dec => decoratorsThis.get(dec)),
version,
);
classDecorationsFlag = hasThis ? 1 : 0;
classDecorations = decs;
}

const elementLocals: t.Identifier[] =
extractElementLocalAssignments(elementDecoratorInfo);
Expand Down Expand Up @@ -992,7 +1012,7 @@ function transformClass(
t.classMethod(
"constructor",
t.identifier("constructor"),
[t.restElement(t.identifier("args"))],
path.node.superClass ? [t.restElement(t.identifier("args"))] : [],
t.blockStatement(body),
),
);
Expand Down Expand Up @@ -1143,7 +1163,6 @@ function transformClass(
superClass = id;
}
}

originalClass.body.body.unshift(
t.staticBlock(
[
Expand All @@ -1152,7 +1171,9 @@ function transformClass(
elementLocals,
classLocals,
elementDecorations,
t.arrayExpression(classDecorations),
classDecorationsId
? t.cloneNode(classDecorationsId)
: t.arrayExpression(classDecorations),
t.numericLiteral(classDecorationsFlag),
needsInstancePrivateBrandCheck ? lastInstancePrivateName : null,
typeof className === "object" ? className : undefined,
Expand Down Expand Up @@ -1192,8 +1213,8 @@ function transformClass(
function createLocalsAssignment(
elementLocals: t.Identifier[],
classLocals: t.Identifier[],
elementDecorations: t.ArrayExpression,
classDecorations: t.ArrayExpression,
elementDecorations: t.ArrayExpression | t.Identifier,
classDecorations: t.ArrayExpression | t.Identifier,
classDecorationsFlag: t.NumericLiteral,
maybePrivateBranName: t.PrivateName | null,
setClassName: t.Identifier | t.StringLiteral | undefined,
Expand Down
Expand Up @@ -1110,7 +1110,8 @@ export function buildFieldsInitNodes(
};

const classRefForInnerBinding =
ref ?? props[0].scope.generateUidIdentifier("class");
ref ??
props[0].scope.generateUidIdentifier(innerBindingRef?.name || "Class");
ref ??= t.cloneNode(innerBindingRef);

for (const prop of props) {
Expand Down
Expand Up @@ -230,7 +230,7 @@ export function createClassFeaturePlugin({
let ref: t.Identifier | null;
if (!innerBinding || !pathIsClassDeclaration) {
nameFunction(path);
ref = path.scope.generateUidIdentifier("class");
ref = path.scope.generateUidIdentifier(innerBinding?.name || "Class");
}
const classRefForDefine = ref ?? t.cloneNode(innerBinding);

Expand Down
@@ -1,13 +1,13 @@
var _class;
var _A;
var _foo = /*#__PURE__*/new WeakSet();
class A extends B {
constructor(...args) {
super(...args);
babelHelpers.classPrivateMethodInitSpec(this, _foo);
}
}
_class = A;
_A = A;
function _foo2() {
let _A;
babelHelpers.get(babelHelpers.getPrototypeOf(_class.prototype), "x", this);
let _A2;
babelHelpers.get(babelHelpers.getPrototypeOf(_A.prototype), "x", this);
}
@@ -1,11 +1,11 @@
export default babelHelpers.decorate([dec()], function (_initialize) {
class _class {
class _Class {
constructor() {
_initialize(this);
}
}
return {
F: _class,
F: _Class,
d: []
};
});
@@ -1,13 +1,13 @@
babelHelpers.decorate([dec()], function (_initialize) {
"use strict";

class _class {
class _Class {
constructor() {
_initialize(this);
}
}
return {
F: _class,
F: _Class,
d: []
};
});
@@ -1,4 +1,4 @@
var _init_a, _init_a2, _get_a, _set_a, _init_computedKey, _init_computedKey2, _init_computedKey3, _init_computedKey4, _init_computedKey5, _init_computedKey6, _computedKey, _init_computedKey7, _initStatic, _class;
var _init_a, _init_a2, _get_a, _set_a, _init_computedKey, _init_computedKey2, _init_computedKey3, _init_computedKey4, _init_computedKey5, _init_computedKey6, _computedKey, _init_computedKey7, _initStatic, _Foo;
const logs = [];
const dec = (value, context) => {
logs.push(context.name);
Expand Down Expand Up @@ -67,55 +67,55 @@ class Foo {
babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _I, v);
}
}
_class = Foo;
_Foo = Foo;
function _set_a2(v) {
_set_a(this, v);
}
function _get_a2() {
return _get_a(this);
}
(() => {
[_init_a, _init_a2, _get_a, _set_a, _init_computedKey, _init_computedKey2, _init_computedKey3, _init_computedKey4, _init_computedKey5, _init_computedKey6, _init_computedKey7, _initStatic] = babelHelpers.applyDecs(_class, [[dec, 6, "a"], [dec, 6, "a", function () {
return babelHelpers.classStaticPrivateFieldSpecGet(this, _class, _B);
[_init_a, _init_a2, _get_a, _set_a, _init_computedKey, _init_computedKey2, _init_computedKey3, _init_computedKey4, _init_computedKey5, _init_computedKey6, _init_computedKey7, _initStatic] = babelHelpers.applyDecs(_Foo, [[dec, 6, "a"], [dec, 6, "a", function () {
return babelHelpers.classStaticPrivateFieldSpecGet(this, _Foo, _B);
}, function (value) {
babelHelpers.classStaticPrivateFieldSpecSet(this, _class, _B, value);
babelHelpers.classStaticPrivateFieldSpecSet(this, _Foo, _B, value);
}], [dec, 6, "b"], [dec, 6, "c"], [dec, 6, 0], [dec, 6, 1], [dec, 6, 2n], [dec, 6, 3n], [dec, 6, _computedKey]], []);
_initStatic(_class);
_initStatic(_Foo);
})();
var _A = {
writable: true,
value: _init_a(_class)
value: _init_a(_Foo)
};
var _B = {
writable: true,
value: _init_a2(_class)
value: _init_a2(_Foo)
};
var _C = {
writable: true,
value: _init_computedKey(_class)
value: _init_computedKey(_Foo)
};
var _D = {
writable: true,
value: _init_computedKey2(_class)
value: _init_computedKey2(_Foo)
};
var _E = {
writable: true,
value: _init_computedKey3(_class)
value: _init_computedKey3(_Foo)
};
var _F = {
writable: true,
value: _init_computedKey4(_class)
value: _init_computedKey4(_Foo)
};
var _G = {
writable: true,
value: _init_computedKey5(_class)
value: _init_computedKey5(_Foo)
};
var _H = {
writable: true,
value: _init_computedKey6(_class)
value: _init_computedKey6(_Foo)
};
var _I = {
writable: true,
value: _init_computedKey7(_class)
value: _init_computedKey7(_Foo)
};
expect(logs).toStrictEqual(["computing f", "calling toPrimitive", "a", "#a", "b", "c", "0", "1", "2", "3", "f()"]);
@@ -1,4 +1,4 @@
var _init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initProto, _class;
var _init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initProto, _Foo;
const dec = () => {};
var _A = /*#__PURE__*/new WeakMap();
var _a = /*#__PURE__*/new WeakMap();
Expand All @@ -24,7 +24,7 @@ class Foo {
});
}
}
_class = Foo;
_Foo = Foo;
function _set_a2(v) {
_set_a(this, v);
}
Expand All @@ -37,7 +37,7 @@ function _set_b2(v) {
function _get_b2() {
return _get_b(this);
}
[_init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initProto] = babelHelpers.applyDecs(_class, [[dec, 1, "a", function () {
[_init_a, _get_a, _set_a, _init_b, _get_b, _set_b, _initProto] = babelHelpers.applyDecs(_Foo, [[dec, 1, "a", function () {
return babelHelpers.classPrivateFieldGet(this, _A);
}, function (value) {
babelHelpers.classPrivateFieldSet(this, _A, value);
Expand Down
@@ -1,4 +1,4 @@
var _init_a, _init_b, _init_computedKey, _initProto, _class;
var _init_a, _init_b, _init_computedKey, _initProto, _Foo;
const dec = () => {};
var _A = /*#__PURE__*/new WeakMap();
var _B = /*#__PURE__*/new WeakMap();
Expand Down Expand Up @@ -37,5 +37,5 @@ class Foo {
babelHelpers.classPrivateFieldSet(this, _C, v);
}
}
_class = Foo;
[_init_a, _init_b, _init_computedKey, _initProto] = babelHelpers.applyDecs(_class, [[dec, 1, "a"], [dec, 1, "b"], [dec, 1, 'c']], []);
_Foo = Foo;
[_init_a, _init_b, _init_computedKey, _initProto] = babelHelpers.applyDecs(_Foo, [[dec, 1, "a"], [dec, 1, "b"], [dec, 1, 'c']], []);

0 comments on commit 87a67bf

Please sign in to comment.