Skip to content

Commit aee9640

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

File tree

3 files changed

+60
-47
lines changed

3 files changed

+60
-47
lines changed

.github/workflows/tests.yml

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -234,44 +234,56 @@ jobs:
234234
steps:
235235
- uses: actions/checkout@v4
236236
- uses: dtolnay/rust-toolchain@stable
237-
- name: Install precompiled wasm-pack
238-
shell: bash
239-
run: |
240-
VERSION=v0.13.1
241-
URL=https://github.com/rustwasm/wasm-pack/releases/download/${VERSION}/wasm-pack-${VERSION}-x86_64-unknown-linux-musl.tar.gz
242-
wget -O - $URL | tar -xz --strip-components=1 -C ~/.cargo/bin
243-
wasm-pack --version
237+
with:
238+
targets: wasm32-unknown-unknown
239+
# - name: Install precompiled wasm-bindgen
240+
# shell: bash
241+
# run: |
242+
# VERSION=v0.2.97
243+
# URL=https://github.com/rustwasm/wasm-bindgen/releases/download/${VERSION}/wasm-bindgen-${VERSION}-x86_64-unknown-linux-musl.tar.gz
244+
# wget -O - $URL | tar -xz --strip-components=1 -C ~/.cargo/bin
245+
# wasm-bindgen --version
246+
- uses: taiki-e/cache-cargo-install-action@v2
247+
with:
248+
tool: wasm-bindgen-cli
249+
git: https://github.com/daxpedda/wasm-bindgen
250+
rev: 82fe725521ab1b95226408027530b3357919d6be
244251
- uses: Swatinem/rust-cache@v2
245252
- name: Test (Node)
246253
env:
247254
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
248-
run: wasm-pack test --node -- --features std
255+
run: cargo test --target wasm32-unknown-unknown --features std
249256
- name: Test (Firefox)
250257
env:
258+
GECKODRIVER: geckodriver
251259
WASM_BINDGEN_USE_BROWSER: 1
252260
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
253-
run: wasm-pack test --headless --firefox -- --features std
261+
run: cargo test --target wasm32-unknown-unknown --features std
254262
- name: Test (Chrome)
255263
env:
264+
CHROMEDRIVER: chromedriver
256265
WASM_BINDGEN_USE_BROWSER: 1
257266
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
258-
run: wasm-pack test --headless --chrome -- --features std
267+
run: cargo test --target wasm32-unknown-unknown --features std
259268
- name: Test (dedicated worker)
260269
env:
270+
GECKODRIVER: geckodriver
261271
WASM_BINDGEN_USE_DEDICATED_WORKER: 1
262272
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
263-
run: wasm-pack test --headless --firefox -- --features std
273+
run: cargo test --target wasm32-unknown-unknown --features std
264274
- name: Test (shared worker)
265275
env:
276+
GECKODRIVER: geckodriver
266277
WASM_BINDGEN_USE_SHARED_WORKER: 1
267278
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
268-
run: wasm-pack test --headless --firefox -- --features std
279+
run: cargo test --target wasm32-unknown-unknown --features std
269280
- name: Test (service worker)
270281
env:
282+
# Firefox doesn't support module service workers and therefor can't import scripts
283+
CHROMEDRIVER: chromedriver
271284
WASM_BINDGEN_USE_SERVICE_WORKER: 1
272285
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
273-
# Firefox doesn't support module service workers and therefor can't import scripts
274-
run: wasm-pack test --headless --chrome -- --features std
286+
run: cargo test --target wasm32-unknown-unknown --features std
275287

276288
wasi:
277289
name: WASI

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,8 @@ pre-build = [
9999
"rm base.tar.xz",
100100
"rm -rf /tmp/netbsd",
101101
]
102+
103+
[patch.crates-io]
104+
wasm-bindgen = { git = "https://github.com/daxpedda/wasm-bindgen", branch = "getrandom" }
105+
js-sys = { git = "https://github.com/daxpedda/wasm-bindgen", branch = "getrandom" }
106+
wasm-bindgen-test = { git = "https://github.com/daxpedda/wasm-bindgen", branch = "getrandom" }

src/backends/wasm_js.rs

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Implementation for WASM based on Web and Node.js
2+
23
use crate::Error;
34
use core::mem::MaybeUninit;
45

@@ -7,52 +8,47 @@ pub use crate::util::{inner_u32, inner_u64};
78
#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
89
compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!");
910

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

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

1718
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);
19+
CRYPTO.with(|crypto| {
20+
let crypto = crypto.as_ref().ok_or(Error::WEB_CRYPTO)?;
21+
22+
// getRandomValues does not work with all types of WASM memory,
23+
// so we initially write to browser memory to avoid exceptions.
24+
let buf = Uint8Array::new_with_length(CRYPTO_BUFFER_SIZE.into());
25+
for chunk in dest.chunks_mut(CRYPTO_BUFFER_SIZE.into()) {
26+
let chunk_len: u32 = chunk
27+
.len()
28+
.try_into()
29+
.expect("chunk length is bounded by CRYPTO_BUFFER_SIZE");
30+
// The chunk can be smaller than buf's length, so we call to
31+
// JS to create a smaller view of buf without allocation.
32+
let sub_buf = buf.subarray(0, chunk_len);
33+
34+
if crypto.get_random_values(&sub_buf).is_err() {
35+
return Err(Error::WEB_GET_RANDOM_VALUES);
36+
}
37+
38+
// SAFETY: `sub_buf`'s length is the same length as `chunk`
39+
unsafe { sub_buf.raw_copy_to_ptr(chunk.as_mut_ptr().cast::<u8>()) };
3940
}
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(())
41+
Ok(())
42+
})
4543
}
4644

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

0 commit comments

Comments
 (0)