Skip to content

Commit

Permalink
Support undecorated static accessor in anonymous classes (#16485)
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed May 14, 2024
1 parent 1199e6a commit 6e14020
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ function generateClassProperty(
}
}

function assignIdForAnonymousClass(
path: NodePath<t.Class>,
className: string | t.Identifier | t.StringLiteral | undefined,
) {
if (!path.node.id) {
path.node.id =
typeof className === "string"
? t.identifier(className)
: path.scope.generateUidIdentifier("Class");
}
}

function addProxyAccessorsFor(
className: t.Identifier,
element: NodePath<ClassDecoratableElement>,
Expand Down Expand Up @@ -998,6 +1010,20 @@ function checkPrivateMethodUpdateError(
});
}

/**
* Apply decorator and accessor transform
* @param path The class path.
* @param state The plugin pass.
* @param constantSuper The constantSuper compiler assumption.
* @param ignoreFunctionLength The ignoreFunctionLength compiler assumption.
* @param className The class name.
* - If className is a `string`, it will be a valid identifier name that can safely serve as a class id
* - If className is an Identifier, it is the reference to the name derived from NamedEvaluation
* - If className is a StringLiteral, it is derived from NamedEvaluation on literal computed keys
* @param propertyVisitor The visitor that should be applied on property prior to the transform.
* @param version The decorator version.
* @returns The transformed class path or undefined if there are no decorators.
*/
function transformClass(
path: NodePath<t.Class>,
state: PluginPass,
Expand All @@ -1006,7 +1032,7 @@ function transformClass(
className: string | t.Identifier | t.StringLiteral | undefined,
propertyVisitor: Visitor<PluginPass>,
version: DecoratorVersionKind,
): NodePath {
): NodePath | undefined {
const body = path.get("body.body");

const classDecorators = path.node.decorators;
Expand All @@ -1031,6 +1057,8 @@ function transformClass(
let protoInitLocal: t.Identifier;
let staticInitLocal: t.Identifier;
const classIdName = path.node.id?.name;
// Whether to generate a setFunctionName call to preserve the class name
const setClassName = typeof className === "object" ? className : undefined;
// Check if the decorator does not reference function-specific
// context or the given identifier name or contains yield or await expression.
// `true` means "maybe" and `false` means "no".
Expand Down Expand Up @@ -1141,6 +1169,8 @@ function transformClass(
setterKey = t.cloneNode(key);
}

assignIdForAnonymousClass(path, className);

addProxyAccessorsFor(
path.node.id,
newPath,
Expand All @@ -1159,6 +1189,16 @@ function transformClass(
}

if (!classDecorators && !hasElementDecorators) {
if (!path.node.id && typeof className === "string") {
path.node.id = t.identifier(className);
}
if (setClassName) {
path.node.body.body.unshift(
createStaticBlockFromExpressions([
createSetFunctionNameCall(state, setClassName),
]),
);
}
// If nothing is decorated and no assignments inserted, return
return;
}
Expand Down Expand Up @@ -1288,9 +1328,7 @@ function transformClass(
}
}
} else {
if (!path.node.id) {
path.node.id = path.scope.generateUidIdentifier("Class");
}
assignIdForAnonymousClass(path, className);
classIdLocal = t.cloneNode(path.node.id);
}

Expand Down Expand Up @@ -1454,6 +1492,7 @@ function transformClass(

locals = [newFieldInitId, getId, setId];
} else {
assignIdForAnonymousClass(path, className);
addProxyAccessorsFor(
path.node.id,
newPath,
Expand Down Expand Up @@ -1958,7 +1997,7 @@ function transformClass(
classDecorationsId ?? t.arrayExpression(classDecorations),
t.numericLiteral(classDecorationsFlag),
needsInstancePrivateBrandCheck ? lastInstancePrivateName : null,
typeof className === "object" ? className : undefined,
setClassName,
t.cloneNode(superClass),
state,
version,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const dec = () => {};
class Foo {
static accessor #a;

static accessor #b = 123;
}

Foo = class {
static accessor #a;

static accessor #b = 123;
}

export default class {
static accessor #a;

static accessor #b = 123;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const dec = () => {};
class Foo {
static #A;
static get #a() {
return Foo.#A;
}
static set #a(v) {
Foo.#A = v;
}
static #B = 123;
static get #b() {
return Foo.#B;
}
static set #b(v) {
Foo.#B = v;
}
}
Foo = class Foo {
static #A;
static get #a() {
return Foo.#A;
}
static set #a(v) {
Foo.#A = v;
}
static #B = 123;
static get #b() {
return Foo.#B;
}
static set #b(v) {
Foo.#B = v;
}
};
export default class _Class {
static #A;
static get #a() {
return _Class.#A;
}
static set #a(v) {
_Class.#A = v;
}
static #B = 123;
static get #b() {
return _Class.#B;
}
static set #b(v) {
_Class.#B = v;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const dec = () => {};
class Foo {
static accessor a;

static accessor b = 123;

static accessor ['c'] = 456;
}

Foo = class {
static accessor a;

static accessor b = 123;

static accessor ['c'] = 456;
}

export default class {
static accessor a;

static accessor b = 123;

static accessor ['c'] = 456;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const dec = () => {};
class Foo {
static #A;
static get a() {
return Foo.#A;
}
static set a(v) {
Foo.#A = v;
}
static #B = 123;
static get b() {
return Foo.#B;
}
static set b(v) {
Foo.#B = v;
}
static #C = 456;
static get ['c']() {
return Foo.#C;
}
static set ['c'](v) {
Foo.#C = v;
}
}
Foo = class Foo {
static #A;
static get a() {
return Foo.#A;
}
static set a(v) {
Foo.#A = v;
}
static #B = 123;
static get b() {
return Foo.#B;
}
static set b(v) {
Foo.#B = v;
}
static #C = 456;
static get ['c']() {
return Foo.#C;
}
static set ['c'](v) {
Foo.#C = v;
}
};
export default class _Class {
static #A;
static get a() {
return _Class.#A;
}
static set a(v) {
_Class.#A = v;
}
static #B = 123;
static get b() {
return _Class.#B;
}
static set b(v) {
_Class.#B = v;
}
static #C = 456;
static get ['c']() {
return _Class.#C;
}
static set ['c'](v) {
_Class.#C = v;
}
}

0 comments on commit 6e14020

Please sign in to comment.