mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
d1d5da22e4
Check if the value returned from user linker function is a null-ish value. `validateInternalField` should be preferred when checking `this` argument to guard against null-ish `this`. Co-authored-by: Mike Ralphson <mike.ralphson@gmail.com> PR-URL: https://github.com/nodejs/node/pull/52162 Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
182 lines
4.8 KiB
JavaScript
182 lines
4.8 KiB
JavaScript
'use strict';
|
|
|
|
// Flags: --experimental-vm-modules
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const {
|
|
Module,
|
|
SourceTextModule,
|
|
SyntheticModule,
|
|
createContext,
|
|
compileFunction,
|
|
} = require('vm');
|
|
const util = require('util');
|
|
|
|
(async function test1() {
|
|
const context = createContext({
|
|
foo: 'bar',
|
|
baz: undefined,
|
|
typeofProcess: undefined,
|
|
});
|
|
const m = new SourceTextModule(
|
|
'baz = foo; typeofProcess = typeof process; typeof Object;',
|
|
{ context }
|
|
);
|
|
assert.strictEqual(m.status, 'unlinked');
|
|
await m.link(common.mustNotCall());
|
|
assert.strictEqual(m.status, 'linked');
|
|
assert.strictEqual(await m.evaluate(), undefined);
|
|
assert.strictEqual(m.status, 'evaluated');
|
|
assert.deepStrictEqual(context, {
|
|
foo: 'bar',
|
|
baz: 'bar',
|
|
typeofProcess: 'undefined'
|
|
});
|
|
}().then(common.mustCall()));
|
|
|
|
(async () => {
|
|
const m = new SourceTextModule(`
|
|
global.vmResultFoo = "foo";
|
|
global.vmResultTypeofProcess = Object.prototype.toString.call(process);
|
|
`);
|
|
await m.link(common.mustNotCall());
|
|
await m.evaluate();
|
|
assert.strictEqual(global.vmResultFoo, 'foo');
|
|
assert.strictEqual(global.vmResultTypeofProcess, '[object process]');
|
|
delete global.vmResultFoo;
|
|
delete global.vmResultTypeofProcess;
|
|
})().then(common.mustCall());
|
|
|
|
(async () => {
|
|
const m = new SourceTextModule('while (true) {}');
|
|
await m.link(common.mustNotCall());
|
|
await m.evaluate({ timeout: 500 })
|
|
.then(() => assert(false), () => {});
|
|
})().then(common.mustCall());
|
|
|
|
// Check the generated identifier for each module
|
|
(async () => {
|
|
const context1 = createContext({ });
|
|
const context2 = createContext({ });
|
|
|
|
const m1 = new SourceTextModule('1', { context: context1 });
|
|
assert.strictEqual(m1.identifier, 'vm:module(0)');
|
|
const m2 = new SourceTextModule('2', { context: context1 });
|
|
assert.strictEqual(m2.identifier, 'vm:module(1)');
|
|
const m3 = new SourceTextModule('3', { context: context2 });
|
|
assert.strictEqual(m3.identifier, 'vm:module(0)');
|
|
})().then(common.mustCall());
|
|
|
|
// Check inspection of the instance
|
|
{
|
|
const context = createContext({ foo: 'bar' });
|
|
const m = new SourceTextModule('1', { context });
|
|
|
|
assert.strictEqual(
|
|
util.inspect(m),
|
|
`SourceTextModule {
|
|
status: 'unlinked',
|
|
identifier: 'vm:module(0)',
|
|
context: { foo: 'bar' }
|
|
}`
|
|
);
|
|
|
|
assert.strictEqual(util.inspect(m, { depth: -1 }), '[SourceTextModule]');
|
|
|
|
for (const value of [null, { __proto__: null }, SourceTextModule.prototype]) {
|
|
assert.throws(
|
|
() => m[util.inspect.custom].call(value),
|
|
{
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: /The "this" argument must be an instance of Module/,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
{
|
|
const context = createContext({ foo: 'bar' });
|
|
const m = new SyntheticModule([], () => {}, { context });
|
|
|
|
assert.strictEqual(
|
|
util.inspect(m),
|
|
`SyntheticModule {
|
|
status: 'unlinked',
|
|
identifier: 'vm:module(0)',
|
|
context: { foo: 'bar' }
|
|
}`
|
|
);
|
|
|
|
assert.strictEqual(util.inspect(m, { depth: -1 }), '[SyntheticModule]');
|
|
}
|
|
|
|
// Check dependencies getter returns same object every time
|
|
{
|
|
const m = new SourceTextModule('');
|
|
const dep = m.dependencySpecifiers;
|
|
assert.notStrictEqual(dep, undefined);
|
|
assert.strictEqual(dep, m.dependencySpecifiers);
|
|
}
|
|
|
|
// Check the impossibility of creating an abstract instance of the Module.
|
|
{
|
|
assert.throws(() => new Module(), {
|
|
message: 'Module is not a constructor',
|
|
name: 'TypeError'
|
|
});
|
|
}
|
|
|
|
// Check to throws invalid exportNames
|
|
{
|
|
assert.throws(() => new SyntheticModule(undefined, () => {}, {}), {
|
|
message: 'The "exportNames" argument must be an ' +
|
|
'Array of unique strings.' +
|
|
' Received undefined',
|
|
name: 'TypeError'
|
|
});
|
|
}
|
|
|
|
// Check to throws duplicated exportNames
|
|
// https://github.com/nodejs/node/issues/32806
|
|
{
|
|
assert.throws(() => new SyntheticModule(['x', 'x'], () => {}, {}), {
|
|
message: 'The property \'exportNames.x\' is duplicated. Received \'x\'',
|
|
name: 'TypeError',
|
|
});
|
|
}
|
|
|
|
// Check to throws invalid evaluateCallback
|
|
{
|
|
assert.throws(() => new SyntheticModule([], undefined, {}), {
|
|
message: 'The "evaluateCallback" argument must be of type function.' +
|
|
' Received undefined',
|
|
name: 'TypeError'
|
|
});
|
|
}
|
|
|
|
// Check to throws invalid options
|
|
{
|
|
assert.throws(() => new SyntheticModule([], () => {}, null), {
|
|
message: 'The "options" argument must be of type object.' +
|
|
' Received null',
|
|
name: 'TypeError'
|
|
});
|
|
}
|
|
|
|
// Test compileFunction importModuleDynamically
|
|
{
|
|
const module = new SyntheticModule([], () => {});
|
|
module.link(() => {});
|
|
const f = compileFunction('return import("x")', [], {
|
|
importModuleDynamically(specifier, referrer) {
|
|
assert.strictEqual(specifier, 'x');
|
|
assert.strictEqual(referrer, f);
|
|
return module;
|
|
},
|
|
});
|
|
f().then((ns) => {
|
|
assert.strictEqual(ns, module.namespace);
|
|
});
|
|
}
|