Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions frb_rust/src/third_party/wasm_bindgen/worker_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,36 @@

use crate::misc::web_utils::script_path;
use crate::web_transfer::transfer_closure::TransferClosure;
// `Array`, `Object`, `Reflect`, `FromIterator`, `Blob`, `BlobPropertyBag`, `Url`
// are used only by the non-emscripten `spawn` body; the emscripten stub doesn't
// need them. Gate the imports so emscripten builds stay warning-free.
#[cfg(not(target_os = "emscripten"))]
use js_sys::{Array, Object, Reflect};
use std::cell::RefCell;
#[cfg(not(target_os = "emscripten"))]
use std::iter::FromIterator;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[cfg(not(target_os = "emscripten"))]
use web_sys::BlobPropertyBag;
use web_sys::ErrorEvent;
use web_sys::MessageEvent;
#[cfg(not(target_os = "emscripten"))]
use web_sys::{Blob, Url};
use web_sys::{Event, Worker};

#[wasm_bindgen]
pub struct WorkerPool {
state: Rc<PoolState>,
// These fields are consumed only by the non-emscripten `spawn` body.
// `new_raw` still stores them on emscripten (the API signature is shared),
// so suppress the resulting dead-code warning rather than drop the fields.
#[cfg_attr(target_os = "emscripten", allow(dead_code))]
script_src: String,
#[cfg_attr(target_os = "emscripten", allow(dead_code))]
worker_js_preamble: String,
#[cfg_attr(target_os = "emscripten", allow(dead_code))]
wasm_bindgen_name: String,
}

Expand Down Expand Up @@ -77,10 +90,19 @@ impl WorkerPool {
worker_js_preamble,
wasm_bindgen_name,
};
// On emscripten, `spawn` is a fail-fast stub (see its doc comment);
// eagerly priming the pool here would make `default()` — which uses
// `hardwareConcurrency` as `initial` — panic on startup for any
// program that just links the library, even if it never dispatches
// worker-bound work. Leave the pool empty on that target; explicit
// calls to `spawn` still return the same descriptive `Err`.
#[cfg(not(target_os = "emscripten"))]
for _ in 0..initial {
let worker = pool.spawn()?;
pool.state.push(worker);
}
#[cfg(target_os = "emscripten")]
let _ = initial; // silence unused-variable warning on emscripten

Ok(pool)
}
Expand All @@ -94,6 +116,12 @@ impl WorkerPool {
///
/// Returns any error that may happen while a JS web worker is created and a
/// message is sent to it.
///
/// On `target_os = "emscripten"` this always returns `Err`: the worker init
/// path calls [`wasm_bindgen::module`], which is unsupported in
/// wasm-bindgen-cli's `OutputMode::Emscripten`. See the emscripten stub of
/// this function for the full context.
#[cfg(not(target_os = "emscripten"))]
fn spawn(&self) -> Result<Worker, JsValue> {
let worker_js_preamble = &self.worker_js_preamble;
let script_src = &self.script_src;
Expand Down Expand Up @@ -148,6 +176,33 @@ impl WorkerPool {
Ok(worker)
}

/// Emscripten stub — see the non-emscripten variant for the normal
/// implementation.
///
/// `wasm_bindgen::module()` is unsupported in wasm-bindgen-cli's
/// `OutputMode::Emscripten` (see `wasm-bindgen-cli-support/src/js/mod.rs`,
/// `Intrinsic::Module`, which bails for Bundler and Emscripten). That mode
/// is force-selected when an emscripten fork with `-sWASM_BINDGEN`
/// integration inserts a `__wasm_bindgen_emscripten_marker` custom
/// section, regardless of any explicit `--target` flag.
///
/// The mere presence of a `wasm_bindgen::module()` call anywhere in the
/// dependency graph fails wasm-bindgen post-link on that target (bindings
/// cannot be generated for the `__wbindgen_module` import), even when
/// `spawn` is never actually called. The `cfg` gate keeps the import out
/// of the wasm entirely.
///
/// At runtime, fail fast with a clear error rather than returning a
/// dead `Worker` initialised with a null module handle.
#[cfg(target_os = "emscripten")]
fn spawn(&self) -> Result<Worker, JsValue> {
Err(JsValue::from_str(
"flutter_rust_bridge::WorkerPool::spawn is not supported on \
target_os = \"emscripten\": wasm_bindgen::module() is \
unsupported in wasm-bindgen-cli's OutputMode::Emscripten",
))
}
Comment thread
gergelyvagujhelyi marked this conversation as resolved.

/// Fetches a worker from this pool, spawning one if necessary.
///
/// This will attempt to pull an already-spawned web worker from our cache
Expand Down
Loading