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
127async function asserts() {
128  const m = new SourceTextModule(`
129  import "foo" assert { n1: 'v1', n2: 'v2' };
130  `, { identifier: 'm' });
131  await m.link((s, r, p) => {
132    assert.strictEqual(s, 'foo');
133    assert.strictEqual(r.identifier, 'm');
134    assert.strictEqual(p.attributes.n1, 'v1');
135    assert.strictEqual(p.assert.n1, 'v1');
136    assert.strictEqual(p.attributes.n2, 'v2');
137    assert.strictEqual(p.assert.n2, 'v2');
138    return new SourceTextModule('');
139  });
140}
141
142const finished = common.mustCall();
143
144(async function main() {
145  await simple();
146  await depth();
147  await circular();
148  await circular2();
149  await asserts();
150  finished();
151})().then(common.mustCall());
152