'use strict'; const common = require('../common'); // Can't process.chdir() in worker. common.skipIfWorker(); const tmpdir = require('../common/tmpdir'); const fixtures = require('../common/fixtures'); const url = require('url'); const fs = require('fs'); const { compileFunction, Script, createContext, constants: { USE_MAIN_CONTEXT_DEFAULT_LOADER }, } = require('vm'); const assert = require('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 testNotFoundErrors(options) { // Import user modules. const script = new Script('import("./message.mjs")', options); // Use try-catch for better async stack traces in the logs. await assert.rejects(script.runInThisContext(), { code: 'ERR_MODULE_NOT_FOUND' }); const imported = compileFunction('return import("./message.mjs")', [], options)(); // Use try-catch for better async stack traces in the logs. await assert.rejects(imported, { code: 'ERR_MODULE_NOT_FOUND' }); } async function testLoader(options) { { // Import built-in modules const script = new Script('import("fs")', options); let result = await script.runInThisContext(); assert.strictEqual(result.constants.F_OK, fs.constants.F_OK); const imported = compileFunction('return import("fs")', [], options)(); result = await imported; assert.strictEqual(result.constants.F_OK, fs.constants.F_OK); } const moduleUrl = fixtures.fileURL('es-modules', 'message.mjs'); fs.copyFileSync(moduleUrl, tmpdir.resolve('message.mjs')); { const namespace = await import(moduleUrl); const script = new Script('import("./message.mjs")', options); const result = await script.runInThisContext(); assert.deepStrictEqual(result, namespace); } { const namespace = await import(moduleUrl); const imported = compileFunction('return import("./message.mjs")', [], options)(); const result = await imported; assert.deepStrictEqual(result, namespace); } } async function main() { { // Importing with absolute path as filename. tmpdir.refresh(); const filename = tmpdir.resolve('index.js'); const options = { filename, importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER }; await testNotFoundErrors(options); await testLoader(options); } { // Importing with file:// URL as filename. tmpdir.refresh(); // We use a search parameter to bypass caching. const filename = url.pathToFileURL(tmpdir.resolve('index.js')).href + '?t=1'; const options = { filename, importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER }; await testNotFoundErrors(options); await testLoader(options); } { // For undefined or non-path/URL filenames, import() should resolve to the cwd. tmpdir.refresh(); process.chdir(tmpdir.path); const undefinedOptions = { importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER }; const nonPathOptions = { filename: 'non-path', importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER }; // Run the error tests first to avoid caching. 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); } } } main().catch(common.mustNotCall());