Introduce trait WeakReferenceable

This allows to take weak references of JS-managed DOM objects.
This commit is contained in:
Anthony Ramine 2015-10-18 13:53:12 +02:00
parent 12f6ba29a7
commit 72c67efe96
10 changed files with 268 additions and 5 deletions

View file

@ -1765,12 +1765,16 @@ class CGDOMJSClass(CGThing):
def define(self):
traceHook = 'Some(%s)' % TRACE_HOOK_NAME
if self.descriptor.isGlobal():
assert not self.descriptor.weakReferenceable
traceHook = "Some(js::jsapi::JS_GlobalObjectTraceHook)"
flags = "JSCLASS_IS_GLOBAL | JSCLASS_DOM_GLOBAL"
slots = "JSCLASS_GLOBAL_SLOT_COUNT + 1"
else:
flags = "0"
slots = "1"
if self.descriptor.weakReferenceable:
slots = "2"
else:
slots = "1"
return """\
static Class: DOMJSClass = DOMJSClass {
base: js::jsapi::Class {
@ -2175,6 +2179,9 @@ let obj = RootedObject::new(cx, obj);\
"\n"
"JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT,\n"
" PrivateValue(raw as *const libc::c_void));")
if descriptor.weakReferenceable:
create += """
JS_SetReservedSlot(obj.ptr, DOM_WEAK_SLOT, PrivateValue(ptr::null()));"""
return create
@ -4521,8 +4528,8 @@ class CGAbstractClassHook(CGAbstractExternMethod):
args)
def definition_body_prologue(self):
return CGGeneric("""\
let this = private_from_object(obj) as *const %s;
return CGGeneric("""
let this = native_from_object::<%s>(obj).unwrap();
""" % self.descriptor.concreteType)
def definition_body(self):
@ -4541,6 +4548,24 @@ def finalizeHook(descriptor, hookName, context):
release += """\
finalize_global(obj);
"""
elif descriptor.weakReferenceable:
release += """\
let weak_box_ptr = JS_GetReservedSlot(obj, DOM_WEAK_SLOT).to_private() as *mut WeakBox<%s>;
if !weak_box_ptr.is_null() {
let count = {
let weak_box = &*weak_box_ptr;
assert!(weak_box.value.get().is_some());
assert!(weak_box.count.get() > 0);
weak_box.value.set(None);
let count = weak_box.count.get() - 1;
weak_box.count.set(count);
count
};
if count == 0 {
mem::drop(Box::from_raw(weak_box_ptr));
}
}
""" % descriptor.concreteType
release += """\
let _ = Box::from_raw(this as *mut %s);
debug!("%s finalize: {:p}", this);\
@ -4718,6 +4743,16 @@ class CGInterfaceTrait(CGThing):
return self.cgRoot.define()
class CGWeakReferenceableTrait(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
assert descriptor.weakReferenceable
self.code = "impl WeakReferenceable for %s {}" % descriptor.interface.identifier.name
def define(self):
return self.code
class CGDescriptor(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
@ -4826,6 +4861,8 @@ class CGDescriptor(CGThing):
if not descriptor.interface.isCallback():
cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))
if descriptor.weakReferenceable:
cgThings.append(CGWeakReferenceableTrait(descriptor))
cgThings = CGList(cgThings, "\n")
# self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
@ -5215,7 +5252,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::conversions::{ConversionBehavior, DOM_OBJECT_SLOT, IDLInterface}',
'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
'dom::bindings::conversions::{private_from_object, root_from_object}',
'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
'dom::bindings::codegen::Bindings::*',
@ -5230,6 +5267,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::str::ByteString',
'dom::bindings::str::USVString',
'dom::bindings::trace::RootedVec',
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
'mem::heap_size_of_raw_self_and_children',
'libc',
'util::str::DOMString',