Skip to content

Instantly share code, notes, and snippets.

@jsonxr
Last active March 29, 2020 04:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsonxr/b7728bbd3675da907d39ca9a4cb8646f to your computer and use it in GitHub Desktop.
Save jsonxr/b7728bbd3675da907d39ca9a4cb8646f to your computer and use it in GitHub Desktop.
wasm_bindgen optional params

Run example

mkdir src && mv src-lib.rs src/lib.rs
npm i
npm run serve
open localhost:8080

Works

javascript

(async () => {
  const demo = await import('./pkg').catch(console.error);
  const div = document.createElement("div"); 
  div.id = 'name'
  document.body.appendChild(div);  
  demo.greet('Hello World One', document.getElementById('name'));
})();

rust

#[wasm_bindgen]
pub fn greet(message: &str, div: HtmlDivElement) {
  div.set_inner_text(message);
}

Doesn't Work

javascript

(async () => {
  const demo = await import('./pkg').catch(console.error);
  const div = document.createElement("div"); 
  div.id = 'name'
  document.body.appendChild(div);  
  demo.greetWithOptions({
    message: 'Hello World Two',
    div: document.getElementById('name')
  });
})();

rust

struct Options<'a> {
  message: &'a str,
  div: &'a HtmlDivElement,
}
#[wasm_bindgen(js_name = greetWithOptions)]
pub fn greet_with_options(options: &Options) {
  let div = options.div;
  let message = options.message;
  div.set_inner_text(message);
}

Answer

javascript

  demo.greet(document.getElementById('name'));
  demo.greet(document.getElementById('name'), { message: 'Hi World!' });

rust

# [wasm_bindgen]
pub fn greet(ele: &JsValue, options: &JsValue) -> Result<(), JsValue> {
  match ele.dyn_ref::<HtmlDivElement>() {
    Some(div) => {
      if (options.is_undefined()) {
        div.set_inner_text("Hello from Rust");
      } else {
        let message: JsValue = Reflect::get(&options, &JsValue::from_str("message"))?;
        let message = message.as_string().unwrap();
        div.set_inner_text(&message);
      }
      Ok(())
    }
    None => Err(JsValue::from_str("ele must be a div"))
  }
}
[package]
name = "hello_world"
version = "0.1.0"
authors = ["The wasm-bindgen Developers"]
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.60"
[dependencies.web-sys]
version = "0.3"
features = [
'console',
'HtmlDivElement',
]
(async () => {
const demo = await import('./pkg').catch(console.error);
const div = document.createElement("div");
div.id = 'name'
document.body.appendChild(div);
// Works
//--------------------
demo.greet('Hello World One', document.getElementById('name'));
// Doesn't work
//--------------------
// demo.greetWithOptions({
// message: 'Hello World Two',
// div: document.getElementById('name')
// });
})();
{
"scripts": {
"build": "webpack",
"serve": "webpack-dev-server"
},
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "1.0.1",
"text-encoding": "^0.7.0",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.29.4",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.0"
}
}
// Move this file to src/lib
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{console, HtmlDivElement};
use js_sys::{Reflect};
#[wasm_bindgen]
pub fn greet(message: &str, div: HtmlDivElement) {
div.set_inner_text(message);
}
# [wasm_bindgen]
pub fn greet(ele: &JsValue, options: &JsValue) -> Result<(), JsValue> {
match ele.dyn_ref::<HtmlDivElement>() {
Some(div) => {
if (options.is_undefined()) {
div.set_inner_text("Hello from Rust");
} else {
let message: JsValue = Reflect::get(&options, &JsValue::from_str("message"))?;
let message = message.as_string().unwrap();
div.set_inner_text(&message);
}
Ok(())
}
None => Err(JsValue::from_str("ele must be a div"))
}
}
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
plugins: [
new HtmlWebpackPlugin(),
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, ".")
}),
// Have this example work in Edge which doesn't ship `TextEncoder` or
// `TextDecoder` at this time.
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
})
],
mode: 'development'
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment