-
Notifications
You must be signed in to change notification settings - Fork 30k
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
[WIP] errors: add internal/errors module #6573
Conversation
assert(msg); | ||
return msg; | ||
}, | ||
ENOTIMPLEMENTED: notImplemented, |
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 should be safe to remove the E
prefix on the error codes... anything at Error[Symbol.for('code')]
will be an error.
Thoughts on exporting the error codes?
... with all of the ENO codes its hard for me not to think of Brian Eno ... well done :)
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.
Error[Symbol.for('code')]
Yeah, considered that possibility also. Definitely makes sense to do it that way.
Somewhat related to #4311 |
2efc255
to
76bc6e6
Compare
@nodejs/ctc ... this now covers all Error/TypeError/RangeError throws we generate from Essentially this PR currently consolidates, and makes consistent, all error messages thrown in lib/*.js and associates a stable code with each. Please review. |
|
||
class NodeError extends Error { | ||
constructor(key, ...args) { | ||
super(message(key, args)); |
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.
does this need to be whoops, this goes to ...args
?message()
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.
Should we have |
|
||
module.exports.Error = NodeError; | ||
module.exports.TypeError = NodeTypeError; | ||
module.exports.RangeError = NodeRangeError; |
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.
no need for module
?
We currently use |
oooh true. that is a better option. |
|
||
// Utility function for registering the error codes. | ||
function E(sym, val) { | ||
Error[Symbol.for(sym)] = val; |
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.
Attaching to existing globals makes me a bit hesitant, but I understand it does kinda make sense here.
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 understand the hesitancy. Use of Symbol should make this less of a problem. TBH, however, we're not documenting that we're hanging these off Error
so I'm fine changing this part.
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'd like to wait to hear others chime in.
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.
Could we possibly prefix the symbol or some such? e.g. Symbol.for(
node.${sym});
to prevent collisions.
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.
sorry. i'm missing why this needs to be hung off the global Error
?
Overall seems good. Definitely think this is a good approach. |
Updated. |
@@ -126,7 +126,8 @@ Protocol.prototype.execute = function(d) { | |||
break; | |||
|
|||
default: | |||
throw new Error('Unknown state'); | |||
const errors = require('internal/errors'); |
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.
shouldn't require
s be at the top of the file?
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.
When there are only one or two cases in a file, I did it like this so the
require is only called in error conditions
On May 9, 2016 5:27 PM, "Rod Vagg" notifications@github.com wrote:
In lib/_debugger.js
#6573 (comment):@@ -126,7 +126,8 @@ Protocol.prototype.execute = function(d) {
break;default:
throw new Error('Unknown state');
const errors = require('internal/errors');
shouldn't requires be at the top of the file?
—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
https://github.com/nodejs/node/pull/6573/files/56d34d36a841cee62adb657548b90bd27ebce870#r62595987
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.
Lazy loading is pretty common in core code. Though I'm not sure how much it actually saves us now.
No, the C++ errors can be done separately, I just want to make sure it gets done. The important thing is that there needs to be agreement on syntax. The only constraint that I can see is that the C++ error messages tend to be far more terse. |
@jasnell just curious, when we upgrade v8 within a major do we ever verify that none of the error messages changed? |
Not that I'm aware of. |
} | ||
|
||
class NodeRangeError extends RangeError { | ||
constructor(key, ... args) { |
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: space in ... args
.
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.
does the linter not catch this?
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 haven't run the linter on this in a while so not sure. I'll be doing an update on this next week so I'll see for sure what lint issues come up.
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.
The linter will not catch this because we do not have the rest-spread-spacing
rule enabled. Sounds like we'd like to enforce no space between the spread operator and the argument, so I'll get a PR for that in Real Soon Now...
Other than the fact that this would generate stacks one line shorter than function fixErrStack(stack) {
const newstring = [];
const idx0 = stack.search(/[\r\n]+/);
newstring.push(stack.substr(0, idx0));
const stack2 = stack.substr(idx0).trim();
const idx1 = stack2.search(/[\r\n]+/);
newstring.push(stack2.substr(idx1).trim());
return newstring.join('\n'); // detect whether to insert \r\n?
}
const e = new Error('hi');
e.stack = fixErrStack(e.stack); instead of creating two error objects. |
@trevnorris ... sorry, not following |
Logically I'd say that changes to error messages in v8 would also be a major if we treat them as major in node. Hasn't been a problem to date, but just throwing it out there.
How you are using |
Re: treating v8 error changes as majors, I don't disagree, just not sure what all we can do about it. |
node version 7 officially deprecates `fs.read` and `fs.readSync` This is done using `internal/util`. The unfortunate side affect being that `graceful-fs v3.x` explodes when running the code in `vm` as `internal/util` is not accessible from userland. This commit uses a regular expression to replaces the require of the specific internal util function with the source of that util function. As such `graceful-fs v3.x` will no longer explode in node v7. One advantage to this approach is that any future deprecation will not break graceful-fs.
const ch = expected.codePointAt(0) | 0x20; | ||
const prefix = (ch === 0x61 || ch === 0x65 || | ||
ch === 0x69 || ch === 0x6f || | ||
ch === 0x75) ? 'an' : '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.
I think this returns false positives for e.g. Uint8Array
– maybe the message should just read something like must be of type ${expected}
?
Pulling this off the v7 milestone. It's not going to get done in time for that. |
c133999
to
83c7a88
Compare
Going to close this PR in favor of breaking these changes up into multiple separate PRs that can be done incrementally. |
// portable with the readable-streams module. | ||
function typeError(code, args) { | ||
const assert = require('assert'); | ||
var msg; |
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.
Why use var
? I think better to use let
.
Checklist
Affected core subsystem(s)
errors (new subsystem)
Description of change
Note: This is a _work in progress. I am opening the PR to begin the discussion about the overall design. I will be iterating based on the feedback. This is far from being ready to land in it's current state._
This is step one to making it so that changes to error messages are not forced to be semver-major changes any more. The internal errors.js module exports three custom error class instances that use an assigned static error code to look up the error message. The message itself can change but the error code would remain the same. Changes to error code would still be considered semver-major, but changes to the messages themselves would not be.
This also updates the Error objects created in lib/internal to use the new mechanism, changing and streamlining several of the error messages in the process. Obviously, this is a semver-major change on it's own.
Several test cases were also modified and a new common.throws method added to test/common.js that understands the new code mechanism. This is added common.js so that the existing assert module api is unchanged.
Update: This PR is purposefully being held back from landing until we are closer to actually releasing v7. Until then, it will need to be periodically updated to pick up any other changes in error handling that land. PRs are welcome. Please label any other PRs that affect error handling with the
error-handling
label so that those can be easily tracked.