4
4
5
5
//! Rust wrappers around the raw JS apis
6
6
7
- use libc:: { size_t, c_uint, c_char, ptrdiff_t } ;
7
+ use libc:: { size_t, c_uint, c_char} ;
8
8
use heapsize:: HeapSizeOf ;
9
9
use std:: char;
10
10
use std:: ffi;
@@ -13,7 +13,6 @@ use std::slice;
13
13
use std:: mem;
14
14
use std:: u32;
15
15
use std:: default:: Default ;
16
- use std:: intrinsics:: return_address;
17
16
use std:: ops:: { Deref , DerefMut } ;
18
17
use std:: cell:: UnsafeCell ;
19
18
use std:: marker:: PhantomData ;
@@ -26,7 +25,6 @@ use jsapi::{JS_SetErrorReporter, Evaluate2, JSErrorReport};
26
25
use jsapi:: { JS_SetGCParameter , JSGCParamKey } ;
27
26
use jsapi:: { Heap , HeapObjectPostBarrier , HeapValuePostBarrier } ;
28
27
use jsapi:: { ContextFriendFields } ;
29
- use jsapi:: { CustomAutoRooter , AutoGCRooter , _vftable_CustomAutoRooter, AutoGCRooter_jspubtd_h_unnamed_1 } ;
30
28
use jsapi:: { Rooted , Handle , MutableHandle , MutableHandleBase , RootedBase } ;
31
29
use jsapi:: { MutableHandleValue , HandleValue , HandleObject , HandleBase } ;
32
30
use jsapi:: AutoObjectVector ;
@@ -270,41 +268,103 @@ impl RootKind for Value {
270
268
fn rootKind ( ) -> jsapi:: RootKind { jsapi:: RootKind :: Value }
271
269
}
272
270
273
- impl < T : RootKind + Copy > Rooted < T > {
274
- pub fn new_with_addr ( cx : * mut JSContext , initial : T , addr : * const u8 ) -> Rooted < T > {
275
- let ctxfriend: & mut ContextFriendFields = unsafe {
276
- mem:: transmute ( cx)
277
- } ;
278
-
279
- let kind = T :: rootKind ( ) as usize ;
280
- let root = Rooted :: < T > {
271
+ impl < T > Rooted < T > {
272
+ pub fn new_unrooted ( initial : T ) -> Rooted < T > {
273
+ Rooted {
281
274
_base : RootedBase { _phantom0 : PhantomData } ,
282
- stack : & mut ctxfriend . roots . stackRoots_ [ kind ] as * mut _ as * mut _ ,
283
- prev : ctxfriend . roots . stackRoots_ [ kind ] as * mut _ ,
275
+ stack : ptr :: null_mut ( ) ,
276
+ prev : ptr :: null_mut ( ) ,
284
277
ptr : initial,
285
- } ;
278
+ }
279
+ }
280
+
281
+ pub unsafe fn add_to_root_stack ( & mut self , cx : * mut JSContext ) where T : RootKind {
282
+ let ctxfriend: & mut ContextFriendFields = mem:: transmute ( cx) ;
283
+
284
+ let kind = T :: rootKind ( ) as usize ;
285
+ self . stack = & mut ctxfriend. roots . stackRoots_ [ kind] as * mut _ as * mut _ ;
286
+ self . prev = ctxfriend. roots . stackRoots_ [ kind] as * mut _ ;
286
287
287
- ctxfriend. roots . stackRoots_ [ kind] = unsafe { mem:: transmute ( addr) } ;
288
- root
288
+ ctxfriend. roots . stackRoots_ [ kind] = self as * mut _ as usize as _ ;
289
289
}
290
290
291
- pub fn new ( cx : * mut JSContext , initial : T ) -> Rooted < T > {
292
- Rooted :: new_with_addr ( cx, initial, unsafe { return_address ( ) } )
291
+ pub unsafe fn remove_from_root_stack ( & mut self ) {
292
+ assert ! ( * self . stack == mem:: transmute( & * self ) ) ;
293
+ * self . stack = self . prev ;
293
294
}
295
+ }
294
296
295
- pub fn handle ( & self ) -> Handle < T > {
297
+ /// Rust API for keeping a Rooted value in the context's root stack.
298
+ /// Example usage: `rooted!(in(cx) let x = UndefinedValue());`.
299
+ /// `RootedGuard::new` also works, but the macro is preferred.
300
+ pub struct RootedGuard < ' a , T : ' a > {
301
+ root : & ' a mut Rooted < T >
302
+ }
303
+
304
+ impl < ' a , T > RootedGuard < ' a , T > {
305
+ pub fn new ( cx : * mut JSContext , root : & ' a mut Rooted < T > ) -> Self where T : RootKind {
296
306
unsafe {
297
- Handle :: from_marked_location ( & self . ptr )
307
+ root . add_to_root_stack ( cx ) ;
298
308
}
309
+ RootedGuard {
310
+ root : root
311
+ }
312
+ }
313
+
314
+ pub fn handle ( & self ) -> Handle < T > where T : Copy {
315
+ unsafe {
316
+ Handle :: from_marked_location ( & self . root . ptr )
317
+ }
318
+ }
319
+
320
+ pub fn handle_mut ( & mut self ) -> MutableHandle < T > where T : Copy {
321
+ unsafe {
322
+ MutableHandle :: from_marked_location ( & mut self . root . ptr )
323
+ }
324
+ }
325
+
326
+ pub fn get ( & self ) -> T where T : Copy {
327
+ self . root . ptr
328
+ }
329
+
330
+ pub fn set ( & mut self , v : T ) {
331
+ self . root . ptr = v;
332
+ }
333
+ }
334
+
335
+ impl < ' a , T > Deref for RootedGuard < ' a , T > {
336
+ type Target = T ;
337
+ fn deref ( & self ) -> & T {
338
+ & self . root . ptr
339
+ }
340
+ }
341
+
342
+ impl < ' a , T > DerefMut for RootedGuard < ' a , T > {
343
+ fn deref_mut ( & mut self ) -> & mut T {
344
+ & mut self . root . ptr
299
345
}
346
+ }
300
347
301
- pub fn handle_mut ( & mut self ) -> MutableHandle < T > {
348
+ impl < ' a , T > Drop for RootedGuard < ' a , T > {
349
+ fn drop ( & mut self ) {
302
350
unsafe {
303
- MutableHandle :: from_marked_location ( & mut self . ptr )
351
+ self . root . remove_from_root_stack ( ) ;
304
352
}
305
353
}
306
354
}
307
355
356
+ #[ macro_export]
357
+ macro_rules! rooted {
358
+ ( in( $cx: expr) let $name: ident = $init: expr) => {
359
+ let mut __root = $crate:: jsapi:: Rooted :: new_unrooted( $init) ;
360
+ let $name = $crate:: rust:: RootedGuard :: new( $cx, & mut __root) ;
361
+ } ;
362
+ ( in( $cx: expr) let mut $name: ident = $init: expr) => {
363
+ let mut __root = $crate:: jsapi:: Rooted :: new_unrooted( $init) ;
364
+ let mut $name = $crate:: rust:: RootedGuard :: new( $cx, & mut __root) ;
365
+ }
366
+ }
367
+
308
368
impl < T : Copy > Handle < T > {
309
369
pub fn get ( & self ) -> T {
310
370
unsafe { * self . ptr }
@@ -391,57 +451,6 @@ impl<T: Copy> MutableHandle<T> {
391
451
}
392
452
}
393
453
394
- impl < T > Drop for Rooted < T > {
395
- fn drop ( & mut self ) {
396
- unsafe {
397
- if self . stack as usize == mem:: POST_DROP_USIZE {
398
- return ;
399
- }
400
- assert ! ( * self . stack == mem:: transmute( & * self ) ) ;
401
- * self . stack = self . prev ;
402
- }
403
- }
404
- }
405
-
406
- impl CustomAutoRooter {
407
- pub fn new ( cx : * mut JSContext , vftable : & ' static _vftable_CustomAutoRooter )
408
- -> CustomAutoRooter {
409
- CustomAutoRooter :: new_with_addr ( cx, vftable, unsafe { return_address ( ) } )
410
- }
411
-
412
- pub fn new_with_addr ( cx : * mut JSContext , vftable : & ' static _vftable_CustomAutoRooter , addr : * const u8 ) -> CustomAutoRooter {
413
- let ctxfriend: & mut ContextFriendFields = unsafe {
414
- & mut * ( cx as * mut ContextFriendFields )
415
- } ;
416
-
417
- let rooter = CustomAutoRooter {
418
- _vftable : vftable as * const _ ,
419
- _base : AutoGCRooter {
420
- down : ctxfriend. roots . autoGCRooters_ ,
421
- tag_ : AutoGCRooter_jspubtd_h_unnamed_1 :: CUSTOM as ptrdiff_t ,
422
- stackTop : & mut ctxfriend. roots . autoGCRooters_ as * mut _ ,
423
- }
424
- } ;
425
-
426
- ctxfriend. roots . autoGCRooters_ = unsafe {
427
- ( addr as * const * const u8 ) . offset ( 1 ) as * const AutoGCRooter as * mut _
428
- } ;
429
- rooter
430
- }
431
- }
432
-
433
- impl Drop for CustomAutoRooter {
434
- fn drop ( & mut self ) {
435
- if self . _base . stackTop as usize == mem:: POST_DROP_USIZE {
436
- return ;
437
- }
438
- unsafe {
439
- assert ! ( * self . _base. stackTop == mem:: transmute( & self . _base) ) ;
440
- * self . _base . stackTop = self . _base . down ;
441
- }
442
- }
443
- }
444
-
445
454
impl Default for jsid {
446
455
fn default ( ) -> jsid { JSID_VOID }
447
456
}
0 commit comments