aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/Configuration.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen/Configuration.py')
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py553
1 files changed, 0 insertions, 553 deletions
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
deleted file mode 100644
index 07822eac1b3..00000000000
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ /dev/null
@@ -1,553 +0,0 @@
-# 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 https://mozilla.org/MPL/2.0/.
-
-import functools
-import os
-
-from WebIDL import IDLExternalInterface, IDLSequenceType, IDLWrapperType, WebIDLError
-
-
-class Configuration:
- """
- Represents global configuration state based on IDL parse data and
- the configuration file.
- """
- def __init__(self, filename, parseData):
- # Read the configuration file.
- glbl = {}
- exec(compile(open(filename).read(), filename, 'exec'), glbl)
- config = glbl['DOMInterfaces']
- self.enumConfig = glbl['Enums']
- self.dictConfig = glbl['Dictionaries']
- self.unionConfig = glbl['Unions']
-
- # Build descriptors for all the interfaces we have in the parse data.
- # This allows callers to specify a subset of interfaces by filtering
- # |parseData|.
- self.descriptors = []
- self.interfaces = {}
- self.maxProtoChainLength = 0
- for thing in parseData:
- # Servo does not support external interfaces.
- if isinstance(thing, IDLExternalInterface):
- raise WebIDLError("Servo does not support external interfaces.",
- [thing.location])
-
- assert not thing.isType()
-
- if not thing.isInterface() and not thing.isNamespace():
- continue
-
- iface = thing
- self.interfaces[iface.identifier.name] = iface
- if iface.identifier.name not in config:
- entry = {}
- else:
- entry = config[iface.identifier.name]
- if not isinstance(entry, list):
- assert isinstance(entry, dict)
- entry = [entry]
- self.descriptors.extend(
- [Descriptor(self, iface, x) for x in entry])
-
- # Mark the descriptors for which only a single nativeType implements
- # an interface.
- for descriptor in self.descriptors:
- interfaceName = descriptor.interface.identifier.name
- otherDescriptors = [d for d in self.descriptors
- if d.interface.identifier.name == interfaceName]
- descriptor.uniqueImplementation = len(otherDescriptors) == 1
-
- self.enums = [e for e in parseData if e.isEnum()]
- self.typedefs = [e for e in parseData if e.isTypedef()]
- self.dictionaries = [d for d in parseData if d.isDictionary()]
- self.callbacks = [c for c in parseData if
- c.isCallback() and not c.isInterface()]
-
- # Keep the descriptor list sorted for determinism.
- def cmp(x, y):
- return (x > y) - (x < y)
- self.descriptors.sort(key=functools.cmp_to_key(lambda x, y: cmp(x.name, y.name)))
-
- def getInterface(self, ifname):
- return self.interfaces[ifname]
-
- def getDescriptors(self, **filters):
- """Gets the descriptors that match the given filters."""
- curr = self.descriptors
- for key, val in filters.items():
- if key == 'webIDLFile':
- def getter(x):
- return x.interface.location.filename
- elif key == 'hasInterfaceObject':
- def getter(x):
- return x.interface.hasInterfaceObject()
- elif key == 'isCallback':
- def getter(x):
- return x.interface.isCallback()
- elif key == 'isNamespace':
- def getter(x):
- return x.interface.isNamespace()
- elif key == 'isJSImplemented':
- def getter(x):
- return x.interface.isJSImplemented()
- elif key == 'isGlobal':
- def getter(x):
- return x.isGlobal()
- elif key == 'isInline':
- def getter(x):
- return x.interface.getExtendedAttribute('Inline') is not None
- elif key == 'isExposedConditionally':
- def getter(x):
- return x.interface.isExposedConditionally()
- elif key == 'isIteratorInterface':
- def getter(x):
- return x.interface.isIteratorInterface()
- else:
- def getter(x):
- return getattr(x, key)
- curr = [x for x in curr if getter(x) == val]
- return curr
-
- def getEnums(self, webIDLFile):
- return [e for e in self.enums if e.filename == webIDLFile]
-
- def getEnumConfig(self, name):
- return self.enumConfig.get(name, {})
-
- def getTypedefs(self, webIDLFile):
- return [e for e in self.typedefs if e.filename == webIDLFile]
-
- @staticmethod
- def _filterForFile(items, webIDLFile=""):
- """Gets the items that match the given filters."""
- if not webIDLFile:
- return items
-
- return [x for x in items if x.filename == webIDLFile]
-
- def getUnionConfig(self, name):
- return self.unionConfig.get(name, {})
-
- def getDictionaries(self, webIDLFile=""):
- return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile)
-
- def getDictConfig(self, name):
- return self.dictConfig.get(name, {})
-
- def getCallbacks(self, webIDLFile=""):
- return self._filterForFile(self.callbacks, webIDLFile=webIDLFile)
-
- def getDescriptor(self, interfaceName):
- """
- Gets the appropriate descriptor for the given interface name.
- """
- iface = self.getInterface(interfaceName)
- descriptors = self.getDescriptors(interface=iface)
-
- # We should have exactly one result.
- if len(descriptors) != 1:
- raise NoSuchDescriptorError("For " + interfaceName + " found "
- + str(len(descriptors)) + " matches")
- return descriptors[0]
-
- def getDescriptorProvider(self):
- """
- Gets a descriptor provider that can provide descriptors as needed.
- """
- return DescriptorProvider(self)
-
-
-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):
- self.config = config
-
- def getDescriptor(self, interfaceName):
- """
- Gets the appropriate descriptor for the given interface name given the
- context of the current descriptor.
- """
- return self.config.getDescriptor(interfaceName)
-
-
-def MemberIsLegacyUnforgeable(member, descriptor):
- return ((member.isAttr() or member.isMethod())
- and not member.isStatic()
- and (member.isLegacyUnforgeable()
- or bool(descriptor.interface.getExtendedAttribute("LegacyUnforgeable"))))
-
-
-class Descriptor(DescriptorProvider):
- """
- Represents a single descriptor for an interface. See Bindings.conf.
- """
- def __init__(self, config, interface, desc):
- DescriptorProvider.__init__(self, config)
- self.interface = interface
-
- if not self.isExposedConditionally():
- if interface.parent and interface.parent.isExposedConditionally():
- raise TypeError("%s is not conditionally exposed but inherits from "
- "%s which is" %
- (interface.identifier.name, interface.parent.identifier.name))
-
- # Read the desc, and fill in the relevant defaults.
- ifaceName = self.interface.identifier.name
- nativeTypeDefault = ifaceName
-
- # For generated iterator interfaces for other iterable interfaces, we
- # just use IterableIterator as the native type, templated on the
- # nativeType of the iterable interface. That way we can have a
- # templated implementation for all the duplicated iterator
- # functionality.
- if self.interface.isIteratorInterface():
- itrName = self.interface.iterableInterface.identifier.name
- itrDesc = self.getDescriptor(itrName)
- nativeTypeDefault = iteratorNativeType(itrDesc)
-
- typeName = desc.get('nativeType', nativeTypeDefault)
-
- spiderMonkeyInterface = desc.get('spiderMonkeyInterface', False)
-
- # Callback and SpiderMonkey types do not use JS smart pointers, so we should not use the
- # built-in rooting mechanisms for them.
- if spiderMonkeyInterface:
- self.returnType = 'Rc<%s>' % typeName
- self.argumentType = '&%s' % typeName
- self.nativeType = typeName
- pathDefault = 'crate::dom::types::%s' % typeName
- elif self.interface.isCallback():
- ty = 'crate::dom::bindings::codegen::Bindings::%sBinding::%s' % (ifaceName, ifaceName)
- pathDefault = ty
- self.returnType = "Rc<%s>" % ty
- self.argumentType = "???"
- self.nativeType = ty
- else:
- self.returnType = "DomRoot<%s>" % typeName
- self.argumentType = "&%s" % typeName
- self.nativeType = "*const %s" % typeName
- if self.interface.isIteratorInterface():
- pathDefault = 'crate::dom::bindings::iterable::IterableIterator'
- else:
- pathDefault = 'crate::dom::types::%s' % MakeNativeName(typeName)
-
- self.concreteType = typeName
- self.register = desc.get('register', True)
- self.path = desc.get('path', pathDefault)
- self.inRealmMethods = [name for name in desc.get('inRealms', [])]
- self.canGcMethods = [name for name in desc.get('canGc', [])]
- self.bindingPath = f"{getModuleFromObject(self.interface)}::{ifaceName}_Binding"
- self.outerObjectHook = desc.get('outerObjectHook', 'None')
- self.proxy = False
- self.weakReferenceable = desc.get('weakReferenceable', False)
-
- # If we're concrete, we need to crawl our ancestor interfaces and mark
- # them as having a concrete descendant.
- self.concrete = (not self.interface.isCallback()
- and not self.interface.isNamespace()
- and not self.interface.getExtendedAttribute("Abstract")
- and not self.interface.getExtendedAttribute("Inline")
- and not spiderMonkeyInterface)
- self.hasLegacyUnforgeableMembers = (self.concrete
- and any(MemberIsLegacyUnforgeable(m, self) for m in
- self.interface.members))
-
- self.operations = {
- 'IndexedGetter': None,
- 'IndexedSetter': None,
- 'IndexedDeleter': None,
- 'NamedGetter': None,
- 'NamedSetter': None,
- 'NamedDeleter': None,
- 'Stringifier': None,
- }
-
- self.hasDefaultToJSON = False
-
- def addOperation(operation, m):
- if not self.operations[operation]:
- self.operations[operation] = m
-
- # Since stringifiers go on the prototype, we only need to worry
- # about our own stringifier, not those of our ancestor interfaces.
- for m in self.interface.members:
- if m.isMethod() and m.isStringifier():
- addOperation('Stringifier', m)
- if m.isMethod() and m.isDefaultToJSON():
- self.hasDefaultToJSON = True
-
- if self.concrete:
- iface = self.interface
- while iface:
- for m in iface.members:
- if not m.isMethod():
- continue
-
- def addIndexedOrNamedOperation(operation, m):
- if not self.isGlobal():
- self.proxy = True
- if m.isIndexed():
- operation = 'Indexed' + operation
- else:
- assert m.isNamed()
- operation = 'Named' + operation
- addOperation(operation, m)
-
- if m.isGetter():
- addIndexedOrNamedOperation('Getter', m)
- if m.isSetter():
- addIndexedOrNamedOperation('Setter', m)
- if m.isDeleter():
- addIndexedOrNamedOperation('Deleter', m)
-
- iface = iface.parent
- if iface:
- iface.setUserData('hasConcreteDescendant', True)
-
- if self.isMaybeCrossOriginObject():
- self.proxy = True
-
- if self.proxy:
- iface = self.interface
- while iface.parent:
- iface = iface.parent
- iface.setUserData('hasProxyDescendant', True)
-
- self.name = interface.identifier.name
-
- # self.extendedAttributes is a dict of dicts, keyed on
- # all/getterOnly/setterOnly and then on member name. Values are an
- # array of extended attributes.
- self.extendedAttributes = {'all': {}, 'getterOnly': {}, 'setterOnly': {}}
-
- def addExtendedAttribute(attribute, config):
- def add(key, members, attribute):
- for member in members:
- self.extendedAttributes[key].setdefault(member, []).append(attribute)
-
- if isinstance(config, dict):
- for key in ['all', 'getterOnly', 'setterOnly']:
- add(key, config.get(key, []), attribute)
- elif isinstance(config, list):
- add('all', config, attribute)
- else:
- assert isinstance(config, str)
- if config == '*':
- iface = self.interface
- while iface:
- add('all', [m.name for m in iface.members], attribute)
- iface = iface.parent
- else:
- add('all', [config], attribute)
-
- self._binaryNames = desc.get('binaryNames', {})
- self._binaryNames.setdefault('__legacycaller', 'LegacyCall')
- self._binaryNames.setdefault('__stringifier', 'Stringifier')
-
- self._internalNames = desc.get('internalNames', {})
-
- for member in self.interface.members:
- if not member.isAttr() and not member.isMethod():
- continue
- binaryName = member.getExtendedAttribute("BinaryName")
- if binaryName:
- assert isinstance(binaryName, list)
- assert len(binaryName) == 1
- self._binaryNames.setdefault(member.identifier.name,
- binaryName[0])
- self._internalNames.setdefault(member.identifier.name,
- member.identifier.name.replace('-', '_'))
-
- # Build the prototype chain.
- self.prototypeChain = []
- parent = interface
- while parent:
- self.prototypeChain.insert(0, parent.identifier.name)
- parent = parent.parent
- self.prototypeDepth = len(self.prototypeChain) - 1
- config.maxProtoChainLength = max(config.maxProtoChainLength,
- len(self.prototypeChain))
-
- def maybeGetSuperModule(self):
- """
- Returns name of super module if self is part of it
- """
- filename = getIdlFileName(self.interface)
- # if interface name is not same as webidl file
- # webidl is super module for interface
- if filename.lower() != self.interface.identifier.name.lower():
- return filename
- return None
-
- def binaryNameFor(self, name):
- return self._binaryNames.get(name, name)
-
- def internalNameFor(self, name):
- return self._internalNames.get(name, name)
-
- def hasNamedPropertiesObject(self):
- if self.interface.isExternal():
- return False
-
- return self.isGlobal() and self.supportsNamedProperties()
-
- def supportsNamedProperties(self):
- return self.operations['NamedGetter'] is not None
-
- def getExtendedAttributes(self, member, getter=False, setter=False):
- def maybeAppendInfallibleToAttrs(attrs, throws):
- if throws is None:
- attrs.append("infallible")
- elif throws is True:
- pass
- else:
- raise TypeError("Unknown value for 'Throws'")
-
- name = member.identifier.name
- if member.isMethod():
- attrs = self.extendedAttributes['all'].get(name, [])
- throws = member.getExtendedAttribute("Throws")
- maybeAppendInfallibleToAttrs(attrs, throws)
- return attrs
-
- assert member.isAttr()
- assert bool(getter) != bool(setter)
- key = 'getterOnly' if getter else 'setterOnly'
- attrs = self.extendedAttributes['all'].get(name, []) + self.extendedAttributes[key].get(name, [])
- throws = member.getExtendedAttribute("Throws")
- if throws is None:
- throwsAttr = "GetterThrows" if getter else "SetterThrows"
- throws = member.getExtendedAttribute(throwsAttr)
- maybeAppendInfallibleToAttrs(attrs, throws)
- return attrs
-
- def getParentName(self):
- parent = self.interface.parent
- while parent:
- if not parent.getExtendedAttribute("Inline"):
- return parent.identifier.name
- parent = parent.parent
- return None
-
- def supportsIndexedProperties(self):
- return self.operations['IndexedGetter'] is not None
-
- def isMaybeCrossOriginObject(self):
- # If we're isGlobal and have cross-origin members, we're a Window, and
- # that's not a cross-origin object. The WindowProxy is.
- return self.concrete and self.interface.hasCrossOriginMembers and not self.isGlobal()
-
- def hasDescendants(self):
- return (self.interface.getUserData("hasConcreteDescendant", False)
- or self.interface.getUserData("hasProxyDescendant", False))
-
- def hasHTMLConstructor(self):
- ctor = self.interface.ctor()
- return ctor and ctor.isHTMLConstructor()
-
- def shouldHaveGetConstructorObjectMethod(self):
- assert self.interface.hasInterfaceObject()
- if self.interface.getExtendedAttribute("Inline"):
- return False
- return (self.interface.isCallback() or self.interface.isNamespace()
- or self.hasDescendants() or self.hasHTMLConstructor())
-
- def shouldCacheConstructor(self):
- return self.hasDescendants() or self.hasHTMLConstructor()
-
- def isExposedConditionally(self):
- return self.interface.isExposedConditionally()
-
- def isGlobal(self):
- """
- Returns true if this is the primary interface for a global object
- of some sort.
- """
- return bool(self.interface.getExtendedAttribute("Global")
- or self.interface.getExtendedAttribute("PrimaryGlobal"))
-
-
-# Some utility methods
-
-
-def MakeNativeName(name):
- return name[0].upper() + name[1:]
-
-
-def getIdlFileName(object):
- return os.path.basename(object.location.filename).split('.webidl')[0]
-
-
-def getModuleFromObject(object):
- return ('crate::dom::bindings::codegen::Bindings::' + getIdlFileName(object) + 'Binding')
-
-
-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())
- members.extend(descriptor.interface.legacyFactoryFunctions)
- 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
- """
- if isinstance(dictionary, IDLWrapperType):
- dictionary = dictionary.inner
- types = []
- curDict = dictionary
- while curDict:
- types.extend([getUnwrappedType(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 getUnwrappedType(type):
- while isinstance(type, IDLSequenceType):
- type = type.inner
- return type
-
-
-def iteratorNativeType(descriptor, infer=False):
- iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
- assert (iterableDecl.isIterable() and iterableDecl.isPairIterator()) \
- or iterableDecl.isSetlike() or iterableDecl.isMaplike()
- res = "IterableIterator%s" % ("" if infer else '<%s>' % descriptor.interface.identifier.name)
- # todo: this hack is telling us that something is still wrong in codegen
- if iterableDecl.isSetlike() or iterableDecl.isMaplike():
- res = f"crate::dom::bindings::iterable::{res}"
- return res