Skip to content
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

New principle: APIs which vend byte buffers should return a Uint8Array #463

Closed
bakkot opened this issue Jan 20, 2024 · 4 comments · Fixed by #480
Closed

New principle: APIs which vend byte buffers should return a Uint8Array #463

bakkot opened this issue Jan 20, 2024 · 4 comments · Fixed by #480

Comments

@bakkot
Copy link
Contributor

bakkot commented Jan 20, 2024

This already seems to be a principle. See some more discussion here.

ArrayBuffer is almost never what you want because you can't read from one directly. You have to create a view such as a Uint8Array to actually read it.

Almost all APIs which accept an ArrayBuffer also accept a Uint8Array, and some APIs require a Uint8Array, so it's rare for a Uint8Array to be less convenient than an ArrayBuffer.

This is currently somewhat inconsistent: some APIs (like Response) provide an ArrayBuffer, while others (like TextEncoder) provide a Uint8Array. Having this written down as a principle could help with that.

I'm not sure what the process here is, but if this is accepted I'm happy to send a PR adding this.

@plinss
Copy link
Member

plinss commented Mar 5, 2024

Discussed this in a breakout today with @hober and @rhiaro. We'd be grateful for you to write a PR.

One nuance we though of is that there may be times when an ArrayBuffer is actually appropriate. In the case where the returned data is really just bytes, then we agree a Uint8Array is the correct choice, but if the data can be reasonably interpreted as other types then an ArrayBuffer is likely more appropriate. @annevk thoughts?

We also note that the ergonomics of converting an ArrayBuffer to a Uint8Array is simpler than converting a Uint8Array to a Int32Array, for example.

@bakkot
Copy link
Contributor Author

bakkot commented Mar 6, 2024

if the data can be reasonably interpreted as other types then an ArrayBuffer is likely more appropriate

If the method actually returns int32s (e.g.), then using an Int32Array would be appropriate. But it's hard to think of a time when an ArrayBuffer specifically would be appropriate: an ArrayBuffer includes no interpretation of the bytes. If there's some interpretation which is not one of the TypedArray types, then you're almost always going to need to read the bytes out individually so you can interpret them, and that's easiest with Uint8Array.

The only exceptions I can think of are if you're returning a byte buffer which contains multiple kinds of data, some of which could be read with a DataView: for example, if the buffer had 64 bytes where the first 32 bytes were 8 Float32 values and then next 32 bytes were 4 Float64 values. But that would be a pretty weird API (and even in that case I think it would make sense to vend both a Float32Array and a Float64Array, possibly backed by the same ArrayBuffer, rather than just vending the ArrayBuffer).

Anyway, I'll write up a PR and try to caveat appropriately, and we can discuss further there.

@bakkot
Copy link
Contributor Author

bakkot commented Mar 11, 2024

Opened #480.

@Jamesernator
Copy link

Jamesernator commented May 15, 2024

then you're almost always going to need to read the bytes out individually so you can interpret them, and that's easiest with Uint8Array.

This doesn't seem that compelling, while u8-only formats exist, most "binary data" tends to be a mix of header sections and binary sections. Most formats use larger/signed integer and floats in their encodings, there DataView would be the more natural format for decoding.

Like in my own encoding/decoding library I've been passing DataView around everywhere because having individual types make their own DataViews just adds massive GC pressure and absolutely tanks performance.

This would be a TC39 proposal (and probably would be rejected for adding nothing new), but it's not clear to me why we don't have just have all of DataView methods directly on ArrayBuffer and/or Uint8Array. Incidentally Node's Buffer object already behaves like this, it is a subclass of Uint8Array that has (equivalents of) all the DataView methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants