From cbccd2028d9e4542fecb261f1f98a2d09ff84d31 Mon Sep 17 00:00:00 2001 From: Robert Masen Date: Fri, 20 Apr 2018 21:13:28 -0500 Subject: [PATCH 1/3] include fetch arg for wasm2es6js --- .travis.yml | 2 + crates/cli-support/src/wasm2es6js.rs | 80 ++++++++++++++++------ crates/cli/src/bin/wasm2es6js.rs | 7 +- examples/hello_world/chrome/build_fetch.sh | 21 ++++++ 4 files changed, 86 insertions(+), 24 deletions(-) create mode 100755 examples/hello_world/chrome/build_fetch.sh diff --git a/.travis.yml b/.travis.yml index e91d42bb..af01b278 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,8 @@ matrix: (cd examples/hello_world && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) - | (cd examples/hello_world/chrome && ./build.sh) + - | + (cd examples/hello_world/chrome && ./build_fetch.sh) - | (cd examples/smorgasboard && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) - | diff --git a/crates/cli-support/src/wasm2es6js.rs b/crates/cli-support/src/wasm2es6js.rs index 998e8d6c..53ed9e5b 100644 --- a/crates/cli-support/src/wasm2es6js.rs +++ b/crates/cli-support/src/wasm2es6js.rs @@ -1,6 +1,7 @@ extern crate base64; use std::collections::HashSet; +use std::path::PathBuf; use parity_wasm::elements::*; @@ -8,17 +9,23 @@ use super::Error; pub struct Config { base64: bool, + fetch: bool, + file_name: String, } pub struct Output { module: Module, base64: bool, + fetch: bool, + file_name: String, } impl Config { pub fn new() -> Config { Config { base64: false, + fetch: false, + file_name: String::new(), } } @@ -26,15 +33,28 @@ impl Config { self.base64 = base64; self } + + pub fn fetch(&mut self, fetch: bool, in_path: &PathBuf) -> &mut Self { + self.fetch = fetch; + self.file_name = match in_path.file_name() { + Some(os_str) => os_str.to_str().unwrap_or("").to_string(), + None => String::new() + }; + self + } pub fn generate(&mut self, wasm: &[u8]) -> Result { - assert!(self.base64); + if !self.base64 && !self.fetch { + panic!() + } let module = deserialize_buffer(wasm).map_err(|e| { ::Error(format!("{:?}", e)) })?; Ok(Output { module, base64: self.base64, + fetch: self.fetch, + file_name: self.file_name.clone(), }) } } @@ -180,35 +200,51 @@ impl Output { )); } } - - let wasm = serialize(self.module) - .expect("failed to serialize"); - - format!(" - {js_imports} - let wasm; - let bytes; - const base64 = \"{base64}\"; - if (typeof Buffer === 'undefined') {{ - bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0)); - }} else {{ - bytes = Buffer.from(base64, 'base64'); - }} - {mem_export} - export const booted = WebAssembly.instantiate(bytes, {{ {imports} }}) + let inst = format!("WebAssembly.instantiate(bytes,{{ {imports} }}) .then(obj => {{ wasm = obj.instance; {memory} - }}); - + }})", + imports = imports, + memory = if export_mem { "memory = wasm.exports.memory;" } else { "" }, + ); + let (bytes, booted) = if self.base64 { + let wasm = serialize(self.module) + .expect("failed to serialize"); + ( + format!(" + let bytes; + const base64 = \"{base64}\"; + if (typeof Buffer === 'undefined') {{ + bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0)); + }} else {{ + bytes = Buffer.from(base64, 'base64'); + }}", base64 = base64::encode(&wasm)), + inst + ) + } else if self.fetch { + ( + String::new(), + format!("fetch('/{name}') + .then(res => res.arrayBuffer()) + .then(bytes => {inst})", name = self.file_name, inst = inst) + ) + } else { + panic!("the option --base64 or --fetch is required"); + }; + format!(" + {js_imports} + let wasm; + {bytes} + {mem_export} + export const booted = {booted}; {exports} ", - base64 = base64::encode(&wasm), + bytes = bytes, + booted = booted, js_imports = js_imports, - imports = imports, exports = exports, mem_export = if export_mem { "export let memory;" } else { "" }, - memory = if export_mem { "memory = wasm.exports.memory;" } else { "" }, ) } } diff --git a/crates/cli/src/bin/wasm2es6js.rs b/crates/cli/src/bin/wasm2es6js.rs index f884ee58..43d887d9 100644 --- a/crates/cli/src/bin/wasm2es6js.rs +++ b/crates/cli/src/bin/wasm2es6js.rs @@ -22,6 +22,7 @@ Options: -o --output FILE File to place output in --typescript Output a `*.d.ts` file next to the JS output --base64 Inline the wasm module using base64 encoding + --fetch Load module via `fetch()` instead of default webpack implementation Note that this is not intended to produce a production-ready output module but rather is intended purely as a temporary \"hack\" until it's standard in @@ -33,6 +34,7 @@ struct Args { flag_output: Option, flag_typescript: bool, flag_base64: bool, + flag_fetch: bool, arg_input: PathBuf, } @@ -41,8 +43,8 @@ fn main() { .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); - if !args.flag_base64 { - panic!("unfortunately only works right now with base64"); + if !args.flag_base64 && !args.flag_fetch { + panic!("unfortunately only works right now with base64 or fetch"); } let mut wasm = Vec::new(); @@ -51,6 +53,7 @@ fn main() { let object = wasm_bindgen_cli_support::wasm2es6js::Config::new() .base64(args.flag_base64) + .fetch(args.flag_fetch, &args.arg_input) .generate(&wasm) .expect("failed to parse wasm"); diff --git a/examples/hello_world/chrome/build_fetch.sh b/examples/hello_world/chrome/build_fetch.sh new file mode 100755 index 00000000..0765d0bc --- /dev/null +++ b/examples/hello_world/chrome/build_fetch.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +set -ex + +# This is the same as the directory above this. +cargo +nightly build --target wasm32-unknown-unknown +cargo +nightly run -p wasm-bindgen-cli --bin wasm-bindgen -- \ + ../../../target/wasm32-unknown-unknown/debug/hello_world.wasm --out-dir . + +# To avoid a bug occurring when webpack, wasm, and Chrome are used together, we +# convert the .wasm module to a .js module that embeds the wasm bytecode. To +# enable this, use the "--resolve-enxensions .js" flag when starting +# webpack-dev-server +cargo +nightly run -p wasm-bindgen-cli --bin wasm2es6js -- \ + --fetch -o hello_world_bg.js hello_world_bg.wasm +# wasm2es6js --base64 -o hello_world_bg.js hello_world_bg.wasm + +# And like the directory above this, from here it's the same. +npm install +#force webpack-dev-server to ignore the .wasm file +npm run serve -- --resolve-extensions .js From 79a49b2a56d73396cb57b5f20f82b46640bf3a73 Mon Sep 17 00:00:00 2001 From: robert masen Date: Mon, 23 Apr 2018 09:04:30 -0500 Subject: [PATCH 2/3] update fetch to take a string parameter --- crates/cli-support/src/wasm2es6js.rs | 31 ++++++++-------------- crates/cli/src/bin/wasm2es6js.rs | 8 +++--- examples/hello_world/chrome/build_fetch.sh | 11 ++++---- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/crates/cli-support/src/wasm2es6js.rs b/crates/cli-support/src/wasm2es6js.rs index 53ed9e5b..906c8a21 100644 --- a/crates/cli-support/src/wasm2es6js.rs +++ b/crates/cli-support/src/wasm2es6js.rs @@ -1,7 +1,6 @@ extern crate base64; use std::collections::HashSet; -use std::path::PathBuf; use parity_wasm::elements::*; @@ -9,23 +8,20 @@ use super::Error; pub struct Config { base64: bool, - fetch: bool, - file_name: String, + fetch_path: Option, } pub struct Output { module: Module, base64: bool, - fetch: bool, - file_name: String, + fetch_path: Option, } impl Config { pub fn new() -> Config { Config { base64: false, - fetch: false, - file_name: String::new(), + fetch_path: None, } } @@ -34,18 +30,14 @@ impl Config { self } - pub fn fetch(&mut self, fetch: bool, in_path: &PathBuf) -> &mut Self { - self.fetch = fetch; - self.file_name = match in_path.file_name() { - Some(os_str) => os_str.to_str().unwrap_or("").to_string(), - None => String::new() - }; + pub fn fetch(&mut self, path: Option) -> &mut Self { + self.fetch_path = path; self } pub fn generate(&mut self, wasm: &[u8]) -> Result { - if !self.base64 && !self.fetch { - panic!() + if !self.base64 && !self.fetch_path.is_some() { + panic!("the option --base64 or --fetch is required"); } let module = deserialize_buffer(wasm).map_err(|e| { ::Error(format!("{:?}", e)) @@ -53,8 +45,7 @@ impl Config { Ok(Output { module, base64: self.base64, - fetch: self.fetch, - file_name: self.file_name.clone(), + fetch_path: self.fetch_path.clone(), }) } } @@ -222,12 +213,12 @@ impl Output { }}", base64 = base64::encode(&wasm)), inst ) - } else if self.fetch { + } else if self.fetch_path.is_some() { ( String::new(), - format!("fetch('/{name}') + format!("fetch('{path}') .then(res => res.arrayBuffer()) - .then(bytes => {inst})", name = self.file_name, inst = inst) + .then(bytes => {inst})", path = self.fetch_path.unwrap(), inst = inst) ) } else { panic!("the option --base64 or --fetch is required"); diff --git a/crates/cli/src/bin/wasm2es6js.rs b/crates/cli/src/bin/wasm2es6js.rs index 43d887d9..f473cab4 100644 --- a/crates/cli/src/bin/wasm2es6js.rs +++ b/crates/cli/src/bin/wasm2es6js.rs @@ -22,7 +22,7 @@ Options: -o --output FILE File to place output in --typescript Output a `*.d.ts` file next to the JS output --base64 Inline the wasm module using base64 encoding - --fetch Load module via `fetch()` instead of default webpack implementation + --fetch PATH Load module by passing the PATH argument to `fetch()` Note that this is not intended to produce a production-ready output module but rather is intended purely as a temporary \"hack\" until it's standard in @@ -34,7 +34,7 @@ struct Args { flag_output: Option, flag_typescript: bool, flag_base64: bool, - flag_fetch: bool, + flag_fetch: Option, arg_input: PathBuf, } @@ -43,7 +43,7 @@ fn main() { .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); - if !args.flag_base64 && !args.flag_fetch { + if !args.flag_base64 && !args.flag_fetch.is_some() { panic!("unfortunately only works right now with base64 or fetch"); } @@ -53,7 +53,7 @@ fn main() { let object = wasm_bindgen_cli_support::wasm2es6js::Config::new() .base64(args.flag_base64) - .fetch(args.flag_fetch, &args.arg_input) + .fetch(args.flag_fetch) .generate(&wasm) .expect("failed to parse wasm"); diff --git a/examples/hello_world/chrome/build_fetch.sh b/examples/hello_world/chrome/build_fetch.sh index 0765d0bc..5fd3acc9 100755 --- a/examples/hello_world/chrome/build_fetch.sh +++ b/examples/hello_world/chrome/build_fetch.sh @@ -8,14 +8,13 @@ cargo +nightly run -p wasm-bindgen-cli --bin wasm-bindgen -- \ ../../../target/wasm32-unknown-unknown/debug/hello_world.wasm --out-dir . # To avoid a bug occurring when webpack, wasm, and Chrome are used together, we -# convert the .wasm module to a .js module that embeds the wasm bytecode. To -# enable this, use the "--resolve-enxensions .js" flag when starting -# webpack-dev-server +# create a .js module that will download the .wasm module via fetch. cargo +nightly run -p wasm-bindgen-cli --bin wasm2es6js -- \ - --fetch -o hello_world_bg.js hello_world_bg.wasm -# wasm2es6js --base64 -o hello_world_bg.js hello_world_bg.wasm + --fetch ./hello_world_bg.wasm -o hello_world_bg.js hello_world_bg.wasm # And like the directory above this, from here it's the same. npm install -#force webpack-dev-server to ignore the .wasm file + +# since we kept the same name for the .js module, we need +# to force webpack to ignore any other file extensions npm run serve -- --resolve-extensions .js From 6a6be7ef889c2332bfaa70ea0279ebddc5072bd3 Mon Sep 17 00:00:00 2001 From: robert masen Date: Mon, 23 Apr 2018 11:32:57 -0500 Subject: [PATCH 3/3] update comment to be more descriptive --- examples/hello_world/chrome/build_fetch.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/hello_world/chrome/build_fetch.sh b/examples/hello_world/chrome/build_fetch.sh index 5fd3acc9..d670af00 100755 --- a/examples/hello_world/chrome/build_fetch.sh +++ b/examples/hello_world/chrome/build_fetch.sh @@ -2,7 +2,10 @@ set -ex -# This is the same as the directory above this. +# This is the same build.sh, later we are going to use the +# fetch flag to avoid including the wasm module as a string +# of base64, instead using the js `fetch` function +#to request the module from the server. cargo +nightly build --target wasm32-unknown-unknown cargo +nightly run -p wasm-bindgen-cli --bin wasm-bindgen -- \ ../../../target/wasm32-unknown-unknown/debug/hello_world.wasm --out-dir . @@ -12,7 +15,7 @@ cargo +nightly run -p wasm-bindgen-cli --bin wasm-bindgen -- \ cargo +nightly run -p wasm-bindgen-cli --bin wasm2es6js -- \ --fetch ./hello_world_bg.wasm -o hello_world_bg.js hello_world_bg.wasm -# And like the directory above this, from here it's the same. +# Install the npm items as usual. npm install # since we kept the same name for the .js module, we need