diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 39a8ea13106d..932d7e080589 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -248,17 +248,6 @@ DOMInterfaces = { } }, -'DummyInterface': { - 'skipGen': True, - 'register': False, -}, - -'DummyInterfaceWorkers': { - 'skipGen': True, - 'register': False, - 'workers': True -}, - 'DynamicsCompressorNode': { 'resultNotAddRefed': [ 'threshold', 'knee', 'ratio', 'reduction', 'attack', 'release' ], diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 13c801825610..dc439058d499 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -10,7 +10,7 @@ import re import string from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType -from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback +from Configuration import NoSuchDescriptorError AUTOGENERATED_WARNING_COMMENT = \ "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n" @@ -389,6 +389,45 @@ class CGIncludeGuard(CGWrapper): declarePre='#ifndef %s\n#define %s\n\n' % (define, define), declarePost='\n#endif // %s\n' % define) +def getTypesFromDescriptor(descriptor): + """ + Get all argument and return types for all members of the descriptor + """ + members = [m for m in descriptor.interface.members] + if descriptor.interface.ctor(): + members.append(descriptor.interface.ctor()) + signatures = [s for m in members if m.isMethod() for s in m.signatures()] + types = [] + for s in signatures: + assert len(s) == 2 + (returnType, arguments) = s + types.append(returnType) + types.extend(a.type for a in arguments) + + types.extend(a.type for a in members if a.isAttr()) + return types + +def getTypesFromDictionary(dictionary): + """ + Get all member types for this dictionary + """ + types = [] + curDict = dictionary + while curDict: + types.extend([m.type for m in curDict.members]) + curDict = curDict.parent + return types + +def getTypesFromCallback(callback): + """ + Get the types this callback depends on: its return type and the + types of its arguments. + """ + sig = callback.signatures()[0] + types = [sig[0]] # Return type + types.extend(arg.type for arg in sig[1]) # Arguments + return types + def getRelevantProviders(descriptor, dictionary, config): assert not descriptor or not dictionary if descriptor is not None: @@ -6484,16 +6523,34 @@ class CGDictionary(CGThing): self.descriptorProvider = descriptorProvider self.workers = descriptorProvider.workers self.needToInitIds = not self.workers and len(dictionary.members) > 0 - self.memberInfo = [ - (member, - getJSToNativeConversionTemplate(member.type, - descriptorProvider, - isMember="Dictionary", - isOptional=(not member.defaultValue), - defaultValue=member.defaultValue)) - for member in dictionary.members ] + if all(CGDictionary(d, descriptorProvider).generatable for + d in CGDictionary.getDictionaryDependencies(dictionary)): + self.generatable = True + else: + self.generatable = False + # Nothing else to do here + return + # 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="Dictionary", + isOptional=(not member.defaultValue), + defaultValue=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) @@ -6542,6 +6599,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" @@ -6825,14 +6884,8 @@ class CGBindingRoot(CGThing): descriptors = config.getDescriptors(webIDLFile=webIDLFile, hasInterfaceOrInterfacePrototypeObject=True, skipGen=False) - mainDictionaries = config.getDictionaries(webIDLFile=webIDLFile, - workers=False) - workerDictionaries = config.getDictionaries(webIDLFile=webIDLFile, - workers=True) - mainCallbacks = config.getCallbacks(webIDLFile=webIDLFile, - workers=False) - workerCallbacks = config.getCallbacks(webIDLFile=webIDLFile, - workers=True) + dictionaries = config.getDictionaries(webIDLFile) + callbacks = config.getCallbacks(webIDLFile) callbackDescriptors = config.getDescriptors(webIDLFile=webIDLFile, isCallback=True) @@ -6841,23 +6894,20 @@ class CGBindingRoot(CGThing): descriptorsForForwardDeclaration = list(descriptors) ifaces = [] workerIfaces = [] - def getInterfacesFromDictionary(d): - return [ type.unroll().inner - for type in getTypesFromDictionary(d) - if type.unroll().isGeckoInterface() ] - for dictionary in mainDictionaries: - ifaces.extend(getInterfacesFromDictionary(dictionary)) - for dictionary in workerDictionaries: - workerIfaces.extend(getInterfacesFromDictionary(dictionary)) + for dictionary in dictionaries: + dictionaryIfaces = [ type.unroll().inner + for type in getTypesFromDictionary(dictionary) + if type.unroll().isGeckoInterface() ] + ifaces.extend(dictionaryIfaces) + workerIfaces.extend(dictionaryIfaces) - def getInterfacesFromCallback(c): - return [ t.unroll().inner - for t in getTypesFromCallback(c) - if t.unroll().isGeckoInterface() ] - for callback in mainCallbacks: - ifaces.extend(getInterfacesFromCallback(callback)) - for callback in workerCallbacks: - workerIfaces.extend(getInterfacesFromCallback(callback)) + for callback in callbacks: + callbackIfaces = [ t.unroll().inner + for t in getTypesFromCallback(callback) + if t.unroll().isGeckoInterface() ] + workerIfaces.extend(callbackIfaces) + if not callback.isWorkerOnly(): + ifaces.extend(callbackIfaces) for callbackDescriptor in callbackDescriptors: callbackDescriptorIfaces = [ @@ -6898,7 +6948,7 @@ class CGBindingRoot(CGThing): # Now add the forward declarations we need for our union types # and callback functions. - for callback in mainCallbacks + workerCallbacks: + for callback in callbacks: forwardDeclares.extend( declareNativeType("mozilla::dom::" + str(t.unroll())) for t in getTypesFromCallback(callback) @@ -6911,7 +6961,7 @@ class CGBindingRoot(CGThing): if t.unroll().isUnion() or t.unroll().isCallback()) # Forward declarations for callback functions used in dictionaries. - for dictionary in mainDictionaries + workerDictionaries: + for dictionary in dictionaries: forwardDeclares.extend( declareNativeType("mozilla::dom::" + str(t.unroll())) for t in getTypesFromDictionary(dictionary) @@ -6957,31 +7007,30 @@ class CGBindingRoot(CGThing): # declares a dictionary which inherits from a dictionary in B and B # declares a dictionary (possibly a different one!) that inherits from a # dictionary in A. The good news is that I expect this to never happen. - def sortDictionaries(dictionaries): - reSortedDictionaries = [] - dictionaries = set(dictionaries) - while len(dictionaries) != 0: - # Find the dictionaries that don't depend on anything else - # anymore and move them over. - toMove = [d for d in dictionaries if - len(CGDictionary.getDictionaryDependencies(d) & - dictionaries) == 0] - if len(toMove) == 0: - raise TypeError("Loop in dictionary dependency graph") - dictionaries = dictionaries - set(toMove) - reSortedDictionaries.extend(toMove) - return reSortedDictionaries + reSortedDictionaries = [] + dictionaries = set(dictionaries) + while len(dictionaries) != 0: + # Find the dictionaries that don't depend on anything else anymore + # and move them over. + toMove = [d for d in dictionaries if + len(CGDictionary.getDictionaryDependencies(d) & + dictionaries) == 0] + if len(toMove) == 0: + raise TypeError("Loop in dictionary dependency graph") + dictionaries = dictionaries - set(toMove) + reSortedDictionaries.extend(toMove) + dictionaries = reSortedDictionaries cgthings.extend([CGDictionary(d, config.getDescriptorProvider(True)) - for d in sortDictionaries(workerDictionaries)]) + for d in dictionaries]) cgthings.extend([CGDictionary(d, config.getDescriptorProvider(False)) - for d in sortDictionaries(mainDictionaries)]) + for d in dictionaries]) # Do codegen for all the callbacks. Only do non-worker codegen for now, # since we don't have a sane setup yet for invoking callbacks in workers # and managing their lifetimes. cgthings.extend(CGCallbackFunction(c, config.getDescriptorProvider(False)) - for c in mainCallbacks) + for c in callbacks) # Do codegen for all the descriptors cgthings.extend([CGDescriptor(x) for x in descriptors]) @@ -7004,8 +7053,8 @@ class CGBindingRoot(CGThing): # Add header includes. curr = CGHeaders(descriptors, - mainDictionaries + workerDictionaries, - mainCallbacks + workerCallbacks, + dictionaries, + callbacks, callbackDescriptors, ['mozilla/dom/BindingDeclarations.h', 'mozilla/ErrorResult.h', @@ -7620,22 +7669,38 @@ class CGCallback(CGClass): name = idlObject.identifier.name if descriptorProvider.workers: name += "Workers" - # For our public methods that needThisHandling we want most of the - # same args and the same return type as what CallbackMember - # generates. So we want to take advantage of all its - # CGNativeMember infrastructure, but that infrastructure can't deal - # with templates and most especially template arguments. So just - # cheat and have CallbackMember compute all those things for us. - realMethods = [] - for method in methods: - if not method.needThisHandling: - realMethods.append(method) - else: - realMethods.extend(self.getMethodImpls(method)) - CGClass.__init__(self, name, - bases=[ClassBase(baseName)], - constructors=self.getConstructors(), - methods=realMethods+getters+setters) + try: + # For our public methods that needThisHandling we want most of the + # same args and the same return type as what CallbackMember + # generates. So we want to take advantage of all its + # CGNativeMember infrastructure, but that infrastructure can't deal + # with templates and most especially template arguments. So just + # cheat and have CallbackMember compute all those things for us. + realMethods = [] + for method in methods: + if not method.needThisHandling: + realMethods.append(method) + else: + realMethods.extend(self.getMethodImpls(method)) + CGClass.__init__(self, name, + bases=[ClassBase(baseName)], + constructors=self.getConstructors(), + methods=realMethods+getters+setters) + self.generatable = True + except NoSuchDescriptorError, err: + if not descriptorProvider.workers: + raise err + self.generatable = False + + def define(self): + if not self.generatable: + return "" + return CGClass.define(self) + + def declare(self): + if not self.generatable: + return "" + return CGClass.declare(self) def getConstructors(self): return [ClassConstructor( @@ -7703,6 +7768,9 @@ class CGCallback(CGClass): class CGCallbackFunction(CGCallback): def __init__(self, callback, descriptorProvider): + if callback.isWorkerOnly() and not descriptorProvider.workers: + self.generatable = False + return CGCallback.__init__(self, callback, descriptorProvider, "CallbackFunction", methods=[CallCallback(callback, descriptorProvider)]) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index e5d3fb0ff231..6f5376cae319 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -62,33 +62,10 @@ class Configuration: descriptor.uniqueImplementation = len(otherDescriptors) == 1 self.enums = [e for e in parseData if e.isEnum()] - - # Figure out what our main-thread and worker dictionaries and callbacks - # are. - mainTypes = set() - for descriptor in self.getDescriptors(workers=False, isExternal=False): - mainTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor))) - (mainCallbacks, mainDictionaries) = findCallbacksAndDictionaries(mainTypes) - - workerTypes = set(); - for descriptor in self.getDescriptors(workers=True, isExternal=False): - workerTypes |= set(getFlatTypes(getTypesFromDescriptor(descriptor))) - (workerCallbacks, workerDictionaries) = findCallbacksAndDictionaries(workerTypes) - self.dictionaries = [d for d in parseData if d.isDictionary()] self.callbacks = [c for c in parseData if c.isCallback() and not c.isInterface()] - def flagWorkerOrMainThread(items, main, worker): - for item in items: - if item in main: - item.setUserData("mainThread", True) - if item in worker: - item.setUserData("workers", True) - flagWorkerOrMainThread(self.dictionaries, mainDictionaries, - workerDictionaries); - flagWorkerOrMainThread(self.callbacks, mainCallbacks, workerCallbacks) - # Keep the descriptor list sorted for determinism. self.descriptors.sort(lambda x,y: cmp(x.name, y.name)) @@ -118,26 +95,14 @@ class Configuration: return curr def getEnums(self, webIDLFile): return filter(lambda e: e.filename() == webIDLFile, self.enums) - - @staticmethod - def _filterForFileAndWorkers(items, filters): - """Gets the items that match the given filters.""" - for key, val in filters.iteritems(): - if key == 'webIDLFile': - items = filter(lambda x: x.filename() == val, items) - elif key == 'workers': - if val: - items = filter(lambda x: x.getUserData("workers", False), items) - else: - items = filter(lambda x: x.getUserData("mainThread", False), items) - else: - assert(0) # Unknown key - return items - def getDictionaries(self, **filters): - return self._filterForFileAndWorkers(self.dictionaries, filters) - def getCallbacks(self, **filters): - return self._filterForFileAndWorkers(self.callbacks, filters) - + def getDictionaries(self, webIDLFile=None): + if not webIDLFile: + return self.dictionaries + return filter(lambda d: d.filename() == webIDLFile, self.dictionaries) + def getCallbacks(self, webIDLFile=None): + if not webIDLFile: + return self.callbacks + return filter(lambda d: d.filename() == webIDLFile, self.callbacks) def getDescriptor(self, interfaceName, workers): """ Gets the appropriate descriptor for the given interface name @@ -442,82 +407,3 @@ class Descriptor(DescriptorProvider): def needsConstructHookHolder(self): assert self.interface.hasInterfaceObject() return not self.hasInstanceInterface and not self.interface.isCallback() - -# Some utility methods -def getTypesFromDescriptor(descriptor): - """ - Get all argument and return types for all members of the descriptor - """ - members = [m for m in descriptor.interface.members] - if descriptor.interface.ctor(): - members.append(descriptor.interface.ctor()) - signatures = [s for m in members if m.isMethod() for s in m.signatures()] - types = [] - for s in signatures: - assert len(s) == 2 - (returnType, arguments) = s - types.append(returnType) - types.extend(a.type for a in arguments) - - types.extend(a.type for a in members if a.isAttr()) - return types - -def getFlatTypes(types): - retval = set() - for type in types: - type = type.unroll() - if type.isUnion(): - retval |= set(type.flatMemberTypes) - else: - retval.add(type) - return retval - -def getTypesFromDictionary(dictionary): - """ - Get all member types for this dictionary - """ - types = [] - curDict = dictionary - while curDict: - types.extend([m.type for m in curDict.members]) - curDict = curDict.parent - return types - -def getTypesFromCallback(callback): - """ - Get the types this callback depends on: its return type and the - types of its arguments. - """ - sig = callback.signatures()[0] - types = [sig[0]] # Return type - types.extend(arg.type for arg in sig[1]) # Arguments - return types - -def findCallbacksAndDictionaries(inputTypes): - """ - Ensure that all callbacks and dictionaries reachable from types end up in - the returned callbacks and dictionaries sets. - - Note that we assume that our initial invocation already includes all types - reachable via descriptors in "types", so we only have to deal with things - that are themeselves reachable via callbacks and dictionaries. - """ - 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) - elif type.isDictionary() and type.inner not in dictionaries: - d = type.inner - unhandledTypes |= getFlatTypes(getTypesFromDictionary(d)) - while d: - dictionaries.add(d) - d = d.parent - if len(unhandledTypes) != 0: - doFindCallbacksAndDictionaries(unhandledTypes, callbacks, dictionaries) - - retCallbacks = set() - retDictionaries = set() - doFindCallbacksAndDictionaries(inputTypes, retCallbacks, retDictionaries) - return (retCallbacks, retDictionaries) diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 825eb83e4dce..754789e15b4a 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -2346,6 +2346,7 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): argument.resolve(self) self._treatNonCallableAsNull = False + self._workerOnly = False def isCallback(self): return True @@ -2386,11 +2387,16 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): return (other.isPrimitive() or other.isString() or other.isEnum() or other.isNonCallbackInterface() or other.isDate()) + def isWorkerOnly(self): + return self._workerOnly + def addExtendedAttributes(self, attrs): unhandledAttrs = [] for attr in attrs: if attr.identifier() == "TreatNonCallableAsNull": self._treatNonCallableAsNull = True + elif attr.identifier() == "WorkerOnly": + self._workerOnly = True else: unhandledAttrs.append(attr) if len(unhandledAttrs) != 0: diff --git a/dom/webidl/DummyBinding.webidl b/dom/webidl/DummyBinding.webidl deleted file mode 100644 index 03050e711619..000000000000 --- a/dom/webidl/DummyBinding.webidl +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -// Dummy bindings that we need to force generation of things that -// aren't actually referenced anywhere in IDL yet but are used in C++. - -interface DummyInterface { - readonly attribute OnErrorEventHandlerNonNull onErrorEventHandler; - FilePropertyBag fileBag(); -}; - -interface DummyInterfaceWorkers { - BlobPropertyBag blobBag(); -}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index a42731e2cd9f..a177d6ef5644 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -40,7 +40,6 @@ webidl_files = \ DOMStringMap.webidl \ DOMTokenList.webidl \ DOMTransaction.webidl \ - DummyBinding.webidl \ DynamicsCompressorNode.webidl \ Element.webidl \ EventHandler.webidl \