Skip to content

Commit

Permalink
feat: support per-field intitializers
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed Jan 27, 2024
1 parent cb47c63 commit e635513
Show file tree
Hide file tree
Showing 20 changed files with 231 additions and 1,018 deletions.
Expand Up @@ -303,6 +303,16 @@ function prependExpressionsToFieldInitializer(
initializer.replaceWith(maybeSequenceExpression(expressions));
}

function prependExpressionsToStaticBlock(
expressions: t.Expression[],
blockPath: NodePath<t.StaticBlock>,
) {
blockPath.unshiftContainer(
"body",
t.expressionStatement(maybeSequenceExpression(expressions)),
);
}

function prependExpressionsToConstructor(
expressions: t.Expression[],
constructorPath: NodePath<t.ClassMethod>,
Expand Down Expand Up @@ -399,7 +409,7 @@ function insertExpressionsAfterSuperCallAndOptimize(
}

/**
* Build a class constructor path from the given expressions. If the class is
* Build a class constructor node from the given expressions. If the class is
* derived, the constructor will call super() first to ensure that `this`
* in the expressions work as expected.
*
Expand Down Expand Up @@ -429,6 +439,12 @@ function createConstructorFromExpressions(
);
}

function createStaticBlockFromExpressions(expressions: t.Expression[]) {
return t.staticBlock([
t.expressionStatement(maybeSequenceExpression(expressions)),
]);
}

// 3 bits reserved to this (0-7)
const FIELD = 0;
const ACCESSOR = 1;
Expand Down Expand Up @@ -802,6 +818,9 @@ function transformClass(
element as NodePath<t.ClassAccessorProperty>,
state,
);
if (version === "2023-11") {
break;
}
/* fallthrough */
default:
if (element.node.static) {
Expand Down Expand Up @@ -945,6 +964,7 @@ function transformClass(
let needsInstancePrivateBrandCheck = false;

let fieldInitializerAssignments = [];
let staticFieldInitializerAssignments = [];

if (hasElementDecorators) {
if (protoInitLocal) {
Expand All @@ -955,6 +975,16 @@ function transformClass(
}
for (const element of body) {
if (!isClassDecoratableElementPath(element)) {
if (
staticFieldInitializerAssignments.length > 0 &&
element.isStaticBlock()
) {
prependExpressionsToStaticBlock(
staticFieldInitializerAssignments,
element,
);
staticFieldInitializerAssignments = [];
}
continue;
}

Expand Down Expand Up @@ -1005,8 +1035,8 @@ function transformClass(
constructorPath = element;
}

let locals: t.Identifier[];
if (hasDecorators) {
let locals: t.Identifier | t.Identifier[];
let privateMethods: Array<
t.FunctionExpression | t.ArrowFunctionExpression
>;
Expand Down Expand Up @@ -1053,7 +1083,7 @@ function transformClass(
version,
isComputed,
);
locals = newFieldInitId;
locals = [newFieldInitId];
}
} else if (kind === FIELD) {
const initId = element.scope.parent.generateDeclaredUidIdentifier(
Expand All @@ -1070,15 +1100,16 @@ function transformClass(
),
);

locals = initId;
locals = [initId];

if (isPrivate) {
privateMethods = extractProxyAccessorsFor(key, version);
}
} else if (isPrivate) {
locals = element.scope.parent.generateDeclaredUidIdentifier(
const callId = element.scope.parent.generateDeclaredUidIdentifier(
`call_${name}`,
);
locals = [callId];

const replaceSupers = new ReplaceSupers({
constantSuper,
Expand Down Expand Up @@ -1110,15 +1141,15 @@ function transformClass(
movePrivateAccessor(
element as NodePath<t.ClassPrivateMethod>,
t.cloneNode(key),
t.cloneNode(locals),
t.cloneNode(callId),
isStatic,
);
} else {
const node = element.node as t.ClassPrivateMethod;

// Unshift
path.node.body.body.unshift(
t.classPrivateProperty(key, t.cloneNode(locals), [], node.static),
t.classPrivateProperty(key, t.cloneNode(callId), [], node.static),
);

decoratedPrivateMethods.add(key.id.name);
Expand Down Expand Up @@ -1161,12 +1192,39 @@ function transformClass(
) {
prependExpressionsToFieldInitializer(
fieldInitializerAssignments,
element as NodePath<
t.ClassProperty | t.ClassPrivateProperty | t.ClassAccessorProperty
>,
element as NodePath<t.ClassProperty | t.ClassPrivateProperty>,
);
fieldInitializerAssignments = [];
}

if (
staticFieldInitializerAssignments.length > 0 &&
isStatic &&
(kind === FIELD || kind === ACCESSOR)
) {
prependExpressionsToFieldInitializer(
staticFieldInitializerAssignments,
element as NodePath<t.ClassProperty | t.ClassPrivateProperty>,
);
staticFieldInitializerAssignments = [];
}

if (hasDecorators && version === "2023-11") {
if (kind === FIELD || kind === ACCESSOR) {
const initExtraId = scopeParent.generateDeclaredUidIdentifier(
`init_extra_${name}`,
);
locals.push(initExtraId);
const initExtraCall = t.callExpression(t.cloneNode(initExtraId), [
t.thisExpression(),
]);
if (!isStatic) {
fieldInitializerAssignments.push(initExtraCall);
} else {
staticFieldInitializerAssignments.push(initExtraCall);
}
}
}
}
}

Expand Down Expand Up @@ -1196,6 +1254,12 @@ function transformClass(
fieldInitializerAssignments = [];
}

if (staticFieldInitializerAssignments.length > 0) {
path.node.body.body.push(
createStaticBlockFromExpressions(staticFieldInitializerAssignments),
);
}

const elementDecorations = generateDecorationExprs(
elementDecoratorInfo,
version,
Expand Down
36 changes: 25 additions & 11 deletions packages/babel-helpers/src/helpers/applyDecs2311.ts
Expand Up @@ -431,18 +431,29 @@ export default /* @no-mangle */ function applyDecs2311(
}

if (isField || isAccessor) {
ret.push(function (instance: any, value: any) {
for (var i = init.length - 1; i >= 0; i--) {
value = init[i].call(instance, value);
}
return value;
});
ret.push(
// init
function (instance: any, value: any) {
for (var i = init.length - 1; i >= 0; i--) {
value = init[i].call(instance, value);
}
return value;
},
// init_extra
runInitializers.bind(null, initializers),
);
}

if (!isField && !isClass) {
if (isPrivate) {
if (isAccessor) {
ret.push(_bindPropCall(desc, "get"), _bindPropCall(desc, "set"));
// get and set should be returned before init_extra
ret.splice(
-1,
0,
_bindPropCall(desc, "get"),
_bindPropCall(desc, "set"),
);
} else {
ret.push(
kind === PROP_KIND.METHOD
Expand Down Expand Up @@ -495,6 +506,7 @@ export default /* @no-mangle */ function applyDecs2311(
kind &= 7; /* 0b111 */

var isField = kind === PROP_KIND.FIELD;
var isAccessor = kind === PROP_KIND.ACCESSOR;

var key = name + "/" + isStatic;

Expand All @@ -521,14 +533,16 @@ export default /* @no-mangle */ function applyDecs2311(
isPrivate ? "#" + name : (toPropertyKey(name) as string),
kind,
metadata,
isStatic
? (staticInitializers = staticInitializers || [])
: (protoInitializers = protoInitializers || []),
isField || isAccessor
? /* fieldInitializers */ []
: isStatic
? (staticInitializers = staticInitializers || [])
: (protoInitializers = protoInitializers || []),
ret,
isStatic,
isPrivate,
isField,
kind === PROP_KIND.ACCESSOR,
isAccessor,
isStatic && isPrivate ? staticBrand : instanceBrand,
);
}
Expand Down
Expand Up @@ -37,8 +37,8 @@ function logFieldDecoratorRun(a, b) {
@logClassDecoratorRun(0, 19, 21)
@logClassDecoratorRun(1, 18, 20)
class A {
@logAccessorDecoratorRun(2, 11, 23, 26)
@logAccessorDecoratorRun(3, 10, 22, 27)
@logAccessorDecoratorRun(2, 11, 25, 22)
@logAccessorDecoratorRun(3, 10, 24, 23)
accessor a;

@logFieldDecoratorRun(4, 15)
Expand All @@ -49,8 +49,8 @@ class A {
@logFieldDecoratorRun(7, 16)
#c;

@logAccessorDecoratorRun(8, 13, 25, 28)
@logAccessorDecoratorRun(9, 12, 24, 29)
@logAccessorDecoratorRun(8, 13, 29, 26)
@logAccessorDecoratorRun(9, 12, 28, 27)
accessor #d;

constructor() {
Expand Down
Expand Up @@ -38,12 +38,12 @@ function logFieldDecoratorRun(a, b) {
@logClassDecoratorRun(0, 11, 13)
@logClassDecoratorRun(1, 10, 12)
class A {
@logAccessorDecoratorRun(2, 7, 15, 18, 22, 25)
@logAccessorDecoratorRun(3, 6, 14, 19, 23, 24)
@logAccessorDecoratorRun(2, 7, 17, 14, 22, 25)
@logAccessorDecoratorRun(3, 6, 16, 15, 23, 24)
accessor a;

@logAccessorDecoratorRun(4, 9, 17, 20, 26, 29)
@logAccessorDecoratorRun(5, 8, 16, 21, 27, 28)
@logAccessorDecoratorRun(4, 9, 21, 18, 26, 29)
@logAccessorDecoratorRun(5, 8, 20, 19, 27, 28)
accessor #b;

constructor() {
Expand Down
Expand Up @@ -43,20 +43,20 @@ function logMethodDecoratorRun(a, b, c, d) {
@logClassDecoratorRun(0, 19, 21)
@logClassDecoratorRun(1, 18, 20)
class A {
@logAccessorDecoratorRun(2, 11, 23, 30)
@logAccessorDecoratorRun(3, 10, 22, 31)
@logAccessorDecoratorRun(2, 11, 29, 26)
@logAccessorDecoratorRun(3, 10, 28, 27)
accessor a;

@logMethodDecoratorRun(4, 13, 25, 35)
@logMethodDecoratorRun(5, 12, 24, 34)
@logMethodDecoratorRun(4, 13, 23, 35)
@logMethodDecoratorRun(5, 12, 22, 34)
b() {};

@logMethodDecoratorRun(6, 15, 27, 37)
@logMethodDecoratorRun(7, 14, 26, 36)
@logMethodDecoratorRun(6, 15, 25, 37)
@logMethodDecoratorRun(7, 14, 24, 36)
#c() {};

@logAccessorDecoratorRun(8, 17, 29, 32)
@logAccessorDecoratorRun(9, 16, 28, 33)
@logAccessorDecoratorRun(8, 17, 33, 30)
@logAccessorDecoratorRun(9, 16, 32, 31)
accessor #d;

constructor() {
Expand Down
Expand Up @@ -25,20 +25,20 @@ function logAccessorDecoratorRun(a, b, c, d) {
@logClassDecoratorRun(0, 19, 29)
@logClassDecoratorRun(1, 18, 28)
class A {
@logAccessorDecoratorRun(2, 15, 31, 34)
@logAccessorDecoratorRun(3, 14, 30, 35)
@logAccessorDecoratorRun(2, 15, 33, 30)
@logAccessorDecoratorRun(3, 14, 32, 31)
accessor a;

@logAccessorDecoratorRun(4, 11, 21, 24)
@logAccessorDecoratorRun(5, 10, 20, 25)
@logAccessorDecoratorRun(4, 11, 23, 20)
@logAccessorDecoratorRun(5, 10, 22, 21)
static accessor b;

@logAccessorDecoratorRun(6, 13, 23, 26)
@logAccessorDecoratorRun(7, 12, 22, 27)
@logAccessorDecoratorRun(6, 13, 27, 24)
@logAccessorDecoratorRun(7, 12, 26, 25)
static accessor #c;

@logAccessorDecoratorRun(8, 17, 33, 36)
@logAccessorDecoratorRun(9, 16, 32, 37)
@logAccessorDecoratorRun(8, 17, 37, 34)
@logAccessorDecoratorRun(9, 16, 36, 35)
accessor #d;
}

Expand Down
Expand Up @@ -47,8 +47,8 @@ class A {
A.b(), A.#c();
}

@logAccessorDecoratorRun(2, 15, 31, 34)
@logAccessorDecoratorRun(3, 14, 30, 35)
@logAccessorDecoratorRun(2, 15, 33, 30)
@logAccessorDecoratorRun(3, 14, 32, 31)
accessor a;

@logMethodDecoratorRun(4, 11, 21, 25)
Expand All @@ -59,8 +59,8 @@ class A {
@logMethodDecoratorRun(7, 12, 22, 26)
static #c() {};

@logAccessorDecoratorRun(8, 17, 33, 36)
@logAccessorDecoratorRun(9, 16, 32, 37)
@logAccessorDecoratorRun(8, 17, 37, 34)
@logAccessorDecoratorRun(9, 16, 36, 35)
accessor #d;

constructor() {
Expand Down

0 comments on commit e635513

Please sign in to comment.