Auto merge of #3726 - ChrisParis:callback-constants, r=jdm

This addresses https://github.com/servo/servo/issues/3149. The immediate purpose is to support the constants in NodeFilter. The changes mostly follow the current Gecko Codegen.py. The main gist is that the generation of certain code artifacts is now gated by hasInterfaceObject() or hasInterfacePrototypeObject(), rather than by isCallback().
This commit is contained in:
bors-servo 2015-04-13 14:34:39 -05:00
commit 1f9c2f9b34
3 changed files with 61 additions and 36 deletions

View file

@ -1240,9 +1240,14 @@ class MethodDefiner(PropertyDefiner):
# 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 __
# 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),
@ -2095,7 +2100,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)
@ -2112,6 +2116,11 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
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"
@ -2136,9 +2145,9 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
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),
@ -2286,9 +2295,11 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
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
@ -4268,9 +4279,10 @@ 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 = []
if not descriptor.interface.isCallback():
cgThings.append(CGGetProtoObjectMethod(descriptor))
if descriptor.interface.hasInterfaceObject():
# https://github.com/mozilla/servo/issues/2665
@ -4285,7 +4297,7 @@ class CGDescriptor(CGThing):
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
@ -4298,7 +4310,7 @@ class CGDescriptor(CGThing):
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
@ -4309,14 +4321,15 @@ class CGDescriptor(CGThing):
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))
@ -4337,6 +4350,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGClassConstructHook(descriptor))
cgThings.append(CGInterfaceObjectJSClass(descriptor))
if not descriptor.interface.isCallback():
cgThings.append(CGPrototypeJSClass(descriptor))
properties = PropertyArrays(descriptor)
@ -4383,6 +4397,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGWrapMethod(descriptor))
if not descriptor.interface.isCallback():
cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))
@ -4638,7 +4653,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 = []

View file

@ -162,10 +162,12 @@ class Descriptor(DescriptorProvider):
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,
@ -190,7 +192,6 @@ class Descriptor(DescriptorProvider):
addOperation('Stringifier', m)
if self.concrete:
self.proxy = False
iface = self.interface
while iface:
for m in iface.members:

View file

@ -180,37 +180,39 @@ 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 {
unsafe {
let proto = match proto_class {
Some(proto_class) => {
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));
}
proto
},
None => ptr::null_mut()
};
match constructor {
Some((native, name, nargs)) => {
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
}
}
/// Creates the *interface object*.
/// Fails on JSAPI failure.