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

Detect awaited rhs values in top level declarations #6

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 15.x, 16.x]
node-version: [14.x, 16.x, 18.x, 20.x, 22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
43 changes: 36 additions & 7 deletions lib/import-export-visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ const codeOfCR = "\r".charCodeAt(0);
const codeOfDoubleQuote = '"'.charCodeAt(0);
const codeOfSingleQuote = "'".charCodeAt(0);

class AwaitDetector extends Visitor {
foundAwait = false;
visitAwaitExpression() {
this.foundAwait = true;
}
}

class ImportExportVisitor extends Visitor {
finalizeHoisting() {
const infoCount = this.bodyInfos.length;
Expand Down Expand Up @@ -388,19 +395,41 @@ class ImportExportVisitor extends Visitor {

visitAwaitExpression(path) {
if (!this.hasTopLevelAwait) {
let parent = path.getParentNode(1);
if (
parent.type === 'ExpressionStatement' &&
path.getParentNode(2).type === 'Program'
) {
this.hasTopLevelAwait = true;
const parent = path.getParentNode(1);
switch (parent.type) {
case "ExpressionStatement":
if (path.getParentNode(2).type === 'Program') {
this.hasTopLevelAwait = true;
}
break;
default:
break;
}
}

// There could be children with import expressions
this.visitChildren(path)
}

containsAwaitExpression(path) {
const subVisitor = new AwaitDetector();
subVisitor.visitChildren(path);
return subVisitor.foundAwait;
}

visitVariableDeclaration(path) {
if (!this.hasTopLevelAwait) {
const parent2 = path.getParentNode(2);
if (parent2?.type !== "Program") {
// Only top level variable declaration(s) impact our TLA detection
return;
}
if (this.containsAwaitExpression(path)) {
this.hasTopLevelAwait = true;
}
}
}

// This is also aliased as visitImport for Babel's AST
visitImportExpression(path) {
if (this.dynamicImport) {
Expand Down
2 changes: 1 addition & 1 deletion node/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ const path = require("path");
const pkgPath = path.join(__dirname, "../package.json");
const SemVer = require("semver");

module.exports = new SemVer(
module.exports = SemVer.parse(
process.env.REIFY_VERSION || fs.readJSON(pkgPath).version
);
3 changes: 3 additions & 0 deletions test/.mocharc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
// grep: /test name to match/i
}
5 changes: 5 additions & 0 deletions test/tla/export-awaited-init-deep.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
await 0

const asyncInitializer = async () => 12;

export const value = Math.max(false ? 666 : await asyncInitializer(), 2);
4 changes: 4 additions & 0 deletions test/tla/export-awaited-init-shallow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const asyncInitializer = async () => 8;

export const value = await asyncInitializer();

10 changes: 10 additions & 0 deletions test/top-level-await-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ import { importSync, importAsync, importAsyncEvaluated } from './tla/nested/pare
assert(exports.value === 5);
});

it('should await shallow variable initializers', async () => {
const exports = await require('./tla/export-awaited-init-shallow.js');
assert(exports.value === 8);
});

it('should await deep variable initializers', async () => {
const exports = await require('./tla/export-awaited-init-deep.js');
assert(exports.value === 12);
});

it('should run setters after module with async dep finished', async () => {
const exports = await require('./tla/export-sync-parent.js');
assert(exports.a === 1);
Expand Down
Loading