Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions 8 test/es-module/test-esm-dynamic-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ function expectFsNamespace(result) {
}

// For direct use of import expressions inside of CJS or ES modules, including
// via eval, all kinds of specifiers should work without issue.
// via direct/indirect eval, all kinds of specifiers should work without issue.
(function testScriptOrModuleImport() {
// Importing another file, both direct & via eval
// Importing another file, both direct & via direct eval
// expectOkNamespace(import(relativePath));
expectOkNamespace(eval(`import("${relativePath}")`));
expectOkNamespace(eval(`import("${relativePath}")`));
expectOkNamespace(eval(`import(${JSON.stringify(targetURL)})`));

// Importing a built-in, both direct & via eval
// Importing a built-in, both direct & via direct eval
expectFsNamespace(import('fs'));
expectFsNamespace(eval('import("fs")'));
expectFsNamespace(eval('import("fs")'));
Expand All @@ -70,6 +70,8 @@ function expectFsNamespace(result) {
// be treated as a file: URL.
expectOkNamespace(import(targetURL.pathname));

// Import with an indirect eval. In this case, the referrer is null and
// defaults to the realm record.
// If the referrer is a realm record, there is no way to resolve the
// specifier.
// TODO(legendecas): https://github.com/tc39/ecma262/pull/3195
Expand Down
73 changes: 73 additions & 0 deletions 73 test/es-module/test-vm-main-context-default-loader-eval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
'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().catch(common.mustNotCall());
27 changes: 0 additions & 27 deletions 27 test/es-module/test-vm-main-context-default-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const fs = require('fs');
const {
compileFunction,
Script,
createContext,
constants: { USE_MAIN_CONTEXT_DEFAULT_LOADER },
} = require('vm');
const assert = require('assert');
Expand Down Expand Up @@ -112,34 +111,8 @@ async function main() {
await testNotFoundErrors(undefinedOptions);
await testNotFoundErrors(nonPathOptions);

// createContext() with null referrer also resolves to cwd.
{
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' });
}

await testLoader(undefinedOptions);
await testLoader(nonPathOptions);

{
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);
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions 12 test/parallel/test-vm-module-referrer-realm.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import * as common from '../common/index.mjs';
import assert from 'node:assert';
import { Script, SourceTextModule, createContext } from 'node:vm';

/**
* 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
* per-context importModuleDynamically callback will be invoked.
*
* 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.
*/

async function test() {
const foo = new SourceTextModule('export const a = 1;');
await foo.link(common.mustNotCall());
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.