diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 689587c377b2..071dc1e5c83b 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1950,12 +1950,12 @@ def CreateBindingJSObject(descriptor, parent=None): """ % (descriptor.name, parent) else: if descriptor.isGlobal(): - create += "let obj = create_dom_global(cx, &Class.base as *const js::Class as *const JSClass);\n" + create += "let obj = create_dom_global(cx, &Class.base as *const js::Class as *const JSClass, object);\n" else: create += ("let obj = with_compartment(cx, proto, || {\n" " JS_NewObject(cx, &Class.base as *const js::Class as *const JSClass, &*proto, &*%s)\n" "});\n" % parent) - create += """\ + create += """\ assert!(!obj.is_null()); JS_SetReservedSlot(obj, DOM_OBJECT_SLOT, @@ -4179,9 +4179,13 @@ def __init__(self, descriptor): args = [Argument('*mut JSTracer', 'trc'), Argument('*mut JSObject', 'obj')] CGAbstractClassHook.__init__(self, descriptor, TRACE_HOOK_NAME, 'void', args) + self.traceGlobal = descriptor.isGlobal() def generate_code(self): - return CGGeneric("(*this).trace(%s);" % self.args[0].name) + body = [CGGeneric("(*this).trace(%s);" % self.args[0].name)] + if self.traceGlobal: + body += [CGGeneric("trace_global(trc, obj);")] + return CGList(body, "\n") class CGClassConstructHook(CGAbstractExternMethod): """ @@ -4766,7 +4770,7 @@ def __init__(self, config, prefix, webIDLFile): 'dom::bindings::utils::{DOMJSClass, JSCLASS_DOM_GLOBAL}', 'dom::bindings::utils::{find_enum_string_index, get_array_index_from_id}', 'dom::bindings::utils::{get_property_on_prototype, get_proto_or_iface_array}', - 'dom::bindings::utils::finalize_global', + 'dom::bindings::utils::{finalize_global, trace_global}', 'dom::bindings::utils::has_property_on_prototype', 'dom::bindings::utils::is_platform_object', 'dom::bindings::utils::{Reflectable}', diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 8d111592a24c..2d2ce5e10493 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -410,14 +410,17 @@ impl VecRootableType for *mut JSObject { fn tag(_a: Option<*mut JSObject>) -> CollectionType { CollectionType::JSObjects } } -enum Void {} +#[must_root] +struct Void { + reflector: Reflector, +} impl VecRootableType for Void { fn tag(_a: Option) -> CollectionType { unreachable!() } } impl Reflectable for Void { - fn reflector<'a>(&'a self) -> &'a Reflector { unreachable!() } + fn reflector<'a>(&'a self) -> &'a Reflector { &self.reflector } } /// A vector of items that are rooted for the lifetime diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 55933484165f..73b2e6ae3270 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -6,10 +6,11 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; -use dom::bindings::conversions::{native_from_reflector_jsmanaged, is_dom_class}; +use dom::bindings::conversions::{native_from_reflector_jsmanaged, is_dom_class, DOM_OBJECT_SLOT}; use dom::bindings::error::{Error, ErrorResult, Fallible, throw_type_error}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{Temporary, Root, Rootable}; +use dom::bindings::trace::trace_object; use dom::browsercontext; use dom::window; use util::namespace; @@ -26,7 +27,7 @@ use js::glue::{IsWrapper, RUST_JSID_IS_INT, RUST_JSID_TO_INT}; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction}; use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype, JS_GetStringCharsAndLength}; -use js::jsapi::JSHandleObject; +use js::jsapi::{JSHandleObject, JSTracer}; use js::jsapi::JS_GetFunctionObject; use js::jsapi::{JS_HasPropertyById, JS_GetPrototype}; use js::jsapi::{JS_GetProperty, JS_HasProperty}; @@ -555,17 +556,20 @@ pub fn has_property_on_prototype(cx: *mut JSContext, proxy: *mut JSObject, } /// Create a DOM global object with the given class. -pub fn create_dom_global(cx: *mut JSContext, class: *const JSClass) +pub fn create_dom_global(cx: *mut JSContext, class: *const JSClass, global: Box) -> *mut JSObject { unsafe { let obj = JS_NewGlobalObject(cx, class, ptr::null_mut()); if obj.is_null() { return ptr::null_mut(); } + JS_SetReservedSlot(obj, DOM_OBJECT_SLOT, + PrivateValue(boxed::into_raw(global) as *const libc::c_void)); + initialize_global(obj); + with_compartment(cx, obj, || { JS_InitStandardClasses(cx, obj); }); - initialize_global(obj); obj } } @@ -576,6 +580,16 @@ pub unsafe fn finalize_global(obj: *mut JSObject) { Box::from_raw(get_proto_or_iface_array(obj) as *mut ProtoOrIfaceArray); } +/// Trace the resources held by reserved slots of a global object +pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) { + let array = get_proto_or_iface_array(obj) as *mut ProtoOrIfaceArray; + for &proto in (*array).iter() { + if !proto.is_null() { + trace_object(tracer, "prototype", proto); + } + } +} + /// Callback to outerize windows when wrapping. pub unsafe extern fn wrap_for_same_compartment(cx: *mut JSContext, obj: *mut JSObject) -> *mut JSObject { JS_ObjectToOuterObject(cx, obj)