esm: refactor get_format

PR-URL: https://github.com/nodejs/node/pull/53872
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
Antoine du Hamel 2024-07-18 19:57:40 +02:00 committed by GitHub
parent 63d7b4280e
commit cafd44dc7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -17,6 +17,7 @@ const {
mimeToFormat,
} = require('internal/modules/esm/formats');
const detectModule = getOptionValue('--experimental-detect-module');
const experimentalNetworkImports =
getOptionValue('--experimental-network-imports');
const { containsModuleSyntax } = internalBinding('contextify');
@ -33,6 +34,17 @@ const protocolHandlers = {
'node:'() { return 'builtin'; },
};
/**
* Determine whether the given ambiguous source contains CommonJS or ES module syntax.
* @param {string | Buffer | undefined} source
* @param {URL} url
*/
function detectModuleFormat(source, url) {
if (!source) { return detectModule ? null : 'commonjs'; }
if (!detectModule) { return 'commonjs'; }
return containsModuleSyntax(`${source}`, fileURLToPath(url), url) ? 'module' : 'commonjs';
}
/**
* @param {URL} parsed
* @returns {string | null}
@ -112,26 +124,23 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
default: { // The user did not pass `--experimental-default-type`.
// `source` is undefined when this is called from `defaultResolve`;
// but this gets called again from `defaultLoad`/`defaultLoadSync`.
if (getOptionValue('--experimental-detect-module')) {
const format = source ?
(containsModuleSyntax(`${source}`, fileURLToPath(url), url) ? 'module' : 'commonjs') :
null;
if (format === 'module') {
// This module has a .js extension, a package.json with no `type` field, and ESM syntax.
// Warn about the missing `type` field so that the user can avoid the performance penalty of detection.
typelessPackageJsonFilesWarnedAbout ??= new SafeSet();
if (!typelessPackageJsonFilesWarnedAbout.has(pjsonPath)) {
const warning = `${url} parsed as an ES module because module syntax was detected;` +
` to avoid the performance penalty of syntax detection, add "type": "module" to ${pjsonPath}`;
process.emitWarning(warning, {
code: 'MODULE_TYPELESS_PACKAGE_JSON',
});
typelessPackageJsonFilesWarnedAbout.add(pjsonPath);
}
// For ambiguous files (no type field, .js extension) we return
// undefined from `resolve` and re-run the check in `load`.
const format = detectModuleFormat(source, url);
if (format === 'module') {
// This module has a .js extension, a package.json with no `type` field, and ESM syntax.
// Warn about the missing `type` field so that the user can avoid the performance penalty of detection.
typelessPackageJsonFilesWarnedAbout ??= new SafeSet();
if (!typelessPackageJsonFilesWarnedAbout.has(pjsonPath)) {
const warning = `${url} parsed as an ES module because module syntax was detected;` +
` to avoid the performance penalty of syntax detection, add "type": "module" to ${pjsonPath}`;
process.emitWarning(warning, {
code: 'MODULE_TYPELESS_PACKAGE_JSON',
});
typelessPackageJsonFilesWarnedAbout.add(pjsonPath);
}
return format;
}
return 'commonjs';
return format;
}
}
}
@ -154,15 +163,14 @@ function getFileProtocolModuleFormat(url, context = { __proto__: null }, ignoreE
return 'commonjs';
}
default: { // The user did not pass `--experimental-default-type`.
if (getOptionValue('--experimental-detect-module')) {
if (!source) { return null; }
const format = getFormatOfExtensionlessFile(url);
if (format === 'module') {
return containsModuleSyntax(`${source}`, fileURLToPath(url), url) ? 'module' : 'commonjs';
}
if (!source) {
return null;
}
const format = getFormatOfExtensionlessFile(url);
if (format === 'wasm') {
return format;
}
return 'commonjs';
return detectModuleFormat(source, url);
}
}
}