From 1453baf82334b22d357491b2182e07bd5f1d15f0 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Sat, 8 Jan 2022 23:52:08 +0800 Subject: [PATCH 1/3] Optimize `transform-async-to-generator` output - remove wrapper if the function length is zero. - remove wrapper if the `assumptions.ignoreFunctionLength` is `true`. --- .../src/index.ts | 8 +++- .../babel-helper-wrap-function/src/index.ts | 48 +++++++++++-------- .../src/index.ts | 9 +++- .../basic/input.js | 7 +++ .../basic/options.json | 6 +++ .../basic/output.js | 9 ++++ .../no-parameters-and-no-id/input.js | 8 ++++ .../no-parameters-and-no-id/output.js | 4 ++ 8 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/options.json create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js diff --git a/packages/babel-helper-remap-async-to-generator/src/index.ts b/packages/babel-helper-remap-async-to-generator/src/index.ts index 47926f221d60..a4df21c8e60e 100644 --- a/packages/babel-helper-remap-async-to-generator/src/index.ts +++ b/packages/babel-helper-remap-async-to-generator/src/index.ts @@ -36,6 +36,7 @@ export default function ( wrapAwait?: any; }, noNewArrows?: boolean, + ignoreFunctionLength?: boolean, ) { path.traverse(awaitVisitor, { wrapAwait: helpers.wrapAwait, @@ -46,7 +47,12 @@ export default function ( path.node.async = false; path.node.generator = true; - wrapFunction(path, cloneNode(helpers.wrapAsync), noNewArrows); + wrapFunction( + path, + cloneNode(helpers.wrapAsync), + noNewArrows, + ignoreFunctionLength, + ); const isProperty = path.isObjectMethod() || diff --git a/packages/babel-helper-wrap-function/src/index.ts b/packages/babel-helper-wrap-function/src/index.ts index 2c876225674f..ada6b3e8b4d5 100644 --- a/packages/babel-helper-wrap-function/src/index.ts +++ b/packages/babel-helper-wrap-function/src/index.ts @@ -66,7 +66,12 @@ function classOrObjectMethod( ).unwrapFunctionEnvironment(); } -function plainFunction(path: NodePath, callId: any, noNewArrows: boolean) { +function plainFunction( + path: NodePath, + callId: any, + noNewArrows: boolean, + ignoreFunctionLength: boolean, +) { const node = path.node; const isDeclaration = path.isFunctionDeclaration(); const functionId = node.id; @@ -87,26 +92,26 @@ function plainFunction(path: NodePath, callId: any, noNewArrows: boolean) { } const built = callExpression(callId, [node]); + const params = node.params.reduce( + (acc, param) => { + acc.done = acc.done || isAssignmentPattern(param) || isRestElement(param); + + if (!acc.done) { + acc.params.push(path.scope.generateUidIdentifier("x")); + } + + return acc; + }, + { + params: [], + done: false, + }, + ).params; const container = wrapper({ NAME: functionId || null, REF: path.scope.generateUidIdentifier(functionId ? functionId.name : "ref"), FUNCTION: built, - PARAMS: node.params.reduce( - (acc, param) => { - acc.done = - acc.done || isAssignmentPattern(param) || isRestElement(param); - - if (!acc.done) { - acc.params.push(path.scope.generateUidIdentifier("x")); - } - - return acc; - }, - { - params: [], - done: false, - }, - ).params, + PARAMS: params, }); if (isDeclaration) { @@ -123,7 +128,11 @@ function plainFunction(path: NodePath, callId: any, noNewArrows: boolean) { }); } - if (!retFunction || retFunction.id || node.params.length) { + if ( + !retFunction || + retFunction.id || + (!ignoreFunctionLength && params.length) + ) { // we have an inferred function id or params so we need this wrapper // @ts-expect-error todo(flow->ts) separate `wrapper` for `isDeclaration` and `else` branches path.replaceWith(container); @@ -139,10 +148,11 @@ export default function wrapFunction( callId: any, // TODO(Babel 8): Consider defaulting to false for spec compliancy noNewArrows: boolean = true, + ignoreFunctionLength: boolean = false, ) { if (path.isMethod()) { classOrObjectMethod(path, callId); } else { - plainFunction(path, callId, noNewArrows); + plainFunction(path, callId, noNewArrows, ignoreFunctionLength); } } diff --git a/packages/babel-plugin-transform-async-to-generator/src/index.ts b/packages/babel-plugin-transform-async-to-generator/src/index.ts index da21acedbf12..0a7f67abdb33 100644 --- a/packages/babel-plugin-transform-async-to-generator/src/index.ts +++ b/packages/babel-plugin-transform-async-to-generator/src/index.ts @@ -8,6 +8,7 @@ export default declare((api, options) => { const { method, module } = options; const noNewArrows = api.assumption("noNewArrows"); + const ignoreFunctionLength = api.assumption("ignoreFunctionLength"); if (method && module) { return { @@ -24,7 +25,12 @@ export default declare((api, options) => { wrapAsync = state.methodWrapper = addNamed(path, method, module); } - remapAsyncToGenerator(path, { wrapAsync }, noNewArrows); + remapAsyncToGenerator( + path, + { wrapAsync }, + noNewArrows, + ignoreFunctionLength, + ); }, }, }; @@ -41,6 +47,7 @@ export default declare((api, options) => { path, { wrapAsync: state.addHelper("asyncToGenerator") }, noNewArrows, + ignoreFunctionLength, ); }, }, diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js new file mode 100644 index 000000000000..b8e929518cb7 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js @@ -0,0 +1,7 @@ +async (x = 1) => 1; +(async function (x = 2) { + return 2; +})(); + +foo(async (...x) => {}); +foo(async (...[...y]) => {}); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/options.json new file mode 100644 index 000000000000..6da7c2f04c43 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["transform-async-to-generator"], + "assumptions": { + "ignoreFunctionLength": true + } +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js new file mode 100644 index 000000000000..2245e9982cf7 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js @@ -0,0 +1,9 @@ +/*#__PURE__*/ +babelHelpers.asyncToGenerator(function* (x = 1) { + return 1; +}); +babelHelpers.asyncToGenerator(function* (x = 2) { + return 2; +})(); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (...x) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (...[...y]) {})); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/input.js index ace10cfe9a0b..451f68978e60 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/input.js +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/input.js @@ -1,3 +1,11 @@ foo(async function () { }); + +bar(async function (x = 1) { + +}); + +baz(async function (...y) { + +}); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/output.js index 1dda565d4241..b2a500ea44a4 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/output.js +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/no-parameters-and-no-id/output.js @@ -1 +1,5 @@ foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* () {})); +bar( /*#__PURE__*/babelHelpers.asyncToGenerator(function* () { + let x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; +})); +baz( /*#__PURE__*/babelHelpers.asyncToGenerator(function* () {})); From c94c94eae801434aa2feab973338f8f04a0378f0 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Sun, 9 Jan 2022 01:41:27 +0800 Subject: [PATCH 2/3] chore: update test case and code style --- .../babel-helper-wrap-function/src/index.ts | 24 +++++++------------ .../basic/input.js | 7 ------ .../basic/input.mjs | 16 +++++++++++++ .../basic/output.js | 9 ------- .../basic/output.mjs | 15 ++++++++++++ 5 files changed, 40 insertions(+), 31 deletions(-) delete mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.mjs delete mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.mjs diff --git a/packages/babel-helper-wrap-function/src/index.ts b/packages/babel-helper-wrap-function/src/index.ts index ada6b3e8b4d5..d38f4dfca4a9 100644 --- a/packages/babel-helper-wrap-function/src/index.ts +++ b/packages/babel-helper-wrap-function/src/index.ts @@ -92,21 +92,15 @@ function plainFunction( } const built = callExpression(callId, [node]); - const params = node.params.reduce( - (acc, param) => { - acc.done = acc.done || isAssignmentPattern(param) || isRestElement(param); - - if (!acc.done) { - acc.params.push(path.scope.generateUidIdentifier("x")); - } - - return acc; - }, - { - params: [], - done: false, - }, - ).params; + + const params: t.Identifier[] = []; + for (const param of node.params) { + if (isAssignmentPattern(param) || isRestElement(param)) { + break; + } + params.push(path.scope.generateUidIdentifier("x")); + } + const container = wrapper({ NAME: functionId || null, REF: path.scope.generateUidIdentifier(functionId ? functionId.name : "ref"), diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js deleted file mode 100644 index b8e929518cb7..000000000000 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.js +++ /dev/null @@ -1,7 +0,0 @@ -async (x = 1) => 1; -(async function (x = 2) { - return 2; -})(); - -foo(async (...x) => {}); -foo(async (...[...y]) => {}); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.mjs b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.mjs new file mode 100644 index 000000000000..b65c145a5e17 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/input.mjs @@ -0,0 +1,16 @@ +foo(async (x) => {}); +foo(async ([x]) => {}); +foo(async ({ x }) => {}); + +foo(async function (x) {}); +foo(async function ([x]) {}); +foo(async function ({ x }) {}); + +foo(async ([]) => {}); +foo(async ({}) => {}); + +foo(async function ([]) {}); +foo(async function ({}) {}); + +export default async ([...x]) => {}; + diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js deleted file mode 100644 index 2245e9982cf7..000000000000 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.js +++ /dev/null @@ -1,9 +0,0 @@ -/*#__PURE__*/ -babelHelpers.asyncToGenerator(function* (x = 1) { - return 1; -}); -babelHelpers.asyncToGenerator(function* (x = 2) { - return 2; -})(); -foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (...x) {})); -foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (...[...y]) {})); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.mjs b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.mjs new file mode 100644 index 000000000000..e563cd15d3ea --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/basic/output.mjs @@ -0,0 +1,15 @@ +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (x) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([x]) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({ + x +}) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (x) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([x]) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({ + x +}) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([]) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({}) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([]) {})); +foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({}) {})); +export default /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([...x]) {}); From 81172a49d49ca6640ff64142af0cbb2223a795bc Mon Sep 17 00:00:00 2001 From: magic-akari Date: Sun, 9 Jan 2022 01:57:57 +0800 Subject: [PATCH 3/3] chore: add test --- .../export-default-function/input.mjs | 1 + .../export-default-function/options.json | 6 ++++++ .../export-default-function/output.mjs | 8 ++++++++ 3 files changed, 15 insertions(+) create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/input.mjs create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/options.json create mode 100644 packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/output.mjs diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/input.mjs b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/input.mjs new file mode 100644 index 000000000000..2aed35189d43 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/input.mjs @@ -0,0 +1 @@ +export default async function (x) {} \ No newline at end of file diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/options.json new file mode 100644 index 000000000000..6da7c2f04c43 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["transform-async-to-generator"], + "assumptions": { + "ignoreFunctionLength": true + } +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/output.mjs b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/output.mjs new file mode 100644 index 000000000000..cfed4f14f0cf --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-ignoreFunctionLength-true/export-default-function/output.mjs @@ -0,0 +1,8 @@ +export default function (_x) { + return _ref.apply(this, arguments); +} + +function _ref() { + _ref = babelHelpers.asyncToGenerator(function* (x) {}); + return _ref.apply(this, arguments); +}