Skip to content

Commit 4194e9f

Browse files
committed
vm: expose hasTopLevelAwait on SourceTextModule
Expose `hasTopLevelAwait` and `getHasAsyncGraph` on `vm.SourceTextModule`. `getHasAsyncGraph` requires the module to be instantiated first.
1 parent 22a864a commit 4194e9f

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed

doc/api/vm.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,33 @@ to disallow any changes to it.
920920
Corresponds to the `[[RequestedModules]]` field of [Cyclic Module Record][]s in
921921
the ECMAScript specification.
922922
923+
### `sourceTextModule.getHasAsyncGraph()`
924+
925+
<!-- YAML
926+
added: REPLACEME
927+
-->
928+
929+
* Returns: {boolean}
930+
931+
Returns `true` if the module has a dependency graph that contains top-level
932+
`await` expressions, otherwise returns `false`.
933+
934+
This requires the module to be instantiated first. If the module is not
935+
instantiated yet, an error will be thrown.
936+
937+
### `sourceTextModule.hasTopLevelAwait`
938+
939+
<!-- YAML
940+
added: REPLACEME
941+
-->
942+
943+
* Type: {boolean}
944+
945+
Indicates whether the module contains any top-level `await` expressions.
946+
947+
This corresponds to the field `[[HasTLA]]` in [Cyclic Module Record][] in the
948+
ECMAScript specification.
949+
923950
### `sourceTextModule.instantiate()`
924951
925952
<!-- YAML

lib/internal/vm/module.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,19 @@ class SourceTextModule extends Module {
429429
return super.error;
430430
}
431431

432+
get hasTopLevelAwait() {
433+
validateThisInternalField(this, kWrap, 'SourceTextModule');
434+
return this[kWrap].hasTopLevelAwait;
435+
}
436+
437+
getHasAsyncGraph() {
438+
validateThisInternalField(this, kWrap, 'SourceTextModule');
439+
if (this[kWrap].getStatus() < kInstantiated) {
440+
throw new ERR_VM_MODULE_STATUS('must be instantiated');
441+
}
442+
return this[kWrap].hasAsyncGraph;
443+
}
444+
432445
createCachedData() {
433446
const { status } = this;
434447
if (status === 'evaluating' ||
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict';
2+
3+
// Flags: --experimental-vm-modules
4+
5+
require('../common');
6+
7+
const assert = require('assert');
8+
9+
const { SourceTextModule } = require('vm');
10+
const test = require('node:test');
11+
12+
test('module is not instantiated yet', () => {
13+
const foo = new SourceTextModule(`
14+
export const foo = 4
15+
export default 5;
16+
`);
17+
assert.throws(() => foo.getHasAsyncGraph(), {
18+
code: 'ERR_VM_MODULE_STATUS',
19+
});
20+
});
21+
22+
test('simple module with top-level await', () => {
23+
const foo = new SourceTextModule(`
24+
export const foo = 4
25+
export default 5;
26+
27+
await 0;
28+
`);
29+
foo.linkRequests([]);
30+
foo.instantiate();
31+
32+
assert.strictEqual(foo.getHasAsyncGraph(), true);
33+
});
34+
35+
test('simple module with non top-level await', () => {
36+
const foo = new SourceTextModule(`
37+
export const foo = 4
38+
export default 5;
39+
40+
export async function f() {
41+
await 0;
42+
}
43+
`);
44+
foo.linkRequests([]);
45+
foo.instantiate();
46+
47+
assert.strictEqual(foo.getHasAsyncGraph(), false);
48+
});
49+
50+
test('module with a dependency containing top-level await', () => {
51+
const foo = new SourceTextModule(`
52+
export const foo = 4
53+
export default 5;
54+
55+
await 0;
56+
`);
57+
foo.linkRequests([]);
58+
59+
const bar = new SourceTextModule(`
60+
export { foo } from 'foo';
61+
`);
62+
bar.linkRequests([foo]);
63+
bar.instantiate();
64+
65+
assert.strictEqual(foo.getHasAsyncGraph(), true);
66+
assert.strictEqual(bar.getHasAsyncGraph(), true);
67+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'use strict';
2+
3+
// Flags: --experimental-vm-modules
4+
5+
require('../common');
6+
7+
const assert = require('assert');
8+
9+
const { SourceTextModule } = require('vm');
10+
const test = require('node:test');
11+
12+
test('simple module', () => {
13+
const foo = new SourceTextModule(`
14+
export const foo = 4
15+
export default 5;
16+
`);
17+
assert.strictEqual(foo.hasTopLevelAwait, false);
18+
});
19+
20+
test('simple module with top-level await', () => {
21+
const foo = new SourceTextModule(`
22+
export const foo = 4
23+
export default 5;
24+
25+
await 0;
26+
`);
27+
assert.strictEqual(foo.hasTopLevelAwait, true);
28+
});
29+
30+
test('simple module with non top-level await', () => {
31+
const foo = new SourceTextModule(`
32+
export const foo = 4
33+
export default 5;
34+
35+
export async function f() {
36+
await 0;
37+
}
38+
`);
39+
assert.strictEqual(foo.hasTopLevelAwait, false);
40+
});
41+
42+
test('module with a dependency containing top-level await', () => {
43+
const foo = new SourceTextModule(`
44+
export const foo = 4
45+
export default 5;
46+
47+
await 0;
48+
`);
49+
foo.linkRequests([]);
50+
51+
const bar = new SourceTextModule(`
52+
export { foo } from 'foo';
53+
`);
54+
bar.linkRequests([foo]);
55+
bar.instantiate();
56+
57+
assert.strictEqual(foo.hasTopLevelAwait, true);
58+
assert.strictEqual(bar.hasTopLevelAwait, false);
59+
});

0 commit comments

Comments
 (0)