| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
I would change the commit message to start with This patch fixes ... then place Following the discussion nodejs#2668 at the bottom as metadata. e.g. Ref: https://github.com/nodejs/node/issues/2668 |
Sorry, something went wrong.
There was a problem hiding this comment.
Do we want NaN values to coerce to 0? (realize that is what was done before, but while were here :-)
Sorry, something went wrong.
There was a problem hiding this comment.
Sure, I ll make that to this.length :-)
Sorry, something went wrong.
|
@trevnorris Updated for NaN. |
Sorry, something went wrong.
|
Great. If CI is happy then LGTM. This is a semver-major, so will go in the v5 release. |
Sorry, something went wrong.
Sorry, something went wrong.
|
I am not able to test this now. |
Sorry, something went wrong.
|
@ChALkeR They'll wrap. Same as they always have. |
Sorry, something went wrong.
|
@trevnorris Ah. So that is out of scope for this commit. This commit now converts negative and NaN values of end to this.length. This looks mostly compatible to what there was before this patch. LGTM, though such behavior is a bit strange. |
Sorry, something went wrong.
|
Judging from the surrounding code, it looks like negative values of end were meant to return an empty string. @trevnorris, what do you think? Though that will be a breaking change, while this one isn't. |
Sorry, something went wrong.
|
@ChALkeR Good catch. You are correct. This PR is a great fix for existing undefined behavior, and making end equal to the length if less than zero seems counter intuitive. Personal opinion, it should be set equal to zero. |
Sorry, something went wrong.
|
@trevnorris @ChALkeR Made sure that the negative value for end is taken as 0. |
Sorry, something went wrong.
|
I'd still recommend putting the reference issue as I posted above, but if CI is good then LGTM. |
Sorry, something went wrong.
|
CI Run before landing: https://ci.nodejs.org/job/node-test-pull-request/364/ @trevnorris I'll fix that while landing. @ChALkeR LGTY? |
Sorry, something went wrong.
|
LGTM code-wise. Only a minor notice that I would re-order the lines and group together the checks based on the variable that they are related to. Something like this: start = +start;
if (!Number.isInteger(start)) {
start = start >>> 0;
}
if (start < 0) start = 0;
if (end === undefined || end === Infinity || end !== end) {
end = this.length;
}
end = +end < 0 ? 0 : end >>> 0;
if (end > this.length) end = this.length;
if (end <= start) return '';
if (!encoding) encoding = 'utf8';
var loweredCase = false;But that is not required and not everyone might agree with this change, I guess. |
Sorry, something went wrong.
|
Eh? this is semver-major? If yes, should the start/end arguments be fixed here completely so they don't get wrapped? @trevnorris, what do you think? Here is what I mean: start = +start;
if (start >= this.length) return '';
start = (start > 0) ? start >>> 0 : 0;
if (end === undefined || end === Infinity || end !== end) {
end = this.length;
} else {
end = +end;
if (end <= start) return '';
end = (end <= this.length) ? end >>> 0 : this.length;
}
if (!encoding) encoding = 'utf8';
var loweredCase = false; |
Sorry, something went wrong.
|
Was going to save some of this for later, but while we're here. I'd say while your here we should make sure parsing is consistent. For example end is first uint32 coerced in JS then int32 coerced in C++. I may suggest we change ParseArrayIndex() in node_internals.h to use Uint32Value() instead of Int32Value(). Then make sure values in JS are a uint32. This would mean the values will go through n >>> 0 before being passed to C++. Open to ideas on how we handle out of range values. I suppose we'll floor any non-integers that are in the uint32 range with the >>> operation. |
Sorry, something went wrong.
|
Yeah, the internals should have unsigned 32-bit numbers, and the js side should validate the indicies for them to be in the allowable range (from 0 to this.length). That's exactly what I proposed on the js side in the above message. Atm, this PR converts the start to start >>> 0 without first checking that it's in between 0 and this.length, so 4294967296 would become 0, which is unexpected and should probably be fixed here while we are on a semver-major change. |
Sorry, something went wrong.
|
okay. so how about this: if (start >= this.length || end <= 0)
return '';
if (start < 0 || start >>> 0 != parseInt(+start))
start = 0;
else
start >>>= 0;
if (end > this.length || end >>> 0 != parseInt(+end))
end = this.length;
else
end >>>= 0;
if (end <= start)
return '';That should handle all the cases discussed on IRC. UPDATE: Based on IRC discussion. |
Sorry, something went wrong.
|
@ChALkeR awesome. Great team work everyone putting together these coercion checks. |
Sorry, something went wrong.
If `start` is not a valid number in the range, then the default value zero will be used. Same way, if `end` is not a valid number in the accepted range, then, by default, the length of the buffer is assumed. Ref: nodejs#2668 PR-URL: nodejs#2919
There was a problem hiding this comment.
I am not sure if these four tests returning empty strings is okay though.
Sorry, something went wrong.
There was a problem hiding this comment.
So should end be coerced to 0 instead of this.length?
Sorry, something went wrong.
There was a problem hiding this comment.
If the end value is not valid, simply ignoring it and assuming the actual length would be logical, wouldn't it?
Sorry, something went wrong.
There was a problem hiding this comment.
I agree.
Sorry, something went wrong.
There was a problem hiding this comment.
if (start >= this.length || end <= 0)
Let's try if (start >= this.length || end < 0).
Sorry, something went wrong.
|
@ChALkeR @trevnorris I updated the PR as per our discussion. PTAL. |
Sorry, something went wrong.
There was a problem hiding this comment.
Not sure if you want to, but maybe also add to comments why both parseInt() and the + are necessary. For example:
parseInt('0o1101') === 0
parseInt(+'0o1101') === 577but also that parseInt() is necessary to do int coercion at 2^53 to make sure there's no wrap around.
Sorry, something went wrong.
There was a problem hiding this comment.
Actually, should be able to use !== here b/c start is being coerced to a number before comparison.
Sorry, something went wrong.
There was a problem hiding this comment.
but may also want to note that this is technically an int32 check, not uint32, b/c the value will be coerced to a uint32 below with start >>>= 0. so we're saving ourselves an operation.
Sorry, something went wrong.
|
two comments, and amazing job on the tests. |
Sorry, something went wrong.
There was a problem hiding this comment.
Maybe end < 0 would better here instead of end <= 0? In order to treat false as this.length, for example.
Sorry, something went wrong.
There was a problem hiding this comment.
so all falsey values will evaluate to default value? I'd be cool with that, except we also assert that true is coerced to 1. seems like a small inconsistency to evaluate the two types differently.
eh. guess it's instead falsey vs. truthy. okay, i'm cool with it.
Sorry, something went wrong.
There was a problem hiding this comment.
Going to revise my opinion. I think we should imitate similar behavior as v8 in other scenarios. Here's one using Typed Arrays:
let ab = new ArrayBuffer(8);
new Uint8Array(ab, 0, false).length === 0;
new Uint8Array(ab, 0, null).length === 0;
new Uint8Array(ab, 0, NaN).length === 0;
new Uint8Array(ab, 0, undefined).length === 8;So end only receives the default length iff end === undefined.
There are cases where Typed Arrays throw where we can't, but we'll leave those aside.
Sorry, something went wrong.
|
@thefourtheye want to move forward with this? |
Sorry, something went wrong.
|
@thefourtheye I can take this over and move it forward if you're ok with that. |
Sorry, something went wrong.
|
@matthewloring please go ahead. Thanks for taking it up :) |
Sorry, something went wrong.
If `start` is not a valid number in the range, then the default value zero will be used. Same way, if `end` is not a valid number in the accepted range, then, by default, the length of the buffer is assumed. Fixes: nodejs#2668 Ref: nodejs#2919 PR-URL: nodejs#4019 Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Verify that start and end are coerced properly. Ref: nodejs#2919 PR-URL: nodejs#4019 Reviewed-By: Trevor Norris <trev.norris@gmail.com>
| Back | FazBrowse Home | New Git URL |
Following the discussion #2668,
this patch fixes the first problem discussed there. If start is not
a valid number in the range, then the default value zero will be used.
Same way, if end is not a valid number in the accepted range, then,
by default, the length of the buffer is assumed.
cc @trevnorris @ChALkeR