-
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
Added the requireStack to loader.js #45734
Conversation
Review requested:
|
lib/internal/modules/cjs/loader.js
Outdated
@@ -413,7 +413,7 @@ function tryPackage(requestPath, exts, isMain, originalPath) { | |||
err.code = 'MODULE_NOT_FOUND'; | |||
err.path = path.resolve(requestPath, 'package.json'); | |||
err.requestPath = originalPath; | |||
// TODO(BridgeAR): Add the requireStack as well. | |||
err.requireStack = new Error().stack; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @BridgeAR's comment was referring to the requireStack
that's generated in
node/lib/internal/modules/cjs/loader.js
Lines 1027 to 1032 in 7811d2d
const requireStack = []; | |
for (let cursor = parent; | |
cursor; | |
cursor = moduleParentCache.get(cursor)) { | |
ArrayPrototypePush(requireStack, cursor.filename || cursor.id); | |
} |
new Error().stack
produces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution!
I'm not super familiar with the CJS space of modules (so not officially 👍), but the implementation LGTM and there was an existing code comment suggesting it is needed, so that seems fine.
Do we add arbitrary properties to |
Yes, e.g. every error from a Node.js API has a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd want to add tests before landing this. Also the same TODO is present twice in the file, IMO it would make sense to address them both at once unless one is more complicated than the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the use case that's would be fixed by it? I think we should start with writing some tests for the feature so we set the expectations for what we want the feature to look like, and then proceed with the implementation. Adding an empty array to an error object doesn't make much sense to me if I can't see in what context it can be used, having tests for that would help greatly.
The use case for this property has been discussed in #25690. As suggested in #45734 (comment), this array should be populated with paths of non-internal modules that are present in the stack trace. |
lib/internal/modules/cjs/loader.js
Outdated
// This function takes the error object and a function as arguments. | ||
// The function is used as a marker for the point in the stack trace where the capture should begin. | ||
// In this case, we are using the anonymous function that follows as the marker. | ||
Error.captureStackTrace(err, () => {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is a hook for users to register their own stack trace customizations. I’m not sure we should be using it internally.
test/parallel/test-loader.js
Outdated
@@ -0,0 +1,56 @@ | |||
import { tryPackage } from '../../lib/internal/modules/cjs/loader' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be tested using the public APIs alone, so I would suggest you to revert the tryPackage
exporting change from lib/internal/modules/cjs/loader.js
and instead create a temporary file structure of this sort dynamically while running the test:
❯ tree -a
.
├── index.js
└── node_modules
├── a
│ ├── a.js
│ └── package.json
└── b
└── package.json
3 directories, 4 files
❯ cat index.js
require('a');
❯ cat node_modules/a/a.js
require('b');
❯ cat node_modules/a/package.json
{
"main": "a.js"
}
❯ cat node_modules/b/package.json
{
"main": "b.js"
}
and assert on the requireStack
property of the error thrown by the index.js
file.
Also, note that this is a CJS file, so the way you used import here won't work.
test/parallel/test-loader.js
Outdated
@@ -0,0 +1,56 @@ | |||
import { tryPackage } from '../../lib/internal/modules/cjs/loader' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test-loader.js
is a much too generic name. test-require-package-errors.js
perhaps?
Or even better, find where we currently test the errors potentially thrown by require
and add your new cases there.
test/parallel/test-loader.js
Outdated
const assert = require('assert'); | ||
|
||
describe('tryPackage', () => { | ||
it('should return the file path when the package is found and main is specified', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely there’s an existing test that require
of a package works?
lib/internal/modules/cjs/loader.js
Outdated
// The function is called for each stack frame in the stack trace, and it should return a string representation of the stack frame. | ||
// In the following example, we use the `util.inspect()` function to get a string representation of each stack frame. | ||
// We then check if the file name of the stack frame is a core module or an internal Node.js module by checking if it starts with `'internal/'` or `'module'`. | ||
// If it is not a core module or an internal Node.js module, we add the file name to the `requireStack` array: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: line lengths here should be <= 100 chars.
uh 🆘 |
I can't re-open it 🤨 |
I guess it cannot be reopened since it has no commits |
I'm so sorry I accidentally blew my code here :( |
// TODO(BridgeAR): Add the requireStack as well.
I also added the require stack