From af453abca101b75470c8d4f4bfe66b5a5be60f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 11 Dec 2020 20:29:07 +0100 Subject: [PATCH] Implement `setClassMethods` assumption (#12407) --- .../babel-core/src/config/validation/options.js | 1 + .../babel-plugin-transform-classes/src/index.js | 6 +++++- .../src/transformClass.js | 5 ++++- .../literal-key/input.js | 5 +++++ .../literal-key/output.js | 13 +++++++++++++ .../method-return-type-annotation/input.js | 6 ++++++ .../method-return-type-annotation/options.json | 10 ++++++++++ .../method-return-type-annotation/output.js | 14 ++++++++++++++ .../method-reuse-prototype/input.js | 5 +++++ .../method-reuse-prototype/output.js | 17 +++++++++++++++++ .../assumption-setClassMethods/options.json | 12 ++++++++++++ .../program-with-use-strict-directive/input.js | 7 +++++++ .../program-with-use-strict-directive/output.js | 13 +++++++++++++ 13 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js create mode 100644 packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js diff --git a/packages/babel-core/src/config/validation/options.js b/packages/babel-core/src/config/validation/options.js index 7d8b606e12dd..81724f7f97d1 100644 --- a/packages/babel-core/src/config/validation/options.js +++ b/packages/babel-core/src/config/validation/options.js @@ -334,6 +334,7 @@ export type NestingPath = RootPath | OverridesPath | EnvPath; export const assumptionsNames = new Set([ "ignoreToPrimitiveHint", "mutableTemplateObject", + "setClassMethods", "setPublicClassFields", ]); diff --git a/packages/babel-plugin-transform-classes/src/index.js b/packages/babel-plugin-transform-classes/src/index.js index 8f0ecfc202ca..9bf8350dd33a 100644 --- a/packages/babel-plugin-transform-classes/src/index.js +++ b/packages/babel-plugin-transform-classes/src/index.js @@ -21,6 +21,8 @@ export default declare((api, options) => { const { loose } = options; + const setClassMethods = api.assumption("setClassMethods") ?? options.loose; + // todo: investigate traversal requeueing const VISITED = Symbol(); @@ -58,7 +60,9 @@ export default declare((api, options) => { node[VISITED] = true; path.replaceWith( - transformClass(path, state.file, builtinClasses, loose), + transformClass(path, state.file, builtinClasses, loose, { + setClassMethods, + }), ); if (path.isCallExpression()) { diff --git a/packages/babel-plugin-transform-classes/src/transformClass.js b/packages/babel-plugin-transform-classes/src/transformClass.js index 0d3fa37600d8..67df2ab0d56d 100644 --- a/packages/babel-plugin-transform-classes/src/transformClass.js +++ b/packages/babel-plugin-transform-classes/src/transformClass.js @@ -11,6 +11,8 @@ import addCreateSuperHelper from "./inline-createSuper-helpers"; type ReadonlySet = Set | { has(val: T): boolean }; +type ClassAssumptions = { setClassMethods: boolean }; + function buildConstructor(classRef, constructorBody, node) { const func = t.functionDeclaration( t.cloneNode(classRef), @@ -26,6 +28,7 @@ export default function transformClass( file: any, builtinClasses: ReadonlySet, isLoose: boolean, + assumptions: ClassAssumptions, ) { const classState = { parent: undefined, @@ -452,7 +455,7 @@ export default function transformClass( } function processMethod(node, scope) { - if (classState.isLoose && !node.decorators) { + if (assumptions.setClassMethods && !node.decorators) { // use assignments instead of define properties for loose classes let { classRef } = classState; if (!node.static) { diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js new file mode 100644 index 000000000000..e3ad20145b86 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js @@ -0,0 +1,5 @@ +class Foo { + "bar"() { + + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js new file mode 100644 index 000000000000..610fbb5a157e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js @@ -0,0 +1,13 @@ +var Foo = /*#__PURE__*/function () { + "use strict"; + + function Foo() { + babelHelpers.classCallCheck(this, Foo); + } + + var _proto = Foo.prototype; + + _proto["bar"] = function bar() {}; + + return Foo; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js new file mode 100644 index 000000000000..918e7469b6c7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js @@ -0,0 +1,6 @@ +// @flow +class C { + m(x: number): string { + return 'a'; + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json new file mode 100644 index 000000000000..1f9617ec390b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + "external-helpers", + "transform-function-name", + ["transform-classes", { "loose": true }], + "transform-spread", + "transform-block-scoping", + "syntax-flow" + ] +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js new file mode 100644 index 000000000000..45403829143d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js @@ -0,0 +1,14 @@ +// @flow +var C = /*#__PURE__*/function () { + "use strict"; + + function C() {} + + var _proto = C.prototype; + + _proto.m = function m(x: number): string { + return 'a'; + }; + + return C; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js new file mode 100644 index 000000000000..1c08a3644980 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js @@ -0,0 +1,5 @@ +class Test { + a() {} + static b() {} + c() {} +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js new file mode 100644 index 000000000000..844b0d7655e7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js @@ -0,0 +1,17 @@ +var Test = /*#__PURE__*/function () { + "use strict"; + + function Test() { + babelHelpers.classCallCheck(this, Test); + } + + var _proto = Test.prototype; + + _proto.a = function a() {}; + + Test.b = function b() {}; + + _proto.c = function c() {}; + + return Test; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json new file mode 100644 index 000000000000..62562eb645d7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-function-name", + "transform-classes", + ["transform-spread", { "loose": true }], + "transform-block-scoping" + ], + "assumptions": { + "setClassMethods": true + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js new file mode 100644 index 000000000000..4bbf0638b3be --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js @@ -0,0 +1,7 @@ +"use strict"; + +class Foo { + method() { + + } +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js new file mode 100644 index 000000000000..96acb356c59a --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js @@ -0,0 +1,13 @@ +"use strict"; + +var Foo = /*#__PURE__*/function () { + function Foo() { + babelHelpers.classCallCheck(this, Foo); + } + + var _proto = Foo.prototype; + + _proto.method = function method() {}; + + return Foo; +}();