From b71199615ce7a1a666166d166a69b46bb1d3857a Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 5 Dec 2024 02:13:50 +0100 Subject: [PATCH] Account for Firefox `SharedArrayBuffer` bug in shared workers --- src/backends/wasm_js.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/backends/wasm_js.rs b/src/backends/wasm_js.rs index 61198f53..e225e6d8 100644 --- a/src/backends/wasm_js.rs +++ b/src/backends/wasm_js.rs @@ -16,7 +16,7 @@ pub use crate::util::{inner_u32, inner_u64}; #[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))] compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!"); -use js_sys::{SharedArrayBuffer, Uint8Array, WebAssembly::Memory}; +use js_sys::{JsString, Object, SharedArrayBuffer, Uint8Array, WebAssembly::Memory}; use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue}; // Size of our temporary Uint8Array buffer used with WebCrypto methods @@ -38,8 +38,21 @@ pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { MEMORY_KIND_NOT_SHARED => false, MEMORY_KIND_SHARED => true, MEMORY_KIND_UNINIT => { - let memory: Memory = wasm_bindgen::memory().unchecked_into(); - let val = if memory.buffer().is_instance_of::() { + let buffer = wasm_bindgen::memory().unchecked_into::().buffer(); + + // `SharedArrayBuffer` is only available with `crossOriginIsolated`. But even + // without its possible to create a shared `WebAssembly.Memory`, so we check + // for that via the constructor name. + // + // Keep in mind that `crossOriginIsolated` is not available on Node.js. + let shared = if let Some(true) = CROSS_ORIGIN_ISOLATED.with(Option::clone) { + buffer.is_instance_of::() + } else { + let constructor_name = Object::from(buffer).constructor().name(); + SHARED_ARRAY_BUFFER_NAME.with(|name| &constructor_name == name) + }; + + let val = if shared { MEMORY_KIND_SHARED } else { MEMORY_KIND_NOT_SHARED @@ -87,6 +100,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { } #[wasm_bindgen] +#[rustfmt::skip] extern "C" { // Web Crypto API: Crypto interface (https://www.w3.org/TR/WebCryptoAPI/) type Crypto; @@ -98,4 +112,9 @@ extern "C" { fn get_random_values(this: &Crypto, buf: &Uint8Array) -> Result<(), JsValue>; #[wasm_bindgen(method, js_name = getRandomValues, catch)] fn get_random_values_ref(this: &Crypto, buf: &mut [u8]) -> Result<(), JsValue>; + /// Returns the [`crossOriginIsolated`](https://developer.mozilla.org/en-US/docs/Web/API/crossOriginIsolated) global property. + #[wasm_bindgen(thread_local_v2, js_namespace = globalThis, js_name = crossOriginIsolated)] + static CROSS_ORIGIN_ISOLATED: Option; + #[wasm_bindgen(thread_local_v2, static_string)] + static SHARED_ARRAY_BUFFER_NAME: JsString = "SharedArrayBuffer"; }