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 # FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=772822
# We should be able to check for special operations without an # We should be able to check for special operations without an
# identifier. For now we check if the name starts with __ # 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 # Ignore non-static methods for callback interfaces
not m.isIdentifierLess()] 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, self.regular = [{"name": m.identifier.name,
"methodInfo": not m.isStatic(), "methodInfo": not m.isStatic(),
"length": methodLength(m), "length": methodLength(m),
@ -2095,7 +2100,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
properties should be a PropertyArrays instance. properties should be a PropertyArrays instance.
""" """
def __init__(self, descriptor, properties): def __init__(self, descriptor, properties):
assert not descriptor.interface.isCallback()
args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'global'), args = [Argument('*mut JSContext', 'cx'), Argument('*mut JSObject', 'global'),
Argument('*mut JSObject', 'receiver')] Argument('*mut JSObject', 'receiver')]
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', '*mut JSObject', args) CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', '*mut JSObject', args)
@ -2112,6 +2116,11 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
getParentProto = ("let parent_proto: *mut JSObject = %s;\n" getParentProto = ("let parent_proto: *mut JSObject = %s;\n"
"assert!(!parent_proto.is_null());\n") % getParentProto "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.concrete:
if self.descriptor.proxy: if self.descriptor.proxy:
domClass = "&Class" domClass = "&Class"
@ -2136,9 +2145,9 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
call = """\ call = """\
return do_create_interface_objects(cx, global, receiver, parent_proto, return do_create_interface_objects(cx, global, receiver, parent_proto,
&PrototypeClass, %s, %s, %s,
%s, %s,
&sNativeProperties);""" % (constructor, domClass) &sNativeProperties);""" % (protoClass, constructor, domClass)
return CGList([ return CGList([
CGGeneric(getParentProto), CGGeneric(getParentProto),
@ -2286,9 +2295,11 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
return CGAbstractMethod.define(self) return CGAbstractMethod.define(self)
def definition_body(self): def definition_body(self):
return CGGeneric("""\ if self.descriptor.interface.isCallback():
assert!(!global.is_null()); code = "CreateInterfaceObjects(cx, global, global);"
assert!(!GetProtoObject(cx, global, global).is_null());""") else:
code = "assert!(!GetProtoObject(cx, global, global).is_null());"
return CGGeneric("assert!(!global.is_null());\n" + code)
def needCx(returnType, arguments, considerTypes): def needCx(returnType, arguments, considerTypes):
return (considerTypes and return (considerTypes and
@ -4268,10 +4279,11 @@ class CGDescriptor(CGThing):
def __init__(self, descriptor): def __init__(self, descriptor):
CGThing.__init__(self) CGThing.__init__(self)
assert not descriptor.interface.isCallback() assert not descriptor.concrete or not descriptor.interface.isCallback()
cgThings = [] cgThings = []
cgThings.append(CGGetProtoObjectMethod(descriptor)) if not descriptor.interface.isCallback():
cgThings.append(CGGetProtoObjectMethod(descriptor))
if descriptor.interface.hasInterfaceObject(): if descriptor.interface.hasInterfaceObject():
# https://github.com/mozilla/servo/issues/2665 # https://github.com/mozilla/servo/issues/2665
# cgThings.append(CGGetConstructorObjectMethod(descriptor)) # cgThings.append(CGGetConstructorObjectMethod(descriptor))
@ -4285,7 +4297,7 @@ class CGDescriptor(CGThing):
if m.isStatic(): if m.isStatic():
assert descriptor.interface.hasInterfaceObject() assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticMethod(descriptor, m)) cgThings.append(CGStaticMethod(descriptor, m))
else: elif not descriptor.interface.isCallback():
cgThings.append(CGSpecializedMethod(descriptor, m)) cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m)) cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True hasMethod = True
@ -4298,7 +4310,7 @@ class CGDescriptor(CGThing):
if m.isStatic(): if m.isStatic():
assert descriptor.interface.hasInterfaceObject() assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticGetter(descriptor, m)) cgThings.append(CGStaticGetter(descriptor, m))
else: elif not descriptor.interface.isCallback():
cgThings.append(CGSpecializedGetter(descriptor, m)) cgThings.append(CGSpecializedGetter(descriptor, m))
if m.hasLenientThis(): if m.hasLenientThis():
hasLenientGetter = True hasLenientGetter = True
@ -4309,14 +4321,15 @@ class CGDescriptor(CGThing):
if m.isStatic(): if m.isStatic():
assert descriptor.interface.hasInterfaceObject() assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticSetter(descriptor, m)) cgThings.append(CGStaticSetter(descriptor, m))
else: elif not descriptor.interface.isCallback():
cgThings.append(CGSpecializedSetter(descriptor, m)) cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis(): if m.hasLenientThis():
hasLenientSetter = True hasLenientSetter = True
else: else:
hasSetter = True hasSetter = True
if not m.isStatic(): if (not m.isStatic() and
not descriptor.interface.isCallback()):
cgThings.append(CGMemberJITInfo(descriptor, m)) cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: if hasMethod:
cgThings.append(CGGenericMethod(descriptor)) cgThings.append(CGGenericMethod(descriptor))
@ -4337,7 +4350,8 @@ class CGDescriptor(CGThing):
cgThings.append(CGClassConstructHook(descriptor)) cgThings.append(CGClassConstructHook(descriptor))
cgThings.append(CGInterfaceObjectJSClass(descriptor)) cgThings.append(CGInterfaceObjectJSClass(descriptor))
cgThings.append(CGPrototypeJSClass(descriptor)) if not descriptor.interface.isCallback():
cgThings.append(CGPrototypeJSClass(descriptor))
properties = PropertyArrays(descriptor) properties = PropertyArrays(descriptor)
cgThings.append(CGGeneric(str(properties))) cgThings.append(CGGeneric(str(properties)))
@ -4383,8 +4397,9 @@ class CGDescriptor(CGThing):
cgThings.append(CGWrapMethod(descriptor)) cgThings.append(CGWrapMethod(descriptor))
cgThings.append(CGIDLInterface(descriptor)) if not descriptor.interface.isCallback():
cgThings.append(CGInterfaceTrait(descriptor)) cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))
cgThings = CGList(cgThings, "\n") cgThings = CGList(cgThings, "\n")
#self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name), #self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
@ -4638,7 +4653,14 @@ class CGBindingRoot(CGThing):
""" """
def __init__(self, config, prefix, webIDLFile): def __init__(self, config, prefix, webIDLFile):
descriptors = config.getDescriptors(webIDLFile=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) dictionaries = config.getDictionaries(webIDLFile=webIDLFile)
cgthings = [] cgthings = []

View file

@ -162,10 +162,12 @@ class Descriptor(DescriptorProvider):
self.concreteType = ifaceName self.concreteType = ifaceName
self.register = desc.get('register', True) self.register = desc.get('register', True)
self.outerObjectHook = desc.get('outerObjectHook', 'None') self.outerObjectHook = desc.get('outerObjectHook', 'None')
self.proxy = False
# If we're concrete, we need to crawl our ancestor interfaces and mark # If we're concrete, we need to crawl our ancestor interfaces and mark
# them as having a concrete descendant. # 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 = { self.operations = {
'IndexedGetter': None, 'IndexedGetter': None,
@ -190,7 +192,6 @@ class Descriptor(DescriptorProvider):
addOperation('Stringifier', m) addOperation('Stringifier', m)
if self.concrete: if self.concrete:
self.proxy = False
iface = self.interface iface = self.interface
while iface: while iface:
for m in iface.members: for m in iface.members:

View file

@ -180,36 +180,38 @@ unsafe impl Sync for NativeProperties {}
pub type NonNullJSNative = pub type NonNullJSNative =
unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> JSBool; unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> JSBool;
/// Creates the *interface prototype object* and the *interface object* (if /// Creates the *interface prototype object* (if a `proto_class` is given)
/// needed). /// and the *interface object* (if a `constructor` is given).
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
pub fn do_create_interface_objects(cx: *mut JSContext, global: *mut JSObject, pub fn do_create_interface_objects(cx: *mut JSContext, global: *mut JSObject,
receiver: *mut JSObject, receiver: *mut JSObject,
proto_proto: *mut JSObject, proto_proto: *mut JSObject,
proto_class: &'static JSClass, proto_class: Option<&'static JSClass>,
constructor: Option<(NonNullJSNative, &'static str, u32)>, constructor: Option<(NonNullJSNative, &'static str, u32)>,
dom_class: *const DOMClass, dom_class: *const DOMClass,
members: &'static NativeProperties) members: &'static NativeProperties)
-> *mut JSObject { -> *mut JSObject {
let proto = create_interface_prototype_object(cx, global, proto_proto,
proto_class, members);
unsafe { unsafe {
JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT, let proto = match proto_class {
PrivateValue(dom_class as *const libc::c_void)); 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()
};
match constructor { if let Some((native, name, nargs)) = constructor {
Some((native, name, nargs)) => {
let s = CString::new(name).unwrap(); let s = CString::new(name).unwrap();
create_interface_object(cx, global, receiver, create_interface_object(cx, global, receiver,
native, nargs, proto, native, nargs, proto,
members, s.as_ptr()) members, s.as_ptr())
}, }
None => (),
}
proto proto
}
} }
/// Creates the *interface object*. /// Creates the *interface object*.