зеркало из https://github.com/mozilla/gecko-dev.git
Bug 763911. Add support for interface members of dictionaries. r=khuey
This commit is contained in:
Родитель
04c02edf69
Коммит
03bc840cdd
|
@ -8,6 +8,7 @@ import os
|
|||
import string
|
||||
|
||||
from WebIDL import *
|
||||
from Configuration import NoSuchDescriptorError
|
||||
|
||||
AUTOGENERATED_WARNING_COMMENT = \
|
||||
"/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
|
||||
|
@ -351,6 +352,12 @@ class CGHeaders(CGWrapper):
|
|||
attrs = [a for a in members if a.isAttr()]
|
||||
types.extend([a.type for a in attrs])
|
||||
|
||||
for dictionary in dictionaries:
|
||||
curDict = dictionary
|
||||
while curDict:
|
||||
types.extend([m.type for m in curDict.members])
|
||||
curDict = curDict.parent
|
||||
|
||||
for t in types:
|
||||
if t.unroll().isInterface():
|
||||
if t.unroll().isSpiderMonkeyInterface():
|
||||
|
@ -1556,15 +1563,15 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
elif descriptor.workers:
|
||||
templateBody += "${declName} = &${val}.toObject();"
|
||||
else:
|
||||
# Either external, or new-binding non-castable. We always have a
|
||||
# holder for these, because we don't actually know whether we have
|
||||
# to addref when unwrapping or not. So we just pass an
|
||||
# getter_AddRefs(nsRefPtr) to XPConnect and if we'll need a release
|
||||
# it'll put a non-null pointer in there.
|
||||
# External interface. We always have a holder for these,
|
||||
# because we don't actually know whether we have to addref
|
||||
# when unwrapping or not. So we just pass an
|
||||
# getter_AddRefs(nsRefPtr) to XPConnect and if we'll need
|
||||
# a release it'll put a non-null pointer in there.
|
||||
if forceOwningType:
|
||||
# Don't return a holderType in this case; our declName
|
||||
# will just own stuff.
|
||||
templateBody += "nsRefPtr<" + typeName + "> ${holderName};"
|
||||
templateBody += "nsRefPtr<" + typeName + "> ${holderName};\n"
|
||||
else:
|
||||
holderType = "nsRefPtr<" + typeName + ">"
|
||||
templateBody += (
|
||||
|
@ -1756,11 +1763,13 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
raise TypeError("Can't handle dictionaries when failureCode is not None")
|
||||
|
||||
if type.nullable():
|
||||
typeName = type.inner.inner.identifier.name
|
||||
typeName = CGDictionary.makeDictionaryName(type.inner.inner,
|
||||
descriptorProvider.workers)
|
||||
declType = CGGeneric("Nullable<%s>" % typeName)
|
||||
selfRef = "${declName}.Value()"
|
||||
else:
|
||||
typeName = type.inner.identifier.name
|
||||
typeName = CGDictionary.makeDictionaryName(type.inner,
|
||||
descriptorProvider.workers)
|
||||
declType = CGGeneric(typeName)
|
||||
selfRef = "${declName}"
|
||||
# If we're optional or a member of something else, the const
|
||||
|
@ -3490,24 +3499,37 @@ class CGNamespacedEnum(CGThing):
|
|||
assert False # Only for headers.
|
||||
|
||||
class CGDictionary(CGThing):
|
||||
def __init__(self, dictionary, workers):
|
||||
def __init__(self, dictionary, descriptorProvider):
|
||||
self.dictionary = dictionary;
|
||||
self.workers = workers
|
||||
# Fake a descriptorProvider
|
||||
# XXXbz this will fail for interface types!
|
||||
for member in dictionary.members:
|
||||
if member.type.unroll().isInterface():
|
||||
raise TypeError("No support for interface members of dictionaries: %s.%s" %
|
||||
(dictionary.identifier.name, member.identifier.name))
|
||||
self.memberInfo = [
|
||||
(member,
|
||||
getJSToNativeConversionTemplate(member.type,
|
||||
{ "workers": workers },
|
||||
isMember=True,
|
||||
isOptional=(not member.defaultValue)))
|
||||
for member in dictionary.members ]
|
||||
self.workers = descriptorProvider.workers
|
||||
if dictionary.parent:
|
||||
parentCGThing = CGDictionary(dictionary.parent, descriptorProvider)
|
||||
self.generatable = parentCGThing.generatable
|
||||
if not self.generatable:
|
||||
# Nothing else to do here
|
||||
return
|
||||
else:
|
||||
self.generatable = True
|
||||
# Getting a conversion template for interface types can fail
|
||||
# if we don't have a relevant descriptor when self.workers is True.
|
||||
# If that happens, just mark ourselves as not being
|
||||
# generatable and move on.
|
||||
try:
|
||||
self.memberInfo = [
|
||||
(member,
|
||||
getJSToNativeConversionTemplate(member.type,
|
||||
descriptorProvider,
|
||||
isMember=True,
|
||||
isOptional=(not member.defaultValue)))
|
||||
for member in dictionary.members ]
|
||||
except NoSuchDescriptorError, err:
|
||||
if not self.workers:
|
||||
raise err
|
||||
self.generatable = False
|
||||
|
||||
def declare(self):
|
||||
if not self.generatable:
|
||||
return ""
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
inheritance = ": public %s " % self.makeClassName(d.parent)
|
||||
|
@ -3535,6 +3557,8 @@ class CGDictionary(CGThing):
|
|||
"inheritance": inheritance }))
|
||||
|
||||
def define(self):
|
||||
if not self.generatable:
|
||||
return ""
|
||||
d = self.dictionary
|
||||
if d.parent:
|
||||
initParent = ("// Per spec, we init the parent's members first\n"
|
||||
|
@ -3590,10 +3614,14 @@ class CGDictionary(CGThing):
|
|||
"idInit": CGIndenter(idinit).define()
|
||||
})
|
||||
|
||||
def makeClassName(self, dictionary):
|
||||
suffix = "Workers" if self.workers else ""
|
||||
@staticmethod
|
||||
def makeDictionaryName(dictionary, workers):
|
||||
suffix = "Workers" if workers else ""
|
||||
return dictionary.identifier.name + suffix
|
||||
|
||||
def makeClassName(self, dictionary):
|
||||
return self.makeDictionaryName(dictionary, self.workers)
|
||||
|
||||
def getMemberType(self, memberInfo):
|
||||
(member, (templateBody, declType,
|
||||
holderType, dealWithOptional)) = memberInfo
|
||||
|
@ -3604,7 +3632,6 @@ class CGDictionary(CGThing):
|
|||
return declType.define()
|
||||
|
||||
def getMemberConversion(self, memberInfo):
|
||||
# Fake a descriptorProvider
|
||||
(member, (templateBody, declType,
|
||||
holderType, dealWithOptional)) = memberInfo
|
||||
replacements = { "val": "temp",
|
||||
|
@ -3616,7 +3643,11 @@ class CGDictionary(CGThing):
|
|||
# the guts of init to a static method which is passed
|
||||
# an explicit reference to our dictionary object, so
|
||||
# we couldn't screw this up even if we wanted to....
|
||||
"declName": ("(this->%s)" % member.identifier.name) }
|
||||
"declName": ("(this->%s)" % member.identifier.name),
|
||||
# We need a holder name for external interfaces, but
|
||||
# it's scoped down to the conversion so we can just use
|
||||
# anything we want.
|
||||
"holderName": "holder"}
|
||||
# We can't handle having a holderType here
|
||||
assert holderType is None
|
||||
if dealWithOptional:
|
||||
|
@ -3696,7 +3727,30 @@ class CGBindingRoot(CGThing):
|
|||
|
||||
forwardDeclares = [CGClassForwardDeclare('XPCWrappedNativeScope')]
|
||||
|
||||
for x in descriptors:
|
||||
descriptorsForForwardDeclaration = list(descriptors)
|
||||
for dictionary in dictionaries:
|
||||
curDict = dictionary
|
||||
ifacemembers = []
|
||||
while curDict:
|
||||
ifacemembers.extend([m.type.unroll().inner for m
|
||||
in curDict.members
|
||||
if m.type.unroll().isInterface()])
|
||||
curDict = curDict.parent
|
||||
# Put in all the non-worker descriptors
|
||||
descriptorsForForwardDeclaration.extend(
|
||||
[config.getDescriptor(iface.identifier.name, False) for
|
||||
iface in ifacemembers])
|
||||
# And now the worker ones. But these may not exist, so we
|
||||
# have to be more careful.
|
||||
for iface in ifacemembers:
|
||||
try:
|
||||
descriptorsForForwardDeclaration.append(
|
||||
config.getDescriptor(iface.identifier.name, True))
|
||||
except NoSuchDescriptorError:
|
||||
# just move along
|
||||
pass
|
||||
|
||||
for x in descriptorsForForwardDeclaration:
|
||||
nativeType = x.nativeType
|
||||
components = x.nativeType.split('::')
|
||||
className = components[-1]
|
||||
|
@ -3755,8 +3809,10 @@ class CGBindingRoot(CGThing):
|
|||
reSortedDictionaries.extend(toMove)
|
||||
|
||||
dictionaries = reSortedDictionaries
|
||||
cgthings.extend([CGDictionary(d, workers=True) for d in dictionaries])
|
||||
cgthings.extend([CGDictionary(d, workers=False) for d in dictionaries])
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True))
|
||||
for d in dictionaries])
|
||||
cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False))
|
||||
for d in dictionaries])
|
||||
|
||||
# Do codegen for all the descriptors
|
||||
cgthings.extend([CGDescriptor(x) for x in descriptors])
|
||||
|
|
|
@ -75,13 +75,55 @@ class Configuration:
|
|||
return filter(lambda e: e.filename() == webIDLFile, self.enums)
|
||||
def getDictionaries(self, webIDLFile):
|
||||
return filter(lambda d: d.filename() == webIDLFile, self.dictionaries)
|
||||
def getDescriptor(self, interfaceName, workers):
|
||||
"""
|
||||
Gets the appropriate descriptor for the given interface name
|
||||
and the given workers boolean.
|
||||
"""
|
||||
iface = self.getInterface(interfaceName)
|
||||
descriptors = self.getDescriptors(interface=iface)
|
||||
|
||||
class Descriptor:
|
||||
# The only filter we currently have is workers vs non-workers.
|
||||
matches = filter(lambda x: x.workers is workers, descriptors)
|
||||
|
||||
# After filtering, we should have exactly one result.
|
||||
if len(matches) is not 1:
|
||||
raise NoSuchDescriptorError("For " + interfaceName + " found " +
|
||||
str(len(matches)) + " matches");
|
||||
return matches[0]
|
||||
def getDescriptorProvider(self, workers):
|
||||
"""
|
||||
Gets a descriptor provider that can provide descriptors as needed,
|
||||
for the given workers boolean
|
||||
"""
|
||||
return DescriptorProvider(self, workers)
|
||||
|
||||
class NoSuchDescriptorError(TypeError):
|
||||
def __init__(self, str):
|
||||
TypeError.__init__(self, str)
|
||||
|
||||
class DescriptorProvider:
|
||||
"""
|
||||
A way of getting descriptors for interface names
|
||||
"""
|
||||
def __init__(self, config, workers):
|
||||
self.config = config
|
||||
self.workers = workers
|
||||
|
||||
def getDescriptor(self, interfaceName):
|
||||
"""
|
||||
Gets the appropriate descriptor for the given interface name given the
|
||||
context of the current descriptor. This selects the appropriate
|
||||
implementation for cases like workers.
|
||||
"""
|
||||
return self.config.getDescriptor(interfaceName, self.workers)
|
||||
|
||||
class Descriptor(DescriptorProvider):
|
||||
"""
|
||||
Represents a single descriptor for an interface. See Bindings.conf.
|
||||
"""
|
||||
def __init__(self, config, interface, desc):
|
||||
self.config = config
|
||||
DescriptorProvider.__init__(self, config, desc.get('workers', False))
|
||||
self.interface = interface
|
||||
|
||||
# Read the desc, and fill in the relevant defaults.
|
||||
|
@ -109,7 +151,6 @@ class Descriptor:
|
|||
|
||||
self.prefable = desc.get('prefable', False)
|
||||
|
||||
self.workers = desc.get('workers', False)
|
||||
self.nativeIsISupports = not self.workers
|
||||
self.customTrace = desc.get('customTrace', self.workers)
|
||||
self.customFinalize = desc.get('customFinalize', self.workers)
|
||||
|
@ -166,24 +207,6 @@ class Descriptor:
|
|||
|
||||
return self.interface.hasInterfaceObject() or self.interface.hasInterfacePrototypeObject()
|
||||
|
||||
def getDescriptor(self, interfaceName):
|
||||
"""
|
||||
Gets the appropriate descriptor for the given interface name given the
|
||||
context of the current descriptor. This selects the appropriate
|
||||
implementation for cases like workers.
|
||||
"""
|
||||
iface = self.config.getInterface(interfaceName)
|
||||
descriptors = self.config.getDescriptors(interface=iface)
|
||||
|
||||
# The only filter we currently have is workers vs non-workers.
|
||||
matches = filter(lambda x: x.workers is self.workers, descriptors)
|
||||
|
||||
# After filtering, we should have exactly one result.
|
||||
if len(matches) is not 1:
|
||||
raise TypeError("For " + interfaceName + " found " +
|
||||
str(len(matches)) + " matches");
|
||||
return matches[0]
|
||||
|
||||
def getExtendedAttributes(self, member, getter=False, setter=False):
|
||||
name = member.identifier.name
|
||||
if member.isMethod():
|
||||
|
|
|
@ -634,6 +634,11 @@ class IDLDictionary(IDLObjectWithScope):
|
|||
|
||||
for member in self.members:
|
||||
member.resolve(self)
|
||||
if not member.type.isComplete():
|
||||
type = member.type.complete(scope)
|
||||
assert not isinstance(type, IDLUnresolvedType)
|
||||
assert not isinstance(type.name, IDLUnresolvedIdentifier)
|
||||
member.type = type
|
||||
|
||||
# Members of a dictionary are sorted in lexicographic order
|
||||
self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
|
||||
|
|
|
@ -304,4 +304,6 @@ dictionary Dict : ParentDict {
|
|||
|
||||
dictionary ParentDict : GrandparentDict {
|
||||
long c = 5;
|
||||
TestInterface someInterface;
|
||||
TestExternalInterface someExternalInterface;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче