Skip to content

Commit

Permalink
Implement async-do-expressions transform (#13117)
Browse files Browse the repository at this point in the history
Co-authored-by: Brian Ng <bng412@gmail.com>
  • Loading branch information
JLHwung and existentialism committed Apr 12, 2021
1 parent a6b98a7 commit 9c923a8
Show file tree
Hide file tree
Showing 27 changed files with 198 additions and 1 deletion.
@@ -0,0 +1,3 @@
src
test
*.log
19 changes: 19 additions & 0 deletions packages/babel-plugin-proposal-async-do-expressions/README.md
@@ -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
```
36 changes: 36 additions & 0 deletions packages/babel-plugin-proposal-async-do-expressions/package.json
@@ -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"
}
51 changes: 51 additions & 0 deletions packages/babel-plugin-proposal-async-do-expressions/src/index.ts
@@ -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),
[],
),
);
},
},
},
};
});
@@ -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 });
@@ -0,0 +1 @@
const x = async do { 21 + 21 };
@@ -0,0 +1,3 @@
const x = (async () => {
return 21 + 21;
})();
@@ -0,0 +1 @@
async do {}
@@ -0,0 +1 @@
(async () => {})();
@@ -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 });
@@ -0,0 +1 @@
const x = async do { var y = 21; y + y }
@@ -0,0 +1,6 @@
var y;

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

const x = (async () => {
await Promise.resolve();
y = 21;
return y + y;
})();
@@ -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 });
@@ -0,0 +1 @@
const x = async do { let x = 21; x + x };
@@ -0,0 +1,5 @@
const x = (async () => {
let x = 21;
return x + x;
})();

@@ -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") });
@@ -0,0 +1 @@
const x = async do { throw new Error("sync") };
@@ -0,0 +1,3 @@
const x = (async () => {
throw new Error("sync");
})();
@@ -0,0 +1,4 @@
{
"plugins": ["proposal-async-do-expressions"],
"minNodeVersion": "8.0.0"
}
@@ -0,0 +1,2 @@
// sync do expressions are not handled by this plugin
(do {});
@@ -0,0 +1,4 @@
{
"plugins": ["proposal-async-do-expressions"],
"minNodeVersion": "6.0.0"
}
@@ -0,0 +1,2 @@
// sync do expressions are not handled by this plugin
(do {});
@@ -0,0 +1,3 @@
import runner from "@babel/helper-plugin-test-runner";

runner(import.meta.url);
18 changes: 17 additions & 1 deletion yarn.lock
Expand Up @@ -1050,6 +1050,22 @@ __metadata:
languageName: unknown
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.5":
version: 7.13.5
resolution: "@babel/plugin-proposal-async-generator-functions@npm:7.13.5"
Expand Down Expand Up @@ -1537,7 +1553,7 @@ __metadata:
languageName: unknown
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
resolution: "@babel/plugin-syntax-async-do-expressions@workspace:packages/babel-plugin-syntax-async-do-expressions"
dependencies:
Expand Down

0 comments on commit 9c923a8

Please sign in to comment.