1'use strict'; 2 3// Flags: --experimental-vm-modules 4 5const common = require('../common'); 6 7const assert = require('assert'); 8 9const { SourceTextModule } = require('vm'); 10 11async function simple() { 12 const foo = new SourceTextModule('export default 5;'); 13 await foo.link(common.mustNotCall()); 14 15 globalThis.fiveResult = undefined; 16 const bar = new SourceTextModule('import five from "foo"; fiveResult = five'); 17 18 assert.deepStrictEqual(bar.dependencySpecifiers, ['foo']); 19 20 await bar.link(common.mustCall((specifier, module) => { 21 assert.strictEqual(module, bar); 22 assert.strictEqual(specifier, 'foo'); 23 return foo; 24 })); 25 26 await bar.evaluate(); 27 assert.strictEqual(globalThis.fiveResult, 5); 28 delete globalThis.fiveResult; 29} 30 31async function depth() { 32 const foo = new SourceTextModule('export default 5'); 33 await foo.link(common.mustNotCall()); 34 35 async function getProxy(parentName, parentModule) { 36 const mod = new SourceTextModule(` 37 import ${parentName} from '${parentName}'; 38 export default ${parentName}; 39 `); 40 await mod.link(common.mustCall((specifier, module) => { 41 assert.strictEqual(module, mod); 42 assert.strictEqual(specifier, parentName); 43 return parentModule; 44 })); 45 return mod; 46 } 47 48 const bar = await getProxy('foo', foo); 49 const baz = await getProxy('bar', bar); 50 const barz = await getProxy('baz', baz); 51 52 await barz.evaluate(); 53 54 assert.strictEqual(barz.namespace.default, 5); 55} 56 57async function circular() { 58 const foo = new SourceTextModule(` 59 import getFoo from 'bar'; 60 export let foo = 42; 61 export default getFoo(); 62 `); 63 const bar = new SourceTextModule(` 64 import { foo } from 'foo'; 65 export default function getFoo() { 66 return foo; 67 } 68 `); 69 await foo.link(common.mustCall(async (specifier, module) => { 70 if (specifier === 'bar') { 71 assert.strictEqual(module, foo); 72 return bar; 73 } 74 assert.strictEqual(specifier, 'foo'); 75 assert.strictEqual(module, bar); 76 assert.strictEqual(foo.status, 'linking'); 77 return foo; 78 }, 2)); 79 80 assert.strictEqual(bar.status, 'linked'); 81 82 await foo.evaluate(); 83 assert.strictEqual(foo.namespace.default, 42); 84} 85 86async function circular2() { 87 const sourceMap = { 88 'root': ` 89 import * as a from './a.mjs'; 90 import * as b from './b.mjs'; 91 if (!('fromA' in a)) 92 throw new Error(); 93 if (!('fromB' in a)) 94 throw new Error(); 95 if (!('fromA' in b)) 96 throw new Error(); 97 if (!('fromB' in b)) 98 throw new Error(); 99 `, 100 './a.mjs': ` 101 export * from './b.mjs'; 102 export let fromA; 103 `, 104 './b.mjs': ` 105 export * from './a.mjs'; 106 export let fromB; 107 ` 108 }; 109 const moduleMap = new Map(); 110 const rootModule = new SourceTextModule(sourceMap.root, { 111 identifier: 'vm:root', 112 }); 113 async function link(specifier, referencingModule) { 114 if (moduleMap.has(specifier)) { 115 return moduleMap.get(specifier); 116 } 117 const mod = new SourceTextModule(sourceMap[specifier], { 118 identifier: new URL(specifier, 'file:///').href, 119 }); 120 moduleMap.set(specifier, mod); 121 return mod; 122 } 123 await rootModule.link(link); 124 await rootModule.evaluate(); 125} 126 127const finished = common.mustCall(); 128 129(async function main() { 130 await simple(); 131 await depth(); 132 await circular(); 133 await circular2(); 134 finished(); 135})().then(common.mustCall()); 136