jstraceable_derive

Derive Macro JSTraceable

source
#[derive(JSTraceable)]
{
    // Attributes available to this derive:
    #[no_trace]
    #[custom_trace]
}
Expand description

Implements JSTraceable on structs and enums

Example:

#[derive(JSTraceable)]
struct S {
  js_managed: JSManagedType,
  #[no_trace]
  non_js: NonJSManagedType,
  #[custom_trace] // Extern type implements CustomTraceable that is in servo => no problem with orphan rules
  extern_managed_type: Extern<JSManagedType>,
}

creates:

unsafe impl JSTraceable for S {
    #[inline]
    unsafe fn trace(&self, tracer: *mut js::jsapi::JSTracer) {
        match *self {
            S {
                js_managed: ref __binding_0,
                non_js: ref __binding_1,
                extern_managed_type: ref __binding_2,
            } => {
                {
                    __binding_0.trace(tracer);
                }
                {
                    // __binding_1 is not traceable so we do not need to trace it
                }
                {
                    <crate::dom::bindings::trace::CustomTraceable>::trace(__binding_2, tracer);
                }
            },
        }
    }
}

In cases where there is a need to make type (empty) traceable (HashMap<NoTraceable, Traceable>), NoTrace wrapper can be used, because it implements empty traceble:

unsafe impl<T> JSTraceable for NoTrace<T> {
    unsafe fn trace(&self, _: *mut ::js::jsapi::JSTracer) { /* nop */}
}

ยงSAFETY

Puting #[no_trace] on fields is safe if there are no types that are JS managed in that field. #[no_trace] should NOT be put on field that does implement (non-empty) JSTraceable (is JS managed). There are safeguards in place to prevent such mistakes. Example error:

error[E0282]: type annotations needed
|
| #[derive(JSTraceable, MallocSizeOf)]
|          ^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `NoTraceOnJSTraceable`
|
= note: this error originates in the derive macro `JSTraceable`

If you can assure that type has empty JSTraceable impl, you can bypass guards, providing your reasoning:

#[derive(JSTraceable)]
struct S {
  #[no_trace = "Safe because both u32 and u64 are empty traceable"]
  field: HashMap<u32, u64>,
}