11use std:: marker:: PhantomData ;
2+ use std:: mem:: MaybeUninit ;
23use std:: ops:: { Deref , DerefMut } ;
34use std:: ptr;
45
56use 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 } ;
78
89use crate :: jsapi:: Handle as RawHandle ;
910use crate :: jsapi:: HandleValue as RawHandleValue ;
@@ -19,60 +20,69 @@ use mozjs_sys::jsgc::ValueArray;
1920 feature = "crown" ,
2021 crown:: unrooted_must_root_lint:: allow_unrooted_interior
2122) ]
22- pub struct RootedGuard < ' a , T : ' a + RootKind + Initialize > {
23+ pub struct RootedGuard < ' a , T : ' a + RootKind > {
2324 root : & ' a mut Rooted < T > ,
2425}
2526
26- impl < ' a , T : ' a + RootKind + Initialize > RootedGuard < ' a , T > {
27+ impl < ' a , T : ' a + RootKind > RootedGuard < ' a , T > {
2728 pub fn new ( cx : * mut JSContext , root : & ' a mut Rooted < T > , initial : T ) -> Self {
28- root. ptr = initial;
29+ root. ptr . write ( initial) ;
2930 unsafe {
3031 root. add_to_root_stack ( cx) ;
3132 }
3233 RootedGuard { root }
3334 }
3435
3536 pub fn handle ( & ' a self ) -> Handle < ' a , T > {
36- Handle :: new ( & self . root . ptr )
37+ Handle :: new ( & self )
3738 }
3839
3940 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 ( ) ) }
4142 }
4243
4344 pub fn get ( & self ) -> T
4445 where
4546 T : Copy ,
4647 {
47- self . root . ptr
48+ // SAFETY: The rooted value is initialized as long as we exist
49+ unsafe { self . root . ptr . assume_init ( ) }
4850 }
4951
5052 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) ;
5259 }
5360}
5461
55- impl < ' a , T : ' a + RootKind + Initialize > Deref for RootedGuard < ' a , T > {
62+ impl < ' a , T : ' a + RootKind > Deref for RootedGuard < ' a , T > {
5663 type Target = T ;
5764 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 ( ) }
5967 }
6068}
6169
62- impl < ' a , T : ' a + RootKind + Initialize > DerefMut for RootedGuard < ' a , T > {
70+ impl < ' a , T : ' a + RootKind > DerefMut for RootedGuard < ' a , T > {
6371 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 ( ) }
6574 }
6675}
6776
68- impl < ' a , T : ' a + RootKind + Initialize > Drop for RootedGuard < ' a , T > {
77+ impl < ' a , T : ' a + RootKind > Drop for RootedGuard < ' a , T > {
6978 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 ( )
7583 }
84+ self . root . ptr = MaybeUninit :: zeroed ( ) ;
85+
7686 unsafe {
7787 self . root . remove_from_root_stack ( ) ;
7888 }
0 commit comments