You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While reading through the new JS explainer in #686, I found myself going back and forth on whether to use typed arrays for list<num>. For list<u8> it seems fairly natural to map that to Uint8Array, but less so for other number types. Like, it's probably quite a footgun to return Int32Array for list<s32>, since most JS devs don't use typed arrays very often, and typed arrays look juuuuuust enough like normal arrays to do some really surprising things:
But that got me thinking - the main difference seems to be that sometimes you want a list of numbers, using whatever list type is idiomatic, but sometimes you just want a blob of bytes. Sure, you can have Int32Array and Float64Array and so on, but at least 95% of the time in JS you just want Array. And after further reflection, I think this is true of other languages too! In C++, do you really want a std::vector<uint8_t>, or would you maybe prefer std::string or some other kind of slice type? In Java, do you want List<Byte> or byte[]? In Python, do you want list or bytes? In Rust, do you want Vec<u8> or &[u8]?
(This is not true for some languages, e.g. Go would always do []byte, but that's fine, the distinction doesn't have to be meaningful in every language.)
So, purely as a hint to bindings generators, I think there is probably some value in having a bytes type that is in every way just an alias for list<u8>. Certainly there is no need for it to be different at the ABI level.
If accepted, I would suggest the following for the JS mapping:
list<T> is returned as a JS array, and as a param only accepts a JS array (...or iterable? idk)
bytes is returned as a Uint8Array, and a param accepts anything the TypedArray constructor would (which encompasses all typed arrays, ArrayBuffers, and JS iterables)
One thing that's unclear to me is what guidance WIT would have for interface authors for when to use bytes-vs-list<u8>. Would it just be "always use bytes"? That's basically what we say with string-vs-list<char>, but b/c string is so ubiquitous and obvious, I don't think anyone even considers list<char>, so it doesn't seem to be a problem, but for list<u8> that seems less true.
I also don't get the Vec<u8>-vs-&[u8] distinction or how one or the other follow from list<u8>-vs-bytes; this mostly seems like a lifetime/W^R issue. To wit, there is a Tokio bytes type, but I don't think that's what anyone would expect.
For JS, it still seems to me like we'd just always spit out the typed array view for all number types, and that's mostly fine (there are plenty of "wat" moments with all JS values if you look hard enough). For multiple number types types arrays should also come with a tidy perf and memory-size boost.
My guidance would basically be "do you expect the user to iterate this one element at a time"? That's not really true of most blob-of-bytes use cases. I do think that it would be rare to see list<u8> if bytes existed, but I don't see a problem with having both.
I really have just changed my mind on the typed array thing because I just think list should mean Array in JS 100% of the time if possible. It's clearly a requirement for everything non-numeric (which I expect to be the majority of use cases) and I'm not even sure how much performance benefit you could expect since you'll have to allocate copies of the data anyhow.
Activity
lukewagner commentedon Sep 28, 2026
One thing that's unclear to me is what guidance WIT would have for interface authors for when to use
bytes-vs-list<u8>. Would it just be "always usebytes"? That's basically what we say withstring-vs-list<char>, but b/cstringis so ubiquitous and obvious, I don't think anyone even considerslist<char>, so it doesn't seem to be a problem, but forlist<u8>that seems less true.I also don't get the
Vec<u8>-vs-&[u8]distinction or how one or the other follow fromlist<u8>-vs-bytes; this mostly seems like a lifetime/W^R issue. To wit, there is a Tokiobytestype, but I don't think that's what anyone would expect.For JS, it still seems to me like we'd just always spit out the typed array view for all number types, and that's mostly fine (there are plenty of "wat" moments with all JS values if you look hard enough). For multiple number types types arrays should also come with a tidy perf and memory-size boost.
bvisness commentedon Sep 29, 2026
My guidance would basically be "do you expect the user to iterate this one element at a time"? That's not really true of most blob-of-bytes use cases. I do think that it would be rare to see
list<u8>ifbytesexisted, but I don't see a problem with having both.I really have just changed my mind on the typed array thing because I just think
listshould meanArrayin JS 100% of the time if possible. It's clearly a requirement for everything non-numeric (which I expect to be the majority of use cases) and I'm not even sure how much performance benefit you could expect since you'll have to allocate copies of the data anyhow.