The Multi-Language Future of Web Assembly

A common dream of many developers have of web assembly is this idea that the web can be written in any language. But one story you don’t hear often talked about is the idea of web having multiple languages work together.

Today I want to present to you an idea I’ve been working on in my project web-dom called dynamic dispatch.

Dynamic dispatch allows someone to call a function on a web assembly module from another web assembly module. Why might you do this you ask? Right now much of the web is thinking of web assembly as a bundled scripting language like webpack javascript, but there’s nothing that prevents us from thinking of web assembly app as a collection of libraries working together to give an experience. Imagine for instance you are writing a calculator app. Why does your math calculation functions have to be inside your web assembly? Wouldn’t it be nice if there were some library calculator.wasm that had all the really gnarly calculations already done for you inside and you just called methods on it like a black box written in a far better language appropriate for math than the language you are using?

What about a game engine? You are writing in one language, but a really cool game engine is written in another language. Why not just load up gameengine.wasm and call an api of functions on the game engine externally?

Don’t get me wrong. It’s always going to be more efficient to call functions in your own code, but software engineering is ripe with examples of “Just drop the new DLL” or “Let the application use the shared library”. Imagine the future of a web assembly operating system environment, it just doesn’t make sense for multiple wasm applications to have the same code statically compiled within them.

Let’s take a look at some code using web-dom and how i’m currently doing dynamic dispatch.

Let’s start with writing calculator.wasm in C

#define WASM_EXPORT __attribute__((visibility("default")))
WASM_EXPORT
int add(int a, int b) {
return a+b;
}

Nice. Pretty advanced stuff here.

Now, let’s write some Rust web assembly to utilize it. The first thing we need to remember before looking at this code is that web assembly modules load asynchronously. So we’ll be dealing with a callback that let’s us know when loading is complete.

use web_dom::*;

fn add(calc_module:DOMReference, a:i32,b:i32) -> i32{
// let's get ready to make the call
let dyn_call = dynamic::begin(calc_module);
// prepare our parameters
dynamic::param_i32(dyn_call,a);
dynamic::param_i32(dyn_call,b);
// make the call on the right exported function
dynamic::call(dyn_call,"add");
// get the result
let result = dynamic::result_i32(dyn_call);
// unload the module if we don't need it anymore
dynamic::unload(calc);
result
}

#[no_mangle]
pub fn callback(_listener: EventListener, event: Event) -> () {
// get a handle to the module
let calc_module = get_property(event,"module");
// call add
let result = add(calc,2,2);
console::log(&format!("{}",result));
}

#[no_mangle]
pub fn main() -> () {
// Load web module asynchronously
let load_listener = create_event_listener();
dynamic::load("calculator.wasm",load_listener);
}

Not too painful for the magic of getting the functionality of an entirely unknown library, yah? Don’t get me wrong, I know this is a lot of ceremony for addition, but let’s pretend for a second instead of a simple addition, it’s a complex derivative calculation from a string. Or a machine learning operation. Maybe it’s some proprietary algorithm someone didn’t easily want you to see. Some mess of code you don’t want to know too much about or have anything to do with. I’d say it’s not too bad a trade off for doing this entirely without having to turn to javascript.

Dynamic dispatch is just starting, and more functionality for c string and memory sharing will be available soon. In the meantime, if you are interested in starting to write web assembly in any language that needs access to DOM, Canvas, or WebGL, and more fun things like this article please check out web-dom and help build a future ecosystem for all web.