@@ -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" ) ) ) ) ]
88compile_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
1515const CRYPTO_BUFFER_SIZE : u16 = 256 ;
1616
1717pub 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]
4845extern "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