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.