From d6a2f0b6218e403c910a7d30528909957bfd5fae Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 18 Jul 2024 19:57:40 +0200 Subject: [PATCH] esm: refactor `get_format` PR-URL: https://github.com/nodejs/node/pull/53872 Reviewed-By: Geoffrey Booth Reviewed-By: Paolo Insogna Reviewed-By: Matteo Collina --- lib/internal/modules/esm/get_format.js | 58 +++++++++++++++----------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index cd5c88dce8e021..c6bc030f8b2b31 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -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); } } }