diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 80bcf9ab..89fc2f26 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -122,6 +122,14 @@ jobs: restore-keys: | wasm32-example-webworker + - name: Setup | Cache | Example webworker-module + uses: actions/cache@v3 + with: + path: examples/webworker-module/target + key: wasm32-example-webworker-module + restore-keys: | + wasm32-example-webworker-module + - name: Setup | Cache | Example webworker-gloo uses: actions/cache@v3 with: @@ -183,6 +191,8 @@ jobs: run: ${{ matrix.binPath }} --config=examples/vanilla/Trunk.toml build - name: Build | Examples | webworker run: ${{ matrix.binPath }} --config=examples/webworker/Trunk.toml build + - name: Build | Examples | webworker-module + run: ${{ matrix.binPath }} --config=examples/webworker-module/Trunk.toml build - name: Build | Examples | webworker-gloo run: ${{ matrix.binPath }} --config=examples/webworker-gloo/Trunk.toml build - name: Build | Examples | yew diff --git a/examples/webworker-module/Cargo.lock b/examples/webworker-module/Cargo.lock new file mode 100644 index 00000000..c6503ea5 --- /dev/null +++ b/examples/webworker-module/Cargo.lock @@ -0,0 +1,155 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "proc-macro2" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webworker-module-example" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "wasm-bindgen", + "web-sys", +] diff --git a/examples/webworker-module/Cargo.toml b/examples/webworker-module/Cargo.toml new file mode 100644 index 00000000..b7af2a53 --- /dev/null +++ b/examples/webworker-module/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "webworker-module-example" +version = "0.1.0" +edition = "2021" + +[dependencies] +console_error_panic_hook = "0.1" +js-sys = "0.3" +wasm-bindgen = "0.2" +web-sys = { version = "0.3", features = [ + "console", + "DedicatedWorkerGlobalScope", + "Document", + "HtmlElement", + "MessageEvent", + "Node", + "Text", + "Url", + "Window", + "Worker", + "WorkerOptions", + "WorkerType", +] } diff --git a/examples/webworker-module/Trunk.toml b/examples/webworker-module/Trunk.toml new file mode 100644 index 00000000..842cc2f7 --- /dev/null +++ b/examples/webworker-module/Trunk.toml @@ -0,0 +1,3 @@ +[build] +target = "index.html" +dist = "dist" diff --git a/examples/webworker-module/index.html b/examples/webworker-module/index.html new file mode 100644 index 00000000..57ebe983 --- /dev/null +++ b/examples/webworker-module/index.html @@ -0,0 +1,14 @@ + + + + + + Trunk | WebWorker | Module + + + + + + + + \ No newline at end of file diff --git a/examples/webworker-module/src/bin/app.rs b/examples/webworker-module/src/bin/app.rs new file mode 100644 index 00000000..13216b62 --- /dev/null +++ b/examples/webworker-module/src/bin/app.rs @@ -0,0 +1,61 @@ +use js_sys::Array; +use wasm_bindgen::{prelude::*, JsCast}; +use web_sys::{MessageEvent, Worker, WorkerOptions, WorkerType}; + +fn worker_new(url: &str) -> Worker { + let mut options = WorkerOptions::new(); + options.type_(WorkerType::Module); + Worker::new_with_options(&url, &options).expect("failed to spawn worker") +} + +fn main() { + console_error_panic_hook::set_once(); + + let worker = worker_new("./worker_loader.js"); + let worker_clone = worker.clone(); + + // NOTE: We must wait for the worker to report that it's ready to receive + // messages. Any message we send beforehand will be discarded / ignored. + // This is different from js-based workers, which can send messages + // before the worker is initialized. + // REASON: This is because javascript only starts processing MessageEvents + // once the worker's script first yields to the javascript event loop. + // For js workers this means that you can register the event listener + // as first thing in the worker and will receive all previously sent + // message events. However, loading wasm is an asynchronous operation + // which yields to the js event loop before the wasm is loaded and had + // a change to register the event listener. At that point js processes + // the message events, sees that there isn't any listener registered, + // and drops them. + + let onmessage = Closure::wrap(Box::new(move |msg: MessageEvent| { + let worker_clone = worker_clone.clone(); + let data = Array::from(&msg.data()); + + if data.length() == 0 { + let msg = Array::new(); + msg.push(&2.into()); + msg.push(&5.into()); + worker_clone + .post_message(&msg.into()) + .expect("sending message to succeed"); + } else { + let a = data + .get(0) + .as_f64() + .expect("first array value to be a number") as u32; + let b = data + .get(1) + .as_f64() + .expect("second array value to be a number") as u32; + let result = data + .get(2) + .as_f64() + .expect("third array value to be a number") as u32; + + web_sys::console::log_1(&format!("{a} x {b} = {result}").into()); + } + }) as Box); + worker.set_onmessage(Some(onmessage.as_ref().unchecked_ref())); + onmessage.forget(); +} diff --git a/examples/webworker-module/src/bin/worker.rs b/examples/webworker-module/src/bin/worker.rs new file mode 100644 index 00000000..9fe7cdb9 --- /dev/null +++ b/examples/webworker-module/src/bin/worker.rs @@ -0,0 +1,37 @@ +use js_sys::Array; +use wasm_bindgen::{prelude::*, JsCast}; +use web_sys::{DedicatedWorkerGlobalScope, MessageEvent}; + +fn main() { + console_error_panic_hook::set_once(); + web_sys::console::log_1(&"worker starting".into()); + + let scope = DedicatedWorkerGlobalScope::from(JsValue::from(js_sys::global())); + let scope_clone = scope.clone(); + + let onmessage = Closure::wrap(Box::new(move |msg: MessageEvent| { + web_sys::console::log_1(&"got message".into()); + + let data = Array::from(&msg.data()); + let a = data + .get(0) + .as_f64() + .expect("first array value to be a number") as u32; + let b = data + .get(1) + .as_f64() + .expect("second array value to be a number") as u32; + + data.push(&(a * b).into()); + scope_clone + .post_message(&data.into()) + .expect("posting result message succeeds"); + }) as Box); + scope.set_onmessage(Some(onmessage.as_ref().unchecked_ref())); + onmessage.forget(); + + // The worker must send a message to indicate that it's ready to receive messages. + scope + .post_message(&Array::new().into()) + .expect("posting ready message succeeds"); +}