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());