Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement async-do-expressions transform #13117

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -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