module: allow overriding linked requests for a ModuleWrap · nodejs/node@389a24b
1+// Flags: --experimental-vm-modules
2+3+'use strict';
4+5+const common = require('../common');
6+const vm = require('vm');
7+const assert = require('assert');
8+9+// This test verifies that a module can be returned multiple
10+// times in the linker function in `module.link(linker)`.
11+// `module.link(linker)` should handle the race condition of
12+// `module.status` when the linker function is asynchronous.
13+14+// Regression of https://github.com/nodejs/node/issues/59480
15+16+const sources = {
17+'./index.js': `
18+ import foo from "./foo.js";
19+ import shared from "./shared.js";
20+ export default {
21+ foo,
22+ shared
23+ };
24+ `,
25+'./foo.js': `
26+ import shared from "./shared.js";
27+ export default {
28+ name: "foo"
29+ };
30+ `,
31+'./shared.js': `
32+ export default {
33+ name: "shared",
34+ };
35+ `,
36+};
37+38+const moduleCache = new Map();
39+40+function getModuleInstance(identifier) {
41+let module = moduleCache.get(identifier);
42+43+if (!module) {
44+module = new vm.SourceTextModule(sources[identifier], {
45+ identifier,
46+});
47+moduleCache.set(identifier, module);
48+}
49+50+return module;
51+}
52+53+async function esmImport(identifier) {
54+const module = getModuleInstance(identifier);
55+const requests = [];
56+57+await module.link(async (specifier, referrer) => {
58+requests.push([specifier, referrer.identifier]);
59+// Use `Promise.resolve` to defer a tick to create a race condition on
60+// `module.status` when a module is being imported several times.
61+return Promise.resolve(getModuleInstance(specifier));
62+});
63+64+await module.evaluate();
65+return [module.namespace, requests];
66+}
67+68+async function test() {
69+const { 0: mod, 1: requests } = await esmImport('./index.js');
70+assert.strictEqual(mod.default.foo.name, 'foo');
71+assert.strictEqual(mod.default.shared.name, 'shared');
72+73+// Assert that there is no duplicated requests.
74+assert.deepStrictEqual(requests, [
75+// [specifier, referrer]
76+['./foo.js', './index.js'],
77+['./shared.js', './index.js'],
78+['./shared.js', './foo.js'],
79+]);
80+}
81+82+test().then(common.mustCall());