Passing High-Level Data Types between AssemblyScript and JavaScript: Announcing as-bind !
WebAssembly ( Wasm ) in it’s current MVP only allows passing and returning numbers from function calls. Therefore, things like strings, arrays, objects, etc… would need to be passed manually through WebAssembly’s linear memory, and developers would need to manage their own memory.
Toolchains like Rust / Wasm, and Emscripten are able to ease this process in the developer workflow by offering tools like wasm-bindgen. AssemblyScript had it’s loader module, but it only solves part of this workflow problem. The loader will handle the heavy lifting of passing a high-level data type for you, but it requires a lot of extra steps compared to wasm-bindgen. 🤔
I’m stoked to share I’ve been working on a library in-between all of my other projects: as-bind ! as-bind is an open-source isomorphic library to handle passing high-level data structures between AssemblyScript and JavaScript. 🤝🚀
This allows for passing something like a string, directly to your exported AssemblyScript functions, in both the browser, and Node.js! To show off this functionality, I built a rough Markdown Parser Example, which you can try here, or take a look at the gif below:
Now that we understand what as-bind can do, let’s take a look on how to use it. 💪
How can I use as-bind?
First, you can install as-bind using npm:
npm install --save as-bind
Then, when you compile your AssemblyScript, you want to add the as-bind entrypoint:
Finally, in your JavaScript, you could do the following:
Then you should be good using as-bind! Also, since as-bind is isomorphic, it should work in both the browser and Node.js! You can get this same JavaScript working in Node.js, by writing it in the appropriate Node.js syntax.
One thing to note, as-bind in its current state supports passing and returning Strings and Typed Arrays from functions. AssemblyScript classes will be supported in a later version. 🔭
Next, let’s take a quick look at some performance considerations before we start using as-bind in ALL of our AssemblyScript projects.
Performance Considerations
as-bind does all of it’s data passing at run time. Meaning this will be initially slower than a code generated bindings generator, such as something like wasm-bindgen. This is because, as-bind needs to cycle through every supported type on every parameter or return value for each function, whenever the function is called. However, this is mitigated due to the speculative execution that the library implements.
For the speculative execution the library, by default, will assume the type of value being passed to, or returned by a function will not change. Thus, the library will only have to cycle through the params once, cache the types, and then for calls to the functions after this it would be as fast as a code generated solution (in theory). 💭
If your project is doing general computations using a high level data type, this project should have a very small impact on performance of your project. However, if you project is doing it’s processing in a very time constrained loop (such as a game running at 60fps), you may want to be more considerate when choosing this library. The speculative execution should greatly help in the amount of time to pass high level data types, but if your project is already not running as fast as you would like, you may want to avoid this library, or use the exposed unbound original exports under the AsBindInstance.unboundExports
as covered in the Reference API on the as-bind README.
In the future, these types of tools will no longer be needed once the WebAssembly Interface Types proposal is implemented, and high-level data types are handled by the runtime / toolchain. But in the more near future, AssemblyScript would want to do some JavaScript code generation in the AssemblyScript compiler itself, as part of an as-bindgen
project for the most performant data passing. ⚡
Thank You!
I’m glad to be able to share this library I’ve been working on! However, it definitely could not be done without the help of the WebAssembly community, the AssemblyScript team, and a few friends of mine in particular:
Till Schneidereit and I had a chat about WasmBoy, and about how I had a really good experience writing the emulator, even though I had to do my own memory management. They helped me realize, building something low level isn’t that bad with manual memory management, but building something like a markdown parser would be very tedious. Which then inspired as-bind, and it’s markdown parser demo. 📝
Ashley Williams and I were talking about Wasm By Example, and they helped me realize, if your docs are becoming too complex, it may be a good idea to write a tool. That way you have less docs to write, and users will have an easier time using your stuff! 🛠️
I’d also like to thank YOU for reading this article! If you are interested in WebAssembly / AssemblyScript, or already use AssemblyScript, please try out as-bind! Take a look at the markdown parser demo, and try to use the library in your projects. I would appreciate any and all feedback, and please feel free to open up issues at the Github repo. Also, contributions are definitely welcome! Contributions can be opening an issue, submitting a PR, or even telling a friend! 🧑🤝🧑
Feel free to reach out over Twitter, would be stoked to chat about WebAssembly (or anything really), and I’m looking forward to see what you build! Have a nice day! 😄