The maintainer of this website has a Spotify Coding Playlist of their Lo-fi Hip Hop beats!

WebAssembly Logo

Wasm By Example

Language:

Importing Javascript Functions Into WebAssembly

Overview

When you are instantiating Wasm modules, you are able to pass in an importObject. This importObject can be used to call host (Javascript) functions within Wasm!

In rust, tools like wasm-bindgen, which is part of wasm-pack workflow, abstracts away the importObject.

In this example, we will import and implement a simple console.log which is called within Wasm. This example is inspired by the console_log example , but simplified. So let's jump into the example:


Implementation

First, let's add the following to our src/lib.rs file:

// The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file.
// Import the wasm-bindgen crate.
use wasm_bindgen::prelude::*;

// Let's define our external function (imported from JS)
// Here, we will define our external `console.log`
#[wasm_bindgen]
extern "C" {
  // Use `js_namespace` here to bind `console.log(..)` instead of just
  // `log(..)`
#[wasm_bindgen(js_namespace = console)]
  fn log(s: &str);
}

// Export a function that will be called in JavaScript
// but call the "imported" console.log.
#[wasm_bindgen]
pub fn console_log_from_wasm() {
  log("This console.log is from wasm!");
}

Then, let's compile that using wasm-pack, which will create a pkg/ directory:

wasm-pack build --target web

Next, lets create an index.js file to load and run our wasm output. Let's import the wasm initialization module from pkg/importing_javascript_functions_into_webassembly.js that was generated by wasm-pack. Then, let's call the module passing in the path to our wasm file at pkg/importing_javascript_functions_into_webassembly_bg.wasm that was generated by wasm-pack. Then, we will go ahead and call our exported wasm function, that will call the "imported" console.log JavaScript function:

NOTE: In this example, we are using the exported function from the wasm module directly to help highlight the WebAssembly API. wasm-bindgen generates JavaScript bindings code that can be imported as an ES6 import, and is the reccomended way to work with your Rust Wasm modules. These JavaScript bindings are shown in the "Passing High Level Data Types with wasm-bindgen" example.

const runWasm = async () => {
  // Instantiate our wasm module
  const rustWasm = await wasmInit(
    "./pkg/importing_javascript_functions_into_webassembly_bg.wasm"
  );

  // Run the exported function
  rustWasm.console_log_from_wasm(); // Should log "This console.log is from wasm!"
};
runWasm();

Lastly, lets load our ES6 Module, index.js Javascript file in our index.html. And you should get something similar to the demo (Source Code) below!


Demo

And that's it for the basics! Next, lets took a look at some "Advanced Web Demos", with an example of Reading and Writing Graphics with WebAssembly.