From 0495d0535a04b05c2b12e7a975172dbe0d60589a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Zwoli=C5=84ski?= Date: Fri, 10 May 2024 15:32:24 +0200 Subject: [PATCH] switch to spawning worker from a static script --- node-wasm/Cargo.toml | 18 ++++++++++++++--- node-wasm/js/worker.js | 24 ++++++++++++++++++++++ node-wasm/src/node.rs | 2 +- node-wasm/src/worker.rs | 44 ++++++++++------------------------------- 4 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 node-wasm/js/worker.js diff --git a/node-wasm/Cargo.toml b/node-wasm/Cargo.toml index 18b6b411..169b97be 100644 --- a/node-wasm/Cargo.toml +++ b/node-wasm/Cargo.toml @@ -30,6 +30,7 @@ blockstore = { workspace = true } celestia-tendermint = { workspace = true } anyhow = "1.0.71" +enum-as-inner = "0.6" console_error_panic_hook = "0.1.7" futures = "0.3" gloo-timers = "0.3" @@ -40,11 +41,22 @@ serde-wasm-bindgen = "0.6.0" serde_repr = "0.1" thiserror = "1.0" time = { version = "0.3", features = ["wasm-bindgen"] } -tokio = { version = "*", features = ["sync"]} +tokio = { version = "*", features = ["sync"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.18", features = ["time"] } tracing-web = "0.1.2" wasm-bindgen = "0.2.88" wasm-bindgen-futures = "0.4.37" -web-sys = { version = "0.3.69", features = ["BroadcastChannel", "MessageEvent", "Worker", "WorkerOptions", "WorkerType", "SharedWorker", "MessagePort", "SharedWorkerGlobalScope", "Blob", "BlobPropertyBag", "Url"]} -enum-as-inner = "0.6" +web-sys = { version = "0.3.69", features = [ + "Blob", + "BlobPropertyBag", + "BroadcastChannel", + "MessageEvent", + "MessagePort", + "SharedWorker", + "SharedWorkerGlobalScope", + "Url", + "Worker", + "WorkerOptions", + "WorkerType", +] } diff --git a/node-wasm/js/worker.js b/node-wasm/js/worker.js new file mode 100644 index 00000000..d41dfd5a --- /dev/null +++ b/node-wasm/js/worker.js @@ -0,0 +1,24 @@ +// this file should be installed by wasm-pack in pkg/snippets/-/js/ +import init, { run_worker } from '../../../lumina_node_wasm.js'; + +// get the path to this file +export function worker_script_url() { + return import.meta.url; +} + +// if we are in a worker +if ( + typeof WorkerGlobalScope !== 'undefined' + && self instanceof WorkerGlobalScope +) { + Error.stackTraceLimit = 99; + + let queued = []; + onconnect = (event) => { + console.log("Queued connection", event); + queued.push(event.ports[0]); + } + + await init(); + await run_worker(queued); +} diff --git a/node-wasm/src/node.rs b/node-wasm/src/node.rs index fb932418..5f40aba2 100644 --- a/node-wasm/src/node.rs +++ b/node-wasm/src/node.rs @@ -51,7 +51,7 @@ impl NodeDriver { /// already have been started. Otherwise it needs to be started with [`NodeDriver::start`]. #[wasm_bindgen(constructor)] pub async fn new() -> Result { - let worker = spawn_worker(LUMINA_SHARED_WORKER_NAME, "/wasm/lumina_node_wasm.js")?; + let worker = spawn_worker(LUMINA_SHARED_WORKER_NAME)?; let onerror_callback: Closure = Closure::new(|ev: MessageEvent| { error!("received error from SharedWorker: {:?}", ev.to_string()); diff --git a/node-wasm/src/worker.rs b/node-wasm/src/worker.rs index ba0b1c50..b743280a 100644 --- a/node-wasm/src/worker.rs +++ b/node-wasm/src/worker.rs @@ -8,7 +8,7 @@ use thiserror::Error; use tokio::sync::mpsc; use tracing::{debug, error, info, warn}; use wasm_bindgen::prelude::*; -use web_sys::{Blob, BlobPropertyBag, MessagePort, SharedWorker, Url, WorkerOptions, WorkerType}; +use web_sys::{MessagePort, SharedWorker, WorkerOptions, WorkerType}; use lumina_node::node::{Node, NodeError}; use lumina_node::store::{IndexedDbStore, SamplingMetadata, Store, StoreError}; @@ -307,39 +307,9 @@ pub async fn run_worker(queued_connections: Vec) { info!("Channel to WorkerMessageServer closed, exiting the SharedWorker"); } -/// SharedWorker can only be spawned from an [`URL`]. To eliminate a need to host a js shim -/// which calls into our Rust wasm code under specific path, we encode its entire contents -/// as a [`Blob`] which is then passed as an URL. -/// -/// [`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL -/// ['Blob']: https://developer.mozilla.org/en-US/docs/Web/API/Blob -pub(crate) fn spawn_worker(name: &str, wasm_url: &str) -> Result { - let script = format!( - r#" -Error.stackTraceLimit = 99; - -let queued = []; -onconnect = (event) => {{ - console.log("Queued connection", event); - queued.push(event.ports[0]); -}} - -self.lumina = await import(self.location.origin + '{wasm_url}'); -await self.lumina.default(); -await self.lumina.run_worker(queued); -"# - ); - - let array = Array::new(); - array.push(&script.into()); - let blob = Blob::new_with_str_sequence_and_options( - &array, - BlobPropertyBag::new().type_("application/javascript"), - ) - .to_error("could not create js shim Blob")?; - - let url = - Url::create_object_url_with_blob(&blob).to_error("could not create js shim Blob Url")?; +/// Spawn a new SharedWorker. +pub(crate) fn spawn_worker(name: &str) -> Result { + let url = worker_script_url(); let mut opts = WorkerOptions::new(); opts.type_(WorkerType::Module); @@ -350,3 +320,9 @@ await self.lumina.run_worker(queued); Ok(worker) } + +#[wasm_bindgen(module = "/js/worker.js")] +extern "C" { + // must be called in order to include this script in generated package + fn worker_script_url() -> String; +}