9
9
#[ cfg( not( all( target_arch = "wasm32" , target_os = "unknown" ) ) ) ]
10
10
compile_error ! ( "This crate is only for the `wasm32-unknown-unknown` target" ) ;
11
11
12
- use core:: cell:: RefCell ;
13
12
use std:: thread_local;
14
13
15
14
use wasm_bindgen:: prelude:: * ;
16
15
17
16
use getrandom:: { register_custom_getrandom, Error } ;
18
17
19
- #[ derive( Clone , Debug ) ]
20
18
enum RngSource {
21
19
Node ( NodeCrypto ) ,
22
20
Browser ( BrowserCrypto ) ,
@@ -25,20 +23,21 @@ enum RngSource {
25
23
// JsValues are always per-thread, so we initialize RngSource for each thread.
26
24
// See: https://github.com/rustwasm/wasm-bindgen/pull/955
27
25
thread_local ! (
28
- static RNG_SOURCE : RefCell < Option < RngSource >> = RefCell :: new ( None ) ;
26
+ static RNG_SOURCE : Result < RngSource , Error > = getrandom_init ( ) ;
29
27
) ;
30
28
31
29
register_custom_getrandom ! ( getrandom_inner) ;
32
30
33
31
fn 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
+ }
42
41
RngSource :: Browser ( n) => {
43
42
// see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
44
43
//
@@ -47,7 +46,9 @@ fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
47
46
// > A QuotaExceededError DOMException is thrown if the
48
47
// > requested length is greater than 65536 bytes.
49
48
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
+ }
51
52
}
52
53
}
53
54
} ;
@@ -63,20 +64,15 @@ fn getrandom_init() -> Result<RngSource, Error> {
63
64
// assume we're in an older web browser and the OS RNG isn't available.
64
65
65
66
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 ) ,
69
70
} ;
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
-
76
71
return Ok ( RngSource :: Browser ( crypto) ) ;
77
72
}
78
73
79
- return Ok ( RngSource :: Node ( MODULE . require ( "crypto" ) ) ) ;
74
+ let crypto = MODULE . require ( "crypto" ) . map_err ( |_| Error :: NODE_CRYPTO ) ?;
75
+ Ok ( RngSource :: Node ( crypto) )
80
76
}
81
77
82
78
#[ wasm_bindgen]
@@ -86,33 +82,23 @@ extern "C" {
86
82
fn get_self ( ) -> Result < Self_ , JsValue > ;
87
83
88
84
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 ;
93
89
94
- #[ derive( Clone , Debug ) ]
95
90
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 > ;
112
93
113
94
#[ wasm_bindgen( js_name = module) ]
114
95
static MODULE : NodeModule ;
115
96
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 > ;
118
104
}
0 commit comments