Skip to content

Commit 1dbda17

Browse files
committed
Cache global Crypto object
1 parent ae0c807 commit 1dbda17

File tree

2 files changed

+30
-35
lines changed

2 files changed

+30
-35
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ windows-targets = "0.52"
6464

6565
# wasm_js
6666
[target.'cfg(all(getrandom_backend = "wasm_js", target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dependencies]
67-
wasm-bindgen = { version = "0.2.96", default-features = false }
68-
js-sys = { version = "0.3.73", default-features = false }
67+
wasm-bindgen = { version = "0.2.98", default-features = false }
68+
js-sys = { version = "0.3.75", default-features = false }
6969
[target.'cfg(all(getrandom_backend = "wasm_js", target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dev-dependencies]
7070
wasm-bindgen-test = "0.3"
7171

src/backends/wasm_js.rs

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,47 @@ pub use crate::util::{inner_u32, inner_u64};
77
#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
88
compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!");
99

10-
use js_sys::{global, Uint8Array};
11-
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
10+
use js_sys::Uint8Array;
11+
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
1212

1313
// Size of our temporary Uint8Array buffer used with WebCrypto methods
1414
// Maximum is 65536 bytes see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
1515
const CRYPTO_BUFFER_SIZE: u16 = 256;
1616

1717
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
18-
let global: Global = global().unchecked_into();
19-
let crypto = global.crypto();
20-
21-
if !crypto.is_object() {
22-
return Err(Error::WEB_CRYPTO);
23-
}
24-
25-
// getRandomValues does not work with all types of WASM memory,
26-
// so we initially write to browser memory to avoid exceptions.
27-
let buf = Uint8Array::new_with_length(CRYPTO_BUFFER_SIZE.into());
28-
for chunk in dest.chunks_mut(CRYPTO_BUFFER_SIZE.into()) {
29-
let chunk_len: u32 = chunk
30-
.len()
31-
.try_into()
32-
.expect("chunk length is bounded by CRYPTO_BUFFER_SIZE");
33-
// The chunk can be smaller than buf's length, so we call to
34-
// JS to create a smaller view of buf without allocation.
35-
let sub_buf = buf.subarray(0, chunk_len);
36-
37-
if crypto.get_random_values(&sub_buf).is_err() {
38-
return Err(Error::WEB_GET_RANDOM_VALUES);
18+
CRYPTO.with(|crypto| {
19+
let crypto = crypto.as_ref().ok_or(Error::WEB_CRYPTO)?;
20+
21+
// getRandomValues does not work with all types of WASM memory,
22+
// so we initially write to browser memory to avoid exceptions.
23+
let buf = Uint8Array::new_with_length(CRYPTO_BUFFER_SIZE.into());
24+
for chunk in dest.chunks_mut(CRYPTO_BUFFER_SIZE.into()) {
25+
let chunk_len: u32 = chunk
26+
.len()
27+
.try_into()
28+
.expect("chunk length is bounded by CRYPTO_BUFFER_SIZE");
29+
// The chunk can be smaller than buf's length, so we call to
30+
// JS to create a smaller view of buf without allocation.
31+
let sub_buf = buf.subarray(0, chunk_len);
32+
33+
if crypto.get_random_values(&sub_buf).is_err() {
34+
return Err(Error::WEB_GET_RANDOM_VALUES);
35+
}
36+
37+
// SAFETY: `sub_buf`'s length is the same length as `chunk`
38+
unsafe { sub_buf.raw_copy_to_ptr(chunk.as_mut_ptr().cast::<u8>()) };
3939
}
40-
41-
// SAFETY: `sub_buf`'s length is the same length as `chunk`
42-
unsafe { sub_buf.raw_copy_to_ptr(chunk.as_mut_ptr().cast::<u8>()) };
43-
}
44-
Ok(())
40+
Ok(())
41+
})
4542
}
4643

4744
#[wasm_bindgen]
4845
extern "C" {
49-
// Return type of js_sys::global()
50-
type Global;
5146
// Web Crypto API: Crypto interface (https://www.w3.org/TR/WebCryptoAPI/)
5247
type Crypto;
53-
// Getters for the Crypto API
54-
#[wasm_bindgen(method, getter)]
55-
fn crypto(this: &Global) -> Crypto;
48+
// Holds the global `Crypto` object.
49+
#[wasm_bindgen(thread_local_v2, js_name = crypto)]
50+
static CRYPTO: Option<Crypto>;
5651
// Crypto.getRandomValues()
5752
#[wasm_bindgen(method, js_name = getRandomValues, catch)]
5853
fn get_random_values(this: &Crypto, buf: &Uint8Array) -> Result<(), JsValue>;

0 commit comments

Comments
 (0)