Skip to content

Commit

Permalink
Optimize transform-async-to-generator output (#14122)
Browse files Browse the repository at this point in the history
* Optimize `transform-async-to-generator` output

- remove wrapper if the function length is zero.
- remove wrapper if the `assumptions.ignoreFunctionLength` is `true`.

* chore: update test case and code style

* chore: add test
  • Loading branch information
magic-akari committed Jan 8, 2022
1 parent 213397b commit 910ece5
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 21 deletions.
8 changes: 7 additions & 1 deletion packages/babel-helper-remap-async-to-generator/src/index.ts
Expand Up @@ -36,6 +36,7 @@ export default function (
wrapAwait?: any;
},
noNewArrows?: boolean,
ignoreFunctionLength?: boolean,
) {
path.traverse(awaitVisitor, {
wrapAwait: helpers.wrapAwait,
Expand All @@ -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() ||
Expand Down
42 changes: 23 additions & 19 deletions packages/babel-helper-wrap-function/src/index.ts
Expand Up @@ -66,7 +66,12 @@ function classOrObjectMethod(
).unwrapFunctionEnvironment();
}

function plainFunction(path: NodePath<any>, callId: any, noNewArrows: boolean) {
function plainFunction(
path: NodePath<any>,
callId: any,
noNewArrows: boolean,
ignoreFunctionLength: boolean,
) {
const node = path.node;
const isDeclaration = path.isFunctionDeclaration();
const functionId = node.id;
Expand All @@ -87,26 +92,20 @@ function plainFunction(path: NodePath<any>, 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) {
Expand All @@ -123,7 +122,11 @@ function plainFunction(path: NodePath<any>, 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);
Expand All @@ -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);
}
}
Expand Up @@ -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 {
Expand All @@ -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,
);
},
},
};
Expand All @@ -41,6 +47,7 @@ export default declare((api, options) => {
path,
{ wrapAsync: state.addHelper("asyncToGenerator") },
noNewArrows,
ignoreFunctionLength,
);
},
},
Expand Down
@@ -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]) => {};

@@ -0,0 +1,6 @@
{
"plugins": ["transform-async-to-generator"],
"assumptions": {
"ignoreFunctionLength": true
}
}
@@ -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]) {});
@@ -0,0 +1 @@
export default async function (x) {}
@@ -0,0 +1,6 @@
{
"plugins": ["transform-async-to-generator"],
"assumptions": {
"ignoreFunctionLength": true
}
}
@@ -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);
}
@@ -1,3 +1,11 @@
foo(async function () {

});

bar(async function (x = 1) {

});

baz(async function (...y) {

});
@@ -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* () {}));

0 comments on commit 910ece5

Please sign in to comment.