@@ -16,8 +16,8 @@ extern crate serde_json;
16
16
17
17
extern crate wasm_bindgen_macro;
18
18
19
- use core:: cell:: UnsafeCell ;
20
19
use core:: fmt;
20
+ use core:: marker;
21
21
use core:: mem;
22
22
use core:: ops:: { Deref , DerefMut } ;
23
23
use core:: ptr;
@@ -64,6 +64,7 @@ if_std! {
64
64
/// but for now it may be slightly slow.
65
65
pub struct JsValue {
66
66
idx : u32 ,
67
+ _marker : marker:: PhantomData < * mut u8 > , // not at all threadsafe
67
68
}
68
69
69
70
const JSIDX_UNDEFINED : u32 = 0 ;
@@ -74,18 +75,36 @@ const JSIDX_RESERVED: u32 = 8;
74
75
75
76
impl JsValue {
76
77
/// The `null` JS value constant.
77
- pub const NULL : JsValue = JsValue { idx : JSIDX_NULL } ;
78
+ pub const NULL : JsValue = JsValue {
79
+ idx : JSIDX_NULL ,
80
+ _marker : marker:: PhantomData ,
81
+ } ;
78
82
79
83
/// The `undefined` JS value constant.
80
84
pub const UNDEFINED : JsValue = JsValue {
81
85
idx : JSIDX_UNDEFINED ,
86
+ _marker : marker:: PhantomData ,
82
87
} ;
83
88
89
+
84
90
/// The `true` JS value constant.
85
- pub const TRUE : JsValue = JsValue { idx : JSIDX_TRUE } ;
91
+ pub const TRUE : JsValue = JsValue {
92
+ idx : JSIDX_TRUE ,
93
+ _marker : marker:: PhantomData ,
94
+ } ;
86
95
87
96
/// The `false` JS value constant.
88
- pub const FALSE : JsValue = JsValue { idx : JSIDX_FALSE } ;
97
+ pub const FALSE : JsValue = JsValue {
98
+ idx : JSIDX_FALSE ,
99
+ _marker : marker:: PhantomData ,
100
+ } ;
101
+
102
+ fn _new ( idx : u32 ) -> JsValue {
103
+ JsValue {
104
+ idx,
105
+ _marker : marker:: PhantomData ,
106
+ }
107
+ }
89
108
90
109
/// Creates a new JS value which is a string.
91
110
///
@@ -94,9 +113,7 @@ impl JsValue {
94
113
#[ inline]
95
114
pub fn from_str ( s : & str ) -> JsValue {
96
115
unsafe {
97
- JsValue {
98
- idx : __wbindgen_string_new ( s. as_ptr ( ) , s. len ( ) ) ,
99
- }
116
+ JsValue :: _new ( __wbindgen_string_new ( s. as_ptr ( ) , s. len ( ) ) )
100
117
}
101
118
}
102
119
@@ -107,9 +124,7 @@ impl JsValue {
107
124
#[ inline]
108
125
pub fn from_f64 ( n : f64 ) -> JsValue {
109
126
unsafe {
110
- JsValue {
111
- idx : __wbindgen_number_new ( n) ,
112
- }
127
+ JsValue :: _new ( __wbindgen_number_new ( n) )
113
128
}
114
129
}
115
130
@@ -142,9 +157,7 @@ impl JsValue {
142
157
unsafe {
143
158
let ptr = description. map ( |s| s. as_ptr ( ) ) . unwrap_or ( ptr:: null ( ) ) ;
144
159
let len = description. map ( |s| s. len ( ) ) . unwrap_or ( 0 ) ;
145
- JsValue {
146
- idx : __wbindgen_symbol_new ( ptr, len) ,
147
- }
160
+ JsValue :: _new ( __wbindgen_symbol_new ( ptr, len) )
148
161
}
149
162
}
150
163
@@ -170,9 +183,7 @@ impl JsValue {
170
183
{
171
184
let s = serde_json:: to_string ( t) ?;
172
185
unsafe {
173
- Ok ( JsValue {
174
- idx : __wbindgen_json_parse ( s. as_ptr ( ) , s. len ( ) ) ,
175
- } )
186
+ Ok ( JsValue :: _new ( __wbindgen_json_parse ( s. as_ptr ( ) , s. len ( ) ) ) )
176
187
}
177
188
}
178
189
@@ -486,7 +497,7 @@ impl Clone for JsValue {
486
497
fn clone ( & self ) -> JsValue {
487
498
unsafe {
488
499
let idx = __wbindgen_object_clone_ref ( self . idx ) ;
489
- JsValue { idx }
500
+ JsValue :: _new ( idx)
490
501
}
491
502
}
492
503
}
@@ -552,43 +563,26 @@ impl Drop for JsValue {
552
563
///
553
564
/// This type implements `Deref` to the inner type so it's typically used as if
554
565
/// it were `&T`.
566
+ #[ cfg( feature = "std" ) ]
555
567
pub struct JsStatic < T : ' static > {
556
568
#[ doc( hidden) ]
557
- pub __inner : & ' static UnsafeCell < Option < T > > ,
558
- #[ doc( hidden) ]
559
- pub __init : fn ( ) -> T ,
569
+ pub __inner : & ' static std:: thread:: LocalKey < T > ,
560
570
}
561
571
562
- unsafe impl < T : Sync > Sync for JsStatic < T > { }
563
- unsafe impl < T : Send > Send for JsStatic < T > { }
564
-
572
+ #[ cfg( feature = "std" ) ]
565
573
impl < T : FromWasmAbi + ' static > Deref for JsStatic < T > {
566
574
type Target = T ;
567
575
fn deref ( & self ) -> & T {
576
+ // We know that our tls key is never overwritten after initialization,
577
+ // so it should be safe (on that axis at least) to hand out a reference
578
+ // that lives longer than the closure below.
579
+ //
580
+ // FIXME: this is not sound if we ever implement thread exit hooks on
581
+ // wasm, as the pointer will eventually be invalidated but you can get
582
+ // `&'static T` from this interface. We... probably need to deprecate
583
+ // and/or remove this interface nowadays.
568
584
unsafe {
569
- // Ideally we want to use `get_or_insert_with` here but
570
- // unfortunately that has subpar codegen for now.
571
- //
572
- // If we get past the `Some` branch here LLVM statically
573
- // knows that we're `None`, but the after the call to the `__init`
574
- // function LLVM can no longer know this because `__init` could
575
- // recursively call this function again (aka if JS came back to Rust
576
- // and Rust referenced this static).
577
- //
578
- // We know, however, that cannot happen. As a result we can
579
- // conclude that even after the call to `__init` our `ptr` still
580
- // points to `None` (and a debug assertion to this effect). Then
581
- // using `ptr::write` should tell rustc to not run destuctors
582
- // (as one isn't there) and this should tighten up codegen for
583
- // `JsStatic` a bit as well.
584
- let ptr = self . __inner . get ( ) ;
585
- if let Some ( ref t) = * ptr {
586
- return t;
587
- }
588
- let init = Some ( ( self . __init ) ( ) ) ;
589
- debug_assert ! ( ( * ptr) . is_none( ) ) ;
590
- ptr:: write ( ptr, init) ;
591
- ( * ptr) . as_ref ( ) . unwrap ( )
585
+ self . __inner . with ( |ptr| & * ( ptr as * const T ) )
592
586
}
593
587
}
594
588
}
@@ -642,9 +636,7 @@ pub fn throw_val(s: JsValue) -> ! {
642
636
/// Returns a handle to this wasm instance's `WebAssembly.Memory`
643
637
pub fn memory ( ) -> JsValue {
644
638
unsafe {
645
- JsValue {
646
- idx : __wbindgen_memory ( ) ,
647
- }
639
+ JsValue :: _new ( __wbindgen_memory ( ) )
648
640
}
649
641
}
650
642
0 commit comments