[decorators] Set method names at compile time instead of at runtime (#9244)

This commit is contained in:
Nicolò Ribaudo 2019-01-10 00:45:02 +01:00 committed by GitHub
parent 778a61a3c2
commit 8e051cae46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 73 additions and 44 deletions

View File

@ -1,5 +1,6 @@
import { types as t, template } from "@babel/core";
import ReplaceSupers from "@babel/helper-replace-supers";
import nameFunction from "@babel/helper-function-name";
export function hasOwnDecorators(node) {
return !!(node.decorators && node.decorators.length);
@ -14,11 +15,13 @@ function prop(key, value) {
return t.objectProperty(t.identifier(key), value);
}
function value(body, params = [], async, generator) {
const method = t.objectMethod("method", t.identifier("value"), params, body);
method.async = !!async;
method.generator = !!generator;
return method;
function method(key, body) {
return t.objectMethod(
"method",
t.identifier(key),
[],
t.blockStatement(body),
);
}
function takeDecorators(node) {
@ -74,13 +77,20 @@ function extractElementDescriptor(/* this: File, */ classRef, superRef, path) {
prop("decorators", takeDecorators(node)),
prop("static", node.static && t.booleanLiteral(true)),
prop("key", getKey(node)),
isMethod
? value(node.body, node.params, node.async, node.generator)
: node.value
? value(template.ast`{ return ${node.value} }`)
: prop("value", scope.buildUndefinedNode()),
].filter(Boolean);
if (isMethod) {
const id = node.computed ? null : node.key;
t.toExpression(node);
properties.push(prop("value", nameFunction({ node, id, scope }) || node));
} else if (node.value) {
properties.push(
method("value", template.statements.ast`return ${node.value}`),
);
} else {
properties.push(prop("value", scope.buildUndefinedNode()));
}
path.remove();
return t.objectExpression(properties);

View File

@ -1653,10 +1653,6 @@ helpers.decorate = helper("7.1.5")`
configurable: true,
enumerable: false,
};
Object.defineProperty(def.value, "name", {
value: typeof key === "symbol" ? "" : key,
configurable: true,
});
} else if (def.kind === "get") {
descriptor = { get: def.value, configurable: true, enumerable: false };
} else if (def.kind === "set") {

View File

@ -13,19 +13,15 @@ let Foo = babelHelpers.decorate([_ => desc = _], function (_initialize) {
d: [{
kind: "method",
key: getKey(),
value() {
value: function () {
return 1;
}
}, {
kind: "method",
key: getKey(),
value() {
value: function () {
return 2;
}
}]
};
});

View File

@ -13,19 +13,15 @@ let Foo = babelHelpers.decorate([_ => desc = _], function (_initialize) {
d: [{
kind: "method",
key: getKeyI(),
value() {
value: function () {
return 1;
}
}, {
kind: "method",
key: getKeyJ(),
value() {
value: function () {
return 2;
}
}]
};
});

View File

@ -0,0 +1,13 @@
function decorator() {}
var method = 1;
@decorator
class Foo {
method() {
return method;
}
}
expect(new Foo().method()).toBe(1);
expect(Foo.prototype.method.name).toBe("method");

View File

@ -0,0 +1,8 @@
var method = 1;
@decorator
class Foo {
method() {
return method;
}
}

View File

@ -0,0 +1,22 @@
var _method = 1;
let Foo = babelHelpers.decorate([decorator], function (_initialize) {
"use strict";
class Foo {
constructor() {
_initialize(this);
}
}
return {
F: Foo,
d: [{
kind: "method",
key: "method",
value: function method() {
return _method;
}
}]
};
});

View File

@ -14,9 +14,7 @@ let A = babelHelpers.decorate([dec(a, b, ...c)], function (_initialize) {
kind: "method",
decorators: [dec(a, b, ...c)],
key: "method",
value() {}
value: function method() {}
}]
};
});

View File

@ -13,21 +13,15 @@ let Foo = babelHelpers.decorate([decorator], function (_initialize) {
d: [{
kind: "method",
key: "f1",
async value() {}
value: async function f1() {}
}, {
kind: "method",
key: "f2",
*value() {}
value: function* f2() {}
}, {
kind: "method",
key: "f3",
async *value() {}
value: async function* f3() {}
}]
};
});

View File

@ -14,9 +14,7 @@
d: [{
kind: "method",
key: "method",
value() {}
value: function method() {}
}]
};
});
@ -38,9 +36,7 @@
d: [{
kind: "method",
key: "method",
value() {}
value: function method() {}
}]
};
});