99#[ cfg( not( all( target_arch = "wasm32" , target_os = "unknown" ) ) ) ]
1010compile_error ! ( "This crate is only for the `wasm32-unknown-unknown` target" ) ;
1111
12- use core:: cell:: RefCell ;
1312use std:: thread_local;
1413
1514use wasm_bindgen:: prelude:: * ;
1615
1716use getrandom:: { register_custom_getrandom, Error } ;
1817
19- #[ derive( Clone , Debug ) ]
2018enum RngSource {
2119 Node ( NodeCrypto ) ,
2220 Browser ( BrowserCrypto ) ,
@@ -25,20 +23,21 @@ enum RngSource {
2523// JsValues are always per-thread, so we initialize RngSource for each thread.
2624// See: https://github.com/rustwasm/wasm-bindgen/pull/955
2725thread_local ! (
28- static RNG_SOURCE : RefCell < Option < RngSource >> = RefCell :: new ( None ) ;
26+ static RNG_SOURCE : Result < RngSource , Error > = getrandom_init ( ) ;
2927) ;
3028
3129register_custom_getrandom ! ( getrandom_inner) ;
3230
3331fn getrandom_inner ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
34- RNG_SOURCE . with ( |f| {
35- let mut source = f. borrow_mut ( ) ;
36- if source. is_none ( ) {
37- * source = Some ( getrandom_init ( ) ?) ;
38- }
39-
40- match source. as_ref ( ) . unwrap ( ) {
41- RngSource :: Node ( n) => n. random_fill_sync ( dest) ,
32+ RNG_SOURCE . with ( |result| {
33+ let source = result. as_ref ( ) . map_err ( |& e| e) ?;
34+
35+ match source {
36+ RngSource :: Node ( n) => {
37+ if n. random_fill_sync ( dest) . is_err ( ) {
38+ return Err ( Error :: NODE_RANDOM_FILL_SYNC ) ;
39+ }
40+ }
4241 RngSource :: Browser ( n) => {
4342 // see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
4443 //
@@ -47,7 +46,9 @@ fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
4746 // > A QuotaExceededError DOMException is thrown if the
4847 // > requested length is greater than 65536 bytes.
4948 for chunk in dest. chunks_mut ( 65536 ) {
50- n. get_random_values ( chunk)
49+ if n. get_random_values ( chunk) . is_err ( ) {
50+ return Err ( Error :: WEB_GET_RANDOM_VALUES ) ;
51+ }
5152 }
5253 }
5354 } ;
@@ -63,20 +64,15 @@ fn getrandom_init() -> Result<RngSource, Error> {
6364 // assume we're in an older web browser and the OS RNG isn't available.
6465
6566 let crypto: BrowserCrypto = match ( self_. crypto ( ) , self_. ms_crypto ( ) ) {
66- ( crypto, _) if !crypto. is_undefined ( ) => crypto. into ( ) ,
67- ( _, crypto) if !crypto. is_undefined ( ) => crypto. into ( ) ,
68- _ => return Err ( Error :: BINDGEN_CRYPTO_UNDEF ) ,
67+ ( crypto, _) if !crypto. is_undefined ( ) => crypto,
68+ ( _, crypto) if !crypto. is_undefined ( ) => crypto,
69+ _ => return Err ( Error :: WEB_CRYPTO ) ,
6970 } ;
70-
71- // Test if `crypto.getRandomValues` is undefined as well
72- if crypto. get_random_values_fn ( ) . is_undefined ( ) {
73- return Err ( Error :: BINDGEN_GRV_UNDEF ) ;
74- }
75-
7671 return Ok ( RngSource :: Browser ( crypto) ) ;
7772 }
7873
79- return Ok ( RngSource :: Node ( MODULE . require ( "crypto" ) ) ) ;
74+ let crypto = MODULE . require ( "crypto" ) . map_err ( |_| Error :: NODE_CRYPTO ) ?;
75+ Ok ( RngSource :: Node ( crypto) )
8076}
8177
8278#[ wasm_bindgen]
@@ -86,33 +82,23 @@ extern "C" {
8682 fn get_self ( ) -> Result < Self_ , JsValue > ;
8783
8884 type Self_ ;
89- #[ wasm_bindgen( method, getter, js_name = "msCrypto" , structural ) ]
90- fn ms_crypto ( me : & Self_ ) -> JsValue ;
91- #[ wasm_bindgen( method, getter, structural ) ]
92- fn crypto ( me : & Self_ ) -> JsValue ;
85+ #[ wasm_bindgen( method, getter, js_name = "msCrypto" ) ]
86+ fn ms_crypto ( me : & Self_ ) -> BrowserCrypto ;
87+ #[ wasm_bindgen( method, getter) ]
88+ fn crypto ( me : & Self_ ) -> BrowserCrypto ;
9389
94- #[ derive( Clone , Debug ) ]
9590 type BrowserCrypto ;
96-
97- // TODO: these `structural` annotations here ideally wouldn't be here to
98- // avoid a JS shim, but for now with feature detection they're
99- // unavoidable.
100- #[ wasm_bindgen( method, js_name = getRandomValues, structural, getter) ]
101- fn get_random_values_fn ( me : & BrowserCrypto ) -> JsValue ;
102- #[ wasm_bindgen( method, js_name = getRandomValues, structural) ]
103- fn get_random_values ( me : & BrowserCrypto , buf : & mut [ u8 ] ) ;
104-
105- #[ derive( Clone , Debug ) ]
106- type NodeCrypto ;
107-
108- #[ wasm_bindgen( method, js_name = randomFillSync, structural) ]
109- fn random_fill_sync ( me : & NodeCrypto , buf : & mut [ u8 ] ) ;
110-
111- type NodeModule ;
91+ #[ wasm_bindgen( method, js_name = getRandomValues, catch) ]
92+ fn get_random_values ( me : & BrowserCrypto , buf : & mut [ u8 ] ) -> Result < ( ) , JsValue > ;
11293
11394 #[ wasm_bindgen( js_name = module) ]
11495 static MODULE : NodeModule ;
11596
116- #[ wasm_bindgen( method) ]
117- fn require ( this : & NodeModule , s : & str ) -> NodeCrypto ;
97+ type NodeModule ;
98+ #[ wasm_bindgen( method, catch) ]
99+ fn require ( this : & NodeModule , s : & str ) -> Result < NodeCrypto , JsValue > ;
100+
101+ type NodeCrypto ;
102+ #[ wasm_bindgen( method, js_name = randomFillSync, catch) ]
103+ fn random_fill_sync ( crypto : & NodeCrypto , buf : & mut [ u8 ] ) -> Result < ( ) , JsValue > ;
118104}
0 commit comments