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