Create file package.json:
{
"type": "module"
}
````
Create file `main` (no extension):
```js
console.log('ok');
Run:
node ./main
Always.
main file to be executed.
> node ./main
internal/modules/run_main.js:54
internalBinding('errors').triggerUncaughtException(
^
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for C:\Users\evg656e\Projects\sandbox\js\experimental-loader\main
at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:65:15)
at Loader.getFormat (internal/modules/esm/loader.js:113:42)
at Loader.getModuleJob (internal/modules/esm/loader.js:244:31)
at async Loader.import (internal/modules/esm/loader.js:178:17) {
code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
This works in version 12. But does not work in versions 13 and 14. --experimental-specifier-resolution=node flag does not help.
Real world example: we have mocha (which main entry file is extensionless), we have ts-node esm-loader, now we want to test ts files with native es modules, like that:
node --loader ts-node/esm.mjs node_modules/mocha/bin/mocha --extension ts
but we get the error described above. But if we rename node_modules/mocha/bin/mocha to node_modules/mocha/bin/mocha.js, then everything works as expected.
@nodejs/modules-active-members
This is intentional. See #31415. The intent is to preserve the ability for extensionless files under "type": "module" to be non-JavaScript in the future, e.g. WASM.
The workarounds are to either make a symlink (e.g. mocha which points to mocha.js) or to create a new "type": "commonjs" package scope and have mocha be a CommonJS file (even if all it does is import() the ESM one). See https://github.com/nodejs/node/pull/31415#issuecomment-576294632.
The problem is that node is supposed to be treating the ./mocha entrypoint as CommonJS, not ESM. mocha's package.json does not declare "type": "module". I believe this is a mistake in the original description of this bug report.
The addition of the --loader flag is causing node to treat the entrypoint as ESM. When --loader is omitted, node correctly treats the entrypoint as CommonJS.
To reproduce on node v14.0.0:
echo '{}' > package.json
touch hooks.mjs
touch foo
node ./foo # <-- this works; no output; exit code 0
node --loader ./hooks.mjs ./foo # <-- this fails with an error, even though ./foo should be treated as CommonJS
I believe this is a mistake in the original description of this bug report.
Do you mind please opening a new issue for this? I think it'll get lost in this one.
Most helpful comment
The problem is that node is supposed to be treating the
./mochaentrypoint as CommonJS, not ESM. mocha's package.json does not declare"type": "module". I believe this is a mistake in the original description of this bug report.The addition of the
--loaderflag is causing node to treat the entrypoint as ESM. When--loaderis omitted, node correctly treats the entrypoint as CommonJS.To reproduce on node v14.0.0: