esm: detect ESM syntax in extensionless files under type:commonjs #61737
+62
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a silent failure where extensionless files containing ES module syntax produce no output and exit with code 0 when the nearest
package.jsonhas"type": "commonjs".This is a common scenario for CLI tools that use shebangs (
#!/usr/bin/env node) without a file extension.Reproduction
Root Cause
In
lib/internal/modules/esm/get_format.js,getFileProtocolModuleFormat()handles extensionless files (line 159-177). WhenpackageTypeis'commonjs', it returns'commonjs'immediately without checking the file content for ESM syntax (line 164-165).This causes the ESM loader to treat the file as a CJS module, routing it through
createCJSModuleWrapin the translators, which wraps the ESM code as CJS — silently producing an empty/non-functional module.Compare with:
'none'(no type field) case for extensionless files, which does calldetectModuleFormat(source, url)at line 176.jsextension case with no type field, which does calldetectModuleFormat(source, url)at line 127Fix
For extensionless files when
packageType !== 'none'(i.e., explicitly'commonjs'), check the source content viadetectModuleFormat()before returning the package type. If the file contains ES module syntax, return'module'so it's loaded correctly.This is consistent with how ambiguous files are already handled elsewhere in the same function, and relies on the existing
containsModuleSyntaxV8 binding (used bydetectModuleFormat) which is already enabled by default via--experimental-detect-module.Test
test/parallel/test-esm-extensionless-commonjs-type.js— creates an extensionless ESM file in atype: commonjsproject, runs it, and asserts it does not silently exit with code 0.Fixes: #61104
Made with Cursor