• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3// Flags: --experimental-vm-modules
4
5const common = require('../common');
6const assert = require('assert');
7const {
8  Module,
9  SourceTextModule,
10  SyntheticModule,
11  createContext,
12  compileFunction,
13} = require('vm');
14const util = require('util');
15
16(async function test1() {
17  const context = createContext({
18    foo: 'bar',
19    baz: undefined,
20    typeofProcess: undefined,
21  });
22  const m = new SourceTextModule(
23    'baz = foo; typeofProcess = typeof process; typeof Object;',
24    { context }
25  );
26  assert.strictEqual(m.status, 'unlinked');
27  await m.link(common.mustNotCall());
28  assert.strictEqual(m.status, 'linked');
29  assert.strictEqual(await m.evaluate(), undefined);
30  assert.strictEqual(m.status, 'evaluated');
31  assert.deepStrictEqual(context, {
32    foo: 'bar',
33    baz: 'bar',
34    typeofProcess: 'undefined'
35  });
36}().then(common.mustCall()));
37
38(async () => {
39  const m = new SourceTextModule(`
40    global.vmResultFoo = "foo";
41    global.vmResultTypeofProcess = Object.prototype.toString.call(process);
42  `);
43  await m.link(common.mustNotCall());
44  await m.evaluate();
45  assert.strictEqual(global.vmResultFoo, 'foo');
46  assert.strictEqual(global.vmResultTypeofProcess, '[object process]');
47  delete global.vmResultFoo;
48  delete global.vmResultTypeofProcess;
49})().then(common.mustCall());
50
51(async () => {
52  const m = new SourceTextModule('while (true) {}');
53  await m.link(common.mustNotCall());
54  await m.evaluate({ timeout: 500 })
55    .then(() => assert(false), () => {});
56})().then(common.mustCall());
57
58// Check the generated identifier for each module
59(async () => {
60  const context1 = createContext({ });
61  const context2 = createContext({ });
62
63  const m1 = new SourceTextModule('1', { context: context1 });
64  assert.strictEqual(m1.identifier, 'vm:module(0)');
65  const m2 = new SourceTextModule('2', { context: context1 });
66  assert.strictEqual(m2.identifier, 'vm:module(1)');
67  const m3 = new SourceTextModule('3', { context: context2 });
68  assert.strictEqual(m3.identifier, 'vm:module(0)');
69})().then(common.mustCall());
70
71// Check inspection of the instance
72{
73  const context = createContext({ foo: 'bar' });
74  const m = new SourceTextModule('1', { context });
75
76  assert.strictEqual(
77    util.inspect(m),
78    `SourceTextModule {
79  status: 'unlinked',
80  identifier: 'vm:module(0)',
81  context: { foo: 'bar' }
82}`
83  );
84
85  assert.strictEqual(util.inspect(m, { depth: -1 }), '[SourceTextModule]');
86
87  assert.throws(
88    () => m[util.inspect.custom].call(Object.create(null)),
89    {
90      code: 'ERR_VM_MODULE_NOT_MODULE',
91      message: 'Provided module is not an instance of Module'
92    },
93  );
94}
95
96{
97  const context = createContext({ foo: 'bar' });
98  const m = new SyntheticModule([], () => {}, { context });
99
100  assert.strictEqual(
101    util.inspect(m),
102    `SyntheticModule {
103  status: 'unlinked',
104  identifier: 'vm:module(0)',
105  context: { foo: 'bar' }
106}`
107  );
108
109  assert.strictEqual(util.inspect(m, { depth: -1 }), '[SyntheticModule]');
110}
111
112// Check dependencies getter returns same object every time
113{
114  const m = new SourceTextModule('');
115  const dep = m.dependencySpecifiers;
116  assert.notStrictEqual(dep, undefined);
117  assert.strictEqual(dep, m.dependencySpecifiers);
118}
119
120// Check the impossibility of creating an abstract instance of the Module.
121{
122  assert.throws(() => new Module(), {
123    message: 'Module is not a constructor',
124    name: 'TypeError'
125  });
126}
127
128// Check to throws invalid exportNames
129{
130  assert.throws(() => new SyntheticModule(undefined, () => {}, {}), {
131    message: 'The "exportNames" argument must be an ' +
132        'Array of unique strings.' +
133        ' Received undefined',
134    name: 'TypeError'
135  });
136}
137
138// Check to throws duplicated exportNames
139// https://github.com/nodejs/node/issues/32806
140{
141  assert.throws(() => new SyntheticModule(['x', 'x'], () => {}, {}), {
142    message: 'The property \'exportNames.x\' is duplicated. Received \'x\'',
143    name: 'TypeError',
144  });
145}
146
147// Check to throws invalid evaluateCallback
148{
149  assert.throws(() => new SyntheticModule([], undefined, {}), {
150    message: 'The "evaluateCallback" argument must be of type function.' +
151      ' Received undefined',
152    name: 'TypeError'
153  });
154}
155
156// Check to throws invalid options
157{
158  assert.throws(() => new SyntheticModule([], () => {}, null), {
159    message: 'The "options" argument must be of type object.' +
160      ' Received null',
161    name: 'TypeError'
162  });
163}
164
165// Test compileFunction importModuleDynamically
166{
167  const module = new SyntheticModule([], () => {});
168  module.link(() => {});
169  const f = compileFunction('return import("x")', [], {
170    importModuleDynamically(specifier, referrer) {
171      assert.strictEqual(specifier, 'x');
172      assert.strictEqual(referrer, f);
173      return module;
174    },
175  });
176  f().then((ns) => {
177    assert.strictEqual(ns, module.namespace);
178  });
179}
180