node/test/es-module/test-vm-main-context-default-loader-eval.js
2025-07-16 10:57:22 +02:00

73 lines
2.5 KiB
JavaScript

'use strict';
/**
* This test verifies that dynamic import in an indirect eval without JS stacks.
* In this case, the referrer for the dynamic import will be null and the main
* context default loader in createContext() resolves to cwd.
*
* Caveat: this test can be unstable if the loader internals are changed and performs
* microtasks with a JS stack (e.g. with CallbackScope). In this case, the
* referrer will be resolved to the top JS stack frame `node:internal/process/task_queues.js`.
* This is due to the implementation detail of how V8 finds the referrer for a dynamic import
* call.
*/
const common = require('../common');
// Can't process.chdir() in worker.
const { isMainThread } = require('worker_threads');
if (!isMainThread) {
common.skip('This test only works on a main thread');
}
const tmpdir = require('../common/tmpdir');
const fixtures = require('../common/fixtures');
const fs = require('node:fs');
const {
Script,
createContext,
constants: { USE_MAIN_CONTEXT_DEFAULT_LOADER },
} = require('node:vm');
const assert = require('node:assert');
common.expectWarning('ExperimentalWarning',
'vm.USE_MAIN_CONTEXT_DEFAULT_LOADER is an experimental feature and might change at any time');
assert(
!process.execArgv.includes('--experimental-vm-modules'),
'This test must be run without --experimental-vm-modules');
assert.strictEqual(typeof USE_MAIN_CONTEXT_DEFAULT_LOADER, 'symbol');
async function main() {
tmpdir.refresh();
process.chdir(tmpdir.path);
//
{
const options = {
importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER,
};
const ctx = createContext({}, options);
const s = new Script('Promise.resolve("import(\'./message.mjs\')").then(eval)', {
importModuleDynamically: common.mustNotCall(),
});
await assert.rejects(s.runInContext(ctx), { code: 'ERR_MODULE_NOT_FOUND' });
}
const moduleUrl = fixtures.fileURL('es-modules', 'message.mjs');
fs.copyFileSync(moduleUrl, tmpdir.resolve('message.mjs'));
{
const options = {
importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER,
};
const ctx = createContext({}, options);
const moduleUrl = fixtures.fileURL('es-modules', 'message.mjs');
const namespace = await import(moduleUrl.href);
const script = new Script('Promise.resolve("import(\'./message.mjs\')").then(eval)', {
importModuleDynamically: common.mustNotCall(),
});
const result = await script.runInContext(ctx);
assert.deepStrictEqual(result, namespace);
}
}
main().then(common.mustCall());