diff --git a/Cargo.toml b/Cargo.toml index 97071e3a4c..231c377767 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -176,6 +176,8 @@ once_cell = { version = "1.8.0", default-features = false, features=["std"] } [target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", target_env = ""))'.dependencies] web-sys = { version = "0.3.51", default-features = false, features = ["Crypto", "Window"], optional = true } +wasm-bindgen = { version = "0.2.80" } +js-sys = { version = "0.3.51" } [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3.9", default-features = false, features = ["ntsecapi", "wtypesbase", "processthreadsapi"] } diff --git a/src/rand.rs b/src/rand.rs index e7ebece216..4ca9fee312 100644 --- a/src/rand.rs +++ b/src/rand.rs @@ -238,6 +238,20 @@ mod sysrand_chunk { ))] mod sysrand_chunk { use crate::error; + use js_sys::Reflect; + use wasm_bindgen::{JsValue, JsCast}; + use web_sys::Crypto; + + /** + * Gets a handle to Crypto in both normal and worker environments. Based on + * the discussion in https://github.com/rustwasm/wasm-bindgen/issues/2148 + * and the approach taken here: https://github.com/devashishdxt/rexie/commit/8637e4ebc2d2dfc6b33cd60dc85b99e46d6afa96 + */ + fn get_crypto() -> Result { + Reflect::get(&js_sys::global(), &JsValue::from("crypto")) + .map_err(|_| error::Unspecified)? + .dyn_into::().map_err(|_| error::Unspecified) + } pub fn chunk(mut dest: &mut [u8]) -> Result { // This limit is specified in @@ -247,10 +261,9 @@ mod sysrand_chunk { dest = &mut dest[..MAX_LEN]; }; - let _ = web_sys::window() - .ok_or(error::Unspecified)? - .crypto() - .map_err(|_| error::Unspecified)? + let crypto = get_crypto()?; + + let _ = crypto .get_random_values_with_u8_array(dest) .map_err(|_| error::Unspecified)?;