Skip to content
Open
Show file tree
Hide file tree
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
21 changes: 11 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@ readme = "README.md"
[features]
default = ["es_modules"]
es_modules = []
wasm_sync_init = []

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2.95"
web-sys = { version = "0.3.72", features = [
"Blob",
"DedicatedWorkerGlobalScope",
"MessageEvent",
"Url",
"Worker",
"WorkerType",
"WorkerOptions",
"Window",
"Navigator",
"WorkerNavigator",
"Blob",
"DedicatedWorkerGlobalScope",
"MessageEvent",
"Url",
"Worker",
"WorkerType",
"WorkerOptions",
"Window",
"Navigator",
"WorkerNavigator",
] }
js-sys = "0.3.72"
futures = "0.3.31"
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# https://rust-lang.github.io/rustup-components-history
[toolchain]
channel = "nightly-2024-03-16"
components = ["rust-src", "rustfmt"]
components = ["rust-src", "rustfmt", "rust-analyzer"]
targets = ["wasm32-unknown-unknown"]
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![feature(thread_id_value)]
#![cfg_attr(target_arch = "wasm32", feature(stdarch_wasm_atomic_wait))]

// Import reusable APIs from std
Expand Down
25 changes: 25 additions & 0 deletions src/wasm32/js/web_worker.sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// synchronously, using the browser, import wasm_bindgen shim JS scripts
importScripts("WASM_BINDGEN_SHIM_URL");

// Wait for the main thread to send us the shared module/memory and work context.
// Once we've got it, initialize it all with the `wasm_bindgen` global we imported via
// `importScripts`.
self.onmessage = (event) => {
let [module, memory, work] = event.data;
try {
let wasm = wasm_bindgen(module, memory);
// Enter rust code by calling entry point defined in `lib.rs`.
// This executes closure defined by work context.
wasm.wasm_thread_entry_point(work);

// Once done, terminate web worker
close();
} catch (err) {
// Propagate to main `onerror`:
setTimeout(() => {
throw err;
});
// Rethrow to keep promise rejected and prevent execution of further commands:
throw err;
}
};
7 changes: 3 additions & 4 deletions src/wasm32/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use scoped::ScopeData;
pub use scoped::{scope, Scope, ScopedJoinHandle};
use signal::Signal;
use utils::SpinLockMutex;
pub use utils::{available_parallelism, get_wasm_bindgen_shim_script_path, get_worker_script, is_web_worker_thread};
pub use utils::{available_parallelism, get_wasm_bindgen_shim_script_path, get_worker_script, is_main_thread};
use wasm_bindgen::prelude::*;
use web_sys::{DedicatedWorkerGlobalScope, Worker, WorkerOptions, WorkerType};

Expand Down Expand Up @@ -57,8 +57,7 @@ impl WorkerMessage {
pub fn post(self) {
let req = Box::new(self);

js_sys::eval("self")
.unwrap()
js_sys::global()
.dyn_into::<DedicatedWorkerGlobalScope>()
.unwrap()
.post_message(&JsValue::from(Box::into_raw(req) as u32))
Expand Down Expand Up @@ -251,7 +250,7 @@ impl Builder {
func: mem::transmute::<Box<dyn FnOnce() + Send + 'a>, Box<dyn FnOnce() + Send + 'static>>(main),
};

if is_web_worker_thread() {
if !is_main_thread() {
WorkerMessage::SpawnThread(BuilderRequest { builder: self, context }).post();
} else {
self.spawn_for_context(context);
Expand Down
4 changes: 2 additions & 2 deletions src/wasm32/scoped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{
},
};

use super::{signal::Signal, utils::is_web_worker_thread, Builder, JoinInner};
use super::{signal::Signal, utils::is_main_thread, Builder, JoinInner};

/// A scope to spawn scoped threads in.
///
Expand Down Expand Up @@ -89,7 +89,7 @@ where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
{
// Fail early to avoid flaky panics that depend on execution time
if !is_web_worker_thread() {
if is_main_thread() {
panic!("scope is not allowed on the main thread");
}

Expand Down
21 changes: 11 additions & 10 deletions src/wasm32/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ use std::{
sync::{LockResult, Mutex, MutexGuard, TryLockError},
};

use js_sys::Reflect;
use wasm_bindgen::prelude::*;
use web_sys::{Blob, Url, WorkerGlobalScope};
use web_sys::{Blob, Url};

pub fn available_parallelism() -> io::Result<NonZeroUsize> {
if let Some(window) = web_sys::window() {
return Ok(NonZeroUsize::new(window.navigator().hardware_concurrency() as usize).unwrap());
}

if let Ok(worker) = js_sys::eval("self").unwrap().dyn_into::<WorkerGlobalScope>() {
return Ok(NonZeroUsize::new(worker.navigator().hardware_concurrency() as usize).unwrap());
if let Ok(navigator) = Reflect::get(&js_sys::global(), &"navigator".into()) {
if let Ok(hardware_concurrency) = Reflect::get(&navigator, &"hardwareConcurrency".into()) {
return Ok(NonZeroUsize::new(hardware_concurrency.as_f64().unwrap() as usize).unwrap());
}
}

Err(io::Error::new(
Expand All @@ -22,8 +21,8 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
))
}

pub fn is_web_worker_thread() -> bool {
js_sys::eval("self").unwrap().dyn_into::<WorkerGlobalScope>().is_ok()
pub fn is_main_thread() -> bool {
std::thread::current().id().as_u64().get() == 1_u64
}

/// Extracts path of the `wasm_bindgen` generated .js shim script.
Expand Down Expand Up @@ -52,8 +51,10 @@ pub fn get_worker_script(wasm_bindgen_shim_url: Option<String>) -> String {
// Generate script from template
#[cfg(feature = "es_modules")]
let template = include_str!("js/web_worker_module.js");
#[cfg(not(feature = "es_modules"))]
#[cfg(all(not(feature = "es_modules"), not(feature = "wasm_sync_init")))]
let template = include_str!("js/web_worker.js");
#[cfg(feature = "wasm_sync_init")]
let template = include_str!("js/web_worker.sync.js");

let script = template.replace("WASM_BINDGEN_SHIM_URL", &wasm_bindgen_shim_url);

Expand Down