• 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');
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