mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 21:19:50 +01: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>
169 lines
4.2 KiB
JavaScript
169 lines
4.2 KiB
JavaScript
'use strict';
|
|
|
|
// Flags: --experimental-vm-modules --harmony-import-attributes
|
|
|
|
const common = require('../common');
|
|
|
|
const assert = require('assert');
|
|
|
|
const { SourceTextModule } = require('vm');
|
|
|
|
async function simple() {
|
|
const foo = new SourceTextModule('export default 5;');
|
|
await foo.link(common.mustNotCall());
|
|
|
|
globalThis.fiveResult = undefined;
|
|
const bar = new SourceTextModule('import five from "foo"; fiveResult = five');
|
|
|
|
assert.deepStrictEqual(bar.dependencySpecifiers, ['foo']);
|
|
|
|
await bar.link(common.mustCall((specifier, module) => {
|
|
assert.strictEqual(module, bar);
|
|
assert.strictEqual(specifier, 'foo');
|
|
return foo;
|
|
}));
|
|
|
|
await bar.evaluate();
|
|
assert.strictEqual(globalThis.fiveResult, 5);
|
|
delete globalThis.fiveResult;
|
|
}
|
|
|
|
async function invalidLinkValue() {
|
|
const invalidValues = [
|
|
undefined,
|
|
null,
|
|
{},
|
|
SourceTextModule.prototype,
|
|
];
|
|
|
|
for (const value of invalidValues) {
|
|
const module = new SourceTextModule('import "foo"');
|
|
await assert.rejects(module.link(() => value), {
|
|
code: 'ERR_VM_MODULE_NOT_MODULE',
|
|
});
|
|
}
|
|
}
|
|
|
|
async function depth() {
|
|
const foo = new SourceTextModule('export default 5');
|
|
await foo.link(common.mustNotCall());
|
|
|
|
async function getProxy(parentName, parentModule) {
|
|
const mod = new SourceTextModule(`
|
|
import ${parentName} from '${parentName}';
|
|
export default ${parentName};
|
|
`);
|
|
await mod.link(common.mustCall((specifier, module) => {
|
|
assert.strictEqual(module, mod);
|
|
assert.strictEqual(specifier, parentName);
|
|
return parentModule;
|
|
}));
|
|
return mod;
|
|
}
|
|
|
|
const bar = await getProxy('foo', foo);
|
|
const baz = await getProxy('bar', bar);
|
|
const barz = await getProxy('baz', baz);
|
|
|
|
await barz.evaluate();
|
|
|
|
assert.strictEqual(barz.namespace.default, 5);
|
|
}
|
|
|
|
async function circular() {
|
|
const foo = new SourceTextModule(`
|
|
import getFoo from 'bar';
|
|
export let foo = 42;
|
|
export default getFoo();
|
|
`);
|
|
const bar = new SourceTextModule(`
|
|
import { foo } from 'foo';
|
|
export default function getFoo() {
|
|
return foo;
|
|
}
|
|
`);
|
|
await foo.link(common.mustCall(async (specifier, module) => {
|
|
if (specifier === 'bar') {
|
|
assert.strictEqual(module, foo);
|
|
return bar;
|
|
}
|
|
assert.strictEqual(specifier, 'foo');
|
|
assert.strictEqual(module, bar);
|
|
assert.strictEqual(foo.status, 'linking');
|
|
return foo;
|
|
}, 2));
|
|
|
|
assert.strictEqual(bar.status, 'linked');
|
|
|
|
await foo.evaluate();
|
|
assert.strictEqual(foo.namespace.default, 42);
|
|
}
|
|
|
|
async function circular2() {
|
|
const sourceMap = {
|
|
'root': `
|
|
import * as a from './a.mjs';
|
|
import * as b from './b.mjs';
|
|
if (!('fromA' in a))
|
|
throw new Error();
|
|
if (!('fromB' in a))
|
|
throw new Error();
|
|
if (!('fromA' in b))
|
|
throw new Error();
|
|
if (!('fromB' in b))
|
|
throw new Error();
|
|
`,
|
|
'./a.mjs': `
|
|
export * from './b.mjs';
|
|
export let fromA;
|
|
`,
|
|
'./b.mjs': `
|
|
export * from './a.mjs';
|
|
export let fromB;
|
|
`
|
|
};
|
|
const moduleMap = new Map();
|
|
const rootModule = new SourceTextModule(sourceMap.root, {
|
|
identifier: 'vm:root',
|
|
});
|
|
async function link(specifier, referencingModule) {
|
|
if (moduleMap.has(specifier)) {
|
|
return moduleMap.get(specifier);
|
|
}
|
|
const mod = new SourceTextModule(sourceMap[specifier], {
|
|
identifier: new URL(specifier, 'file:///').href,
|
|
});
|
|
moduleMap.set(specifier, mod);
|
|
return mod;
|
|
}
|
|
await rootModule.link(link);
|
|
await rootModule.evaluate();
|
|
}
|
|
|
|
async function asserts() {
|
|
const m = new SourceTextModule(`
|
|
import "foo" with { n1: 'v1', n2: 'v2' };
|
|
`, { identifier: 'm' });
|
|
await m.link((s, r, p) => {
|
|
assert.strictEqual(s, 'foo');
|
|
assert.strictEqual(r.identifier, 'm');
|
|
assert.strictEqual(p.attributes.n1, 'v1');
|
|
assert.strictEqual(p.assert.n1, 'v1');
|
|
assert.strictEqual(p.attributes.n2, 'v2');
|
|
assert.strictEqual(p.assert.n2, 'v2');
|
|
return new SourceTextModule('');
|
|
});
|
|
}
|
|
|
|
const finished = common.mustCall();
|
|
|
|
(async function main() {
|
|
await simple();
|
|
await invalidLinkValue();
|
|
await depth();
|
|
await circular();
|
|
await circular2();
|
|
await asserts();
|
|
finished();
|
|
})().then(common.mustCall());
|