-
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
Ensure ES2016 engines construct Uint8Array (not Buffer) from Buffer.p… #4702
Conversation
…rototype.slice In the ES2016 draft specification, TypedArray methods like %TypedArray%.prototype.subarray() call out to a constructor for the result based on the receiver. Ordinarily, the constructor is instance.constructor, but subclasses can override this using the Symbol.species property on the constructor. Buffer.prototype.slice calls out to %TypedArray%.prototype.subarray, which calls this calculated constructor with three arguments. The argument pattern doesn't correspond to a constructor for Buffer, so without setting Symbol.species appropriately, the wrong kind of result is created. This patch sets Buffer[Symbol.species] to Uint8Array when appropriate, to address the issue.
cc: @trevnorris |
Note, this patch has only been tested in the browser context (actually testing feross/buffer#97), and running the basic node tests to ensure there isn't a regression. It could use some more testing when the next version of V8 is pulled in, and it can also definitely wait to be merged until then. |
@@ -70,6 +70,11 @@ function Buffer(arg, encoding) { | |||
Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); | |||
Object.setPrototypeOf(Buffer, Uint8Array); | |||
|
|||
if (Symbol.species && Buffer[Symbol.species] === Buffer) { |
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.
In Node we probably want to wait for V8 4.9 to land and then remove the if, replacing it with a comment.
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 species ends up being staged, but not shipped, for a Node release, do you think it might make sense to keep the conditional?
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.
Yeah, that's fair.
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 you expound on why "being staged, but not shipped" requires node to do language feature detection?
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.
That way it will work whether or not people do --harmony
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.
ah. gotcha.
semver-minor? |
Yes, I'd say so. |
Just to confirm, this technically wouldn't be necessary until v4.8 lands, correct? |
4.9 I believe. I think this is semver-patch. It adds no new features. |
This isn't necessary until V8 lands |
* Add runtime property "process.jsEngine" to indicate current JS engine node runs on (JS engine is determined at build time). * Update REPL to work with Chakra engine. * Buffer/SlowBuffer currently does not support @@species constructor. Mark them as such to avoid failure as per ES6 TypedArray @@species spec. * Minor fix in `string_bytes.cc` because of way Chakra handles `String::NewExternal`.
Just want to let folks know that we shipped @littledan's change (feross/buffer#97) in feross/buffer v4.5.0. Works great. I'll share here if there are any user reports of gotchas in real-world usage. |
@trevnorris @littledan ... what's the status on this? |
I don't see any reason why it can't merge. However, it might not be needed if given the new Buffer constructor signature. |
@@ -70,6 +70,11 @@ function Buffer(arg, encoding) { | |||
Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype); | |||
Object.setPrototypeOf(Buffer, Uint8Array); | |||
|
|||
if (Symbol.species && Buffer[Symbol.species] === Buffer) { | |||
Object.defineProperty(Buffer, Symbol.species, | |||
{ value: null, configurable: true }); |
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.
style nit: bump over one space.
@littledan ... can you rebase on master and address the style nit? |
Do we still want this if the three-argument constructor pattern is allowed? |
I'll leave that up to @trevnorris and @bnoordhuis if they think it is worthwhile |
No strong opinion, except that I'd be a bit worried about I understand this doesn't need to land until we upgrade to a V8 version that ships |
Is this supposed to fix where |
@bnoordhuis Actually even in 51, I put in a workaround for |
7da4fd4
to
c7066fb
Compare
We're now approaching Node V6 on V8 5 but from what I can see it's still not there. |
This issue should not affect V8 5.0, only V8 5.1 and later. I don't see the downside to the three-argument approach or the reason why it should have lower performance. If someone explains that, then I will rebase and update this patch. |
@littledan Buffer has already been updated to accept three arguments, to be compatible with the Uint8Array constructor. |
OK, sounds like this patch is no longer needed. |
…rototype.slice
In the ES2016 draft specification, TypedArray methods like
%TypedArray%.prototype.subarray()
call out to a constructor for the resultbased on the receiver. Ordinarily, the constructor is instance.constructor,
but subclasses can override this using the Symbol.species property on the
constructor.
Buffer.prototype.slice
calls out to%TypedArray%.prototype.subarray
, whichcalls this calculated constructor with three arguments. The argument pattern
doesn't correspond to a constructor for Buffer, so without setting
Symbol.species
appropriately, the wrong kind of result is created.This patch sets
Buffer[Symbol.species]
to Uint8Array when appropriate, toaddress the issue.
This addresses issue #4701