esm: detect ESM syntax in extensionless files under type:commonjs#61737
Open
scott-memco wants to merge 1 commit intonodejs:mainfrom
Open
esm: detect ESM syntax in extensionless files under type:commonjs#61737scott-memco wants to merge 1 commit intonodejs:mainfrom
scott-memco wants to merge 1 commit intonodejs:mainfrom
Conversation
When an extensionless file (common for CLI scripts with shebangs) contains ES module syntax but the nearest package.json has "type": "commonjs", Node.js silently exits with code 0 and produces no output or error. This happens because getFileProtocolModuleFormat() returns 'commonjs' for extensionless files based solely on the package type, without checking the file content for ESM syntax. For extensionless files, when source is available, run detectModuleFormat() before returning the package type. If the file contains ES module syntax, return 'module' so it is loaded as ESM rather than silently failing as CJS. This is consistent with how the 'none' (no type field) case already works for extensionless files, where detectModuleFormat() is called at line 176. Fixes: nodejs#61104 Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
|
Review requested:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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