wasm-bindgen icon indicating copy to clipboard operation
wasm-bindgen copied to clipboard

Documentation: The "Supported types: number slices" page is confusing

Open mstange opened this issue 6 years ago • 6 comments
trafficstars

The documentation about passing number slices between JS and rust is a bit confusing to me, because it doesn't make clear whether there are any copies happening when passing such data, and if they happen, when.

The "Javascript Representation" column currently says:

A JavaScript TypedArray view of the Wasm memory for the boxed slice of the appropriate type (Int32Array, Uint8Array, etc)

First, there is no boxed slice here, this page is about slice references. Second, "view of the Wasm memory" makes it sound like JavaScript has direct access to the wasm module's memory buffer, which is also not the case. Everything is copied.

I recommend changing the "JavaScript Representation" column to just the following:

A JavaScript TypedArray of the appropriate type (Int32Array, Uint8Array, etc)

And then adding the following note about copies underneath:

The contents of the JavaScript TypedArray get copied into wasm memory when the function is called. For arrays which are passed to a &mut T parameter, there is an additional copy: The modified values are copied back out into the JavaScript TypedArray at the end of the function call, so that any mutations are reflected on the JS side.

mstange avatar Jul 11 '19 21:07 mstange

Thanks again for the sharp eye! This is unfortunately nuanced though and doesn't have an easily documentable answer. As incoming arguments to WebAssembly, typed arrays must be copied in. As outgoing arguments to JS, we pass raw views of wasm memory that don't copy any data. Basically we don't copy wherever we can, but otherwise we're forced to in a number of situations.

alexcrichton avatar Jul 11 '19 22:07 alexcrichton

Oh, but the table on that page says that number slices are not supported as return values anyway. There are only two "Yes" cells in the table: "&T parameter" and "&mut T parameter". So "as incoming arguments" is the only case that applies here, I think. Or is the table inaccurate?

mstange avatar Jul 11 '19 22:07 mstange

The table is accurate but there's a distinction between "this is coming from JS to wasm" and "this is going from wasm to JS". When coming into wasm we have no choice but to copy bytes, but when going out to JS we can give out cheap views.

alexcrichton avatar Jul 12 '19 15:07 alexcrichton

Oohh! You just made me realize a fundamental gap in my understanding of these documentation pages: I thought the "&T parameter" column meant "JS passing something to a &T parameter of an exported rust function". But apparently it also means "Rust passing something to a &T parameter of an imported JS function"? Brb, filing more issues.

mstange avatar Jul 15 '19 18:07 mstange

Ok, filed #1667 about my confusion about which parameter direction is described by these documentation pages. I also filed #1668 about the fact that the "cheap views" trick doesn't work reliably.

mstange avatar Jul 15 '19 19:07 mstange

Is there any way to give Rust a read-only view of a typed array in the JS runtime? It sounds like "no," but it really lowers the value of WebAssembly for me if I can't pass in typed array references. (Not that I blame any wasm-bindgen developers; it sounds like an innate limitation.)

JonathanWilbur avatar Jul 01 '22 15:07 JonathanWilbur

@JonathanWilbur This isn't a terrible limitation because you can treat the WebAssembly module as an allocator for all the typed arrays that you wish to create in your JS code.

prideout avatar Apr 29 '23 20:04 prideout

I think this doc page would be less confusing if it had examples of the data flowing the other way. Currently it is only showing an example a number slice being consumed by the WASM module, not the other way around.

prideout avatar Apr 29 '23 20:04 prideout