Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upmodule: add note when cjs loader throws error #28950
Conversation
This comment has been minimized.
This comment has been minimized.
|
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 |
This comment has been minimized.
This comment has been minimized.
bmeck
approved these changes
Aug 4, 2019
|
nits, but nothing blocking |
ljharb
approved these changes
Aug 4, 2019
gntem
force-pushed the
gntem:esm-modules-note-for-invalid-imports
branch
from
c829d54
to
dc3792d
Aug 5, 2019
Trott
reviewed
Aug 5, 2019
lib/internal/modules/cjs/loader.js Outdated
jkrems
reviewed
Aug 5, 2019
gntem
force-pushed the
gntem:esm-modules-note-for-invalid-imports
branch
2 times, most recently
from
610067e
to
d2ede7d
Aug 6, 2019
This comment has been minimized.
This comment has been minimized.
Trott
reviewed
Aug 7, 2019
gntem
force-pushed the
gntem:esm-modules-note-for-invalid-imports
branch
from
d2ede7d
to
3d5741c
Aug 7, 2019
targos
closed this
Aug 7, 2019
This comment has been minimized.
This comment has been minimized.
|
Why was this closed? |
This comment has been minimized.
This comment has been minimized.
|
I don't know, probably a missclick, sorry |
targos
reopened this
Aug 7, 2019
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Test failures here all seem to be flakes at this point. Any further feedback on this PR at all? Good to merge? |
This comment has been minimized.
This comment has been minimized.
Trott
reviewed
Aug 11, 2019
| */ | ||
| if (err.message.startsWith('Unexpected token export') || | ||
| (/^\s*import(?=[ {'"*])\s*(?![ (])/).test(lineWithErr)) { | ||
| err.stack = 'Note: To load an ES module set "type": "module" ' + |
This comment has been minimized.
This comment has been minimized.
Trott
Aug 11, 2019
Member
| err.stack = 'Note: To load an ES module set "type": "module" ' + | |
| err.stack = 'To load an ES module, set "type": "module" ' + |
Trott
reviewed
Aug 11, 2019
| const Import5 = fixtures.path('/es-modules/es-note-unexpected-import-5.cjs'); | ||
|
|
||
| // Expect note to be included in the error output | ||
| const expectedNote = 'Note: To load an ES module ' + |
This comment has been minimized.
This comment has been minimized.
Trott
Aug 11, 2019
Member
| const expectedNote = 'Note: To load an ES module ' + | |
| const expectedNote = 'To load an ES module, ' + |
Trott
force-pushed the
gntem:esm-modules-note-for-invalid-imports
branch
from
53c4037
to
1bc60b0
Aug 11, 2019
This comment has been minimized.
This comment has been minimized.
Trott
reviewed
Aug 11, 2019
Trott
dismissed
their
stale review
Aug 11, 2019
rescinding my approval as I have a comment/change request
Trott
reviewed
Aug 11, 2019
| */ | ||
| if (err.message.startsWith('Unexpected token export') || | ||
| (/^\s*import(?=[ {'"*])\s*(?![ (])/).test(lineWithErr)) { | ||
| err.stack = 'To load an ES module, set "type": "module" ' + |
This comment has been minimized.
This comment has been minimized.
Trott
Aug 11, 2019
Member
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?
This comment has been minimized.
This comment has been minimized.
ljharb
Aug 11, 2019
Member
actually yeah, good call - this will make the stacks violate the spec, if i can ever get that proposal advanced.
This comment has been minimized.
This comment has been minimized.
guybedford
Aug 12, 2019
•
Contributor
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.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Trott
Aug 12, 2019
Member
Maybe an acceptable solution would be to leave the error contents alone and emit a separate warning with the note?
This comment has been minimized.
This comment has been minimized.
ljharb
Aug 12, 2019
Member
You could even overwrite the own data property with an accessory that console.warned.
This comment has been minimized.
This comment has been minimized.
gntem
Aug 12, 2019
Author
Contributor
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.
This comment has been minimized.
This comment has been minimized.
Trott
reviewed
Aug 12, 2019
| */ | ||
| if (err.message.startsWith('Unexpected token export') || | ||
| (/^\s*import(?=[ {'"*])\s*(?![ (])/).test(lineWithErr)) { | ||
| console.warn('To load an ES module, set "type": "module" ' + |
This comment has been minimized.
This comment has been minimized.
Trott
Aug 12, 2019
Member
I think we'd want to use process.emitWarning() instead to allow the end user to decide how to handle warnings?
This comment has been minimized.
This comment has been minimized.
gntem
Aug 12, 2019
•
Author
Contributor
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);
This comment has been minimized.
This comment has been minimized.
Trott
Aug 12, 2019
•
Member
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):
This comment has been minimized.
This comment has been minimized.
Trott
Aug 12, 2019
Member
I wonder if the problem you're having is that the error is thrown before the warning is emitted....
This comment has been minimized.
This comment has been minimized.
Trott
Aug 12, 2019
Member
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....
Trott
force-pushed the
gntem:esm-modules-note-for-invalid-imports
branch
from
d25077d
to
3372860
Aug 12, 2019
This comment has been minimized.
This comment has been minimized.
|
Updated, rebased, squashed, force-pushed. I think this is ready to go? |
Trott
approved these changes
Aug 12, 2019
This comment has been minimized.
This comment has been minimized.
guybedford
approved these changes
Aug 13, 2019
|
LGTM! |
This comment has been minimized.
This comment has been minimized.
|
Landed in 427e534 |
Trott
closed this
Aug 13, 2019
Trott
added a commit
to Trott/io.js
that referenced
this pull request
Aug 13, 2019
This comment has been minimized.
This comment has been minimized.
|
Thanks for the contribution! |
gntem commentedAug 3, 2019
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