diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d3b7b95d..6b9857eb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -178,6 +178,7 @@ jobs: - webworker - webworker-gloo - webworker-module + - webworker-module-sharedworker - wasm_threads - yew - yew-tailwindcss diff --git a/examples/webworker-module-sharedworker/Cargo.lock b/examples/webworker-module-sharedworker/Cargo.lock new file mode 100644 index 00000000..9be2a654 --- /dev/null +++ b/examples/webworker-module-sharedworker/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.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" + +[[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-sharedworker/Cargo.toml b/examples/webworker-module-sharedworker/Cargo.toml new file mode 100644 index 00000000..16f5006c --- /dev/null +++ b/examples/webworker-module-sharedworker/Cargo.toml @@ -0,0 +1,18 @@ +[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", + "SharedWorkerGlobalScope", + "MessageEvent", + "SharedWorker", + "WorkerOptions", + "WorkerType", + "MessagePort", +] } diff --git a/examples/webworker-module-sharedworker/Trunk.toml b/examples/webworker-module-sharedworker/Trunk.toml new file mode 100644 index 00000000..842cc2f7 --- /dev/null +++ b/examples/webworker-module-sharedworker/Trunk.toml @@ -0,0 +1,3 @@ +[build] +target = "index.html" +dist = "dist" diff --git a/examples/webworker-module-sharedworker/index.html b/examples/webworker-module-sharedworker/index.html new file mode 100644 index 00000000..57ebe983 --- /dev/null +++ b/examples/webworker-module-sharedworker/index.html @@ -0,0 +1,14 @@ + + + + + + Trunk | WebWorker | Module + + + + + + + + \ No newline at end of file diff --git a/examples/webworker-module-sharedworker/src/bin/app.rs b/examples/webworker-module-sharedworker/src/bin/app.rs new file mode 100644 index 00000000..eec2773e --- /dev/null +++ b/examples/webworker-module-sharedworker/src/bin/app.rs @@ -0,0 +1,43 @@ +use wasm_bindgen::{prelude::*, JsCast}; +use web_sys::{MessageEvent, SharedWorker, WorkerOptions, WorkerType}; + +fn worker_new(url: &str) -> SharedWorker { + let mut options = WorkerOptions::new(); + options.type_(WorkerType::Module); + options.name("example shared worker"); + SharedWorker::new_with_worker_options(url, &options).expect("failed to spawn worker") +} + +fn main() { + console_error_panic_hook::set_once(); + + let worker = worker_new("./worker_loader.js"); + + // FIX: When creating the first worker connection withn SharedWorker(...) + // the spec described connect event in worker processing model + // does not reach the worker's onconnect handler. + // > 13. If is shared is true, then queue a global task on the DOM manipulation + // > task source given worker global scope to fire an event named connect at + // > worker global scope, using MessageEvent, with the data attribute + // > initialized to the empty string, the ports attribute initialized to + // > a new frozen array containing inside port, and the source attribute + // > initialized to inside port. + // (https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model) + // This means that only subsequent worker connections reach that handler + // because SharedWorkerGlobalScope is already initialized + // (https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface) + + let onmessage = Closure::wrap(Box::new(move |msg: MessageEvent| { + web_sys::console::log_2( + &"webpage received message from worker".into(), + &JsValue::from(msg), + ); + }) as Box); + + let port = worker.port(); + port.set_onmessage(Some(onmessage.as_ref().unchecked_ref())); + onmessage.forget(); + + port.post_message(&"Hello from webpage".into()) + .expect("Successfully queing a message to be handled by worker"); +} diff --git a/examples/webworker-module-sharedworker/src/bin/worker.rs b/examples/webworker-module-sharedworker/src/bin/worker.rs new file mode 100644 index 00000000..3a6862c8 --- /dev/null +++ b/examples/webworker-module-sharedworker/src/bin/worker.rs @@ -0,0 +1,37 @@ +use wasm_bindgen::{prelude::*, JsCast}; +use web_sys::{MessageEvent, MessagePort, SharedWorkerGlobalScope}; + +fn main() { + console_error_panic_hook::set_once(); + web_sys::console::log_1(&"worker starting".into()); + + let scope = SharedWorkerGlobalScope::from(JsValue::from(js_sys::global())); + + let onconnect = Closure::wrap(Box::new(move |msg: MessageEvent| { + web_sys::console::log_2(&"got connect".into(), &JsValue::from(&msg)); + + let port = msg.ports().get(0); + let port = port.dyn_ref::().unwrap(); + + let callback = Closure::wrap(Box::new(|msg: MessageEvent| { + web_sys::console::log_2( + &"Received message from website".into(), + &JsValue::from(&msg), + ); + let target = msg.target().expect("message event should have a target"); + let port = target + .dyn_ref::() + .expect("message event target should be the port which sent the message"); + port.post_message(&"thank you for the message".into()) + .expect("worker should be able to send a message back"); + }) as Box); + + port.add_event_listener_with_callback("message", callback.as_ref().unchecked_ref()) + .unwrap_throw(); + callback.forget(); + port.start(); // this is requred when not using port.onmessage both for worker and webpage + }) as Box); + + scope.set_onconnect(Some(onconnect.as_ref().unchecked_ref())); + onconnect.forget(); +}