1
1
use std:: marker:: PhantomData ;
2
+ use std:: mem:: MaybeUninit ;
2
3
use std:: ops:: { Deref , DerefMut } ;
3
4
use std:: ptr;
4
5
5
6
use crate :: jsapi:: { jsid, JSContext , JSFunction , JSObject , JSScript , JSString , Symbol , Value , JS } ;
6
- use mozjs_sys:: jsgc:: { Initialize , RootKind , Rooted } ;
7
+ use mozjs_sys:: jsgc:: { RootKind , Rooted } ;
7
8
8
9
use crate :: jsapi:: Handle as RawHandle ;
9
10
use crate :: jsapi:: HandleValue as RawHandleValue ;
@@ -19,60 +20,69 @@ use mozjs_sys::jsgc::ValueArray;
19
20
feature = "crown" ,
20
21
crown:: unrooted_must_root_lint:: allow_unrooted_interior
21
22
) ]
22
- pub struct RootedGuard < ' a , T : ' a + RootKind + Initialize > {
23
+ pub struct RootedGuard < ' a , T : ' a + RootKind > {
23
24
root : & ' a mut Rooted < T > ,
24
25
}
25
26
26
- impl < ' a , T : ' a + RootKind + Initialize > RootedGuard < ' a , T > {
27
+ impl < ' a , T : ' a + RootKind > RootedGuard < ' a , T > {
27
28
pub fn new ( cx : * mut JSContext , root : & ' a mut Rooted < T > , initial : T ) -> Self {
28
- root. ptr = initial;
29
+ root. ptr . write ( initial) ;
29
30
unsafe {
30
31
root. add_to_root_stack ( cx) ;
31
32
}
32
33
RootedGuard { root }
33
34
}
34
35
35
36
pub fn handle ( & ' a self ) -> Handle < ' a , T > {
36
- Handle :: new ( & self . root . ptr )
37
+ Handle :: new ( & self )
37
38
}
38
39
39
40
pub fn handle_mut ( & mut self ) -> MutableHandle < T > {
40
- unsafe { MutableHandle :: from_marked_location ( & mut self . root . ptr ) }
41
+ unsafe { MutableHandle :: from_marked_location ( self . deref_mut ( ) ) }
41
42
}
42
43
43
44
pub fn get ( & self ) -> T
44
45
where
45
46
T : Copy ,
46
47
{
47
- self . root . ptr
48
+ // SAFETY: The rooted value is initialized as long as we exist
49
+ unsafe { self . root . ptr . assume_init ( ) }
48
50
}
49
51
50
52
pub fn set ( & mut self , v : T ) {
51
- self . root . ptr = v;
53
+ // SAFETY: The rooted value is initialized as long as we exist
54
+ unsafe {
55
+ // Make sure the drop impl for T is called
56
+ self . root . ptr . assume_init_drop ( )
57
+ }
58
+ self . root . ptr . write ( v) ;
52
59
}
53
60
}
54
61
55
- impl < ' a , T : ' a + RootKind + Initialize > Deref for RootedGuard < ' a , T > {
62
+ impl < ' a , T : ' a + RootKind > Deref for RootedGuard < ' a , T > {
56
63
type Target = T ;
57
64
fn deref ( & self ) -> & T {
58
- & self . root . ptr
65
+ // SAFETY: The rooted value is initialized as long as we exist
66
+ unsafe { self . root . ptr . assume_init_ref ( ) }
59
67
}
60
68
}
61
69
62
- impl < ' a , T : ' a + RootKind + Initialize > DerefMut for RootedGuard < ' a , T > {
70
+ impl < ' a , T : ' a + RootKind > DerefMut for RootedGuard < ' a , T > {
63
71
fn deref_mut ( & mut self ) -> & mut T {
64
- & mut self . root . ptr
72
+ // SAFETY: The rooted value is initialized as long as we exist
73
+ unsafe { self . root . ptr . assume_init_mut ( ) }
65
74
}
66
75
}
67
76
68
- impl < ' a , T : ' a + RootKind + Initialize > Drop for RootedGuard < ' a , T > {
77
+ impl < ' a , T : ' a + RootKind > Drop for RootedGuard < ' a , T > {
69
78
fn drop ( & mut self ) {
70
- // SAFETY:
71
- // All implementations are expected to return meaningful defaults that
72
- // do not contain non-default GC pointers.
73
- if let Some ( val) = unsafe { T :: initial ( ) } {
74
- self . root . ptr = val;
79
+ // SAFETY: The rooted value is initialized as long as we exist
80
+ unsafe {
81
+ // Make sure the drop impl for T is called
82
+ self . root . ptr . assume_init_drop ( )
75
83
}
84
+ self . root . ptr = MaybeUninit :: zeroed ( ) ;
85
+
76
86
unsafe {
77
87
self . root . remove_from_root_stack ( ) ;
78
88
}
0 commit comments