Skip to content

Commit

Permalink
test: add a webworker example using modules
Browse files Browse the repository at this point in the history
  • Loading branch information
ctron committed Dec 19, 2023
1 parent a02632c commit ad8d9f2
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
155 changes: 155 additions & 0 deletions examples/webworker-module/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions examples/webworker-module/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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",
] }
3 changes: 3 additions & 0 deletions examples/webworker-module/Trunk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build]
target = "index.html"
dist = "dist"
14 changes: 14 additions & 0 deletions examples/webworker-module/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Trunk | WebWorker | Module</title>

<base data-trunk-public-url />
</head>
<body>
<link data-trunk rel="rust" href="Cargo.toml" data-wasm-opt="z" data-bin="app" data-type="main" />
<link data-trunk rel="rust" href="Cargo.toml" data-wasm-opt="z" data-bin="worker" data-type="worker" data-loader-shim data-bindgen-target="web" />
</body>
</html>
61 changes: 61 additions & 0 deletions examples/webworker-module/src/bin/app.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Fn(MessageEvent)>);
worker.set_onmessage(Some(onmessage.as_ref().unchecked_ref()));
onmessage.forget();
}
37 changes: 37 additions & 0 deletions examples/webworker-module/src/bin/worker.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Fn(MessageEvent)>);
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");
}

0 comments on commit ad8d9f2

Please sign in to comment.