node/test/parallel/test-vm-module-dynamic-impo...

136 lines
3.8 KiB
JavaScript

// Flags: --experimental-vm-modules
'use strict';
const common = require('../common');
const assert = require('assert');
const { createContext, Script, SourceTextModule } = require('vm');
// Verifies that a `import` call returns a promise created in the context
// where the `import` was called, not the context of `importModuleDynamically`
// callback.
async function testScript() {
const ctx = createContext();
const mod1 = new SourceTextModule('export const a = 1;', {
context: ctx,
});
// No import statements, so must not link statically.
await mod1.link(common.mustNotCall());
const script2 = new Script(`
const promise = import("mod1");
if (Object.getPrototypeOf(promise) !== Promise.prototype) {
throw new Error('Expected promise to be created in the current context');
}
globalThis.__result = promise;
`, {
importModuleDynamically: common.mustCall((specifier, referrer) => {
assert.strictEqual(specifier, 'mod1');
assert.strictEqual(referrer, script2);
return mod1;
}),
});
script2.runInContext(ctx);
// Wait for the promise to resolve.
await ctx.__result;
}
async function testScriptImportFailed() {
const ctx = createContext();
const mod1 = new SourceTextModule('export const a = 1;', {
context: ctx,
});
// No import statements, so must not link statically.
await mod1.link(common.mustNotCall());
const err = new Error('import failed');
const script2 = new Script(`
const promise = import("mod1");
if (Object.getPrototypeOf(promise) !== Promise.prototype) {
throw new Error('Expected promise to be created in the current context');
}
globalThis.__result = promise;
`, {
importModuleDynamically: common.mustCall((specifier, referrer) => {
throw err;
}),
});
script2.runInContext(ctx);
// Wait for the promise to reject.
await assert.rejects(ctx.__result, err);
}
async function testModule() {
const ctx = createContext();
const mod1 = new SourceTextModule('export const a = 1;', {
context: ctx,
});
// No import statements, so must not link statically.
await mod1.link(common.mustNotCall());
const mod2 = new SourceTextModule(`
const promise = import("mod1");
if (Object.getPrototypeOf(promise) !== Promise.prototype) {
throw new Error('Expected promise to be created in the current context');
}
await promise;
`, {
context: ctx,
importModuleDynamically: common.mustCall((specifier, referrer) => {
assert.strictEqual(specifier, 'mod1');
assert.strictEqual(referrer, mod2);
return mod1;
}),
});
// No import statements, so must not link statically.
await mod2.link(common.mustNotCall());
await mod2.evaluate();
}
async function testModuleImportFailed() {
const ctx = createContext();
const mod1 = new SourceTextModule('export const a = 1;', {
context: ctx,
});
// No import statements, so must not link statically.
await mod1.link(common.mustNotCall());
const err = new Error('import failed');
ctx.__err = err;
const mod2 = new SourceTextModule(`
const promise = import("mod1");
if (Object.getPrototypeOf(promise) !== Promise.prototype) {
throw new Error('Expected promise to be created in the current context');
}
await promise.then(() => {
throw new Error('Expected promise to be rejected');
}, (e) => {
if (e !== globalThis.__err) {
throw new Error('Expected promise to be rejected with "import failed"');
}
});
`, {
context: ctx,
importModuleDynamically: common.mustCall((specifier, referrer) => {
throw err;
}),
});
// No import statements, so must not link statically.
await mod2.link(common.mustNotCall());
await mod2.evaluate();
}
Promise.all([
testScript(),
testScriptImportFailed(),
testModule(),
testModuleImportFailed(),
]).then(common.mustCall());