• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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