Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle decorated async private method and generator #16258

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -634,12 +634,6 @@ function addCallAccessorsFor(
);
}

function isNotTsParameter(
node: t.Identifier | t.Pattern | t.RestElement | t.TSParameterProperty,
): node is t.Identifier | t.Pattern | t.RestElement {
return node.type !== "TSParameterProperty";
}

function movePrivateAccessor(
element: NodePath<t.ClassPrivateMethod>,
key: t.PrivateName,
Expand Down Expand Up @@ -702,6 +696,25 @@ function maybeSequenceExpression(exprs: t.Expression[]) {
return t.sequenceExpression(exprs);
}

/**
* Create FunctionExpression from a ClassPrivateMethod.
* The returned FunctionExpression node takes ownership of the private method's body and params.
*
* @param {t.ClassPrivateMethod} node
* @returns
*/
function createFunctionExpressionFromPrivateMethod(node: t.ClassPrivateMethod) {
const { params, body, generator: isGenerator, async: isAsync } = node;
return t.functionExpression(
undefined,
// @ts-expect-error todo: Improve typings: TSParameterProperty is only allowed in constructor
params,
body,
isGenerator,
isAsync,
);
}

function createSetFunctionNameCall(
state: PluginPass,
className: t.Identifier | t.StringLiteral,
Expand Down Expand Up @@ -1122,18 +1135,9 @@ function transformClass(

replaceSupers.replace();

const {
params,
body,
async: isAsync,
} = element.node as t.ClassPrivateMethod;

privateMethods = [
t.functionExpression(
undefined,
params.filter(isNotTsParameter),
body,
isAsync,
createFunctionExpressionFromPrivateMethod(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the original inline version a bit, but that's okay.

element.node as t.ClassPrivateMethod,
),
];

Expand Down
@@ -0,0 +1,23 @@
let counter = 0;

class Foo {
@(function (fn) {
counter++;
expect(fn.constructor.name).toBe("AsyncFunction");
})
async #a() {}

@(function (fn) {
counter++;
expect(fn.constructor.name).toBe("GeneratorFunction");
})
*#g() {}

@(function (fn) {
counter++;
expect(fn.constructor.name).toBe("AsyncGeneratorFunction");
})
async *#ag() {}
}

expect(counter).toBe(3);
@@ -0,0 +1,10 @@
class Foo {
@dec
async #a() {}

@dec
*#g() {}

@dec
async *#ag() {}
}
@@ -0,0 +1,3 @@
{
"minNodeVersion": "10.0.0"
}
@@ -0,0 +1,26 @@
var _initProto, _dec, _call_a, _dec2, _call_g, _dec3, _call_ag, _Foo;
_dec = dec;
_dec2 = dec;
_dec3 = dec;
var _ag = /*#__PURE__*/new WeakMap();
var _g = /*#__PURE__*/new WeakMap();
var _a = /*#__PURE__*/new WeakMap();
class Foo {
constructor() {
babelHelpers.classPrivateFieldInitSpec(this, _ag, {
writable: true,
value: _call_ag
});
babelHelpers.classPrivateFieldInitSpec(this, _g, {
writable: true,
value: _call_g
});
babelHelpers.classPrivateFieldInitSpec(this, _a, {
writable: true,
value: _call_a
});
_initProto(this);
}
}
_Foo = Foo;
[_call_a, _call_g, _call_ag, _initProto] = babelHelpers.applyDecs2311(_Foo, [[_dec, 2, "a", async function () {}], [_dec2, 2, "g", function* () {}], [_dec3, 2, "ag", async function* () {}]], [], 0, _ => _a.has(babelHelpers.checkInRHS(_))).e;
@@ -0,0 +1,23 @@
let counter = 0;

class Foo {
@(function (fn) {
counter++;
expect(fn.constructor.name).toBe("AsyncFunction");
})
async #a() {}

@(function (fn) {
counter++;
expect(fn.constructor.name).toBe("GeneratorFunction");
})
*#g() {}

@(function (fn) {
counter++;
expect(fn.constructor.name).toBe("AsyncGeneratorFunction");
})
async *#ag() {}
}

expect(counter).toBe(3);
@@ -0,0 +1,10 @@
class Foo {
@dec
async #a() {}

@dec
*#g() {}

@dec
async *#ag() {}
}
@@ -0,0 +1,3 @@
{
"minNodeVersion": "16.11.0"
}
@@ -0,0 +1,15 @@
var _initProto, _dec, _call_a, _dec2, _call_g, _dec3, _call_ag;
_dec = dec;
_dec2 = dec;
_dec3 = dec;
class Foo {
static {
[_call_a, _call_g, _call_ag, _initProto] = babelHelpers.applyDecs2311(this, [[_dec, 2, "a", async function () {}], [_dec2, 2, "g", function* () {}], [_dec3, 2, "ag", async function* () {}]], [], 0, _ => #a in _).e;
}
constructor() {
_initProto(this);
}
#ag = _call_ag;
#g = _call_g;
#a = _call_a;
}