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..d38f4dfca4a9 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,20 @@ function plainFunction(path: NodePath, callId: any, noNewArrows: boolean) { } const built = callExpression(callId, [node]); + + 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"), 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 +122,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 +142,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.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/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.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]) {}); 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); +} 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* () {}));