@@ -7,52 +7,47 @@ pub use crate::util::{inner_u32, inner_u64};
7
7
#[ cfg( not( all( target_arch = "wasm32" , any( target_os = "unknown" , target_os = "none" ) ) ) ) ]
8
8
compile_error ! ( "`wasm_js` backend can be enabled only for OS-less WASM targets!" ) ;
9
9
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 } ;
12
12
13
13
// Size of our temporary Uint8Array buffer used with WebCrypto methods
14
14
// Maximum is 65536 bytes see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
15
15
const CRYPTO_BUFFER_SIZE : u16 = 256 ;
16
16
17
17
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 > ( ) ) } ;
39
39
}
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
+ } )
45
42
}
46
43
47
44
#[ wasm_bindgen]
48
45
extern "C" {
49
- // Return type of js_sys::global()
50
- type Global ;
51
46
// Web Crypto API: Crypto interface (https://www.w3.org/TR/WebCryptoAPI/)
52
47
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 > ;
56
51
// Crypto.getRandomValues()
57
52
#[ wasm_bindgen( method, js_name = getRandomValues, catch) ]
58
53
fn get_random_values ( this : & Crypto , buf : & Uint8Array ) -> Result < ( ) , JsValue > ;
0 commit comments