-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
module: improve error decoration for cjs named exports for multi-line import statements #35259
Comments
cc @nodejs/modules-active-members |
This is definitely less than ideal. I like the solution in ctavan@248eada as a place to start. We can definitely improve the regex and support multi-line in the future. |
Great, I‘ll provide a PR tomorrow. |
The node process crashes when trying to parse a multiline import statement for named exports of a CommonJS module: TypeError: Cannot read property '0' of null at ModuleJob._instantiate (internal/modules/esm/module_job.js:112:77) at async ModuleJob.run (internal/modules/esm/module_job.js:137:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25), The reason is that the regexp that is currently used to decorate the original error fails for multi line import statements. Unfortunately the undecorated error stack only contains the single line which causes the import to fail: file:///***/node/test/fixtures/es-modules/package-cjs-named-error/multi-line.mjs:2 comeOn, ^^^^^^ SyntaxError: The requested module './fail.cjs' does not provide an export named 'comeOn' at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21) at async ModuleJob.run (internal/modules/esm/module_job.js:141:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25) Hence, for multiline import statements we cannot create an equivalent piece of code that uses default import followed by an object destructuring assignment. In any case the node process should definitely not crash. So until we have a more sophisticated way of extracting the entire problematic multiline import statement, show the code example only for single-line imports where the current regexp approach works well. Refs: nodejs#35259
The node process crashes when trying to parse a multiline import statement for named exports of a CommonJS module: TypeError: Cannot read property '0' of null at ModuleJob._instantiate (internal/modules/esm/module_job.js:112:77) at async ModuleJob.run (internal/modules/esm/module_job.js:137:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25), The reason is that the regexp that is currently used to decorate the original error fails for multi line import statements. Unfortunately the undecorated error stack only contains the single line which causes the import to fail: file:///***/node/test/fixtures/es-modules/package-cjs-named-error/multi-line.mjs:2 comeOn, ^^^^^^ SyntaxError: The requested module './fail.cjs' does not provide an export named 'comeOn' at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21) at async ModuleJob.run (internal/modules/esm/module_job.js:141:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25) Hence, for multiline import statements we cannot create an equivalent piece of code that uses default import followed by an object destructuring assignment. In any case the node process should definitely not crash. So until we have a more sophisticated way of extracting the entire problematic multiline import statement, show the code example only for single-line imports where the current regexp approach works well. Refs: #35259 PR-URL: #35275 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Rich Trott <[email protected]>
The node process crashes when trying to parse a multiline import statement for named exports of a CommonJS module: TypeError: Cannot read property '0' of null at ModuleJob._instantiate (internal/modules/esm/module_job.js:112:77) at async ModuleJob.run (internal/modules/esm/module_job.js:137:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25), The reason is that the regexp that is currently used to decorate the original error fails for multi line import statements. Unfortunately the undecorated error stack only contains the single line which causes the import to fail: file:///***/node/test/fixtures/es-modules/package-cjs-named-error/multi-line.mjs:2 comeOn, ^^^^^^ SyntaxError: The requested module './fail.cjs' does not provide an export named 'comeOn' at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21) at async ModuleJob.run (internal/modules/esm/module_job.js:141:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25) Hence, for multiline import statements we cannot create an equivalent piece of code that uses default import followed by an object destructuring assignment. In any case the node process should definitely not crash. So until we have a more sophisticated way of extracting the entire problematic multiline import statement, show the code example only for single-line imports where the current regexp approach works well. Refs: #35259 PR-URL: #35275 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Rich Trott <[email protected]>
I've changed the title of this issue to track having to improve the existing message which is not giving the hint for a multiline import |
@MylesBorins if you have a rough idea of how to extract the multiline import in that place then let me know and I'm happy to work on a patch. |
@ctavan honestly the best idea I can come up with is using acorn to parse the entire file, but that seems like it might be overkill |
The node process crashes when trying to parse a multiline import statement for named exports of a CommonJS module: TypeError: Cannot read property '0' of null at ModuleJob._instantiate (internal/modules/esm/module_job.js:112:77) at async ModuleJob.run (internal/modules/esm/module_job.js:137:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25), The reason is that the regexp that is currently used to decorate the original error fails for multi line import statements. Unfortunately the undecorated error stack only contains the single line which causes the import to fail: file:///***/node/test/fixtures/es-modules/package-cjs-named-error/multi-line.mjs:2 comeOn, ^^^^^^ SyntaxError: The requested module './fail.cjs' does not provide an export named 'comeOn' at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21) at async ModuleJob.run (internal/modules/esm/module_job.js:141:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25) Hence, for multiline import statements we cannot create an equivalent piece of code that uses default import followed by an object destructuring assignment. In any case the node process should definitely not crash. So until we have a more sophisticated way of extracting the entire problematic multiline import statement, show the code example only for single-line imports where the current regexp approach works well. Refs: nodejs#35259 PR-URL: nodejs#35275 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Rich Trott <[email protected]>
@MylesBorins hmm, I was hoping for a simpler solution. While digging through the error decoration code I realized that @bcoe you have touched this recently with the sourcemap patch (458677f5ef2). I didn't check the sourcemap implementation in detail, but maybe it also involves rewriting error messages that show the offending (mapped) lines of code? Any ideas from that perspective? |
Is this really overkill? The process is exiting, so the few milliseconds it takes for Acorn to parse the file shouldn’t matter too much I’d think. And this would be a solid solution without the brittleness of a regex. |
@GeoffreyBooth I’ll explore this over the next few days to see how much complexity this will add. |
The node process crashes when trying to parse a multiline import statement for named exports of a CommonJS module: TypeError: Cannot read property '0' of null at ModuleJob._instantiate (internal/modules/esm/module_job.js:112:77) at async ModuleJob.run (internal/modules/esm/module_job.js:137:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25), The reason is that the regexp that is currently used to decorate the original error fails for multi line import statements. Unfortunately the undecorated error stack only contains the single line which causes the import to fail: file:///***/node/test/fixtures/es-modules/package-cjs-named-error/multi-line.mjs:2 comeOn, ^^^^^^ SyntaxError: The requested module './fail.cjs' does not provide an export named 'comeOn' at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21) at async ModuleJob.run (internal/modules/esm/module_job.js:141:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25) Hence, for multiline import statements we cannot create an equivalent piece of code that uses default import followed by an object destructuring assignment. In any case the node process should definitely not crash. So until we have a more sophisticated way of extracting the entire problematic multiline import statement, show the code example only for single-line imports where the current regexp approach works well. Refs: #35259 PR-URL: #35275 Backport-PR-URL: #35385 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Rich Trott <[email protected]>
@GeoffreyBooth @MylesBorins @ljharb @guybedford I have prepared a pull request over at #35453 which uses acorn to parse the offending file to always produce an equivalent code example. Since I'm still new to the Node.js codebase I have a ton of questions w.r.t. my code which I have added as inline comments on the PR. Would be super happy to receive your feedback over there. |
When trying to import named exports from a CommonJS module an error is thrown. Unfortunately the V8 error only contains the single line that causes the error, it is therefore impossible to construct an equivalent code consisting of default import + object descructuring assignment. This was the reason why the example code was removed for multi line import statements in nodejs#35275 To generate a helpful error messages for any case we can parse the file where the error happens using acorn and construct a valid example code from the parsed ImportDeclaration. This will work for _any_ valid import statement. Since this code is only executed shortly before the node process crashes anyways performance should not be a concern here. Fixes: nodejs#35259 Refs: nodejs#35275
The node process crashes when trying to parse a multiline import statement for named exports of a CommonJS module: TypeError: Cannot read property '0' of null at ModuleJob._instantiate (internal/modules/esm/module_job.js:112:77) at async ModuleJob.run (internal/modules/esm/module_job.js:137:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25), The reason is that the regexp that is currently used to decorate the original error fails for multi line import statements. Unfortunately the undecorated error stack only contains the single line which causes the import to fail: file:///***/node/test/fixtures/es-modules/package-cjs-named-error/multi-line.mjs:2 comeOn, ^^^^^^ SyntaxError: The requested module './fail.cjs' does not provide an export named 'comeOn' at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21) at async ModuleJob.run (internal/modules/esm/module_job.js:141:5) at async Loader.import (internal/modules/esm/loader.js:165:24) at async rejects.name (file:///***/node/test/es-module/test-esm-cjs-named-error.mjs:56:3) at async waitForActual (assert.js:721:5) at async rejects (assert.js:830:25) Hence, for multiline import statements we cannot create an equivalent piece of code that uses default import followed by an object destructuring assignment. In any case the node process should definitely not crash. So until we have a more sophisticated way of extracting the entire problematic multiline import statement, show the code example only for single-line imports where the current regexp approach works well. Refs: nodejs#35259 PR-URL: nodejs#35275 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Rich Trott <[email protected]>
When trying to import named exports from a CommonJS module an error is thrown. Unfortunately the V8 error only contains the single line that causes the error, it is therefore impossible to construct an equivalent code consisting of default import + object descructuring assignment. This was the reason why the example code was removed for multi line import statements in nodejs#35275 To generate a helpful error messages for any case we can parse the file where the error happens using acorn and construct a valid example code from the parsed ImportDeclaration. This will work for _any_ valid import statement. Since this code is only executed shortly before the node process crashes anyways performance should not be a concern here. Fixes: nodejs#35259 Refs: nodejs#35275
There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document. |
There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment. For more information on how the project manages feature requests, please consult the feature request management document. |
What steps will reproduce the bug?
Failing test can be found here: ctavan@ba9e734
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior?
When trying to import named exports from a CommonJS module, there's usually a helpful error message which is assembled here:
node/lib/internal/modules/esm/module_job.js
Lines 102 to 124 in ed8af4e
What do you see instead?
When using multi-line import statements like:
the following regex does not match:
node/lib/internal/modules/esm/module_job.js
Line 112 in ed8af4e
and the following error is produced:
Additional information
I would love to contribute a fix for this issue, however I need some guidance on how to proceed. The problem I see is that the full error stack only contains the first line of the multi-line import statement:
So while the goal of the additional error decoration which was added in #33256 seems to be to provide a copy & pastable solution, I don't see how this could be achieved with the error information at hand when the error comes from a multi-line import statement.
Options that come to my mind:
/cc @MylesBorins
The text was updated successfully, but these errors were encountered: