WebAssembly / interface-types

Other
641 stars 57 forks source link

Why is ByteString a string? #131

Open annevk opened 3 years ago

annevk commented 3 years ago

It seems nicer if it could map to a byte sequence, or is that not something that exists? (Same for ArrayBuffer I suppose.)

lukewagner commented 3 years ago

That's a good question. So as background, I think it's important to have wasm-to-Web-IDL calls be mostly equivalent to wasm-to-JS-to-Web-IDL calls, where the interposed JS simply forwards arguments/results back and forth to Web IDL -- that way, if a built-in Web IDL function is polyfilled/virtualized by JS, it doesn't suddenly break wasm. While (list u8) would be the most natural match for ByteString, passing a (list u8) to JS would produce a Uint8Array, and the ECMAScript ByteString coercion won't accept a Uint8Array. But I think you're right that string isn't a good match either.

Thinking about it some more, it seems like there are three options:

  1. extend Web IDL so that ByteString accepts a Uint8Array
  2. add a new abbreviation bytestring ≡ (list u8) that matches ByteString and that the JS API would coerce into a JS string
  3. punt, saying ByteString only matches externref, requiring wasm to create ByteStrings with a separate import call

I think 1 would be ideal, and perhaps it would be beneficial for other reasons. WDYT?

annevk commented 3 years ago

I see, if it has to be mostly equivalent it will have to be a string, as that is what it is in JavaScript. I suppose IDL could accept a Uint8Array on the coercion side, but it couldn't start returning Uint8Array where it previously returned a string. (Unless there is some magic that would enable this for Wasm callers only?)

(I was mainly suggesting this because I think it makes sense for IDL to convert this string to a byte sequence for specifications and to allow specifications to return a byte sequence to something that wants a ByteString. Whether this makes sense to copy in implementations would vary, but for HTTP header related cases it definitely would.)

lukewagner commented 3 years ago

Ah, good point about the return case, I forgot to consider that. Because of the "allow interposed JS" goal I mentioned above, I don't think we can use "if the caller is wasm ..." logic. However, I think we could say that ToWebAssemblyValue(v, (list u8)) accepts JS strings in v (in addition to the obvious cases, like arrays) by performing a Web IDL JS-to-ByteString conversion which throws if any element of the string is >255.