Implement async-do-expressions transform (#13117)

Co-authored-by: Brian Ng <bng412@gmail.com>
This commit is contained in:
Huáng Jùnliàng 2021-04-12 10:00:42 -04:00 committed by Nicolò Ribaudo
parent 28d7442aae
commit 50e0e353ee
27 changed files with 198 additions and 1 deletions

View File

@ -0,0 +1,3 @@
src
test
*.log

View File

@ -0,0 +1,19 @@
# @babel/plugin-proposal-async-do-expressions
> Transforms async do expressions to ES2021
See our website [@babel/plugin-proposal-async-do-expressions](https://babeljs.io/docs/en/babel-plugin-proposal-async-do-expressions) for more information.
## Install
Using npm:
```sh
npm install --save-dev @babel/plugin-proposal-async-do-expressions
```
or using yarn:
```sh
yarn add @babel/plugin-proposal-async-do-expressions --dev
```

View File

@ -0,0 +1,36 @@
{
"name": "@babel/plugin-proposal-async-do-expressions",
"version": "7.13.11",
"description": "Transform async do expressions to ES2021",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-plugin-proposal-async-do-expressions"
},
"license": "MIT",
"publishConfig": {
"access": "public"
},
"main": "./lib/index.js",
"exports": {
".": "./lib/index.js"
},
"keywords": [
"babel-plugin"
],
"dependencies": {
"@babel/helper-hoist-variables": "workspace:^7.13.0",
"@babel/helper-plugin-utils": "workspace:^7.13.0",
"@babel/plugin-syntax-async-do-expressions": "workspace:^7.13.0"
},
"peerDependencies": {
"@babel/core": "^7.13.0"
},
"devDependencies": {
"@babel/core": "workspace:*",
"@babel/helper-plugin-test-runner": "workspace:*",
"@babel/traverse": "workspace:*",
"@babel/types": "workspace:*"
},
"homepage": "https://babel.dev/docs/en/next/babel-plugin-proposal-async-do-expressions"
}

View File

@ -0,0 +1,51 @@
import { declare } from "@babel/helper-plugin-utils";
import syntaxAsyncDoExpressions from "@babel/plugin-syntax-async-do-expressions";
import hoistVariables from "@babel/helper-hoist-variables";
import type * as t from "@babel/types";
import type { NodePath } from "@babel/traverse";
export default declare(({ types: t, assertVersion }) => {
assertVersion("^7.13.0");
return {
name: "proposal-async-do-expressions",
inherits: syntaxAsyncDoExpressions,
visitor: {
DoExpression: {
exit(path: NodePath<t.DoExpression>) {
if (!path.is("async")) {
// non-async do expressions are handled by proposal-do-expressions
return;
}
const { scope } = path;
// Hoist variable declaration to containing function scope
// `async do { var x = 1; x }` -> `var x; (async() => { x = 1; return x })()`
hoistVariables(
path,
(id: t.Identifier) => {
scope.push({ id: t.cloneNode(id) });
},
"var",
);
const bodyPath = path.get("body");
// add implicit returns to all ending expression statements
const completionRecords = bodyPath.getCompletionRecords();
for (const p of completionRecords) {
if (p.isExpressionStatement()) {
p.replaceWith(t.returnStatement(p.node.expression));
}
}
path.replaceWith(
t.callExpression(
t.arrowFunctionExpression([], bodyPath.node, /* async */ true),
[],
),
);
},
},
},
};
});

View File

@ -0,0 +1,4 @@
const x = async do { 21 + 21 };
expect(x).toBeInstanceOf(Promise);
x.then((v) => expect(v).toBe(42)).catch(err => { throw err });

View File

@ -0,0 +1 @@
const x = async do { 21 + 21 };

View File

@ -0,0 +1,3 @@
const x = (async () => {
return 21 + 21;
})();

View File

@ -0,0 +1,6 @@
const x = async do { var y = 21; y + y }
expect(y).toBe(21);
x.then((resolved) => {
expect(resolved).toBe(42);
}).catch(err => { throw err });

View File

@ -0,0 +1,6 @@
var y;
const x = (async () => {
y = 21;
return y + y;
})();

View File

@ -0,0 +1,7 @@
const x = async do { await Promise.resolve(); var y = 21; y + y }
expect(y).toBe(undefined);
x.then((resolved) => {
expect(y).toBe(21);
expect(resolved).toBe(42);
}).catch(err => { throw err });

View File

@ -0,0 +1 @@
const x = async do { await Promise.resolve(); var y = 21; y + y }

View File

@ -0,0 +1,7 @@
var y;
const x = (async () => {
await Promise.resolve();
y = 21;
return y + y;
})();

View File

@ -0,0 +1,4 @@
const x = async do { let x = 21; x + x };
expect(x).toBeInstanceOf(Promise);
x.then((v) => expect(v).toBe(42)).catch(err => { throw err });

View File

@ -0,0 +1 @@
const x = async do { let x = 21; x + x };

View File

@ -0,0 +1,5 @@
const x = (async () => {
let x = 21;
return x + x;
})();

View File

@ -0,0 +1,5 @@
const x = async do { throw new Error("sync") };
expect(x).toBeInstanceOf(Promise);
x.then(() => { throw new Error("expected an error: sync is thrown.") })
.catch(err => { expect(err.message).toEqual("sync") });

View File

@ -0,0 +1 @@
const x = async do { throw new Error("sync") };

View File

@ -0,0 +1,3 @@
const x = (async () => {
throw new Error("sync");
})();

View File

@ -0,0 +1,4 @@
{
"plugins": ["proposal-async-do-expressions"],
"minNodeVersion": "8.0.0"
}

View File

@ -0,0 +1,2 @@
// sync do expressions are not handled by this plugin
(do {});

View File

@ -0,0 +1,4 @@
{
"plugins": ["proposal-async-do-expressions"],
"minNodeVersion": "6.0.0"
}

View File

@ -0,0 +1,2 @@
// sync do expressions are not handled by this plugin
(do {});

View File

@ -0,0 +1,3 @@
import runner from "@babel/helper-plugin-test-runner";
runner(import.meta.url);

View File

@ -1021,6 +1021,22 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@babel/plugin-proposal-async-do-expressions@workspace:packages/babel-plugin-proposal-async-do-expressions":
version: 0.0.0-use.local
resolution: "@babel/plugin-proposal-async-do-expressions@workspace:packages/babel-plugin-proposal-async-do-expressions"
dependencies:
"@babel/core": "workspace:*"
"@babel/helper-hoist-variables": "workspace:^7.13.0"
"@babel/helper-plugin-test-runner": "workspace:*"
"@babel/helper-plugin-utils": "workspace:^7.13.0"
"@babel/plugin-syntax-async-do-expressions": "workspace:^7.13.0"
"@babel/traverse": "workspace:*"
"@babel/types": "workspace:*"
peerDependencies:
"@babel/core": ^7.13.0
languageName: unknown
linkType: soft
"@babel/plugin-proposal-async-generator-functions@npm:^7.13.15": "@babel/plugin-proposal-async-generator-functions@npm:^7.13.15":
version: 7.13.15 version: 7.13.15
resolution: "@babel/plugin-proposal-async-generator-functions@npm:7.13.15" resolution: "@babel/plugin-proposal-async-generator-functions@npm:7.13.15"
@ -1512,7 +1528,7 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@babel/plugin-syntax-async-do-expressions@workspace:packages/babel-plugin-syntax-async-do-expressions": "@babel/plugin-syntax-async-do-expressions@workspace:^7.13.0, @babel/plugin-syntax-async-do-expressions@workspace:packages/babel-plugin-syntax-async-do-expressions":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@babel/plugin-syntax-async-do-expressions@workspace:packages/babel-plugin-syntax-async-do-expressions" resolution: "@babel/plugin-syntax-async-do-expressions@workspace:packages/babel-plugin-syntax-async-do-expressions"
dependencies: dependencies: