| // Flags: --experimental-vm-modules |
| |
| 'use strict'; |
| |
| const common = require('../common'); |
| const vm = require('vm'); |
| const assert = require('assert'); |
| |
| // This test verifies that a module can be returned multiple |
| // times in the linker function in `module.link(linker)`. |
| // `module.link(linker)` should handle the race condition of |
| // `module.status` when the linker function is asynchronous. |
| |
| // Regression of https://github.com/nodejs/node/issues/59480 |
| |
| const sources = { |
| './index.js': ` |
| import foo from "./foo.js"; |
| import shared from "./shared.js"; |
| export default { |
| foo, |
| shared |
| }; |
| `, |
| './foo.js': ` |
| import shared from "./shared.js"; |
| export default { |
| name: "foo" |
| }; |
| `, |
| './shared.js': ` |
| export default { |
| name: "shared", |
| }; |
| `, |
| }; |
| |
| const moduleCache = new Map(); |
| |
| function getModuleInstance(identifier) { |
| let module = moduleCache.get(identifier); |
| |
| if (!module) { |
| module = new vm.SourceTextModule(sources[identifier], { |
| identifier, |
| }); |
| moduleCache.set(identifier, module); |
| } |
| |
| return module; |
| } |
| |
| async function esmImport(identifier) { |
| const module = getModuleInstance(identifier); |
| const requests = []; |
| |
| await module.link(async (specifier, referrer) => { |
| requests.push([specifier, referrer.identifier]); |
| // Use `Promise.resolve` to defer a tick to create a race condition on |
| // `module.status` when a module is being imported several times. |
| return Promise.resolve(getModuleInstance(specifier)); |
| }); |
| |
| await module.evaluate(); |
| return [module.namespace, requests]; |
| } |
| |
| async function test() { |
| const { 0: mod, 1: requests } = await esmImport('./index.js'); |
| assert.strictEqual(mod.default.foo.name, 'foo'); |
| assert.strictEqual(mod.default.shared.name, 'shared'); |
| |
| // Assert that there is no duplicated requests. |
| assert.deepStrictEqual(requests, [ |
| // [specifier, referrer] |
| ['./foo.js', './index.js'], |
| ['./shared.js', './index.js'], |
| ['./shared.js', './foo.js'], |
| ]); |
| } |
| |
| test().then(common.mustCall()); |