3 ms·
There are a few use cases here and I personally think only one of them is really important in the sense that it would provide a lot of value for many people. W
by kevingadd 3y ago
There are a few use cases here and I personally think only one of them is really important in the sense that it would provide a lot of value for many people.
What JS in general needs is a 'StringView' type, which is most useful for asm.js/wasm scenarios, but is useful for other scenarios too. You could define it for UTF16 only, or define it to work with both UTF8 and UTF16. Why?
Well, a very common use case for asm.js/wasm scenarios is that you have a big wasm application that needs to chat with things outside of the wasm sandbox. The vast majority of APIs available to a wasm application are browser APIs, which communicate using objects (we have a solution for those, externref), strings, doubles (native wasm support), i32s (semi-native support - v8 only supports 31-bit integers, but it's usually good enough) and booleans (just use i31s).
Right now if you want to send a string from wasm to a browser API, you need the help of some JS glue to construct a brand new JS string on demand from bytes living in the wasm heap. This glue is Not Fast, and it becomes increasingly Not Fast the larger your strings are. If you have a great many strings - for example, text that you want to cram into textareas or spans inside of a table in the DOM - you will waste a lot of time doing this. And then if you want to transfer strings back into wasm, you have to do the reverse, painstakingly copying the string back into the wasm heap one character at a time.
If you're lucky, the browser has native APIs that accelerate this process by decoding/encoding UTF16, but those APIs have limitations - for example, TextDecoder does not support SharedArrayBuffer, so enabling multithreading in your wasm application will instantly make it slower to send strings across the js/wasm boundary. Cool.
The widely used wasm platform I work on (.NET / Blazor) does a lot of sending strings across the js/wasm boundary, so we've had to jump through some hoops to optimize this as much as possible. For example, we maintain an 'interned string' table on both sides of the boundary so that commonly reused strings like method names or enum value names don't have to get encoded/decoded each time they cross. This significantly increases memory usage and means we have to jump through hoops to avoid using too much memory, but the advantage in terms of performance is measurable, upwards of 10% per boundary crossing even for small strings. A typical application has lots of grids, tables and lists filled with string data, so it spends a sizable amount of time doing all this string encoding/decoding. Incidentally this interning table is harder to implement efficiently because nobody is willing to expose a getHashCode equivalent for JS types or even specifically for JS strings, but I can understand that decision at least...
If you had a StringView type, you could basically go "here's an ArrayView, I promise it contains WTF16 (or UTF16) data, and I promise I won't mutate it. You can make a defensive copy if you want. Please turn it into something string-like so I can use it with DOM properties like textContent or APIs like WebSocket, thanks." JS runtimes already have support under the hood for diverse string storage formats, whether it's ropes, latin1 buffers, or utf16 buffers, so this would just be a new one of those.
Maybe we'll get one before 2030. Not holding out hope though, this was a known need at the very beginning of the WebAssembly spec process and I doubt anyone has forgotten about it, it just doesn't seem to be considered that important compared to features like "having multiple distinct address spaces for some reason" and "64-bit address spaces that probably won't be available in web browsers for 20 years because Chrome on Android is still 32-bit"