node/test/es-module/test-esm-dynamic-import.js
Chengzhong Wu ccf105df2a
test: split indirect eval import tests
Split indirect eval import tests as they depends on the JS stack to
resolve the referrer.

PR-URL: https://github.com/nodejs/node/pull/58637
Reviewed-By: Jacob Smith <jacob@frende.me>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2025-06-11 09:06:22 +00:00

81 lines
3.1 KiB
JavaScript

'use strict';
const common = require('../common');
const { pathToFileURL } = require('url');
const assert = require('assert');
const relativePath = '../fixtures/es-modules/test-esm-ok.mjs';
const absolutePath = require.resolve(relativePath);
const targetURL = pathToFileURL(absolutePath);
function expectModuleError(result, code, message) {
Promise.resolve(result).catch(common.mustCall((error) => {
assert.strictEqual(error.code, code);
if (message) assert.strictEqual(error.message, message);
}));
}
function expectOkNamespace(result) {
Promise.resolve(result)
.then(common.mustCall((ns) => {
const expected = { default: true };
Object.defineProperty(expected, Symbol.toStringTag, {
value: 'Module'
});
Object.setPrototypeOf(expected, Object.getPrototypeOf(ns));
assert.deepStrictEqual(ns, expected);
}));
}
function expectFsNamespace(result) {
Promise.resolve(result)
.then(common.mustCall((ns) => {
assert.strictEqual(typeof ns.default.writeFile, 'function');
assert.strictEqual(typeof ns.writeFile, 'function');
}));
}
// For direct use of import expressions inside of CJS or ES modules, including
// via direct/indirect eval, all kinds of specifiers should work without issue.
(function testScriptOrModuleImport() {
// 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 direct eval
expectFsNamespace(import('fs'));
expectFsNamespace(eval('import("fs")'));
expectFsNamespace(eval('import("fs")'));
expectFsNamespace(import('node:fs'));
expectModuleError(import('node:unknown'),
'ERR_UNKNOWN_BUILTIN_MODULE');
expectModuleError(import('node:internal/test/binding'),
'ERR_UNKNOWN_BUILTIN_MODULE');
expectModuleError(import('./not-an-existing-module.mjs'),
'ERR_MODULE_NOT_FOUND');
expectModuleError(import('http://example.com/foo.js'),
'ERR_UNSUPPORTED_ESM_URL_SCHEME');
if (common.isWindows) {
const msg =
'Only URLs with a scheme in: file, data, and node are supported by the default ' +
'ESM loader. On Windows, absolute paths must be valid file:// URLs. ' +
"Received protocol 'c:'";
expectModuleError(import('C:\\example\\foo.mjs'),
'ERR_UNSUPPORTED_ESM_URL_SCHEME',
msg);
}
// If the specifier is an origin-relative URL, it should
// 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
expectModuleError(Promise.resolve('import("node:fs")').then(eval),
'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING');
})();