vm: import call should return a promise in the current context · nodejs/node@2d5a1ef
1+// Flags: --experimental-vm-modules
2+'use strict';
3+4+const common = require('../common');
5+6+const assert = require('assert');
7+const { createContext, Script, SourceTextModule } = require('vm');
8+9+// Verifies that a `import` call returns a promise created in the context
10+// where the `import` was called, not the context of `importModuleDynamically`
11+// callback.
12+13+async function testScript() {
14+const ctx = createContext();
15+16+const mod1 = new SourceTextModule('export const a = 1;', {
17+context: ctx,
18+});
19+// No import statements, so must not link statically.
20+await mod1.link(common.mustNotCall());
21+22+const script2 = new Script(`
23+ const promise = import("mod1");
24+ if (Object.getPrototypeOf(promise) !== Promise.prototype) {
25+ throw new Error('Expected promise to be created in the current context');
26+ }
27+ globalThis.__result = promise;
28+ `, {
29+importModuleDynamically: common.mustCall((specifier, referrer) => {
30+assert.strictEqual(specifier, 'mod1');
31+assert.strictEqual(referrer, script2);
32+return mod1;
33+}),
34+});
35+script2.runInContext(ctx);
36+37+// Wait for the promise to resolve.
38+await ctx.__result;
39+}
40+41+async function testScriptImportFailed() {
42+const ctx = createContext();
43+44+const mod1 = new SourceTextModule('export const a = 1;', {
45+context: ctx,
46+});
47+// No import statements, so must not link statically.
48+await mod1.link(common.mustNotCall());
49+50+const err = new Error('import failed');
51+const script2 = new Script(`
52+ const promise = import("mod1");
53+ if (Object.getPrototypeOf(promise) !== Promise.prototype) {
54+ throw new Error('Expected promise to be created in the current context');
55+ }
56+ globalThis.__result = promise;
57+ `, {
58+importModuleDynamically: common.mustCall((specifier, referrer) => {
59+throw err;
60+}),
61+});
62+script2.runInContext(ctx);
63+64+// Wait for the promise to reject.
65+await assert.rejects(ctx.__result, err);
66+}
67+68+async function testModule() {
69+const ctx = createContext();
70+71+const mod1 = new SourceTextModule('export const a = 1;', {
72+context: ctx,
73+});
74+// No import statements, so must not link statically.
75+await mod1.link(common.mustNotCall());
76+77+const mod2 = new SourceTextModule(`
78+ const promise = import("mod1");
79+ if (Object.getPrototypeOf(promise) !== Promise.prototype) {
80+ throw new Error('Expected promise to be created in the current context');
81+ }
82+ await promise;
83+ `, {
84+context: ctx,
85+importModuleDynamically: common.mustCall((specifier, referrer) => {
86+assert.strictEqual(specifier, 'mod1');
87+assert.strictEqual(referrer, mod2);
88+return mod1;
89+}),
90+});
91+// No import statements, so must not link statically.
92+await mod2.link(common.mustNotCall());
93+await mod2.evaluate();
94+}
95+96+async function testModuleImportFailed() {
97+const ctx = createContext();
98+99+const mod1 = new SourceTextModule('export const a = 1;', {
100+context: ctx,
101+});
102+// No import statements, so must not link statically.
103+await mod1.link(common.mustNotCall());
104+105+const err = new Error('import failed');
106+ctx.__err = err;
107+const mod2 = new SourceTextModule(`
108+ const promise = import("mod1");
109+ if (Object.getPrototypeOf(promise) !== Promise.prototype) {
110+ throw new Error('Expected promise to be created in the current context');
111+ }
112+ await promise.then(() => {
113+ throw new Error('Expected promise to be rejected');
114+ }, (e) => {
115+ if (e !== globalThis.__err) {
116+ throw new Error('Expected promise to be rejected with "import failed"');
117+ }
118+ });
119+ `, {
120+context: ctx,
121+importModuleDynamically: common.mustCall((specifier, referrer) => {
122+throw err;
123+}),
124+});
125+// No import statements, so must not link statically.
126+await mod2.link(common.mustNotCall());
127+await mod2.evaluate();
128+}
129+130+Promise.all([
131+testScript(),
132+testScriptImportFailed(),
133+testModule(),
134+testModuleImportFailed(),
135+]).then(common.mustCall());