From 5c9a2705e4155a268632b924eac6362af4e1310c Mon Sep 17 00:00:00 2001 From: Dominic Elm Date: Fri, 3 Jun 2022 00:01:44 +0200 Subject: [PATCH] fixup: fix tests --- .DS_Store | Bin 0 -> 6148 bytes .github/workflows/main.yml | 2 +- Cargo.toml | 1 + crates/cli-support/src/js/mod.rs | 59 +++++++++++------- crates/cli/tests/wasm-bindgen/main.rs | 4 +- examples/synchronous-instantiation/Cargo.toml | 11 ++++ examples/synchronous-instantiation/README.md | 23 +++++++ examples/synchronous-instantiation/build.sh | 6 ++ examples/synchronous-instantiation/index.html | 46 ++++++++++++++ examples/synchronous-instantiation/src/lib.rs | 12 ++++ examples/synchronous-instantiation/worker.js | 23 +++++++ .../src/examples/synchronous-instantiation.md | 33 ++++++++++ 12 files changed, 195 insertions(+), 25 deletions(-) create mode 100644 .DS_Store create mode 100644 examples/synchronous-instantiation/Cargo.toml create mode 100644 examples/synchronous-instantiation/README.md create mode 100755 examples/synchronous-instantiation/build.sh create mode 100644 examples/synchronous-instantiation/index.html create mode 100644 examples/synchronous-instantiation/src/lib.rs create mode 100644 examples/synchronous-instantiation/worker.js create mode 100644 guide/src/examples/synchronous-instantiation.md diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..038ad50aa8c1fe289434b91a014e9e0c88a4ed39 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8-BN@e6nb3nTCmkpDPBUYFJMFuDm5WNgK4%jtrbckXMG``#OHBl zcLSE@;7P>Jz~-BspWU4gvOkP5K9~m`#u|(<0S%F(QXpt9bd_u{BG+R~Sj<9}`ipc@ zFwkE#;o1eP`IUKW%)YJPkChL;4}TIz>8#!U;C$(^A-fW%@yy-3W zu9S-XT=)FzC|ryh`{yc|c~KHhbwU(`5OQ}DC4pKD)I14No$DHhsEOLB(OfRO-P4xr z^*gJUT=tLKE!jQktyVR0aCmffIeL!AiFz|+a^PLdp2ZyALD{J5#hoUxN*=+N=jHK) z!~iis3=jj`!+<>lM16Zorb>wcV&I1i;Qkaq-D0{YUl!s@ng!TXp1>-VQKtNx+1V9J(k*0PU czeFA49E+Jj90lz<9gr>pnh^RB1HZt)7uwWKC;$Ke literal 0 HcmV?d00001 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f2bb58f6d95..331164c5837 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -228,7 +228,7 @@ jobs: ln -snf `pwd`/target/debug/wasm-bindgen $(dirname `which cargo`)/wasm-bindgen - run: mv _package.json package.json && npm install && rm package.json - run: | - for dir in `ls examples | grep -v README | grep -v asm.js | grep -v raytrace | grep -v without-a-bundler | grep -v wasm-in-web-worker | grep -v websockets | grep -v webxr | grep -v deno`; do + for dir in `ls examples | grep -v README | grep -v asm.js | grep -v raytrace | grep -v without-a-bundler | grep -v wasm-in-web-worker | grep -v websockets | grep -v webxr | grep -v deno | grep -v synchronous-instantiation`; do (cd examples/$dir && ln -fs ../../node_modules . && npm run build -- --output-path ../../exbuild/$dir) || exit 1; diff --git a/Cargo.toml b/Cargo.toml index b77314cebb1..6b1fdf56a0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,7 @@ members = [ "examples/webxr", "examples/without-a-bundler", "examples/without-a-bundler-no-modules", + "examples/synchronous-instantiation", "tests/no-std", ] diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 3b737fea633..707a4523328 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -469,8 +469,8 @@ impl<'a> Context<'a> { OutputMode::Web => { self.imports_post.push_str("let wasm;\n"); init = self.gen_init(needs_manual_start, Some(&mut imports))?; - footer.push_str("export { getImports, initMemory, finalizeInit }\n"); - footer.push_str("export default init;\n"); + footer.push_str("export { initSync }\n"); + footer.push_str("export default init;"); } } @@ -638,34 +638,39 @@ impl<'a> Context<'a> { // So using "declare" everywhere for at least the NoModules option. // Also in (at least) the NoModules, the `init()` method is renamed to `wasm_bindgen()`. let setup_function_declaration; - let internal_helper_functions; + let mut sync_init_function = String::new(); let declare_or_export; if self.config.mode.no_modules() { declare_or_export = "declare"; - internal_helper_functions = ""; setup_function_declaration = "declare function wasm_bindgen"; } else { declare_or_export = "export"; - internal_helper_functions = "\ - export function getImports(): ModuleImports;\n\ - export function initMemory(imports: ModuleImports, maybe_memory?: WebAssembly.Memory): void;\n\ - export function finalizeInit(instance: WebAssembly.Instance, module: WebAssembly.Module): InitOutput;\n\ - "; + + sync_init_function.push_str(&format!("\ + /**\n\ + * Synchronously compiles the given `bytes` and instantiates the WebAssembly module.\n\ + *\n\ + * @param {{BufferSource}} bytes\n\ + {memory_doc}\ + *\n\ + * @returns {{InitOutput}}\n\ + */\n\ + export function initSync(bytes: BufferSource{memory_param}): InitOutput;\n\n\ + ", + memory_doc = memory_doc, + memory_param = memory_param + )); + setup_function_declaration = "export default function init"; } Ok(format!( "\n\ - type ExportValue = Function | WebAssembly.Global | WebAssembly.Memory | WebAssembly.Table;\n\ - type ImportValue = ExportValue | number;\n\ - type Imports = Record;\n\ - type ModuleImports = Record;\n\ - \n\ {declare_or_export} type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;\n\ \n\ {declare_or_export} interface InitOutput {{\n\ {output}}}\n\ \n\ - {internal_helper_functions}\n\ + {sync_init_function}\ /**\n\ * If `module_or_path` is {{RequestInfo}} or {{URL}}, makes a request and\n\ * for everything else, calls `WebAssembly.instantiate` directly.\n\ @@ -679,8 +684,8 @@ impl<'a> Context<'a> { (module_or_path{}: InitInput | Promise{}): Promise;\n", memory_doc, arg_optional, memory_param, output = output, + sync_init_function = sync_init_function, declare_or_export = declare_or_export, - internal_helper_functions = internal_helper_functions, setup_function_declaration = setup_function_declaration, )) } @@ -748,11 +753,11 @@ impl<'a> Context<'a> { // Initialize the `imports` object for all import definitions that we're // directed to wire up. let mut imports_init = String::new(); - if self.wasm_import_definitions.len() > 0 { - imports_init.push_str("imports."); - imports_init.push_str(module_name); - imports_init.push_str(" = {};\n"); - } + + imports_init.push_str("imports."); + imports_init.push_str(module_name); + imports_init.push_str(" = {};\n"); + for (id, js) in crate::sorted_iter(&self.wasm_import_definitions) { let import = self.module.imports.get_mut(*id); import.module = module_name.to_string(); @@ -842,12 +847,22 @@ impl<'a> Context<'a> { function finalizeInit(instance, module) {{ wasm = instance.exports; init.__wbindgen_wasm_module = module; - {post_instantiate} {start} return wasm; }} + function initSync(bytes{init_memory_arg}) {{ + const imports = getImports(); + + initMemory(imports{init_memory_arg}); + + const module = new WebAssembly.Module(bytes); + const instance = new WebAssembly.Instance(module, imports); + + return finalizeInit(instance, module); + }} + async function init(input{init_memory_arg}) {{ {default_module_path} const imports = getImports(); diff --git a/crates/cli/tests/wasm-bindgen/main.rs b/crates/cli/tests/wasm-bindgen/main.rs index d534b5a9724..b52f14e64c3 100644 --- a/crates/cli/tests/wasm-bindgen/main.rs +++ b/crates/cli/tests/wasm-bindgen/main.rs @@ -289,7 +289,7 @@ fn omit_default_module_path_target_web() { "\ async function init(input) { - const imports = {};", + const imports = getImports();", )); } @@ -309,7 +309,7 @@ fn omit_default_module_path_target_no_modules() { "\ async function init(input) { - const imports = {};", + const imports = getImports();", )); } diff --git a/examples/synchronous-instantiation/Cargo.toml b/examples/synchronous-instantiation/Cargo.toml new file mode 100644 index 00000000000..f68b62f9b9d --- /dev/null +++ b/examples/synchronous-instantiation/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "synchronous-instantiation" +version = "0.1.0" +authors = ["The wasm-bindgen Developers"] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = "0.2.80" diff --git a/examples/synchronous-instantiation/README.md b/examples/synchronous-instantiation/README.md new file mode 100644 index 00000000000..9c0bc743ed1 --- /dev/null +++ b/examples/synchronous-instantiation/README.md @@ -0,0 +1,23 @@ +# Synchronous Instantiation + +[View documentation for this example online][dox] + +[dox]: https://rustwasm.github.io/docs/wasm-bindgen/examples/synchronous-instantiation.html + +You can build the example locally with: + +``` +$ wasm-pack build --target web +``` + +Then serve this directory in your favourite webserver and navigate to `host:port` +to open the index.html in your browser: + +``` +# static server from https://crates.io/crates/https +http + +# or use python +python2 -m SimpleHTTPServer +python3 -m http.server +``` diff --git a/examples/synchronous-instantiation/build.sh b/examples/synchronous-instantiation/build.sh new file mode 100755 index 00000000000..cb05aadb1a9 --- /dev/null +++ b/examples/synchronous-instantiation/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -ex + +wasm-pack build --target web +python3 -m http.server diff --git a/examples/synchronous-instantiation/index.html b/examples/synchronous-instantiation/index.html new file mode 100644 index 00000000000..f62e8efb274 --- /dev/null +++ b/examples/synchronous-instantiation/index.html @@ -0,0 +1,46 @@ + + + + + + + Document + + + + + diff --git a/examples/synchronous-instantiation/src/lib.rs b/examples/synchronous-instantiation/src/lib.rs new file mode 100644 index 00000000000..e5afafcb563 --- /dev/null +++ b/examples/synchronous-instantiation/src/lib.rs @@ -0,0 +1,12 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(value: &str); +} + +#[wasm_bindgen] +pub fn greet(name: &str) { + log(&format!("Hello, {}!", name)); +} diff --git a/examples/synchronous-instantiation/worker.js b/examples/synchronous-instantiation/worker.js new file mode 100644 index 00000000000..1163234e301 --- /dev/null +++ b/examples/synchronous-instantiation/worker.js @@ -0,0 +1,23 @@ +import * as wasm from "./pkg/synchronous_instantiation.js"; + +self.onmessage = ({ data: bytes }) => { + /** + * When we receive the bytes as an `ArrayBuffer` we can use that to + * synchronously initialize the module as opposed to asynchronously + * via the default export. The synchronous method internally uses + * `new WebAssembly.Module()` and `new WebAssembly.Instance()`. + */ + wasm.initSync(bytes); + + /** + * Once initialized we can call our exported `greet()` functions. + */ + wasm.greet("Dominic"); +}; + +/** + * Once the Web Worker was spwaned we ask the main thread to fetch the bytes + * for the WebAssembly module. Once fetched it will send the bytes back via + * a `postMessage` (see above). + */ +self.postMessage({ type: "FETCH_WASM" }); diff --git a/guide/src/examples/synchronous-instantiation.md b/guide/src/examples/synchronous-instantiation.md new file mode 100644 index 00000000000..087558537dd --- /dev/null +++ b/guide/src/examples/synchronous-instantiation.md @@ -0,0 +1,33 @@ +# Synchronous Instantiation + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/synchronous-instantiation + +This example shows how to synchronously initialize a WebAssembly module as opposed to [asynchronously][without-bundler]. In most cases, the default way of asynchronously initializing a module will suffice. However, there might be use cases where you'd like to lazy load a module on demand and synchronously compile and instantiate it. Note that this only works off the main thread and since compilation and instantiation of large modules can be expensive you should only use this method if it's absolutely required in your use case. Otherwise you should use the [default method][without-bundler]. + +For this deployment strategy bundlers like Webpack are not required. For more information on deployment see the [dedicated +documentation][deployment]. + +First let's take a look at our tiny lib: + +```rust +{{#include ../../../examples/synchronous-instantiation/src/lib.rs}} +``` + +Next, let's have a look at the `index.html`: + +```html +{{#include ../../../examples/synchronous-instantiation/index.html}} +``` + +Otherwise the rest of the magic happens in `worker.js`: + +```js +{{#include ../../../examples/synchronous-instantiation/worker.js}} +``` + +And that's it! Be sure to read up on the [deployment options][deployment] to see what it means to deploy without a bundler. + +[deployment]: ../reference/deployment.html +[without-bundler]: ./without-a-bundler.html