Create wasm-in-wasm-imports example (#2229)

This commit is contained in:
Colin Moore 2020-07-08 10:17:20 -04:00 committed by GitHub
parent e372596bc9
commit 17950202ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 168 additions and 0 deletions

View File

@ -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",

View File

@ -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"

View File

@ -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!

View File

@ -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>

View File

@ -0,0 +1,4 @@
// For more comments about what's going on here, check out the `hello_world`
// example
import('./pkg')
.catch(console.error);

View File

@ -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"
}
}

View File

@ -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 not shown.

View File

@ -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'
};