Skip to content

Commit

Permalink
Create wasm-in-wasm-imports example (#2229)
Browse files Browse the repository at this point in the history
  • Loading branch information
Perseus101 authored Jul 8, 2020
1 parent e372596 commit 1795020
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ members = [
"examples/request-animation-frame",
"examples/todomvc",
"examples/wasm-in-wasm",
"examples/wasm-in-wasm-imports",
"examples/wasm2js",
"examples/webaudio",
"examples/webgl",
Expand Down
13 changes: 13 additions & 0 deletions examples/wasm-in-wasm-imports/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "wasm-in-wasm-imports"
version = "0.1.0"
authors = ["The wasm-bindgen Developers"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.64"
js-sys = "0.3.41"
wasm-bindgen-futures = "0.4.14"
15 changes: 15 additions & 0 deletions examples/wasm-in-wasm-imports/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# js-sys: WebAssembly in WebAssembly

[View documentation for this example online][dox] or [View compiled example
online][compiled]

[compiled]: https://rustwasm.github.io/wasm-bindgen/exbuild/wasm-in-wasm/
[dox]: https://rustwasm.github.io/docs/wasm-bindgen/examples/wasm-in-wasm.html

You can build the example locally with:

```
$ npm run serve
```

and then visiting http://localhost:8080 in a browser should run the example!
8 changes: 8 additions & 0 deletions examples/wasm-in-wasm-imports/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<p>The developer console should have messages in it</p>
</body>
</html>
4 changes: 4 additions & 0 deletions examples/wasm-in-wasm-imports/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// For more comments about what's going on here, check out the `hello_world`
// example
import('./pkg')
.catch(console.error);
14 changes: 14 additions & 0 deletions examples/wasm-in-wasm-imports/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"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"
}
}
86 changes: 86 additions & 0 deletions examples/wasm-in-wasm-imports/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use js_sys::{Function, Map, Object, Reflect, WebAssembly};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::{spawn_local, JsFuture};

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
pub(crate) fn log(a: &str);

#[wasm_bindgen(js_namespace = console)]
pub(crate) fn error(a: &str);

}

#[macro_use]
macro_rules! console_log {
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}

#[macro_use]
macro_rules! console_error {
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}

const WASM: &[u8] = include_bytes!("native_add.wasm");

async fn run_async() -> Result<(), JsValue> {
console_log!("instantiating a new wasm module directly");

let imports = make_imports()?;
let a = JsFuture::from(WebAssembly::instantiate_buffer(WASM, &imports)).await?;

let instance: WebAssembly::Instance = Reflect::get(&a, &"instance".into())?.dyn_into()?;

let exports = instance.exports();

let add = Reflect::get(&exports, &"add".into())?
.dyn_into::<Function>()
.expect("add export wasn't a function");

let three = add.call2(&JsValue::undefined(), &1.into(), &2.into())?;
console_log!("1 + 2 = {:?}", three);

Ok(())
}

fn bind(this: &JsValue, func_name: &str) -> Result<(), JsValue> {
let property_key = JsValue::from(func_name);
let orig_func = Reflect::get(this, &property_key)?.dyn_into::<Function>()?;
let func = orig_func.bind(this);
if !Reflect::set(this, &property_key, &func)? {
return Err(JsValue::from("failed to set property"));
}
Ok(())
}

pub fn make_imports() -> Result<Object, JsValue> {
let map = Map::new();
let imports: JsValue = Imports.into();

bind(&imports, "native_add")?;

map.set(&JsValue::from("env"), &imports);
Object::from_entries(&map.into())
}

#[wasm_bindgen]
pub struct Imports;

#[wasm_bindgen]
impl Imports {
pub fn native_add(&self, a: i32, b: i32) -> i32 {
a + b
}
}

#[wasm_bindgen(start)]
pub fn run() {
spawn_local(async {
match run_async().await {
Ok(_) => console_log!("Finished"),
Err(e) => console_error!("{:?}", e),
}
});
}
Binary file added examples/wasm-in-wasm-imports/src/native_add.wasm
Binary file not shown.
27 changes: 27 additions & 0 deletions examples/wasm-in-wasm-imports/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
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({
template: 'index.html'
}),
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'
};

0 comments on commit 1795020

Please sign in to comment.