diff --git a/Makefile b/Makefile index b1c267ed5526fe..f931c047d7e929 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,7 @@ EXEEXT := $(shell $(PYTHON) -c \ "import sys; print('.exe' if sys.platform == 'win32' else '')") NODE_EXE = node$(EXEEXT) +NODE_ESM_EXE = node-esm${EXEEXT} NODE ?= ./$(NODE_EXE) NODE_G_EXE = node_g$(EXEEXT) NPM ?= ./deps/npm/bin/npm-cli.js @@ -132,6 +133,7 @@ $(NODE_EXE): build_type:=Release $(NODE_G_EXE): build_type:=Debug $(NODE_EXE) $(NODE_G_EXE): config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=${build_type} V=$(V) + ln -fs $(NODE_EXE) out/${build_type}/$(NODE_ESM_EXE) if [ ! -r $@ ] || [ ! -L $@ ]; then \ ln -fs out/${build_type}/$(NODE_EXE) $@; fi else @@ -147,10 +149,12 @@ else endif $(NODE_EXE): config.gypi out/Release/build.ninja $(NINJA) -C out/Release $(NINJA_ARGS) + ln -fs $(NODE_EXE) out/Release/$(NODE_ESM_EXE) if [ ! -r $@ ] || [ ! -L $@ ]; then ln -fs out/Release/$(NODE_EXE) $@; fi $(NODE_G_EXE): config.gypi out/Debug/build.ninja $(NINJA) -C out/Debug $(NINJA_ARGS) + ln -fs $(NODE_EXE) out/Debug/$(NODE_ESM_EXE) if [ ! -r $@ ] || [ ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi else $(NODE_EXE) $(NODE_G_EXE): diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 4ac9c011d153f4..cd28a65b309959 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -13,6 +13,7 @@ const { extensionFormatMap, mimeToFormat, } = require('internal/modules/esm/formats'); +const { isNodeESM } = require('internal/modules/helpers'); const experimentalNetworkImports = getOptionValue('--experimental-network-imports'); @@ -73,8 +74,13 @@ function extname(url) { * @returns {string} */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { + const defaultESM = isNodeESM(); + const ext = extname(url); if (ext === '.js') { + if (defaultESM) { + return getPackageType(url) === 'commonjs' ? 'commonjs' : 'module'; + } return getPackageType(url) === 'module' ? 'module' : 'commonjs'; } @@ -83,6 +89,11 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { // Explicit undefined return indicates load hook should rerun format check if (ignoreErrors) { return undefined; } + + if (defaultESM) { + return 'module'; + } + const filepath = fileURLToPath(url); let suggestion = ''; if (getPackageType(url) === 'module' && ext === '') { diff --git a/lib/internal/modules/helpers.js b/lib/internal/modules/helpers.js index 307a34cb09b512..837dcd682a6073 100644 --- a/lib/internal/modules/helpers.js +++ b/lib/internal/modules/helpers.js @@ -256,11 +256,17 @@ function hasEsmSyntax(code) { stmt.type === 'ExportAllDeclaration'); } +function isNodeESM() { + const execname = path.basename(process.argv0); + return execname === 'node-esm' || execname === 'node-esm.exe'; +} + module.exports = { addBuiltinLibsToObject, getCjsConditions, initializeCjsConditions, hasEsmSyntax, + isNodeESM, loadBuiltinModule, makeRequireFunction, normalizeReferrerURL, diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js index 0bfe7b11241416..e9a87af56cb35e 100644 --- a/lib/internal/modules/run_main.js +++ b/lib/internal/modules/run_main.js @@ -5,6 +5,7 @@ const { } = primordials; const { getOptionValue } = require('internal/options'); +const { isNodeESM } = require('internal/modules/helpers'); const path = require('path'); function resolveMainPath(main) { @@ -42,8 +43,13 @@ function shouldUseESMLoader(mainPath) { return true; if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) return false; + const pkg = readPackageScope(mainPath); - return pkg && pkg.data.type === 'module'; + + if (isNodeESM()) + return pkg.data?.type !== 'commonjs'; + + return pkg.data?.type === 'module'; } function runMainESM(mainPath) {