diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 0ea268bcec7ece..3a8a34051eaa9d 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -1929,6 +1929,15 @@ Module._extensions['.js'] = function(module, filename) { } else { format = 'typescript'; } + } else if (path.extname(filename) === '') { + // Extensionless files skip the .js suffix check above. When type is explicit, + // follow it so ESM syntax surfaces as SyntaxError for commonjs instead of + // silently delegating to ESM. + pkg = packageJsonReader.getNearestParentPackageJSON(filename); + const typeFromPjson = pkg?.data?.type; + if (typeFromPjson === 'commonjs' || typeFromPjson === 'module') { + format = typeFromPjson; + } } const { source, format: loadedFormat } = loadSource(module, filename, format); // Function require shouldn't be used in ES modules when require(esm) is disabled. diff --git a/test/es-module/test-extensionless-esm-type-commonjs.js b/test/es-module/test-extensionless-esm-type-commonjs.js new file mode 100644 index 00000000000000..c5aef8fde8b47c --- /dev/null +++ b/test/es-module/test-extensionless-esm-type-commonjs.js @@ -0,0 +1,25 @@ +'use strict'; + +const { spawnSyncAndAssert } = require('../common/child_process'); +const fixtures = require('../common/fixtures'); + +const commonjsDir = fixtures.path('es-modules', 'extensionless-esm-commonjs'); + +spawnSyncAndAssert(process.execPath, ['--no-experimental-detect-module', './script'], { + cwd: commonjsDir, + encoding: 'utf8', +}, { + status: 1, + stderr: /.+/, + trim: true, +}); + +const moduleDir = fixtures.path('es-modules', 'extensionless-esm-module'); + +spawnSyncAndAssert(process.execPath, ['--no-experimental-detect-module', './script'], { + cwd: moduleDir, + encoding: 'utf8', +}, { + stdout: /script STARTED[\s\S]*v\d+\./, + trim: true, +}); diff --git a/test/fixtures/es-modules/extensionless-esm-commonjs/package.json b/test/fixtures/es-modules/extensionless-esm-commonjs/package.json new file mode 100644 index 00000000000000..5bbefffbabee39 --- /dev/null +++ b/test/fixtures/es-modules/extensionless-esm-commonjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/test/fixtures/es-modules/extensionless-esm-commonjs/script b/test/fixtures/es-modules/extensionless-esm-commonjs/script new file mode 100755 index 00000000000000..75798ebfc99202 --- /dev/null +++ b/test/fixtures/es-modules/extensionless-esm-commonjs/script @@ -0,0 +1,4 @@ +#!/usr/bin/env node +console.log('script STARTED') +import { version } from 'node:process' +console.log(version) diff --git a/test/fixtures/es-modules/extensionless-esm-module/package.json b/test/fixtures/es-modules/extensionless-esm-module/package.json new file mode 100644 index 00000000000000..3dbc1ca591c055 --- /dev/null +++ b/test/fixtures/es-modules/extensionless-esm-module/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/fixtures/es-modules/extensionless-esm-module/script b/test/fixtures/es-modules/extensionless-esm-module/script new file mode 100755 index 00000000000000..75798ebfc99202 --- /dev/null +++ b/test/fixtures/es-modules/extensionless-esm-module/script @@ -0,0 +1,4 @@ +#!/usr/bin/env node +console.log('script STARTED') +import { version } from 'node:process' +console.log(version)