module: add note when cjs loader throws error#28950
module: add note when cjs loader throws error#28950gntem wants to merge 1 commit intonodejs:masterfrom
Conversation
|
I've been working with @gntem as part of the mentorship program and one of the projects we discussed was seeing if we could improve the error messages for using ES modules in Node.js to provide easier onboarding. Currently if you write a Node.js module say With this PR, the above error message instead becomes: Providing the actionable information to the user to use modules in Node.js. The tricky case here was catching invalid import syntax as that throws a different unexpected token message depending on the syntax as dynamic |
|
//cc @nodejs/modules-active-members |
c829d54 to
dc3792d
Compare
610067e to
d2ede7d
Compare
d2ede7d to
3d5741c
Compare
|
Why was this closed? |
|
I don't know, probably a missclick, sorry |
|
Test failures here all seem to be flakes at this point. Any further feedback on this PR at all? Good to merge? |
lib/internal/modules/cjs/loader.js
Outdated
There was a problem hiding this comment.
| err.stack = 'Note: To load an ES module set "type": "module" ' + | |
| err.stack = 'To load an ES module, set "type": "module" ' + |
There was a problem hiding this comment.
| const expectedNote = 'Note: To load an ES module ' + | |
| const expectedNote = 'To load an ES module, ' + |
53c4037 to
1bc60b0
Compare
rescinding my approval as I have a comment/change request
lib/internal/modules/cjs/loader.js
Outdated
There was a problem hiding this comment.
Shouldn't text like this be added to err.message or something like that? Wedging stuff that isn't a stack trace into err.stack seems like the wrong place to put it, no?
There was a problem hiding this comment.
actually yeah, good call - this will make the stacks violate the spec, if i can ever get that proposal advanced.
There was a problem hiding this comment.
I believe the reasoning here was originally that if we append the message the error looks like:
(node:7720) ExperimentalWarning: The ESM module loader is experimental.
C:\Users\Guy\x.js:1
export var p = 5;
^^^^^^
To load an ES module using --experimental-modules set "type": "module" in
the package.json or use the .mjs extension.
SyntaxError: Unexpected token export
at Module._compile (internal/modules/cjs/loader.js:720:23)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:643:32)
at Function.Module._load (internal/modules/cjs/loader.js:556:12)
at internal/modules/esm/translators.js:87:15
at Object.meta.done (internal/modules/esm/create_dynamic_module.js:48:9)
at file:///C:/Users/Guy/x.js:9:13
at ModuleJob.run (internal/modules/esm/module_job.js:111:37)
at processTicksAndRejections (internal/process/task_queues.js:85:5)
at async Loader.import (internal/modules/esm/loader.js:134:24)
where the note is hidden beneath the error frame.
Ideally we'd have more control over mutating these error outputs though.
There was a problem hiding this comment.
Correction - I mean the note is hidden beneath the error frame.
There was a problem hiding this comment.
Maybe an acceptable solution would be to leave the error contents alone and emit a separate warning with the note?
There was a problem hiding this comment.
You could even overwrite the own data property with an accessory that console.warned.
There was a problem hiding this comment.
Maybe an acceptable solution would be to leave the error contents alone and emit a separate warning with the note?
So call console.warn after the error condition, would be enough, right? it would still print before the error message and stack.
lib/internal/modules/cjs/loader.js
Outdated
There was a problem hiding this comment.
I think we'd want to use process.emitWarning() instead to allow the end user to decide how to handle warnings?
There was a problem hiding this comment.
I can't seem to get the tests passing I changed to listen for .on('warning',(warning) => ..assertions..) or .on('close',...) also debugged the stderr output but nothing is showing up, the arguments --trace-warnings is provided to the spawned process, but no warning is emitted. In that line, I just replaced with the console.warn with
process.emitWarning('To load an ES module, set "type": "module" ' +
'in the package.json or use the .mjs ' +
'extension.\n\n', 'ExperimentalWarning', undefined);
There was a problem hiding this comment.
I don't think we want it as an ExperimentalWarning because we'll want it even after ES modules are no longer experimental. I'd say stick with the default (which is just Warning):
There was a problem hiding this comment.
I wonder if the problem you're having is that the error is thrown before the warning is emitted....
There was a problem hiding this comment.
To get it to work, you have to use the undocumented now argument for process.emitWarning(). I'll add a commit to this branch in a little bit....
This will allow users to know how to change their project to support ES modules.
d25077d to
3372860
Compare
|
Updated, rebased, squashed, force-pushed. I think this is ready to go? |
|
Landed in 427e534 |
This will allow users to know how to change their project to support ES modules. PR-URL: nodejs#28950 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
|
Thanks for the contribution! 🎉 |
This will allow users to know how to change their project to support ES modules. PR-URL: #28950 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
This will allow users to know how to change their project to support ES modules. PR-URL: #28950 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
subsystem: module: add note to error when import,export is detected.
These will allow users to know how to change their project to support
es modules when the message is displayed.
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes