mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
esm: remove specifier resolution flag
PR-URL: https://github.com/nodejs/node/pull/44859 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
This commit is contained in:
parent
417458da9b
commit
f594cc85b7
@ -427,23 +427,6 @@ added: REPLACEME
|
||||
|
||||
Use this flag to enable [ShadowRealm][] support.
|
||||
|
||||
### `--experimental-specifier-resolution=mode`
|
||||
|
||||
<!-- YAML
|
||||
added:
|
||||
- v13.4.0
|
||||
- v12.16.0
|
||||
-->
|
||||
|
||||
Sets the resolution algorithm for resolving ES module specifiers. Valid options
|
||||
are `explicit` and `node`.
|
||||
|
||||
The default is `explicit`, which requires providing the full path to a
|
||||
module. The `node` mode enables support for optional file extensions and
|
||||
the ability to import a directory that has an index file.
|
||||
|
||||
See [customizing ESM specifier resolution][] for example usage.
|
||||
|
||||
### `--experimental-vm-modules`
|
||||
|
||||
<!-- YAML
|
||||
@ -2312,7 +2295,6 @@ done
|
||||
[`worker_threads.threadId`]: worker_threads.md#workerthreadid
|
||||
[conditional exports]: packages.md#conditional-exports
|
||||
[context-aware]: addons.md#context-aware-addons
|
||||
[customizing ESM specifier resolution]: esm.md#customizing-esm-specifier-resolution-algorithm
|
||||
[debugger]: debugger.md
|
||||
[debugging security implications]: https://nodejs.org/en/docs/guides/debugging-getting-started/#security-implications
|
||||
[emit_warning]: process.md#processemitwarningwarning-options
|
||||
|
@ -1518,31 +1518,9 @@ _isImports_, _conditions_)
|
||||
|
||||
### Customizing ESM specifier resolution algorithm
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
> Do not rely on this flag. We plan to remove it once the
|
||||
> [Loaders API][] has advanced to the point that equivalent functionality can
|
||||
> be achieved via custom loaders.
|
||||
|
||||
The current specifier resolution does not support all default behavior of
|
||||
the CommonJS loader. One of the behavior differences is automatic resolution
|
||||
of file extensions and the ability to import directories that have an index
|
||||
file.
|
||||
|
||||
The `--experimental-specifier-resolution=[mode]` flag can be used to customize
|
||||
the extension resolution algorithm. The default mode is `explicit`, which
|
||||
requires the full path to a module be provided to the loader. To enable the
|
||||
automatic extension resolution and importing from directories that include an
|
||||
index file use the `node` mode.
|
||||
|
||||
```console
|
||||
$ node index.mjs
|
||||
success!
|
||||
$ node index # Failure!
|
||||
Error: Cannot find module
|
||||
$ node --experimental-specifier-resolution=node index
|
||||
success!
|
||||
```
|
||||
The [Loaders API][] provides a mechanism for customizing the ESM specifier
|
||||
resolution algorithm. An example loader that provides CommonJS-style resolution
|
||||
for ESM specifiers is [commonjs-extension-resolution-loader][].
|
||||
|
||||
<!-- Note: The cjs-module-lexer link should be kept in-sync with the deps version -->
|
||||
|
||||
@ -1583,6 +1561,7 @@ success!
|
||||
[`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
|
||||
[`util.TextDecoder`]: util.md#class-utiltextdecoder
|
||||
[cjs-module-lexer]: https://github.com/nodejs/cjs-module-lexer/tree/1.2.2
|
||||
[commonjs-extension-resolution-loader]: https://github.com/nodejs/loaders-test/tree/main/commonjs-extension-resolution-loader
|
||||
[custom https loader]: #https-loader
|
||||
[load hook]: #loadurl-context-nextload
|
||||
[percent-encoded]: url.md#percent-encoding-in-urls
|
||||
|
@ -171,9 +171,6 @@ Disable exposition of the Web Crypto API on the global scope.
|
||||
.It Fl -no-experimental-repl-await
|
||||
Disable top-level await keyword support in REPL.
|
||||
.
|
||||
.It Fl -experimental-specifier-resolution
|
||||
Select extension resolution algorithm for ES Modules; either 'explicit' (default) or 'node'.
|
||||
.
|
||||
.It Fl -experimental-vm-modules
|
||||
Enable experimental ES module support in VM module.
|
||||
.
|
||||
|
@ -5,7 +5,6 @@ const {
|
||||
} = primordials;
|
||||
const { getOptionValue } = require('internal/options');
|
||||
|
||||
|
||||
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
|
||||
|
||||
const extensionFormatMap = {
|
||||
@ -16,17 +15,8 @@ const extensionFormatMap = {
|
||||
'.mjs': 'module',
|
||||
};
|
||||
|
||||
const legacyExtensionFormatMap = {
|
||||
'__proto__': null,
|
||||
'.cjs': 'commonjs',
|
||||
'.js': 'commonjs',
|
||||
'.json': 'commonjs',
|
||||
'.mjs': 'module',
|
||||
'.node': 'commonjs',
|
||||
};
|
||||
|
||||
if (experimentalWasmModules) {
|
||||
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
|
||||
extensionFormatMap['.wasm'] = 'wasm';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,13 +35,7 @@ function mimeToFormat(mime) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getLegacyExtensionFormat(ext) {
|
||||
return legacyExtensionFormatMap[ext];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
extensionFormatMap,
|
||||
getLegacyExtensionFormat,
|
||||
legacyExtensionFormatMap,
|
||||
mimeToFormat,
|
||||
};
|
||||
|
@ -11,14 +11,11 @@ const { getOptionValue } = require('internal/options');
|
||||
const { fetchModule } = require('internal/modules/esm/fetch_module');
|
||||
const {
|
||||
extensionFormatMap,
|
||||
getLegacyExtensionFormat,
|
||||
mimeToFormat,
|
||||
} = require('internal/modules/esm/formats');
|
||||
|
||||
const experimentalNetworkImports =
|
||||
getOptionValue('--experimental-network-imports');
|
||||
const experimentalSpecifierResolution =
|
||||
getOptionValue('--experimental-specifier-resolution');
|
||||
const { getPackageType, getPackageScopeConfig } = require('internal/modules/esm/resolve');
|
||||
const { URL, fileURLToPath } = require('internal/url');
|
||||
const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
|
||||
@ -61,25 +58,21 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) {
|
||||
const format = extensionFormatMap[ext];
|
||||
if (format) return format;
|
||||
|
||||
if (experimentalSpecifierResolution !== 'node') {
|
||||
// Explicit undefined return indicates load hook should rerun format check
|
||||
if (ignoreErrors) return undefined;
|
||||
let suggestion = '';
|
||||
if (getPackageType(url) === 'module' && ext === '') {
|
||||
const config = getPackageScopeConfig(url);
|
||||
const fileBasename = basename(filepath);
|
||||
const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1);
|
||||
suggestion = 'Loading extensionless files is not supported inside of ' +
|
||||
'"type":"module" package.json contexts. The package.json file ' +
|
||||
`${config.pjsonPath} caused this "type":"module" context. Try ` +
|
||||
`changing ${filepath} to have a file extension. Note the "bin" ` +
|
||||
'field of package.json can point to a file with an extension, for example ' +
|
||||
`{"type":"module","bin":{"${fileBasename}":"${relativePath}.js"}}`;
|
||||
}
|
||||
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion);
|
||||
// Explicit undefined return indicates load hook should rerun format check
|
||||
if (ignoreErrors) { return undefined; }
|
||||
let suggestion = '';
|
||||
if (getPackageType(url) === 'module' && ext === '') {
|
||||
const config = getPackageScopeConfig(url);
|
||||
const fileBasename = basename(filepath);
|
||||
const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1);
|
||||
suggestion = 'Loading extensionless files is not supported inside of ' +
|
||||
'"type":"module" package.json contexts. The package.json file ' +
|
||||
`${config.pjsonPath} caused this "type":"module" context. Try ` +
|
||||
`changing ${filepath} to have a file extension. Note the "bin" ` +
|
||||
'field of package.json can point to a file with an extension, for example ' +
|
||||
`{"type":"module","bin":{"${fileBasename}":"${relativePath}.js"}}`;
|
||||
}
|
||||
|
||||
return getLegacyExtensionFormat(ext) ?? null;
|
||||
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,8 +89,6 @@ const { getOptionValue } = require('internal/options');
|
||||
|
||||
// [2] `validate...()`s throw the wrong error
|
||||
|
||||
let emittedSpecifierResolutionWarning = false;
|
||||
|
||||
/**
|
||||
* A utility function to iterate through a hook chain, track advancement in the
|
||||
* chain, and generate and supply the `next<HookName>` argument to the custom
|
||||
@ -241,16 +239,6 @@ class ESMLoader {
|
||||
if (getOptionValue('--experimental-network-imports')) {
|
||||
emitExperimentalWarning('Network Imports');
|
||||
}
|
||||
if (
|
||||
!emittedSpecifierResolutionWarning &&
|
||||
getOptionValue('--experimental-specifier-resolution') === 'node'
|
||||
) {
|
||||
process.emitWarning(
|
||||
'The Node.js specifier resolution flag is experimental. It could change or be removed at any time.',
|
||||
'ExperimentalWarning'
|
||||
);
|
||||
emittedSpecifierResolutionWarning = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,6 @@ const {
|
||||
ArrayPrototypeConcat,
|
||||
ArrayPrototypeJoin,
|
||||
ArrayPrototypeShift,
|
||||
JSONParse,
|
||||
JSONStringify,
|
||||
ObjectFreeze,
|
||||
ObjectGetOwnPropertyNames,
|
||||
@ -37,7 +36,7 @@ const { getOptionValue } = require('internal/options');
|
||||
const policy = getOptionValue('--experimental-policy') ?
|
||||
require('internal/process/policy') :
|
||||
null;
|
||||
const { sep, relative, resolve } = require('path');
|
||||
const { sep, relative } = require('path');
|
||||
const preserveSymlinks = getOptionValue('--preserve-symlinks');
|
||||
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
|
||||
const experimentalNetworkImports =
|
||||
@ -60,7 +59,6 @@ const {
|
||||
} = require('internal/errors').codes;
|
||||
|
||||
const { Module: CJSModule } = require('internal/modules/cjs/loader');
|
||||
const packageJsonReader = require('internal/modules/package_json_reader');
|
||||
const { getPackageConfig, getPackageScopeConfig } = require('internal/modules/esm/package_config');
|
||||
|
||||
/**
|
||||
@ -234,50 +232,6 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
fileURLToPath(new URL('.', packageJSONUrl)), fileURLToPath(base));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {URL} search
|
||||
* @returns {URL | undefined}
|
||||
*/
|
||||
function resolveExtensionsWithTryExactName(search) {
|
||||
if (fileExists(search)) return search;
|
||||
return resolveExtensions(search);
|
||||
}
|
||||
|
||||
const extensions = ['.js', '.json', '.node', '.mjs'];
|
||||
|
||||
/**
|
||||
* @param {URL} search
|
||||
* @returns {URL | undefined}
|
||||
*/
|
||||
function resolveExtensions(search) {
|
||||
for (let i = 0; i < extensions.length; i++) {
|
||||
const extension = extensions[i];
|
||||
const guess = new URL(`${search.pathname}${extension}`, search);
|
||||
if (fileExists(guess)) return guess;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {URL} search
|
||||
* @returns {URL | undefined}
|
||||
*/
|
||||
function resolveDirectoryEntry(search) {
|
||||
const dirPath = fileURLToPath(search);
|
||||
const pkgJsonPath = resolve(dirPath, 'package.json');
|
||||
if (fileExists(pkgJsonPath)) {
|
||||
const pkgJson = packageJsonReader.read(pkgJsonPath);
|
||||
if (pkgJson.containsKeys) {
|
||||
const { main } = JSONParse(pkgJson.string);
|
||||
if (main != null) {
|
||||
const mainUrl = pathToFileURL(resolve(dirPath, main));
|
||||
return resolveExtensionsWithTryExactName(mainUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolveExtensions(new URL('index', search));
|
||||
}
|
||||
|
||||
const encodedSepRegEx = /%2F|%5C/i;
|
||||
/**
|
||||
* @param {URL} resolved
|
||||
@ -291,25 +245,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
|
||||
resolved.pathname, 'must not include encoded "/" or "\\" characters',
|
||||
fileURLToPath(base));
|
||||
|
||||
let path = fileURLToPath(resolved);
|
||||
if (getOptionValue('--experimental-specifier-resolution') === 'node') {
|
||||
let file = resolveExtensionsWithTryExactName(resolved);
|
||||
|
||||
// Directory
|
||||
if (file === undefined) {
|
||||
file = StringPrototypeEndsWith(path, '/') ?
|
||||
(resolveDirectoryEntry(resolved) || resolved) : resolveDirectoryEntry(new URL(`${resolved}/`));
|
||||
|
||||
if (file === resolved) return file;
|
||||
|
||||
if (file === undefined) {
|
||||
throw new ERR_MODULE_NOT_FOUND(
|
||||
resolved.pathname, fileURLToPath(base), 'module');
|
||||
}
|
||||
}
|
||||
|
||||
path = file;
|
||||
}
|
||||
const path = fileURLToPath(resolved);
|
||||
|
||||
const stats = tryStatSync(StringPrototypeEndsWith(path, '/') ?
|
||||
StringPrototypeSlice(path, -1) : path);
|
||||
|
@ -40,10 +40,6 @@ function shouldUseESMLoader(mainPath) {
|
||||
const userImports = getOptionValue('--import');
|
||||
if (userLoaders.length > 0 || userImports.length > 0)
|
||||
return true;
|
||||
const esModuleSpecifierResolution =
|
||||
getOptionValue('--experimental-specifier-resolution');
|
||||
if (esModuleSpecifierResolution === 'node')
|
||||
return true;
|
||||
// Determine the module format of the main
|
||||
if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs'))
|
||||
return true;
|
||||
|
@ -180,7 +180,6 @@ const {
|
||||
const history = require('internal/repl/history');
|
||||
const {
|
||||
extensionFormatMap,
|
||||
legacyExtensionFormatMap,
|
||||
} = require('internal/modules/esm/formats');
|
||||
|
||||
let nextREPLResourceNumber = 1;
|
||||
@ -1377,10 +1376,7 @@ function complete(line, callback) {
|
||||
if (this.allowBlockingCompletions) {
|
||||
const subdir = match[2] || '';
|
||||
// File extensions that can be imported:
|
||||
const extensions = ObjectKeys(
|
||||
getOptionValue('--experimental-specifier-resolution') === 'node' ?
|
||||
legacyExtensionFormatMap :
|
||||
extensionFormatMap);
|
||||
const extensions = ObjectKeys(extensionFormatMap);
|
||||
|
||||
// Only used when loading bare module specifiers from `node_modules`:
|
||||
const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`);
|
||||
|
@ -113,14 +113,6 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!experimental_specifier_resolution.empty()) {
|
||||
if (experimental_specifier_resolution != "node" &&
|
||||
experimental_specifier_resolution != "explicit") {
|
||||
errors->push_back(
|
||||
"invalid value for --experimental-specifier-resolution");
|
||||
}
|
||||
}
|
||||
|
||||
if (syntax_check_only && has_eval_string) {
|
||||
errors->push_back("either --check or --eval can be used, not both");
|
||||
}
|
||||
@ -444,11 +436,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
||||
"set module type for string input",
|
||||
&EnvironmentOptions::module_type,
|
||||
kAllowedInEnvironment);
|
||||
AddOption("--experimental-specifier-resolution",
|
||||
"Select extension resolution algorithm for es modules; "
|
||||
"either 'explicit' (default) or 'node'",
|
||||
&EnvironmentOptions::experimental_specifier_resolution,
|
||||
kAllowedInEnvironment);
|
||||
AddOption(
|
||||
"--experimental-specifier-resolution", "", NoOp{}, kAllowedInEnvironment);
|
||||
AddAlias("--es-module-specifier-resolution",
|
||||
"--experimental-specifier-resolution");
|
||||
AddOption("--deprecation",
|
||||
|
@ -112,7 +112,6 @@ class EnvironmentOptions : public Options {
|
||||
bool experimental_global_customevent = false;
|
||||
bool experimental_global_web_crypto = true;
|
||||
bool experimental_https_modules = false;
|
||||
std::string experimental_specifier_resolution;
|
||||
bool experimental_wasm_modules = false;
|
||||
bool experimental_import_meta_resolve = false;
|
||||
std::string module_type;
|
||||
|
@ -27,7 +27,6 @@ describe('ESM: warn for obsolete hooks provided', { concurrency: true }, () => {
|
||||
const [experiment, arg] of [
|
||||
[/Custom ESM Loaders/, `--experimental-loader=${fileURL('es-module-loaders', 'hooks-custom.mjs')}`],
|
||||
[/Network Imports/, '--experimental-network-imports'],
|
||||
[/specifier resolution/, '--experimental-specifier-resolution=node'],
|
||||
]
|
||||
) {
|
||||
it(`should print for ${experiment.toString().replaceAll('/', '')}`, async () => {
|
||||
|
@ -1,40 +0,0 @@
|
||||
import * as common from '../common/index.mjs';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import tmpdir from '../common/tmpdir.js';
|
||||
import { spawn } from 'child_process';
|
||||
import assert from 'assert';
|
||||
|
||||
tmpdir.refresh();
|
||||
const tmpDir = tmpdir.path;
|
||||
|
||||
// Create the following file structure:
|
||||
// ├── index.mjs
|
||||
// ├── subfolder
|
||||
// │ ├── index.mjs
|
||||
// │ └── node_modules
|
||||
// │ └── package-a
|
||||
// │ └── index.mjs
|
||||
// └── symlink.mjs -> ./subfolder/index.mjs
|
||||
const entry = path.join(tmpDir, 'index.mjs');
|
||||
const symlink = path.join(tmpDir, 'symlink.mjs');
|
||||
const real = path.join(tmpDir, 'subfolder', 'index.mjs');
|
||||
const packageDir = path.join(tmpDir, 'subfolder', 'node_modules', 'package-a');
|
||||
const packageEntry = path.join(packageDir, 'index.mjs');
|
||||
try {
|
||||
await fs.symlink(real, symlink);
|
||||
} catch (err) {
|
||||
if (err.code !== 'EPERM') throw err;
|
||||
common.skip('insufficient privileges for symlinks');
|
||||
}
|
||||
await fs.mkdir(packageDir, { recursive: true });
|
||||
await Promise.all([
|
||||
fs.writeFile(entry, 'import "./symlink.mjs";'),
|
||||
fs.writeFile(real, 'export { a } from "package-a/index.mjs"'),
|
||||
fs.writeFile(packageEntry, 'export const a = 1;'),
|
||||
]);
|
||||
|
||||
spawn(process.execPath, ['--experimental-specifier-resolution=node', entry],
|
||||
{ stdio: 'inherit' }).on('exit', common.mustCall((code) => {
|
||||
assert.strictEqual(code, 0);
|
||||
}));
|
@ -1,82 +0,0 @@
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import { match, strictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
|
||||
describe('ESM: specifier-resolution=node', { concurrency: true }, () => {
|
||||
it(async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-specifier-resolution=node',
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
[
|
||||
'import { strictEqual } from "node:assert";',
|
||||
// CommonJS index.js
|
||||
`import commonjs from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-commonjs'))};`,
|
||||
// ESM index.js
|
||||
`import module from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-module'))};`,
|
||||
// Directory entry with main.js
|
||||
`import main from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/dir-with-main'))};`,
|
||||
// Notice the trailing slash
|
||||
`import success, { explicit, implicit, implicitModule } from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/'))};`,
|
||||
'strictEqual(commonjs, "commonjs");',
|
||||
'strictEqual(module, "module");',
|
||||
'strictEqual(main, "main");',
|
||||
'strictEqual(success, "success");',
|
||||
'strictEqual(explicit, "esm");',
|
||||
'strictEqual(implicit, "cjs");',
|
||||
'strictEqual(implicitModule, "cjs");',
|
||||
].join('\n'),
|
||||
]);
|
||||
|
||||
strictEqual(stderr, '');
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 0);
|
||||
});
|
||||
|
||||
it('should throw when the file doesn\'t exist', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-module-specifiers/do-not-exist.js'),
|
||||
]);
|
||||
|
||||
match(stderr, /Cannot find module/);
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 1);
|
||||
});
|
||||
|
||||
it('should throw when the omitted file extension is .mjs (legacy loader doesn\'t support it)', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-specifier-resolution=node',
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import whatever from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/implicit-main-type-commonjs'))};`,
|
||||
]);
|
||||
|
||||
match(stderr, /ERR_MODULE_NOT_FOUND/);
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 1);
|
||||
});
|
||||
|
||||
for (
|
||||
const item of [
|
||||
'package-type-commonjs',
|
||||
'package-type-module',
|
||||
'/',
|
||||
'/index',
|
||||
]
|
||||
) it('should ', async () => {
|
||||
const { code } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-specifier-resolution=node',
|
||||
'--es-module-specifier-resolution=node',
|
||||
fixtures.path('es-module-specifiers', item),
|
||||
]);
|
||||
|
||||
strictEqual(code, 0);
|
||||
});
|
||||
});
|
@ -1 +0,0 @@
|
||||
module.exports = 'main';
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"main": "./main.js"
|
||||
}
|
@ -1 +0,0 @@
|
||||
module.exports = 'a';
|
@ -1 +0,0 @@
|
||||
export const b = 'b';
|
@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
one: 1,
|
||||
two: 2,
|
||||
three: 3
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
// js file that is common.js
|
||||
import a from './a.js';
|
||||
// ESM with named export
|
||||
import {b} from './b.mjs';
|
||||
// import 'c.cjs';
|
||||
import cjs from './c.cjs';
|
||||
// proves cross boundary fun bits
|
||||
import jsAsEsm from '../package-type-module/a.js';
|
||||
|
||||
// named export from core
|
||||
import {strictEqual, deepStrictEqual} from 'assert';
|
||||
|
||||
strictEqual(a, jsAsEsm);
|
||||
strictEqual(b, 'b');
|
||||
deepStrictEqual(cjs, {
|
||||
one: 1,
|
||||
two: 2,
|
||||
three: 3
|
||||
});
|
||||
|
||||
export default 'commonjs';
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
@ -1 +0,0 @@
|
||||
export default 'a'
|
@ -1 +0,0 @@
|
||||
export const b = 'b';
|
@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
one: 1,
|
||||
two: 2,
|
||||
three: 3
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
// ESM with only default
|
||||
import a from './a.js';
|
||||
// ESM with named export
|
||||
import {b} from './b.mjs';
|
||||
// import 'c.cjs';
|
||||
import cjs from './c.cjs';
|
||||
// import across boundaries
|
||||
import jsAsCjs from '../package-type-commonjs/a.js'
|
||||
|
||||
// named export from core
|
||||
import {strictEqual, deepStrictEqual} from 'assert';
|
||||
|
||||
strictEqual(a, jsAsCjs);
|
||||
strictEqual(b, 'b');
|
||||
deepStrictEqual(cjs, {
|
||||
one: 1,
|
||||
two: 2,
|
||||
three: 3
|
||||
});
|
||||
|
||||
export default 'module';
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
Loading…
Reference in New Issue
Block a user