Bug 913053. Split up IDLTypedef and IDLTypedefType, and likewise for IDLCallback vs IDLCallbackType, so it's clearer whether we're operating on types or objects represented by those types. r=khuey

This commit is contained in:
Boris Zbarsky 2015-05-13 22:19:22 -04:00
parent 032b148208
commit 368bafb0ef
4 changed files with 98 additions and 68 deletions

View File

@ -1086,8 +1086,7 @@ class CGHeaders(CGWrapper):
elif unrolled.isDictionary():
headerSet.add(self.getDeclarationFilename(unrolled.inner))
elif unrolled.isCallback():
# Callbacks are both a type and an object
headerSet.add(self.getDeclarationFilename(unrolled))
headerSet.add(self.getDeclarationFilename(unrolled.callback))
elif unrolled.isFloat() and not unrolled.isUnrestricted():
# Restricted floats are tested for finiteness
bindingHeaders.add("mozilla/FloatingPoint.h")
@ -1276,7 +1275,7 @@ def UnionTypes(unionTypes, config):
# Callbacks always use strong refs, so we need to include
# the right header to be able to Release() in our inlined
# code.
headers.add(CGHeaders.getDeclarationFilename(f))
headers.add(CGHeaders.getDeclarationFilename(f.callback))
elif f.isMozMap():
headers.add("mozilla/dom/MozMap.h")
# And add headers for the type we're parametrized over
@ -5130,7 +5129,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not type.treatNonObjectAsNull() or type.nullable()
assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull()
name = type.unroll().identifier.name
callback = type.unroll().callback
name = callback.identifier.name
if type.nullable():
declType = CGGeneric("nsRefPtr<%s>" % name)
else:
@ -6233,7 +6233,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
result = CGGeneric("auto")
return result, None, None, None, conversion
if returnType.isCallback():
name = returnType.unroll().identifier.name
name = returnType.unroll().callback.identifier.name
return CGGeneric("nsRefPtr<%s>" % name), None, None, None, None
if returnType.isAny():
if isMember:
@ -8782,7 +8782,7 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
return CGGeneric(type.inner.identifier.name)
if type.isCallback():
return CGGeneric("%s&" % type.unroll().identifier.name)
return CGGeneric("%s&" % type.unroll().callback.identifier.name)
if type.isAny():
return CGGeneric("JS::Value")
@ -12414,7 +12414,7 @@ class CGForwardDeclarations(CGWrapper):
# Note: Spidermonkey interfaces are typedefs, so can't be
# forward-declared
elif t.isCallback():
builder.addInMozillaDom(str(t))
builder.addInMozillaDom(t.callback.identifier.name)
elif t.isDictionary():
builder.addInMozillaDom(t.inner.identifier.name, isStruct=True)
elif t.isCallbackInterface():
@ -12441,12 +12441,12 @@ class CGForwardDeclarations(CGWrapper):
builder.add(d.nativeType + "Atoms", isStruct=True)
for callback in mainCallbacks:
forwardDeclareForType(callback)
builder.addInMozillaDom(callback.identifier.name)
for t in getTypesFromCallback(callback):
forwardDeclareForType(t, workerness='mainthreadonly')
for callback in workerCallbacks:
forwardDeclareForType(callback)
builder.addInMozillaDom(callback.identifier.name)
for t in getTypesFromCallback(callback):
forwardDeclareForType(t, workerness='workeronly')
@ -12829,7 +12829,7 @@ class CGNativeMember(ClassMethod):
# .forget() to get our already_AddRefed.
return result.define(), "nullptr", "return ${declName}.forget();\n"
if type.isCallback():
return ("already_AddRefed<%s>" % type.unroll().identifier.name,
return ("already_AddRefed<%s>" % type.unroll().callback.identifier.name,
"nullptr", "return ${declName}.forget();\n")
if type.isAny():
if isMember:
@ -13059,7 +13059,7 @@ class CGNativeMember(ClassMethod):
else:
declType = "%s&"
if type.isCallback():
name = type.unroll().identifier.name
name = type.unroll().callback.identifier.name
else:
name = type.unroll().inner.identifier.name
return declType % name, False, False

View File

@ -48,11 +48,10 @@ class Configuration:
"%s\n"
"%s" %
(thing.location, thing.implementor.location))
# Some toplevel things are sadly types, and those have an
# isInterface that doesn't mean the same thing as IDLObject's
# isInterface()...
if (not isinstance(thing, IDLInterface) and
not isinstance(thing, IDLExternalInterface)):
assert not thing.isType();
if not thing.isInterface():
continue
iface = thing
self.interfaces[iface.identifier.name] = iface
@ -800,9 +799,9 @@ def findCallbacksAndDictionaries(inputTypes):
def doFindCallbacksAndDictionaries(types, callbacks, dictionaries):
unhandledTypes = set()
for type in types:
if type.isCallback() and type not in callbacks:
unhandledTypes |= getFlatTypes(getTypesFromCallback(type))
callbacks.add(type)
if type.isCallback() and type.callback not in callbacks:
unhandledTypes |= getFlatTypes(getTypesFromCallback(type.callback))
callbacks.add(type.callback)
elif type.isDictionary() and type.inner not in dictionaries:
d = type.inner
unhandledTypes |= getFlatTypes(getTypesFromDictionary(d))

View File

@ -164,6 +164,9 @@ class IDLObject(object):
def isUnion(self):
return False
def isTypedef(self):
return False
def getUserData(self, key, default):
return self.userData.get(key, default)
@ -1789,11 +1792,11 @@ class IDLType(IDLObject):
def treatNonCallableAsNull(self):
assert self.tag() == IDLType.Tags.callback
return self.nullable() and self.inner._treatNonCallableAsNull
return self.nullable() and self.inner.callback._treatNonCallableAsNull
def treatNonObjectAsNull(self):
assert self.tag() == IDLType.Tags.callback
return self.nullable() and self.inner._treatNonObjectAsNull
return self.nullable() and self.inner.callback._treatNonObjectAsNull
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
@ -1833,11 +1836,17 @@ class IDLUnresolvedType(IDLType):
assert obj
if obj.isType():
# obj itself might not be complete; deal with that.
assert obj != self
if not obj.isComplete():
obj = obj.complete(scope)
return obj
print obj
assert not obj.isType()
if obj.isTypedef():
assert self.name.name == obj.identifier.name
typedefType = IDLTypedefType(self.location, obj.innerType,
obj.identifier)
assert not typedefType.isComplete()
return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
return IDLCallbackType(self.location, obj)
if self._promiseInnerType and not self._promiseInnerType.isComplete():
self._promiseInnerType = self._promiseInnerType.complete(scope)
@ -2358,23 +2367,17 @@ class IDLArrayType(IDLType):
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
class IDLTypedefType(IDLType):
def __init__(self, location, innerType, name):
IDLType.__init__(self, location, innerType.name)
identifier = IDLUnresolvedIdentifier(location, name)
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
IDLType.__init__(self, location, name)
self.inner = innerType
self.name = name
self.builtin = False
def __eq__(self, other):
return isinstance(other, IDLTypedefType) and self.inner == other.inner
def __str__(self):
return self.identifier.name
return self.name
def nullable(self):
return self.inner.nullable()
@ -2442,16 +2445,6 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
assert self.inner.isComplete()
return self.inner
def finish(self, parentScope):
# Maybe the IDLObjectWithIdentifier for the typedef should be
# a separate thing from the type? If that happens, we can
# remove some hackery around avoiding isInterface() in
# Configuration.py.
self.complete(parentScope)
def validate(self):
pass
# Do we need a resolveType impl? I don't think it's particularly useful....
def tag(self):
@ -2466,6 +2459,31 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
def _getDependentObjects(self):
return self.inner._getDependentObjects()
class IDLTypedef(IDLObjectWithIdentifier):
def __init__(self, location, parentScope, innerType, name):
identifier = IDLUnresolvedIdentifier(location, name)
IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
self.innerType = innerType
def __str__(self):
return "Typedef %s %s" % (self.identifier.name, self.innerType)
def finish(self, parentScope):
if not self.innerType.isComplete():
self.innerType = self.innerType.complete(parentScope)
def validate(self):
pass
def isTypedef(self):
return True
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
def _getDependentObjects(self):
return self.innerType._getDependentObjects()
class IDLWrapperType(IDLType):
def __init__(self, location, inner, promiseInnerType=None):
IDLType.__init__(self, location, inner.identifier.name)
@ -3655,12 +3673,10 @@ class IDLArgument(IDLObjectWithIdentifier):
def canHaveMissingValue(self):
return self.optional and not self.defaultValue
class IDLCallbackType(IDLType, IDLObjectWithScope):
class IDLCallback(IDLObjectWithScope):
def __init__(self, location, parentScope, identifier, returnType, arguments):
assert isinstance(returnType, IDLType)
IDLType.__init__(self, location, identifier.name)
self._returnType = returnType
# Clone the list
self._arguments = list(arguments)
@ -3680,9 +3696,6 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
def signatures(self):
return [(self._returnType, self._arguments)]
def tag(self):
return IDLType.Tags.callback
def finish(self, scope):
if not self._returnType.isComplete():
type = self._returnType.complete(scope)
@ -3706,14 +3719,6 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
def validate(self):
pass
def isDistinguishableFrom(self, other):
if other.isUnion():
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate() or
other.isSequence())
def addExtendedAttributes(self, attrs):
unhandledAttrs = []
for attr in attrs:
@ -3732,6 +3737,28 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
def _getDependentObjects(self):
return set([self._returnType] + self._arguments)
class IDLCallbackType(IDLType):
def __init__(self, location, callback):
IDLType.__init__(self, location, callback.identifier.name)
self.callback = callback
def isCallback(self):
return True
def tag(self):
return IDLType.Tags.callback
def isDistinguishableFrom(self, other):
if other.isUnion():
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate() or
other.isSequence())
def _getDependentObjects(self):
return self.callback._getDependentObjects()
class IDLMethodOverload:
"""
A class that represents a single overload of a WebIDL method. This is not
@ -4738,8 +4765,8 @@ class Parser(Tokenizer):
CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(),
identifier, p[3], p[5])
p[0] = IDLCallback(self.getLocation(p, 1), self.globalScope(),
identifier, p[3], p[5])
def p_ExceptionMembers(self, p):
"""
@ -4752,8 +4779,8 @@ class Parser(Tokenizer):
"""
Typedef : TYPEDEF Type IDENTIFIER SEMICOLON
"""
typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3])
typedef.resolve(self.globalScope())
typedef = IDLTypedef(self.getLocation(p, 1), self.globalScope(),
p[2], p[3])
p[0] = typedef
def p_ImplementsStatement(self, p):
@ -5488,8 +5515,12 @@ class Parser(Tokenizer):
try:
if self.globalScope()._lookupIdentifier(p[1]):
obj = self.globalScope()._lookupIdentifier(p[1])
if obj.isType():
type = obj
assert not obj.isType()
if obj.isTypedef():
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():
type = IDLCallbackType(self.getLocation(p, 1), obj)
else:
type = IDLWrapperType(self.getLocation(p, 1), p[1])
p[0] = self.handleModifiers(type, p[2])
@ -5825,9 +5856,7 @@ class Parser(Tokenizer):
for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
builtin = BuiltinTypes[x]
name = builtin.name
typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name)
typedef.resolve(scope)
typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name)
@ staticmethod
def handleModifiers(type, modifiers):

View File

@ -7,6 +7,7 @@
typedef long myLong;
typedef TestInterface AnotherNameForTestInterface;
typedef TestInterface? NullableTestInterface;
typedef CustomEventInit TestDictionaryTypedef;
interface TestExternalInterface;
@ -1019,6 +1020,7 @@ dictionary Dict : ParentDict {
required object requiredObject;
CustomEventInit customEventInit;
TestDictionaryTypedef dictionaryTypedef;
};
dictionary ParentDict : GrandparentDict {