-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
lib/src: refactoring out of range index and and migrate error for consistency #11296
Conversation
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.
If we were to do this, I'd prefer to make it part of the migration to using internal/errors.js
. See #11273.
Changing error messages like this is a semver-major change and has a very real chance of breaking user code. Accordingly, since we'll be moving this code over to using internal/errors.js
anyway, we might as well do both at the same time.
@jasnell wrote:
I don't think there's any question we should do this. There is no reason for let buf = Buffer.alloc(9);
try {
buf.writeInt8(1, -1);
} catch (e) {
console.log(e.toString()); // RangeError: Index out of range
}
try {
buf.writeFloatLE(1, -1);
} catch (e) {
console.log(e.toString()); // RangeError: out of range index
} @jasnell continued:
Would you be OK with that being a subsequent PR? I'd prefer we separate out changes to error messages from migrations to internal/error.js rather than bundling those adjacent-but-not-integrally-related things. I can make sure that second PR happens immediately after this one lands if that affects your spider-sense on this one. |
As long as the two land closely together, or perhaps even as two commits in the same PR, that's fine. |
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.
LGTM if CI is green. Might be good to edit the commit message to make it clear that this is not changing an error message just to change it, but rather taking two error messages that are used in essentially identical situations and making them consistent.
I will clear my "changes requested" review once I get a chance to review the other PR. |
@jasnell It looks like sometimes this For the sake of consistency, I wonder if it makes sense to not migrate the JS-land errors to the new system until we can do errors thrown in C++ as well. This way, you don't get very dissimilar |
We're always going to have at least some inconsistency given that errors thrown from V8 will not have this information and neither will userland code. I will work on providing an equivalent mechanism for the errors thrown from C/C++ but I think it makes sense (and is best) to incrementally move forward. If we try to hold off and do them all at once, we're going to end up with too much of a moving target (I've already tried it). I think userland will be willing to forgive some short term inconsistency if it means we're making progress towards something better. |
invalidArgs[1] = -1; | ||
assert.throws( | ||
() => Buffer.alloc(9)[funx](...invalidArgs), | ||
/^RangeError: (?:Index )?out of range(?: index)?$/ | ||
//(err) => err instanceof RangeError && err.message === "Index out of range" |
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: Should this commented-out code be removed?
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.
ok, fixing it
There was a force push right after last CI, so it didn't go through. New CI: https://ci.nodejs.org/job/node-test-pull-request/6519/ |
Heh, seems like there is a merge conflict: https://ci.nodejs.org/job/node-test-commit/8037/console @larissayvette can you |
@TimothyGu alright |
Seems to be working now: https://ci.nodejs.org/job/node-test-pull-request/6521/ |
Tests are passing (hooray!) but linter is failing because a number of lines in Easiest solution is probably to change things like this: assert.throws(() =>
Buffer.allocUnsafe(8).fill('a', -1),
/^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/); ...to something more like this: assert.throws(
() => Buffer.allocUnsafe(8).fill('a', -1),
/^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/
); |
Is there a problem using common.expectsError()? |
@jasnell when |
@Trott I think the lint is correct now |
On closer inspection, @jasnell is right to suggest that the regular expression is unnecessary in most of the places it's used here. It only needs to be used in places where the throw might be C++ or JS. That's probably only going to happen in test-buffer-write-noassert and/or test-buffer-read. |
test/parallel/test-buffer-alloc.js
Outdated
@@ -956,7 +956,7 @@ assert.throws(() => { | |||
const a = Buffer.alloc(1); | |||
const b = Buffer.alloc(1); | |||
a.copy(b, 0, 0x100000000, 0x100000001); | |||
}, /out of range index/); | |||
}, /^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/); |
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 regexp can be replaced with common.expectsError(undefined, RangeError, 'Index out of range')
@@ -57,7 +57,7 @@ assert.strictEqual(1, a.compare(b, Infinity, -Infinity)); | |||
// zero length target because default for targetEnd <= targetSource | |||
assert.strictEqual(1, a.compare(b, '0xff')); | |||
|
|||
const oor = /out of range index/; | |||
const oor = /^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/; |
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 line can be replaced with:
const oor = common.expectsError('ERR_INDEX_OUT_OF_RANGE');
Will need to change the require('../common');
to const common = require('../common');
too.
test/parallel/test-buffer-fill.js
Outdated
buf1.fill('a', 0, 0, 'foo'), /^TypeError: Unknown encoding: foo$/); | ||
assert.throws( | ||
() => buf1.fill(0, -1), | ||
/^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/); |
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 one (and likely the others in this file) can be replaced with common.expectsError('ERR_INDEX_OUT_OF_RANGE'));
. (Will need to add const common = require...
at top of 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.
From line 187 to 196 , test passes only when it is regular expression. and for the subsequent error message it is common.expectsError(undefined, RangeError, 'Index out of range'));
that works and not common.expectsError('ERR_INDEX_OUT_OF_RANGE'));
{ | ||
const invalidArgs = Array.from(args); | ||
invalidArgs[1] = -1; | ||
assert.throws( | ||
() => Buffer.alloc(9)[funx](...invalidArgs), | ||
/^RangeError: (?:Index )?out of range(?: index)?$/ | ||
/^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/ |
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 is the only regexp that should stay because we don't know ahead of time whether the error is coming from JS (if writing an int, for example) or C++ (if writing a float, for example).
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.
+1... we should probably look at fixing up common.expectsError()
to account for this, however. Will have to think on that for a bit
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.
@jasnell If we really wanted to use common.expectsError()
and not a RegExp
, we could do something like the following (untested) code:
let expectedError;
if (['writeFloatBE', 'writeFloatLE'].includes(funx)) {
expectedError = common.expectsError(undefined, RangeError, 'Index out of range');
} else {
expectedError = common.expectsError('ERR_INDEX_OUT_OF_RANGE', RangeError, 'Index out of range');
}
assert.throws(() => { Buffer.alloc(9)[funx](...invalidArgs) }, expectedError);
Definitely more complicated, though, so I'm fine with the RegExp
approach. Either way.
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.
bleh... let's keep it with the regex for now
Keep in mind also that eventually, even the C/C++ errors thrown by Node.js will include these codes and the augmented |
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.
Generally LGTM with some nits and @Trott's comments addressed. Thank you for this!
doc/api/errors.md
Outdated
<a id="ERR_INDEX_OUT_OF_RANGE"></a> | ||
### ERR_INDEX_OUT_OF_RANGE | ||
|
||
The `'ERR_INDEX_OUT_OF_RANGE'` error code is used to alert user that index parsed is out of range |
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 would suggest rewording just a bit here...
The `'ERR_INDEX_OUT_OF_RANGE'` error code is used when a given index is out of the
accepted range.
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 will make the change
test/parallel/test-buffer-fill.js
Outdated
/^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/); | ||
assert.throws( | ||
() => buf1.fill(0, 0, buf1.length + 1), | ||
/^RangeError(?:\[ERR_INDEX_OUT_OF_RANGE\])?: Index out of range$/); |
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.
For the cases where the regex must still be provided, it would be easiest to change later on if the regex was defined once and assigned then used multiple times... e.g.
const errRegex = /^RangeError .../;
assert.throws(() => { /* ... */ }, errRegex);
assert.throws(() => { /* ... */ }, errRegex);
test/parallel/test-buffer-fill.js
Outdated
const assert = require('assert'); | ||
const errors = require('../../lib/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.
Can this be require('internal/errors');
along with a // Flags: --expose-internals
comment at the top of the file instead?
test/parallel/test-buffer-fill.js
Outdated
/^TypeError: encoding must be a string$/); | ||
assert.throws(() => | ||
buf1.fill('a', 0, 0, 'foo'), /^TypeError: Unknown encoding: foo$/); | ||
const errRegex = |
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 don't think we need errRegex
in this file. I think all instances of it can be replaced with common.expectsError()
.
test/parallel/test-buffer-fill.js
Outdated
const assert = require('assert'); | ||
const errors = require('../../lib/internal/errors');// Flags: --expose-internals |
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 the comment needs to be the first line of the file. The idea of using it is to be able to change ../../lib/internal/errors
on this line to internal/errors
. This way, the test runs based on version of node that is compiled and not the contents of lib
in the source tree at the time the test is run.
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.
(Also, it means that in order to run the test from the command line, you need to either use tools/test.py
or else pass the --expose-internals
flag to node
. But lots of tests are like that already, so that should be fine.)
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.
Indeed. The // Flags: --expose-internals
should be the first line of the test file,
The import must also be require('internal/errors')
, without the ../../lib/
part.
@jasnell Two things: Can you give this another look since it has changed a bit? Also, are we not landing these new internal error things on master yet? What needs to happen before we can start doing that? |
Oh, it looks like this needs to be updated for the new Instead of |
36226c2
to
a47c1d1
Compare
Rebased and force pushed. |
Landed in 234353a. |
PR-URL: #11296 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
lib, src
Changing where
RangeError
wasout of range index
toIndex out of range