Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow package.json to have type: "module" #114

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

stoivo
Copy link

@stoivo stoivo commented Jun 9, 2022

I changes my package.json(rails app), I added type: "module" and then assets:precompile stoped working.

root@runner--project-0-concurrent-0:/builds/project-0# rake assets:precompile
rake aborted!
ExecJS::RuntimeError: node:internal/errors:465
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for /tmp/execjs20220609-2343-1czx37hjs. Loading extensionless files is not supported inside of "type":"module" package.json contexts. The package.json file /package.json caused this "type":"module" context. Try changing /tmp/execjs20220609-2343-1czx37hjs to have a file extension. Note the "bin" field of package.json can point to a file with an extension, for example {"type":"module","bin":{"execjs20220609-2343-1czx37hjs":"./tmp/execjs20220609-2343-1czx37hjs.js"}}
    at new NodeError (node:internal/errors:372:5)
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:76:11)
    at defaultGetFormat (node:internal/modules/esm/get_format:118:38)
    at defaultLoad (node:internal/modules/esm/load:21:20)
    at ESMLoader.load (node:internal/modules/esm/loader:407:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:326:22)
    at new ModuleJob (node:internal/modules/esm/module_job:66:26)
    at ESMLoader.#createModuleJob (node:internal/modules/esm/loader:345:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:304:34)
    at async Promise.all (index 0) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
(execjs):465
Tasks: TOP => assets:precompile
(See full trace by running task with --trace)

I believe node works like if you try to run a .js file it will use the type in
package.json. If you want to run a script with commonjs name it .cjs or as a
module .mjs.

back in 2014 it seam like it did add the extension to the file

commit b3f5dc69226c83ab5b3c47ba61c852831eeb2380
Author:     Joshua Peek <josh@joshpeek.com>
AuthorDate: Thu Jun 5 14:59:16 2014 -0500
Commit:     Joshua Peek <josh@joshpeek.com>
CommitDate: Thu Jun 5 14:59:16 2014 -0500

    Use similar code to Tempfile.create instead of Tempfile.open

...
-          tempfile = Tempfile.open(['execjs', '.js'])
+          tmpfile = create_tempfile(['execjs', 'js'])
...

I don't know why it was removed.

Tempfile.open has some finalizer and unlinking overhead that was don't
actually use since we close the file right away. Tempfile.create was added in
Ruby 2.1 to help, but it isn't widely available yet. Copy pasta some of its
internals here.

sstephenson#149

So I don't think it was on purpose. Also (I think) we didn't have js modules
like we have them now so there where no reason to have the extension.

Maybe I should have created a minimal replication case but I didn't. It was just. Also I could not reproduce it on my mac but only on linux.

I changes my package.json, I added type: "module" and then assets:precompile stoped working.

```
root@runner--project-0-concurrent-0:/builds/project-0# rake assets:precompile
rake aborted!
ExecJS::RuntimeError: node:internal/errors:465
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for /tmp/execjs20220609-2343-1czx37hjs. Loading extensionless files is not supported inside of "type":"module" package.json contexts. The package.json file /package.json caused this "type":"module" context. Try changing /tmp/execjs20220609-2343-1czx37hjs to have a file extension. Note the "bin" field of package.json can point to a file with an extension, for example {"type":"module","bin":{"execjs20220609-2343-1czx37hjs":"./tmp/execjs20220609-2343-1czx37hjs.js"}}
    at new NodeError (node:internal/errors:372:5)
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:76:11)
    at defaultGetFormat (node:internal/modules/esm/get_format:118:38)
    at defaultLoad (node:internal/modules/esm/load:21:20)
    at ESMLoader.load (node:internal/modules/esm/loader:407:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:326:22)
    at new ModuleJob (node:internal/modules/esm/module_job:66:26)
    at ESMLoader.#createModuleJob (node:internal/modules/esm/loader:345:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:304:34)
    at async Promise.all (index 0) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
(execjs):465
Tasks: TOP => assets:precompile
(See full trace by running task with --trace)
```

I believe node works like if you try to run a .js file it will use the type in
package.json. If  you want to run a script with commonjs name it .cjs or as a
module .mjs.

back in 2014 it seam like it did add the extension to the file

commit b3f5dc6
Author:     Joshua Peek <josh@joshpeek.com>
AuthorDate: Thu Jun 5 14:59:16 2014 -0500
Commit:     Joshua Peek <josh@joshpeek.com>
CommitDate: Thu Jun 5 14:59:16 2014 -0500

    Use similar code to Tempfile.create instead of Tempfile.open

...
-          tempfile = Tempfile.open(['execjs', '.js'])
+          tmpfile = create_tempfile(['execjs', 'js'])
...

I don't know why it was removed.

> `Tempfile.open` has some finalizer and unlinking overhead that was don't
> actually use since we close the file right away. `Tempfile.create` was added in
> Ruby 2.1 to help, but it isn't widely available yet. Copy pasta some of its
> internals here.

sstephenson#149

So I don't think it was on purpose. Also (I think) we didn't have js modules
like we have them now so there where no reason to have the extension.
@stoivo
Copy link
Author

stoivo commented Jun 16, 2022

After some more hours of research, I have learned some more useful information.

The cause of the error was: I had left a package.json in the root in my docker container with type: module. When execjs created a tmp file(/tmp/........./execjs1312312js on linux and /var/folders/kt/... on macs) there package.json the root file was detected as closes parent package.json. It contain type: module. When I remove it all works fine.

From the error message below, I think node is requires users to spesicy cjs or mjs when type module is set in package.json

Error [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for /tmp/execjs20220616-1662-1q9n3vujs. Loading extensionless files is not supported inside of "type":"module" package.json contexts. The package.json file /package.json caused this "type":"module" context. Try changing /tmp/execjs20220616-1662-1q9n3vujs to have a file extension. Note the "bin" field of package.json can point to a file with an extension, for example {"type":"module","bin":{"execjs20220616-1662-1q9n3vujs":"./tmp/execjs20220616-1662-1q9n3vujs.js"}}

I still think this is a good thing too add since this is common.js

@stoivo
Copy link
Author

stoivo commented Jun 24, 2022

If the nearest parent package.json lacks a "type" field, or contains "type": "commonjs", .js files are treated as CommonJS. If the volume root is reached and no package.json is found, .js files are treated as CommonJS.
https://nodejs.org/api/packages.html#type

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant