-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
feature: support initializing Buffer from an ArrayBuffer #106
Comments
Curious: would this copy the memory represented by the |
@chrisdickinson It should behave the same way as |
I think it makes sense to make the binary data APIs as compatible as possible. |
Reason this is a pain is because you can't access the I've already gone down this road, and it's a bigger pain then it seems. Just a warning. |
@feross The reason you're seeing that result is because internally |
@vkurchatkin I bring this up since the buffers in browserify are implemented on top of typed arrays. The ideal behavior (in browser, at least) would be to present the Buffer as a view of the given ArrayBuffer, I imagine. A copy operation, OTOH, would be implementable in JS, but much slower for the desired use case. For example, if an XHR hands you an ArrayBuffer representing 8mb it would be nice to be able to wrap that up as a Buffer without having to copy the entire contents -- and if that's the desired behavior in browser, it would be best if |
@chrisdickinson Reference ("view") semantics probably won't be much faster. For the Buffer object to get a pointer to the ArrayBuffer's memory, it needs to externalize the ArrayBuffer. That means copying its contents from the JS heap to the C heap; besides being slow, it also makes it more likely to hit out-of-memory errors, because it needs An approach that doesn't need additional memory is to conjure up a Buffer instance that intercepts numeric loads and stores and looks them up in the ArrayBuffer. That's probably at least a hundred times slower, though. |
@chrisdickinson Agreed. Presenting the Buffer as a view on the ArrayBuffer makes the most sense in the browser context. But it would diverge from the way the Buffer constructor handles all other argument types, i.e. copying them. For the record, to convert an ArrayBuffer or typed array to a Buffer without a copy in the browser, you can use |
Wouldn't it be possible to completely obsolete Buffers and encourage moving onto ArrayBuffers? Don't we have Buffers only because there was no ArrayBuffers when Node was first released? |
@phaux No. Typed Arrays can't be extended. So it would be impossible to have an API where the data can both be accessed by index, and have custom methods on it. Also ArrayBuffer requires a zero fill on the data, which on the server isn't necessary for most cases and comes at a performance hit. Plus a few others. Array Buffers are great for the client, but not what's best for a server application. |
That only handles typed array views like Uint8Array, but it doesn't handle ArrayBuffer. Please re-open. |
@feross Do you want to allow setting byte range's, or just use the entire ArrayBuffer? |
@trevnorris Using the entire ArrayBuffer is probably fine since you can just wrap the ArrayBuffer in a Uint8Array to get a slice of it. The Uint8Array constructor takes The real question: do you want to do a copy or just make the buffer point to the same memory? All the other argument types to Buffer do a copy, so there's an argument for just doing that. On the other hand, the typed array constructors (e.g. Uint8Array, etc.) treat an ArrayBuffer argument differently, and point to the same memory. The API is |
I vote for copy. We could have alternative API for views ( |
@vkurchatkin That also sounds the most reasonable from the existing API, which will make a copy of a buffer instance if passed. |
@trevnorris Uint8Arrays also do a copy if you pass in another Uint8Array instance. I think it would be nice if the Buffer constructor kept parity with typed arrays as much as possible. We pretty much have that right now, but if we make ArrayBuffer do a copy then we'll diverge. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#Syntax |
@feross That also makes sense being that Buffer will basically become an extension of Uint8Array. I honestly don't care either way. I have a patch ready, and the difference between copy or use is 2 lines of code. Implementing the byteOffset and length parameters is pretty trivial, so I'll throw that in as well. Just let me know what you all want. |
Whatever is the least surprising probably, so maybe like the builtins unless they do things in not-reasonable ways? |
Then I'd say using the ArrayBuffer. Since Buffer is essentially just an extension of Uint8Array. |
Buffer now uses the ArrayBuffer as the backing store if passed to the constructor. Fixes: nodejs#106
Fixed by 197ba00. |
|
I propose we make the
Buffer
constructor also acceptArrayBuffer
.Currently this is what happens:
This is what should happen:
When writing isomorphic code (i.e. code that runs on the server and in the browser), it's often the case that you'll get an
ArrayBuffer
from a DOM API (xhr, websockets, webrtc, etc.) and need to convert it to aBuffer
to work with modules in the npm ecosystem. Users often expect thatnew Buffer(arraybuffer)
will work and they open issues when it doesn't.We have the
buffer
npm module which gives us the sameBuffer
API in the browser (and is used by browserify), however it tracks the node.js/io.js buffer exactly, so we can't add support fornew Buffer(arraybuffer)
unless core does too.I know the
Buffer
constructor already takes a million different argument types, so it couldn't hurt to add one more, right? Curious to see what the community thinks about this. If there's interest, I can send a PR.The text was updated successfully, but these errors were encountered: