Skip to content

Commit

Permalink
Support callback interfaces with constants.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisParis committed Apr 11, 2015
1 parent 10c68e7 commit d2b0d5e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 37 deletions.
60 changes: 41 additions & 19 deletions components/script/dom/bindings/codegen/CodegenRust.py
Original file line number Diff line number Diff line change
Expand Up @@ -1240,9 +1240,14 @@ def __init__(self, descriptor, name, static):
# FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=772822
# We should be able to check for special operations without an
# identifier. For now we check if the name starts with __
methods = [m for m in descriptor.interface.members if
m.isMethod() and m.isStatic() == static and
not m.isIdentifierLess()]

# Ignore non-static methods for callback interfaces
if not descriptor.interface.isCallback() or static:
methods = [m for m in descriptor.interface.members if
m.isMethod() and m.isStatic() == static and
not m.isIdentifierLess()]
else:
methods = []
self.regular = [{"name": m.identifier.name,
"methodInfo": not m.isStatic(),
"length": methodLength(m),
Expand Down Expand Up @@ -2085,7 +2090,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
properties should be a PropertyArrays instance.
"""
def __init__(self, descriptor, properties):
assert not descriptor.interface.isCallback()
args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'global'),
Argument('*mut JSObject', 'receiver')]
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', '*mut JSObject', args)
Expand All @@ -2102,6 +2106,11 @@ def definition_body(self):
getParentProto = ("let parent_proto: *mut JSObject = %s;\n"
"assert!(!parent_proto.is_null());\n") % getParentProto

if self.descriptor.interface.isCallback():
protoClass = "None"
else:
protoClass = "Some(&PrototypeClass)"

if self.descriptor.concrete:
if self.descriptor.proxy:
domClass = "&Class"
Expand All @@ -2126,9 +2135,9 @@ def definition_body(self):

call = """\
return do_create_interface_objects(cx, global, receiver, parent_proto,
&PrototypeClass, %s,
%s, %s,
%s,
&sNativeProperties);""" % (constructor, domClass)
&sNativeProperties);""" % (protoClass, constructor, domClass)

return CGList([
CGGeneric(getParentProto),
Expand Down Expand Up @@ -2276,9 +2285,11 @@ def define(self):
return CGAbstractMethod.define(self)

def definition_body(self):
return CGGeneric("""\
assert!(!global.is_null());
assert!(!GetProtoObject(cx, global, global).is_null());""")
if self.descriptor.interface.isCallback():
code = "CreateInterfaceObjects(cx, global, global);"
else:
code = "assert!(!GetProtoObject(cx, global, global).is_null());"
return CGGeneric("assert!(!global.is_null());\n" + code)

def needCx(returnType, arguments, considerTypes):
return (considerTypes and
Expand Down Expand Up @@ -4258,10 +4269,11 @@ class CGDescriptor(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)

assert not descriptor.interface.isCallback()
assert not descriptor.concrete or not descriptor.interface.isCallback()

cgThings = []
cgThings.append(CGGetProtoObjectMethod(descriptor))
if not descriptor.interface.isCallback():
cgThings.append(CGGetProtoObjectMethod(descriptor))
if descriptor.interface.hasInterfaceObject():
# https://github.com/mozilla/servo/issues/2665
# cgThings.append(CGGetConstructorObjectMethod(descriptor))
Expand All @@ -4275,7 +4287,7 @@ def __init__(self, descriptor):
if m.isStatic():
assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticMethod(descriptor, m))
else:
elif not descriptor.interface.isCallback():
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True
Expand All @@ -4288,7 +4300,7 @@ def __init__(self, descriptor):
if m.isStatic():
assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticGetter(descriptor, m))
else:
elif not descriptor.interface.isCallback():
cgThings.append(CGSpecializedGetter(descriptor, m))
if m.hasLenientThis():
hasLenientGetter = True
Expand All @@ -4299,14 +4311,15 @@ def __init__(self, descriptor):
if m.isStatic():
assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticSetter(descriptor, m))
else:
elif not descriptor.interface.isCallback():
cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis():
hasLenientSetter = True
else:
hasSetter = True

if not m.isStatic():
if (not m.isStatic() and
not descriptor.interface.isCallback()):
cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod:
cgThings.append(CGGenericMethod(descriptor))
Expand All @@ -4327,7 +4340,8 @@ def __init__(self, descriptor):
cgThings.append(CGClassConstructHook(descriptor))
cgThings.append(CGInterfaceObjectJSClass(descriptor))

cgThings.append(CGPrototypeJSClass(descriptor))
if not descriptor.interface.isCallback():
cgThings.append(CGPrototypeJSClass(descriptor))

properties = PropertyArrays(descriptor)
cgThings.append(CGGeneric(str(properties)))
Expand Down Expand Up @@ -4373,8 +4387,9 @@ def __init__(self, descriptor):

cgThings.append(CGWrapMethod(descriptor))

cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))
if not descriptor.interface.isCallback():
cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))

cgThings = CGList(cgThings, "\n")
#self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
Expand Down Expand Up @@ -4628,7 +4643,14 @@ class CGBindingRoot(CGThing):
"""
def __init__(self, config, prefix, webIDLFile):
descriptors = config.getDescriptors(webIDLFile=webIDLFile,
isCallback=False)
hasInterfaceObject=True)
# We also want descriptors that have an interface prototype object
# (isCallback=False), but we don't want to include a second copy
# of descriptors that we also matched in the previous line
# (hence hasInterfaceObject=False).
descriptors.extend(config.getDescriptors(webIDLFile=webIDLFile,
hasInterfaceObject=False,
isCallback=False))
dictionaries = config.getDictionaries(webIDLFile=webIDLFile)

cgthings = []
Expand Down
5 changes: 3 additions & 2 deletions components/script/dom/bindings/codegen/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,12 @@ def __init__(self, config, interface, desc):
self.concreteType = ifaceName
self.register = desc.get('register', True)
self.outerObjectHook = desc.get('outerObjectHook', 'None')
self.proxy = False

# If we're concrete, we need to crawl our ancestor interfaces and mark
# them as having a concrete descendant.
self.concrete = desc.get('concrete', True)
self.concrete = (not self.interface.isCallback() and
desc.get('concrete', True))

self.operations = {
'IndexedGetter': None,
Expand All @@ -190,7 +192,6 @@ def addOperation(operation, m):
addOperation('Stringifier', m)

if self.concrete:
self.proxy = False
iface = self.interface
while iface:
for m in iface.members:
Expand Down
34 changes: 18 additions & 16 deletions components/script/dom/bindings/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,36 +180,38 @@ unsafe impl Sync for NativeProperties {}
pub type NonNullJSNative =
unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> JSBool;

/// Creates the *interface prototype object* and the *interface object* (if
/// needed).
/// Creates the *interface prototype object* (if a `proto_class` is given)
/// and the *interface object* (if a `constructor` is given).
/// Fails on JSAPI failure.
pub fn do_create_interface_objects(cx: *mut JSContext, global: *mut JSObject,
receiver: *mut JSObject,
proto_proto: *mut JSObject,
proto_class: &'static JSClass,
proto_class: Option<&'static JSClass>,
constructor: Option<(NonNullJSNative, &'static str, u32)>,
dom_class: *const DOMClass,
members: &'static NativeProperties)
-> *mut JSObject {
let proto = create_interface_prototype_object(cx, global, proto_proto,
proto_class, members);

unsafe {
JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
PrivateValue(dom_class as *const libc::c_void));
}

match constructor {
Some((native, name, nargs)) => {
let proto = match proto_class {
Some(proto_class) => {
let proto = create_interface_prototype_object(cx, global, proto_proto,
proto_class, members);
JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
PrivateValue(dom_class as *const libc::c_void));
proto
},
None => ptr::null_mut()
};

if let Some((native, name, nargs)) = constructor {
let s = CString::new(name).unwrap();
create_interface_object(cx, global, receiver,
native, nargs, proto,
members, s.as_ptr())
},
None => (),
}
}

proto
proto
}
}

/// Creates the *interface object*.
Expand Down

0 comments on commit d2b0d5e

Please sign in to comment.