Skip to content

Commit 37db8c1

Browse files
committed
Implement no_std support for Wasm
1 parent 69b3536 commit 37db8c1

File tree

5 files changed

+61
-14
lines changed

5 files changed

+61
-14
lines changed

.github/workflows/tests.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -257,15 +257,15 @@ jobs:
257257
- name: Test (Node)
258258
env:
259259
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
260-
run: wasm-pack test --node
260+
run: wasm-pack test --node -- --features std
261261
- name: Test (Firefox)
262262
env:
263263
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
264-
run: wasm-pack test --headless --firefox
264+
run: wasm-pack test --headless --firefox -- --features std
265265
- name: Test (Chrome)
266266
env:
267267
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" --cfg getrandom_browser_test
268-
run: wasm-pack test --headless --chrome
268+
run: wasm-pack test --headless --chrome -- --features std
269269

270270
wasi:
271271
name: WASI

.github/workflows/workspace.yml

+10-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
# Fixed Nigthly version is used to prevent
2424
# CI failures which are not relevant to PR changes
2525
# on introduction of new Clippy lints.
26-
toolchain: nightly-2024-10-08
26+
toolchain: nightly-2024-10-24
2727
components: clippy,rust-src
2828
- name: std feature
2929
run: cargo clippy --features std
@@ -48,7 +48,15 @@ jobs:
4848
- name: Web WASM (wasm_js.rs)
4949
env:
5050
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
51-
run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown
51+
run: cargo clippy --features std -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
52+
- name: Web WASM no_std (wasm_js.rs)
53+
env:
54+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
55+
run: cargo clippy -Zbuild-std=core,alloc --target wasm32-unknown-unknown
56+
- name: Web WASM no_std with atomics (wasm_js.rs)
57+
env:
58+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory
59+
run: cargo clippy -Zbuild-std=core,alloc --target wasm32-unknown-unknown
5260
- name: Linux (linux_android.rs)
5361
env:
5462
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"

Cargo.toml

+5-4
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,16 @@ windows-targets = "0.52"
6464

6565
# wasm_js
6666
[target.'cfg(all(getrandom_backend = "wasm_js", target_arch = "wasm32", target_os = "unknown"))'.dependencies]
67-
wasm-bindgen = { version = "0.2.89", default-features = false }
68-
js-sys = "0.3"
67+
wasm-bindgen = { version = "0.2.96", default-features = false }
68+
js-sys = { version = "0.3.73", default-features = false }
69+
once_cell = { version = "1", default-features = false }
6970
[target.'cfg(all(getrandom_backend = "wasm_js", getrandom_browser_test, target_arch = "wasm32", target_os = "unknown"))'.dev-dependencies]
70-
wasm-bindgen-test = "0.3.39"
71+
wasm-bindgen-test = { version = "0.3", default-features = false }
7172

7273
[features]
7374
# Implement std::error::Error for getrandom::Error and
7475
# use std to retrieve OS error descriptions
75-
std = []
76+
std = ["wasm-bindgen/std", "js-sys/std", "wasm-bindgen-test/std"]
7677
# Unstable feature to support being a libstd dependency
7778
rustc-dep-of-std = ["compiler_builtins", "core"]
7879

src/backends/wasm_js.rs

+33-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
//! Implementation for WASM based on Web and Node.js
22
use crate::Error;
33

4+
#[cfg(feature = "std")]
45
extern crate std;
5-
use std::{mem::MaybeUninit, thread_local};
6+
use core::mem::MaybeUninit;
67

78
pub use crate::util::{inner_u32, inner_u64};
89

910
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown",)))]
1011
compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!");
1112

1213
use js_sys::{global, Function, Uint8Array};
14+
#[cfg(not(feature = "std"))]
15+
use once_cell::unsync::Lazy;
1316
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
1417

1518
// Size of our temporary Uint8Array buffer used with WebCrypto methods
@@ -25,12 +28,37 @@ enum RngSource {
2528

2629
// JsValues are always per-thread, so we initialize RngSource for each thread.
2730
// See: https://github.com/rustwasm/wasm-bindgen/pull/955
28-
thread_local!(
29-
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
30-
);
31+
struct Local;
32+
33+
impl Local {
34+
#[cfg(feature = "std")]
35+
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
36+
std::thread_local!(
37+
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
38+
);
39+
RNG_SOURCE.with(f)
40+
}
41+
42+
#[cfg(all(not(feature = "std"), not(target_feature = "atomics")))]
43+
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
44+
struct Wrapper<T>(T);
45+
unsafe impl<T> Send for Wrapper<T> {}
46+
unsafe impl<T> Sync for Wrapper<T> {}
47+
static RNG_SOURCE: Wrapper<Lazy<Result<RngSource, Error>>> =
48+
Wrapper(Lazy::new(getrandom_init));
49+
f(&RNG_SOURCE.0)
50+
}
51+
52+
#[cfg(all(not(feature = "std"), target_feature = "atomics"))]
53+
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
54+
#[thread_local]
55+
static RNG_SOURCE: Lazy<Result<RngSource, Error>> = Lazy::new(getrandom_init);
56+
f(&RNG_SOURCE)
57+
}
58+
}
3159

3260
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
33-
RNG_SOURCE.with(|result| {
61+
Local::with(|result| {
3462
let source = result.as_ref().map_err(|&e| e)?;
3563

3664
match source {

src/lib.rs

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
1212
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
1313
#![cfg_attr(getrandom_sanitize, feature(cfg_sanitize))]
14+
#![cfg_attr(
15+
all(
16+
getrandom_backend = "wasm_js",
17+
any(target_arch = "wasm32", target_arch = "wasm64"),
18+
target_os = "unknown",
19+
not(feature = "std"),
20+
target_feature = "atomics"
21+
),
22+
feature(thread_local)
23+
)]
1424
#![deny(
1525
clippy::cast_lossless,
1626
clippy::cast_possible_truncation,

0 commit comments

Comments
 (0)