Skip to content

Commit 910ece5

Browse files
authored
Optimize transform-async-to-generator output (#14122)
* 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
1 parent 213397b commit 910ece5

11 files changed

Lines changed: 102 additions & 21 deletions

File tree

packages/babel-helper-remap-async-to-generator/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default function (
3636
wrapAwait?: any;
3737
},
3838
noNewArrows?: boolean,
39+
ignoreFunctionLength?: boolean,
3940
) {
4041
path.traverse(awaitVisitor, {
4142
wrapAwait: helpers.wrapAwait,
@@ -46,7 +47,12 @@ export default function (
4647
path.node.async = false;
4748
path.node.generator = true;
4849

49-
wrapFunction(path, cloneNode(helpers.wrapAsync), noNewArrows);
50+
wrapFunction(
51+
path,
52+
cloneNode(helpers.wrapAsync),
53+
noNewArrows,
54+
ignoreFunctionLength,
55+
);
5056

5157
const isProperty =
5258
path.isObjectMethod() ||

packages/babel-helper-wrap-function/src/index.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ function classOrObjectMethod(
6666
).unwrapFunctionEnvironment();
6767
}
6868

69-
function plainFunction(path: NodePath<any>, callId: any, noNewArrows: boolean) {
69+
function plainFunction(
70+
path: NodePath<any>,
71+
callId: any,
72+
noNewArrows: boolean,
73+
ignoreFunctionLength: boolean,
74+
) {
7075
const node = path.node;
7176
const isDeclaration = path.isFunctionDeclaration();
7277
const functionId = node.id;
@@ -87,26 +92,20 @@ function plainFunction(path: NodePath<any>, callId: any, noNewArrows: boolean) {
8792
}
8893

8994
const built = callExpression(callId, [node]);
95+
96+
const params: t.Identifier[] = [];
97+
for (const param of node.params) {
98+
if (isAssignmentPattern(param) || isRestElement(param)) {
99+
break;
100+
}
101+
params.push(path.scope.generateUidIdentifier("x"));
102+
}
103+
90104
const container = wrapper({
91105
NAME: functionId || null,
92106
REF: path.scope.generateUidIdentifier(functionId ? functionId.name : "ref"),
93107
FUNCTION: built,
94-
PARAMS: node.params.reduce(
95-
(acc, param) => {
96-
acc.done =
97-
acc.done || isAssignmentPattern(param) || isRestElement(param);
98-
99-
if (!acc.done) {
100-
acc.params.push(path.scope.generateUidIdentifier("x"));
101-
}
102-
103-
return acc;
104-
},
105-
{
106-
params: [],
107-
done: false,
108-
},
109-
).params,
108+
PARAMS: params,
110109
});
111110

112111
if (isDeclaration) {
@@ -123,7 +122,11 @@ function plainFunction(path: NodePath<any>, callId: any, noNewArrows: boolean) {
123122
});
124123
}
125124

126-
if (!retFunction || retFunction.id || node.params.length) {
125+
if (
126+
!retFunction ||
127+
retFunction.id ||
128+
(!ignoreFunctionLength && params.length)
129+
) {
127130
// we have an inferred function id or params so we need this wrapper
128131
// @ts-expect-error todo(flow->ts) separate `wrapper` for `isDeclaration` and `else` branches
129132
path.replaceWith(container);
@@ -139,10 +142,11 @@ export default function wrapFunction(
139142
callId: any,
140143
// TODO(Babel 8): Consider defaulting to false for spec compliancy
141144
noNewArrows: boolean = true,
145+
ignoreFunctionLength: boolean = false,
142146
) {
143147
if (path.isMethod()) {
144148
classOrObjectMethod(path, callId);
145149
} else {
146-
plainFunction(path, callId, noNewArrows);
150+
plainFunction(path, callId, noNewArrows, ignoreFunctionLength);
147151
}
148152
}

packages/babel-plugin-transform-async-to-generator/src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default declare((api, options) => {
88

99
const { method, module } = options;
1010
const noNewArrows = api.assumption("noNewArrows");
11+
const ignoreFunctionLength = api.assumption("ignoreFunctionLength");
1112

1213
if (method && module) {
1314
return {
@@ -24,7 +25,12 @@ export default declare((api, options) => {
2425
wrapAsync = state.methodWrapper = addNamed(path, method, module);
2526
}
2627

27-
remapAsyncToGenerator(path, { wrapAsync }, noNewArrows);
28+
remapAsyncToGenerator(
29+
path,
30+
{ wrapAsync },
31+
noNewArrows,
32+
ignoreFunctionLength,
33+
);
2834
},
2935
},
3036
};
@@ -41,6 +47,7 @@ export default declare((api, options) => {
4147
path,
4248
{ wrapAsync: state.addHelper("asyncToGenerator") },
4349
noNewArrows,
50+
ignoreFunctionLength,
4451
);
4552
},
4653
},
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
foo(async (x) => {});
2+
foo(async ([x]) => {});
3+
foo(async ({ x }) => {});
4+
5+
foo(async function (x) {});
6+
foo(async function ([x]) {});
7+
foo(async function ({ x }) {});
8+
9+
foo(async ([]) => {});
10+
foo(async ({}) => {});
11+
12+
foo(async function ([]) {});
13+
foo(async function ({}) {});
14+
15+
export default async ([...x]) => {};
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"plugins": ["transform-async-to-generator"],
3+
"assumptions": {
4+
"ignoreFunctionLength": true
5+
}
6+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (x) {}));
2+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([x]) {}));
3+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({
4+
x
5+
}) {}));
6+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* (x) {}));
7+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([x]) {}));
8+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({
9+
x
10+
}) {}));
11+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([]) {}));
12+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({}) {}));
13+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([]) {}));
14+
foo( /*#__PURE__*/babelHelpers.asyncToGenerator(function* ({}) {}));
15+
export default /*#__PURE__*/babelHelpers.asyncToGenerator(function* ([...x]) {});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default async function (x) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"plugins": ["transform-async-to-generator"],
3+
"assumptions": {
4+
"ignoreFunctionLength": true
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default function (_x) {
2+
return _ref.apply(this, arguments);
3+
}
4+
5+
function _ref() {
6+
_ref = babelHelpers.asyncToGenerator(function* (x) {});
7+
return _ref.apply(this, arguments);
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
foo(async function () {
22

33
});
4+
5+
bar(async function (x = 1) {
6+
7+
});
8+
9+
baz(async function (...y) {
10+
11+
});

0 commit comments

Comments
 (0)