aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/parser/WebIDL.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen/parser/WebIDL.py')
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py824
1 files changed, 602 insertions, 222 deletions
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index df88cf120dd..b934c21db5b 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -1,16 +1,18 @@
# 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/.
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
""" A WebIDL parser. """
+from __future__ import print_function
from ply import lex, yacc
import re
import os
import traceback
import math
import string
-from collections import defaultdict
+from collections import defaultdict, OrderedDict
+from itertools import chain
# Machinery
@@ -40,32 +42,22 @@ def parseInt(literal):
return value * sign
-# Magic for creating enums
-def M_add_class_attribs(attribs, start):
- def foo(name, bases, dict_):
- for v, k in enumerate(attribs):
- dict_[k] = start + v
- assert 'length' not in dict_
- dict_['length'] = start + len(attribs)
- return type(name, bases, dict_)
- return foo
-
-
def enum(*names, **kw):
- if len(kw) == 1:
- base = kw['base'].__class__
- start = base.length
- else:
- assert len(kw) == 0
- base = object
- start = 0
-
- class Foo(base):
- __metaclass__ = M_add_class_attribs(names, start)
-
+ class Foo(object):
+ attrs = OrderedDict()
+ def __init__(self, names):
+ for v, k in enumerate(names):
+ self.attrs[k] = v
+ def __getattr__(self, attr):
+ if attr in self.attrs:
+ return self.attrs[attr]
+ raise AttributeError
def __setattr__(self, name, value): # this makes it read-only
raise NotImplementedError
- return Foo()
+
+ if "base" not in kw:
+ return Foo(names)
+ return Foo(chain(kw["base"].attrs.keys(), names))
class WebIDLError(Exception):
@@ -322,7 +314,7 @@ class IDLScope(IDLObject):
newObject.location)
raise WebIDLError(
- "Multiple unresolvable definitions of identifier '%s' in scope '%s%s"
+ "Multiple unresolvable definitions of identifier '%s' in scope '%s'%s"
% (identifier.name, str(self), conflictdesc), [])
def _lookupIdentifier(self, identifier):
@@ -482,9 +474,6 @@ class IDLExposureMixins():
def isExposedOnMainThread(self):
return self.isExposedInWindow()
- def isExposedOffMainThread(self):
- return len(self.exposureSet - {'Window', 'FakeTestPrimaryGlobal'}) > 0
-
def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0
@@ -568,6 +557,9 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def isNavigatorProperty(self):
return False
+ def isSerializable(self):
+ return False
+
def _getDependentObjects(self):
return set()
@@ -613,7 +605,7 @@ class IDLPartialInterfaceOrNamespace(IDLObject):
self._haveSecureContextExtendedAttribute = False
self._nonPartialInterfaceOrNamespace = nonPartialInterfaceOrNamespace
self._finished = False
- nonPartialInterfaceOrNamespace.addPartialInterface(self)
+ nonPartialInterfaceOrNamespace.addPartial(self)
def addExtendedAttributes(self, attrs):
for attr in attrs:
@@ -684,29 +676,212 @@ def globalNameSetToExposureSet(globalScope, nameSet, exposureSet):
for name in nameSet:
exposureSet.update(globalScope.globalNameMapping[name])
+class IDLInterfaceOrInterfaceMixinOrNamespace(IDLObjectWithScope, IDLExposureMixins):
+ def __init__(self, location, parentScope, name):
+ assert isinstance(parentScope, IDLScope)
+ assert isinstance(name, IDLUnresolvedIdentifier)
+
+ self._finished = False
+ self.members = []
+ self._partials = []
+ self._extendedAttrDict = {}
+ self._isKnownNonPartial = False
+
+ IDLObjectWithScope.__init__(self, location, parentScope, name)
+ IDLExposureMixins.__init__(self, location)
+
+ def finish(self, scope):
+ if not self._isKnownNonPartial:
+ raise WebIDLError("%s does not have a non-partial declaration" %
+ str(self), [self.location])
+
+ IDLExposureMixins.finish(self, scope)
+
+ # Now go ahead and merge in our partials.
+ for partial in self._partials:
+ partial.finish(scope)
+ self.addExtendedAttributes(partial.propagatedExtendedAttrs)
+ self.members.extend(partial.members)
+
+ def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
+ assert isinstance(scope, IDLScope)
+ assert isinstance(originalObject, IDLInterfaceMember)
+ assert isinstance(newObject, IDLInterfaceMember)
+
+ retval = IDLScope.resolveIdentifierConflict(self, scope, identifier,
+ originalObject, newObject)
+
+ # Might be a ctor, which isn't in self.members
+ if newObject in self.members:
+ self.members.remove(newObject)
+ return retval
+
+ def typeName(self):
+ if self.isInterface():
+ return "interface"
+ if self.isNamespace():
+ return "namespace"
+ return "interface mixin"
+
+ def getExtendedAttribute(self, name):
+ return self._extendedAttrDict.get(name, None)
+
+ def setNonPartial(self, location, members):
+ if self._isKnownNonPartial:
+ raise WebIDLError("Two non-partial definitions for the "
+ "same %s" % self.typeName(),
+ [location, self.location])
+ self._isKnownNonPartial = True
+ # Now make it look like we were parsed at this new location, since
+ # that's the place where the interface is "really" defined
+ self.location = location
+ # Put the new members at the beginning
+ self.members = members + self.members
+
+ def addPartial(self, partial):
+ assert self.identifier.name == partial.identifier.name
+ self._partials.append(partial)
+
+ def getPartials(self):
+ # Don't let people mutate our guts.
+ return list(self._partials)
+
+ def finishMembers(self, scope):
+ # Assuming we've merged in our partials, set the _exposureGlobalNames on
+ # any members that don't have it set yet. Note that any partial
+ # interfaces that had [Exposed] set have already set up
+ # _exposureGlobalNames on all the members coming from them, so this is
+ # just implementing the "members default to interface or interface mixin
+ # that defined them" and "partial interfaces or interface mixins default
+ # to interface or interface mixin they're a partial for" rules from the
+ # spec.
+ for m in self.members:
+ # If m, or the partial m came from, had [Exposed]
+ # specified, it already has a nonempty exposure global names set.
+ if len(m._exposureGlobalNames) == 0:
+ m._exposureGlobalNames.update(self._exposureGlobalNames)
+
+ # resolve() will modify self.members, so we need to iterate
+ # over a copy of the member list here.
+ for member in list(self.members):
+ member.resolve(self)
+
+ for member in self.members:
+ member.finish(scope)
+
+ # Now that we've finished our members, which has updated their exposure
+ # sets, make sure they aren't exposed in places where we are not.
+ for member in self.members:
+ if not member.exposureSet.issubset(self.exposureSet):
+ raise WebIDLError("Interface or interface mixin member has"
+ "larger exposure set than its container",
+ [member.location, self.location])
+
+
+class IDLInterfaceMixin(IDLInterfaceOrInterfaceMixinOrNamespace):
+ def __init__(self, location, parentScope, name, members, isKnownNonPartial):
+ self.actualExposureGlobalNames = set()
+
+ assert isKnownNonPartial or len(members) == 0
+ IDLInterfaceOrInterfaceMixinOrNamespace.__init__(self, location, parentScope, name)
+
+ if isKnownNonPartial:
+ self.setNonPartial(location, members)
+
+ def __str__(self):
+ return "Interface mixin '%s'" % self.identifier.name
+
+ def finish(self, scope):
+ if self._finished:
+ return
+ self._finished = True
+
+ # Expose to the globals of interfaces that includes this mixin if this
+ # mixin has no explicit [Exposed] so that its members can be exposed
+ # based on the base interface exposure set.
+ # Make sure this is done before IDLExposureMixins.finish call to
+ # prevent exposing to PrimaryGlobal by default.
+ hasImplicitExposure = len(self._exposureGlobalNames) == 0
+ if hasImplicitExposure:
+ self._exposureGlobalNames.update(self.actualExposureGlobalNames)
+
+ IDLInterfaceOrInterfaceMixinOrNamespace.finish(self, scope)
+
+ self.finishMembers(scope)
+
+ def validate(self):
+ for member in self.members:
+
+ if member.isAttr():
+ if member.inherit:
+ raise WebIDLError("Interface mixin member cannot include "
+ "an inherited attribute",
+ [member.location, self.location])
+ if member.isStatic():
+ raise WebIDLError("Interface mixin member cannot include "
+ "a static member",
+ [member.location, self.location])
+
+ if member.isMethod():
+ if member.isStatic():
+ raise WebIDLError("Interface mixin member cannot include "
+ "a static operation",
+ [member.location, self.location])
+ if (member.isGetter() or
+ member.isSetter() or
+ member.isDeleter() or
+ member.isLegacycaller()):
+ raise WebIDLError("Interface mixin member cannot include a "
+ "special operation",
+ [member.location, self.location])
+
+ def addExtendedAttributes(self, attrs):
+ for attr in attrs:
+ identifier = attr.identifier()
+
+ if identifier == "SecureContext":
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must take no arguments" % identifier,
+ [attr.location])
+ # This gets propagated to all our members.
+ for member in self.members:
+ if member.getExtendedAttribute("SecureContext"):
+ raise WebIDLError("[SecureContext] specified on both "
+ "an interface mixin member and on"
+ "the interface mixin itself",
+ [member.location, attr.location])
+ member.addExtendedAttributes([attr])
+ elif identifier == "Exposed":
+ convertExposedAttrToGlobalNameSet(attr,
+ self._exposureGlobalNames)
+ else:
+ raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
+ [attr.location])
+
+ attrlist = attr.listValue()
+ self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
-class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
+ def _getDependentObjects(self):
+ return set(self.members)
+
+
+class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
def __init__(self, location, parentScope, name, parent, members,
isKnownNonPartial, toStringTag):
- assert isinstance(parentScope, IDLScope)
- assert isinstance(name, IDLUnresolvedIdentifier)
assert isKnownNonPartial or not parent
assert isKnownNonPartial or len(members) == 0
self.parent = None
self._callback = False
- self._finished = False
- self.members = []
self.maplikeOrSetlikeOrIterable = None
- self._partialInterfaces = []
- self._extendedAttrDict = {}
# namedConstructors needs deterministic ordering because bindings code
# outputs the constructs in the order that namedConstructors enumerates
# them.
self.namedConstructors = list()
+ self.legacyWindowAliases = []
self.implementedInterfaces = set()
+ self.includedMixins = set()
self._consequential = False
- self._isKnownNonPartial = False
# self.interfacesBasedOnSelf is the set of interfaces that inherit from
# self or have self as a consequential interface, including self itself.
# Used for distinguishability checking.
@@ -727,8 +902,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
self.toStringTag = toStringTag
- IDLObjectWithScope.__init__(self, location, parentScope, name)
- IDLExposureMixins.__init__(self, location)
+ IDLInterfaceOrInterfaceMixinOrNamespace.__init__(self, location, parentScope, name)
if isKnownNonPartial:
self.setNonPartial(location, parent, members)
@@ -748,37 +922,23 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
def isIteratorInterface(self):
return self.iterableInterface is not None
- def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
- assert isinstance(scope, IDLScope)
- assert isinstance(originalObject, IDLInterfaceMember)
- assert isinstance(newObject, IDLInterfaceMember)
-
- retval = IDLScope.resolveIdentifierConflict(self, scope, identifier,
- originalObject, newObject)
-
- # Might be a ctor, which isn't in self.members
- if newObject in self.members:
- self.members.remove(newObject)
- return retval
-
def finish(self, scope):
if self._finished:
return
self._finished = True
- if not self._isKnownNonPartial:
- raise WebIDLError("Interface %s does not have a non-partial "
- "declaration" % self.identifier.name,
- [self.location])
-
- IDLExposureMixins.finish(self, scope)
+ IDLInterfaceOrInterfaceMixinOrNamespace.finish(self, scope)
- # Now go ahead and merge in our partial interfaces.
- for partial in self._partialInterfaces:
- partial.finish(scope)
- self.addExtendedAttributes(partial.propagatedExtendedAttrs)
- self.members.extend(partial.members)
+ if len(self.legacyWindowAliases) > 0:
+ if not self.hasInterfaceObject():
+ raise WebIDLError("Interface %s unexpectedly has [LegacyWindowAlias] "
+ "and [NoInterfaceObject] together" % self.identifier.name,
+ [self.location])
+ if not self.isExposedInWindow():
+ raise WebIDLError("Interface %s has [LegacyWindowAlias] "
+ "but not exposed in Window" % self.identifier.name,
+ [self.location])
# Generate maplike/setlike interface members. Since generated members
# need to be treated like regular interface members, do this before
@@ -801,19 +961,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# our required methods in Codegen. Generate members now.
self.maplikeOrSetlikeOrIterable.expand(self.members, self.isJSImplemented())
- # Now that we've merged in our partial interfaces, set the
- # _exposureGlobalNames on any members that don't have it set yet. Note
- # that any partial interfaces that had [Exposed] set have already set up
- # _exposureGlobalNames on all the members coming from them, so this is
- # just implementing the "members default to interface that defined them"
- # and "partial interfaces default to interface they're a partial for"
- # rules from the spec.
- for m in self.members:
- # If m, or the partial interface m came from, had [Exposed]
- # specified, it already has a nonempty exposure global names set.
- if len(m._exposureGlobalNames) == 0:
- m._exposureGlobalNames.update(self._exposureGlobalNames)
-
assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
parent = self.parent.finish(scope) if self.parent else None
if parent and isinstance(parent, IDLExternalInterface):
@@ -909,6 +1056,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
for iface in self.implementedInterfaces:
iface.finish(scope)
+ for mixin in self.includedMixins:
+ mixin.finish(scope)
cycleInGraph = self.findInterfaceLoopPoint(self)
if cycleInGraph:
@@ -923,24 +1072,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# And that we're not consequential.
assert not self.isConsequential()
- # Now resolve() and finish() our members before importing the
- # ones from our implemented interfaces.
-
- # resolve() will modify self.members, so we need to iterate
- # over a copy of the member list here.
- for member in list(self.members):
- member.resolve(self)
-
- for member in self.members:
- member.finish(scope)
-
- # Now that we've finished our members, which has updated their exposure
- # sets, make sure they aren't exposed in places where we are not.
- for member in self.members:
- if not member.exposureSet.issubset(self.exposureSet):
- raise WebIDLError("Interface member has larger exposure set "
- "than the interface itself",
- [member.location, self.location])
+ self.finishMembers(scope)
ctor = self.ctor()
if ctor is not None:
@@ -962,7 +1094,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# self.members. Sort our consequential interfaces by name
# just so we have a consistent order.
for iface in sorted(self.getConsequentialInterfaces(),
- cmp=cmp,
key=lambda x: x.identifier.name):
# Flag the interface as being someone's consequential interface
iface.setIsConsequentialInterfaceOf(self)
@@ -994,6 +1125,10 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
self.members.extend(additionalMembers)
iface.interfacesImplementingSelf.add(self)
+ for mixin in sorted(self.includedMixins,
+ key=lambda x: x.identifier.name):
+ self.members.extend(mixin.members)
+
for ancestor in self.getInheritedInterfaces():
ancestor.interfacesBasedOnSelf.add(self)
if (ancestor.maplikeOrSetlikeOrIterable is not None and
@@ -1325,6 +1460,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
for bindingAlias in member.bindingAliases:
checkDuplicateNames(member, bindingAlias, "BindingAlias")
+
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object,
@@ -1427,6 +1563,10 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
assert(isinstance(implementedInterface, IDLInterface))
self.implementedInterfaces.add(implementedInterface)
+ def addIncludedMixin(self, includedMixin):
+ assert(isinstance(includedMixin, IDLInterfaceMixin))
+ self.includedMixins.add(includedMixin)
+
def getInheritedInterfaces(self):
"""
Returns a list of the interfaces this interface inherits from
@@ -1475,34 +1615,11 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
if loopPoint:
return loopPoint
return None
-
- def getExtendedAttribute(self, name):
- return self._extendedAttrDict.get(name, None)
-
def setNonPartial(self, location, parent, members):
assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
- if self._isKnownNonPartial:
- raise WebIDLError("Two non-partial definitions for the "
- "same %s" %
- ("interface" if self.isInterface()
- else "namespace"),
- [location, self.location])
- self._isKnownNonPartial = True
- # Now make it look like we were parsed at this new location, since
- # that's the place where the interface is "really" defined
- self.location = location
+ IDLInterfaceOrInterfaceMixinOrNamespace.setNonPartial(self, location, members)
assert not self.parent
self.parent = parent
- # Put the new members at the beginning
- self.members = members + self.members
-
- def addPartialInterface(self, partial):
- assert self.identifier.name == partial.identifier.name
- self._partialInterfaces.append(partial)
-
- def getPartialInterfaces(self):
- # Don't let people mutate our guts.
- return list(self._partialInterfaces)
def getJSImplementation(self):
classId = self.getExtendedAttribute("JSImplementation")
@@ -1565,6 +1682,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
def _getDependentObjects(self):
deps = set(self.members)
deps.update(self.implementedInterfaces)
+ deps.update(self.includedMixins)
if self.parent:
deps.add(self.parent)
return deps
@@ -1640,6 +1758,11 @@ class IDLInterface(IDLInterfaceOrNamespace):
raise WebIDLError(str(identifier) + " must take no arguments",
[attr.location])
+ if self.globalNames:
+ raise WebIDLError("[%s] must not be specified together with "
+ "[Global]" % identifier,
+ [self.location, attr.location])
+
args = attr.args() if attr.hasArgs() else []
retType = IDLWrapperType(self.location, self)
@@ -1700,6 +1823,10 @@ class IDLInterface(IDLInterfaceOrNamespace):
"an interface with inherited interfaces",
[attr.location, self.location])
elif identifier == "Global":
+ if self.ctor() or self.namedConstructors:
+ raise WebIDLError("[Global] cannot be specified on an "
+ "interface with a constructor",
+ [attr.location, self.location]);
if attr.hasValue():
self.globalNames = [attr.value()]
elif attr.hasArgs():
@@ -1723,6 +1850,18 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.parentScope.addIfaceGlobalNames(self.identifier.name,
[self.identifier.name])
self._isOnGlobalProtoChain = True
+ elif identifier == "LegacyWindowAlias":
+ if attr.hasValue():
+ self.legacyWindowAliases = [attr.value()]
+ elif attr.hasArgs():
+ self.legacyWindowAliases = attr.args()
+ else:
+ raise WebIDLError("[%s] must either take an identifier "
+ "or take an identifier list" % identifier,
+ [attr.location])
+ for alias in self.legacyWindowAliases:
+ unresolved = IDLUnresolvedIdentifier(attr.location, alias)
+ IDLObjectWithIdentifier(attr.location, self.parentScope, unresolved)
elif identifier == "SecureContext":
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
@@ -1744,6 +1883,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
+ identifier == "Serializable" or
identifier == "Abstract" or
identifier == "Inline"):
# Known extended attributes that do not take values
@@ -1770,6 +1910,19 @@ class IDLInterface(IDLInterfaceOrNamespace):
attrlist = attr.listValue()
self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
+ def validate(self):
+ IDLInterfaceOrNamespace.validate(self)
+ if self.parent and self.isSerializable() and not self.parent.isSerializable():
+ raise WebIDLError(
+ "Serializable interface inherits from non-serializable "
+ "interface. Per spec, that means the object should not be "
+ "serializable, so chances are someone made a mistake here "
+ "somewhere.",
+ [self.location, self.parent.location])
+
+ def isSerializable(self):
+ return self.getExtendedAttribute("Serializable")
+
class IDLNamespace(IDLInterfaceOrNamespace):
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
@@ -1805,7 +1958,9 @@ class IDLNamespace(IDLInterfaceOrNamespace):
if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location])
- elif identifier == "Pref" or identifier == "Func":
+ elif (identifier == "Pref" or
+ identifier == "HeaderFile" or
+ identifier == "Func"):
# Known extended attributes that take a string value
if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier,
@@ -1818,6 +1973,9 @@ class IDLNamespace(IDLInterfaceOrNamespace):
attrlist = attr.listValue()
self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
+ def isSerializable(self):
+ return False
+
class IDLDictionary(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members):
@@ -1877,7 +2035,7 @@ class IDLDictionary(IDLObjectWithScope):
assert member.type.isComplete()
# Members of a dictionary are sorted in lexicographic order
- self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
+ self.members.sort(key=lambda x: x.identifier.name)
inheritedMembers = []
ancestor = self.parent
@@ -2232,7 +2390,7 @@ class IDLUnresolvedType(IDLType):
assert obj
if obj.isType():
- print obj
+ print(obj)
assert not obj.isType()
if obj.isTypedef():
assert self.name.name == obj.identifier.name
@@ -3562,8 +3720,6 @@ class IDLNullValue(IDLObject):
def coerceToType(self, type, location):
if (not isinstance(type, IDLNullableType) and
not (type.isUnion() and type.hasNullableType) and
- not (type.isUnion() and type.hasDictionaryType()) and
- not type.isDictionary() and
not type.isAny()):
raise WebIDLError("Cannot coerce null value to type %s." % type,
[location])
@@ -3612,6 +3768,35 @@ class IDLEmptySequenceValue(IDLObject):
return set()
+class IDLDefaultDictionaryValue(IDLObject):
+ def __init__(self, location):
+ IDLObject.__init__(self, location)
+ self.type = None
+ self.value = None
+
+ def coerceToType(self, type, location):
+ if type.isUnion():
+ # We use the flat member types here, because if we have a nullable
+ # member type, or a nested union, we want the type the value
+ # actually coerces to, not the nullable or nested union type.
+ for subtype in type.unroll().flatMemberTypes:
+ try:
+ return self.coerceToType(subtype, location)
+ except:
+ pass
+
+ if not type.isDictionary():
+ raise WebIDLError("Cannot coerce default dictionary value to type %s." % type,
+ [location])
+
+ defaultDictionaryValue = IDLDefaultDictionaryValue(self.location)
+ defaultDictionaryValue.type = type
+ return defaultDictionaryValue
+
+ def _getDependentObjects(self):
+ return set()
+
+
class IDLUndefinedValue(IDLObject):
def __init__(self, location):
IDLObject.__init__(self, location)
@@ -3689,7 +3874,7 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
def finish(self, scope):
# We better be exposed _somewhere_.
if (len(self._exposureGlobalNames) == 0):
- print self.identifier.name
+ print(self.identifier.name)
assert len(self._exposureGlobalNames) != 0
IDLExposureMixins.finish(self, scope)
@@ -4577,7 +4762,9 @@ class IDLArgument(IDLObjectWithIdentifier):
elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True
elif (self.dictionaryMember and
- (identifier == "ChromeOnly" or identifier == "Func")):
+ (identifier == "ChromeOnly" or
+ identifier == "Func" or
+ identifier == "Pref")):
if not self.optional:
raise WebIDLError("[%s] must not be used on a required "
"dictionary member" % identifier,
@@ -4609,14 +4796,7 @@ class IDLArgument(IDLObjectWithIdentifier):
assert not isinstance(type.name, IDLUnresolvedIdentifier)
self.type = type
- if ((self.type.isDictionary() or
- self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
- self.optional and not self.defaultValue and not self.variadic and
- not self.dictionaryMember):
- # Default optional non-variadic dictionary arguments to null,
- # for simplicity, so the codegen doesn't have to special-case this.
- self.defaultValue = IDLNullValue(self.location)
- elif self.type.isAny():
+ if self.type.isAny():
assert (self.defaultValue is None or
isinstance(self.defaultValue, IDLNullValue))
# optional 'any' values always have a default value
@@ -4648,7 +4828,7 @@ class IDLArgument(IDLObjectWithIdentifier):
class IDLCallback(IDLObjectWithScope):
- def __init__(self, location, parentScope, identifier, returnType, arguments):
+ def __init__(self, location, parentScope, identifier, returnType, arguments, isConstructor):
assert isinstance(returnType, IDLType)
self._returnType = returnType
@@ -4663,10 +4843,15 @@ class IDLCallback(IDLObjectWithScope):
self._treatNonCallableAsNull = False
self._treatNonObjectAsNull = False
+ self._isRunScriptBoundary = False
+ self._isConstructor = isConstructor
def isCallback(self):
return True
+ def isConstructor(self):
+ return self._isConstructor
+
def signatures(self):
return [(self._returnType, self._arguments)]
@@ -4699,7 +4884,16 @@ class IDLCallback(IDLObjectWithScope):
if attr.identifier() == "TreatNonCallableAsNull":
self._treatNonCallableAsNull = True
elif attr.identifier() == "TreatNonObjectAsNull":
+ if self._isConstructor:
+ raise WebIDLError("[TreatNonObjectAsNull] is not supported "
+ "on constructors", [self.location])
self._treatNonObjectAsNull = True
+ elif attr.identifier() == "MOZ_CAN_RUN_SCRIPT_BOUNDARY":
+ if self._isConstructor:
+ raise WebIDLError("[MOZ_CAN_RUN_SCRIPT_BOUNDARY] is not "
+ "permitted on constructors",
+ [self.location])
+ self._isRunScriptBoundary = True
else:
unhandledAttrs.append(attr)
if self._treatNonCallableAsNull and self._treatNonObjectAsNull:
@@ -4711,6 +4905,9 @@ class IDLCallback(IDLObjectWithScope):
def _getDependentObjects(self):
return set([self._returnType] + self._arguments)
+ def isRunScriptBoundary(self):
+ return self._isRunScriptBoundary;
+
class IDLCallbackType(IDLType):
def __init__(self, location, callback):
@@ -4757,6 +4954,9 @@ class IDLMethodOverload:
deps.add(self.returnType)
return deps
+ def includesRestrictedFloatArgument(self):
+ return any(arg.type.includesRestrictedFloat() for arg in self.arguments)
+
class IDLMethod(IDLInterfaceMember, IDLScope):
@@ -4928,10 +5128,25 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def addOverload(self, method):
assert len(method._overloads) == 1
- if self._extendedAttrDict != method ._extendedAttrDict:
- raise WebIDLError("Extended attributes differ on different "
- "overloads of %s" % method.identifier,
- [self.location, method.location])
+ if self._extendedAttrDict != method._extendedAttrDict:
+ extendedAttrDiff = set(self._extendedAttrDict.keys()) ^ set(method._extendedAttrDict.keys())
+
+ if extendedAttrDiff == { "LenientFloat" }:
+ if "LenientFloat" not in self._extendedAttrDict:
+ for overload in self._overloads:
+ if overload.includesRestrictedFloatArgument():
+ raise WebIDLError("Restricted float behavior differs on different "
+ "overloads of %s" % method.identifier,
+ [overload.location, method.location])
+ self._extendedAttrDict["LenientFloat"] = method._extendedAttrDict["LenientFloat"]
+ elif method._overloads[0].includesRestrictedFloatArgument():
+ raise WebIDLError("Restricted float behavior differs on different "
+ "overloads of %s" % method.identifier,
+ [self.location, method.location])
+ else:
+ raise WebIDLError("Extended attributes differ on different "
+ "overloads of %s" % method.identifier,
+ [self.location, method.location])
self._overloads.extend(method._overloads)
@@ -5039,6 +5254,15 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
"must be optional",
[argument.location])
+ if (not argument.defaultValue and
+ all(arg.optional for arg in arguments[idx+1:])):
+ raise WebIDLError("Dictionary argument without any "
+ "required fields or union argument "
+ "containing such dictionary not "
+ "followed by a required argument "
+ "must have a default value",
+ [argument.location])
+
# An argument cannot be a Nullable Dictionary
if argument.type.nullable():
raise WebIDLError("An argument cannot be a nullable "
@@ -5162,12 +5386,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
[attr.location, self.location])
elif identifier == "LenientFloat":
# This is called before we've done overload resolution
- assert len(self.signatures()) == 1
- sig = self.signatures()[0]
- if not sig[0].isVoid():
+ overloads = self._overloads
+ assert len(overloads) == 1
+ if not overloads[0].returnType.isVoid():
raise WebIDLError("[LenientFloat] used on a non-void method",
[attr.location, self.location])
- if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
+ if not overloads[0].includesRestrictedFloatArgument():
raise WebIDLError("[LenientFloat] used on an operation with no "
"restricted float type arguments",
[attr.location, self.location])
@@ -5238,7 +5462,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
if self.signatures()[0][0] != BuiltinTypes[IDLBuiltinType.Types.object]:
raise WebIDLError("The return type of the default toJSON "
"operation must be 'object'",
- [attr.location, self.location]);
+ [attr.location, self.location])
elif (identifier == "Throws" or
identifier == "CanOOM" or
identifier == "NewObject" or
@@ -5251,7 +5475,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "NeedsSubjectPrincipal" or
identifier == "NeedsCallerType" or
identifier == "StaticClassOverride" or
- identifier == "NonEnumerable"):
+ identifier == "NonEnumerable" or
+ identifier == "Unexposed"):
# Known attributes that we don't need to do anything with here
pass
else:
@@ -5318,6 +5543,49 @@ class IDLImplementsStatement(IDLObject):
"allowed on implements statements",
[attrs[0].location, self.location])
+class IDLIncludesStatement(IDLObject):
+ def __init__(self, location, interface, mixin):
+ IDLObject.__init__(self, location)
+ self.interface = interface
+ self.mixin = mixin
+ self._finished = False
+
+ def finish(self, scope):
+ if self._finished:
+ return
+ self._finished = True
+ assert(isinstance(self.interface, IDLIdentifierPlaceholder))
+ assert(isinstance(self.mixin, IDLIdentifierPlaceholder))
+ interface = self.interface.finish(scope)
+ mixin = self.mixin.finish(scope)
+ # NOTE: we depend on not setting self.interface and
+ # self.mixin here to keep track of the original
+ # locations.
+ if not isinstance(interface, IDLInterface):
+ raise WebIDLError("Left-hand side of 'includes' is not an "
+ "interface",
+ [self.interface.location])
+ if interface.isCallback():
+ raise WebIDLError("Left-hand side of 'includes' is a callback "
+ "interface",
+ [self.interface.location])
+ if not isinstance(mixin, IDLInterfaceMixin):
+ raise WebIDLError("Right-hand side of 'includes' is not an "
+ "interface mixin",
+ [self.mixin.location])
+ mixin.actualExposureGlobalNames.update(interface._exposureGlobalNames)
+ interface.addIncludedMixin(mixin)
+ self.interface = interface
+ self.mixin = mixin
+
+ def validate(self):
+ pass
+
+ def addExtendedAttributes(self, attrs):
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on includes statements",
+ [attrs[0].location, self.location])
class IDLExtendedAttribute(IDLObject):
"""
@@ -5414,12 +5682,14 @@ class Tokenizer(object):
"module": "MODULE",
"interface": "INTERFACE",
"partial": "PARTIAL",
+ "mixin": "MIXIN",
"dictionary": "DICTIONARY",
"exception": "EXCEPTION",
"enum": "ENUM",
"callback": "CALLBACK",
"typedef": "TYPEDEF",
"implements": "IMPLEMENTS",
+ "includes": "INCLUDES",
"const": "CONST",
"null": "NULL",
"true": "TRUE",
@@ -5478,6 +5748,7 @@ class Tokenizer(object):
"iterable": "ITERABLE",
"namespace": "NAMESPACE",
"ReadableStream": "READABLESTREAM",
+ "constructor": "CONSTRUCTOR",
}
tokens.extend(keywords.values())
@@ -5573,7 +5844,7 @@ class Parser(Tokenizer):
def p_Definition(self, p):
"""
- Definition : CallbackOrInterface
+ Definition : CallbackOrInterfaceOrMixin
| Namespace
| Partial
| Dictionary
@@ -5581,13 +5852,14 @@ class Parser(Tokenizer):
| Enum
| Typedef
| ImplementsStatement
+ | IncludesStatement
"""
p[0] = p[1]
assert p[1] # We might not have implemented something ...
- def p_CallbackOrInterfaceCallback(self, p):
+ def p_CallbackOrInterfaceOrMixinCallback(self, p):
"""
- CallbackOrInterface : CALLBACK CallbackRestOrInterface
+ CallbackOrInterfaceOrMixin : CALLBACK CallbackRestOrInterface
"""
if p[2].isInterface():
assert isinstance(p[2], IDLInterface)
@@ -5595,16 +5867,17 @@ class Parser(Tokenizer):
p[0] = p[2]
- def p_CallbackOrInterfaceInterface(self, p):
+ def p_CallbackOrInterfaceOrMixinInterfaceOrMixin(self, p):
"""
- CallbackOrInterface : Interface
+ CallbackOrInterfaceOrMixin : INTERFACE InterfaceOrMixin
"""
- p[0] = p[1]
+ p[0] = p[2]
def p_CallbackRestOrInterface(self, p):
"""
CallbackRestOrInterface : CallbackRest
- | Interface
+ | CallbackConstructorRest
+ | CallbackInterface
"""
assert p[1]
p[0] = p[1]
@@ -5637,7 +5910,7 @@ class Parser(Tokenizer):
[location, existingObj.location])
existingObj.setNonPartial(*nonPartialArgs)
return existingObj
- except Exception, ex:
+ except Exception as ex:
if isinstance(ex, WebIDLError):
raise ex
pass
@@ -5645,14 +5918,27 @@ class Parser(Tokenizer):
# True for isKnownNonPartial
return constructor(*(constructorArgs + [True]))
- def p_Interface(self, p):
+ def p_InterfaceOrMixin(self, p):
"""
- Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
+ InterfaceOrMixin : InterfaceRest
+ | MixinRest
+ """
+ p[0] = p[1]
+
+ def p_CallbackInterface(self, p):
+ """
+ CallbackInterface : INTERFACE InterfaceRest
+ """
+ p[0] = p[2]
+
+ def p_InterfaceRest(self, p):
+ """
+ InterfaceRest : IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
"""
location = self.getLocation(p, 1)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
- members = p[5]
- parent = p[3]
+ identifier = IDLUnresolvedIdentifier(location, p[1])
+ members = p[4]
+ parent = p[2]
p[0] = self.handleNonPartialObject(
location, identifier, IDLInterface,
@@ -5661,10 +5947,10 @@ class Parser(Tokenizer):
def p_InterfaceForwardDecl(self, p):
"""
- Interface : INTERFACE IDENTIFIER SEMICOLON
+ InterfaceRest : IDENTIFIER SEMICOLON
"""
location = self.getLocation(p, 1)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ identifier = IDLUnresolvedIdentifier(location, p[1])
try:
if self.globalScope()._lookupIdentifier(identifier):
@@ -5675,13 +5961,26 @@ class Parser(Tokenizer):
"%s and %s" % (identifier.name, p[0]),
[location, p[0].location])
return
- except Exception, ex:
+ except Exception as ex:
if isinstance(ex, WebIDLError):
raise ex
pass
p[0] = IDLExternalInterface(location, self.globalScope(), identifier)
+ def p_MixinRest(self, p):
+ """
+ MixinRest : MIXIN IDENTIFIER LBRACE MixinMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[4]
+
+ p[0] = self.handleNonPartialObject(
+ location, identifier, IDLInterfaceMixin,
+ [location, self.globalScope(), identifier, members],
+ [location, members])
+
def p_Namespace(self, p):
"""
Namespace : NAMESPACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
@@ -5701,10 +6000,15 @@ class Parser(Tokenizer):
"""
p[0] = p[2]
+ def p_PartialDefinitionInterface(self, p):
+ """
+ PartialDefinition : INTERFACE PartialInterfaceOrPartialMixin
+ """
+ p[0] = p[2]
+
def p_PartialDefinition(self, p):
"""
- PartialDefinition : PartialInterface
- | PartialNamespace
+ PartialDefinition : PartialNamespace
| PartialDictionary
"""
p[0] = p[1]
@@ -5739,7 +6043,7 @@ class Parser(Tokenizer):
"non-%s object" %
(prettyname, prettyname),
[location, nonPartialObject.location])
- except Exception, ex:
+ except Exception as ex:
if isinstance(ex, WebIDLError):
raise ex
pass
@@ -5747,34 +6051,55 @@ class Parser(Tokenizer):
if not nonPartialObject:
nonPartialObject = nonPartialConstructor(
# No members, False for isKnownNonPartial
- *(nonPartialConstructorArgs + [[], False]))
+ *(nonPartialConstructorArgs), members=[], isKnownNonPartial=False)
partialObject = None
if isinstance(nonPartialObject, IDLDictionary):
partialObject = IDLPartialDictionary(
*(partialConstructorArgs + [nonPartialObject]))
- elif isinstance(nonPartialObject, (IDLInterface, IDLNamespace)):
+ elif isinstance(nonPartialObject, (IDLInterface, IDLInterfaceMixin, IDLNamespace)):
partialObject = IDLPartialInterfaceOrNamespace(
*(partialConstructorArgs + [nonPartialObject]))
else:
raise WebIDLError("Unknown partial object type %s" %
- type(partialObject))
+ type(partialObject),
+ [location])
return partialObject
- def p_PartialInterface(self, p):
+ def p_PartialInterfaceOrPartialMixin(self, p):
"""
- PartialInterface : INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
+ PartialInterfaceOrPartialMixin : PartialInterfaceRest
+ | PartialMixinRest
+ """
+ p[0] = p[1]
+
+ def p_PartialInterfaceRest(self, p):
+ """
+ PartialInterfaceRest : IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
"""
location = self.getLocation(p, 1)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
- members = p[4]
+ identifier = IDLUnresolvedIdentifier(location, p[1])
+ members = p[3]
p[0] = self.handlePartialObject(
location, identifier, IDLInterface,
[location, self.globalScope(), identifier, None],
[location, identifier, members])
+ def p_PartialMixinRest(self, p):
+ """
+ PartialMixinRest : MIXIN IDENTIFIER LBRACE MixinMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[4]
+
+ p[0] = self.handlePartialObject(
+ location, identifier, IDLInterfaceMixin,
+ [location, self.globalScope(), identifier],
+ [location, identifier, members])
+
def p_PartialNamespace(self, p):
"""
PartialNamespace : NAMESPACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
@@ -5817,7 +6142,7 @@ class Parser(Tokenizer):
"""
InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
"""
- p[0] = [p[2]] if p[2] else []
+ p[0] = [p[2]]
assert not p[1] or p[2]
p[2].addExtendedAttributes(p[1])
@@ -5837,6 +6162,32 @@ class Parser(Tokenizer):
"""
p[0] = p[1]
+
+ def p_MixinMembersEmpty(self, p):
+ """
+ MixinMembers :
+ """
+ p[0] = []
+
+ def p_MixinMembers(self, p):
+ """
+ MixinMembers : ExtendedAttributeList MixinMember MixinMembers
+ """
+ p[0] = [p[2]]
+
+ assert not p[1] or p[2]
+ p[2].addExtendedAttributes(p[1])
+
+ p[0].extend(p[3])
+
+ def p_MixinMember(self, p):
+ """
+ MixinMember : Const
+ | Attribute
+ | Operation
+ """
+ p[0] = p[1]
+
def p_Dictionary(self, p):
"""
Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
@@ -5905,12 +6256,23 @@ class Parser(Tokenizer):
"""
DefaultValue : ConstValue
| LBRACKET RBRACKET
+ | LBRACE RBRACE
"""
if len(p) == 2:
p[0] = p[1]
else:
- assert len(p) == 3 # Must be []
- p[0] = IDLEmptySequenceValue(self.getLocation(p, 1))
+ assert len(p) == 3 # Must be [] or {}
+ if p[1] == "[":
+ p[0] = IDLEmptySequenceValue(self.getLocation(p, 1))
+ else:
+ assert p[1] == "{"
+ p[0] = IDLDefaultDictionaryValue(self.getLocation(p, 1))
+
+ def p_DefaultValueNull(self, p):
+ """
+ DefaultValue : NULL
+ """
+ p[0] = IDLNullValue(self.getLocation(p, 1))
def p_Exception(self, p):
"""
@@ -5967,7 +6329,15 @@ class Parser(Tokenizer):
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
p[0] = IDLCallback(self.getLocation(p, 1), self.globalScope(),
- identifier, p[3], p[5])
+ identifier, p[3], p[5], isConstructor=False)
+
+ def p_CallbackConstructorRest(self, p):
+ """
+ CallbackConstructorRest : CONSTRUCTOR IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
+ """
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ p[0] = IDLCallback(self.getLocation(p, 2), self.globalScope(),
+ identifier, p[4], p[6], isConstructor=True)
def p_ExceptionMembers(self, p):
"""
@@ -5994,6 +6364,15 @@ class Parser(Tokenizer):
p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor,
implementee)
+ def p_IncludesStatement(self, p):
+ """
+ IncludesStatement : ScopedName INCLUDES ScopedName SEMICOLON
+ """
+ assert(p[2] == "includes")
+ interface = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1])
+ mixin = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3])
+ p[0] = IDLIncludesStatement(self.getLocation(p, 1), interface, mixin)
+
def p_Const(self, p):
"""
Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON
@@ -6041,12 +6420,6 @@ class Parser(Tokenizer):
stringType = BuiltinTypes[IDLBuiltinType.Types.domstring]
p[0] = IDLValue(location, stringType, p[1])
- def p_ConstValueNull(self, p):
- """
- ConstValue : NULL
- """
- p[0] = IDLNullValue(self.getLocation(p, 1))
-
def p_BooleanLiteralTrue(self, p):
"""
BooleanLiteral : TRUE
@@ -6442,6 +6815,7 @@ class Parser(Tokenizer):
| ATTRIBUTE
| CALLBACK
| CONST
+ | CONSTRUCTOR
| DELETER
| DICTIONARY
| ENUM
@@ -6566,6 +6940,7 @@ class Parser(Tokenizer):
| BYTE
| LEGACYCALLER
| CONST
+ | CONSTRUCTOR
| DELETER
| DOUBLE
| EXCEPTION
@@ -6619,9 +6994,9 @@ class Parser(Tokenizer):
"""
p[0] = p[2].withExtendedAttributes(p[1])
- def p_SingleTypeNonAnyType(self, p):
+ def p_SingleTypeDistinguishableType(self, p):
"""
- SingleType : NonAnyType
+ SingleType : DistinguishableType
"""
p[0] = p[1]
@@ -6631,6 +7006,14 @@ class Parser(Tokenizer):
"""
p[0] = BuiltinTypes[IDLBuiltinType.Types.any]
+ # Note: Promise<void> is allowed, so we want to parametrize on ReturnType,
+ # not Type. Promise types can't be null, hence no "Null" in there.
+ def p_SingleTypePromiseType(self, p):
+ """
+ SingleType : PROMISE LT ReturnType GT
+ """
+ p[0] = IDLPromiseType(self.getLocation(p, 1), p[3])
+
def p_UnionType(self, p):
"""
UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN
@@ -6639,9 +7022,9 @@ class Parser(Tokenizer):
types.extend(p[5])
p[0] = IDLUnionType(self.getLocation(p, 1), types)
- def p_UnionMemberTypeNonAnyType(self, p):
+ def p_UnionMemberTypeDistinguishableType(self, p):
"""
- UnionMemberType : ExtendedAttributeList NonAnyType
+ UnionMemberType : ExtendedAttributeList DistinguishableType
"""
p[0] = p[2].withExtendedAttributes(p[1])
@@ -6664,13 +7047,13 @@ class Parser(Tokenizer):
"""
p[0] = []
- def p_NonAnyType(self, p):
+ def p_DistinguishableType(self, p):
"""
- NonAnyType : PrimitiveType Null
- | ARRAYBUFFER Null
- | SHAREDARRAYBUFFER Null
- | READABLESTREAM Null
- | OBJECT Null
+ DistinguishableType : PrimitiveType Null
+ | ARRAYBUFFER Null
+ | SHAREDARRAYBUFFER Null
+ | READABLESTREAM Null
+ | OBJECT Null
"""
if p[1] == "object":
type = BuiltinTypes[IDLBuiltinType.Types.object]
@@ -6685,40 +7068,32 @@ class Parser(Tokenizer):
p[0] = self.handleNullable(type, p[2])
- def p_NonAnyTypeStringType(self, p):
+ def p_DistinguishableTypeStringType(self, p):
"""
- NonAnyType : StringType Null
+ DistinguishableType : StringType Null
"""
p[0] = self.handleNullable(p[1], p[2])
- def p_NonAnyTypeSequenceType(self, p):
+ def p_DistinguishableTypeSequenceType(self, p):
"""
- NonAnyType : SEQUENCE LT TypeWithExtendedAttributes GT Null
+ DistinguishableType : SEQUENCE LT TypeWithExtendedAttributes GT Null
"""
innerType = p[3]
type = IDLSequenceType(self.getLocation(p, 1), innerType)
p[0] = self.handleNullable(type, p[5])
- # Note: Promise<void> is allowed, so we want to parametrize on ReturnType,
- # not Type. Promise types can't be null, hence no "Null" in there.
- def p_NonAnyTypePromiseType(self, p):
+ def p_DistinguishableTypeRecordType(self, p):
"""
- NonAnyType : PROMISE LT ReturnType GT
- """
- p[0] = IDLPromiseType(self.getLocation(p, 1), p[3])
-
- def p_NonAnyTypeRecordType(self, p):
- """
- NonAnyType : RECORD LT StringType COMMA TypeWithExtendedAttributes GT Null
+ DistinguishableType : RECORD LT StringType COMMA TypeWithExtendedAttributes GT Null
"""
keyType = p[3]
valueType = p[5]
type = IDLRecordType(self.getLocation(p, 1), keyType, valueType)
p[0] = self.handleNullable(type, p[7])
- def p_NonAnyTypeScopedName(self, p):
+ def p_DistinguishableTypeScopedName(self, p):
"""
- NonAnyType : ScopedName Null
+ DistinguishableType : ScopedName Null
"""
assert isinstance(p[1], IDLUnresolvedIdentifier)
@@ -6748,28 +7123,26 @@ class Parser(Tokenizer):
type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
p[0] = self.handleNullable(type, p[2])
- def p_NonAnyTypeDate(self, p):
+ def p_DistinguishableTypeDate(self, p):
"""
- NonAnyType : DATE Null
+ DistinguishableType : DATE Null
"""
p[0] = self.handleNullable(BuiltinTypes[IDLBuiltinType.Types.date],
p[2])
def p_ConstType(self, p):
"""
- ConstType : PrimitiveType Null
+ ConstType : PrimitiveType
"""
- type = BuiltinTypes[p[1]]
- p[0] = self.handleNullable(type, p[2])
+ p[0] = BuiltinTypes[p[1]]
def p_ConstTypeIdentifier(self, p):
"""
- ConstType : IDENTIFIER Null
+ ConstType : IDENTIFIER
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
- type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
- p[0] = self.handleNullable(type, p[2])
+ p[0] = IDLUnresolvedType(self.getLocation(p, 1), identifier)
def p_PrimitiveTypeUint(self, p):
"""
@@ -7040,8 +7413,8 @@ class Parser(Tokenizer):
def _installBuiltins(self, scope):
assert isinstance(scope, IDLScope)
- # xrange omits the last value.
- for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
+ # range omits the last value.
+ for x in range(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
builtin = BuiltinTypes[x]
name = builtin.name
typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name)
@@ -7130,10 +7503,17 @@ class Parser(Tokenizer):
# XXX khuey hates this bit and wants to nuke it from orbit.
implementsStatements = [p for p in self._productions if
isinstance(p, IDLImplementsStatement)]
+ # Make sure we finish IDLIncludesStatements before we finish the
+ # IDLInterfaces.
+ includesStatements = [p for p in self._productions if
+ isinstance(p, IDLIncludesStatement)]
otherStatements = [p for p in self._productions if
- not isinstance(p, IDLImplementsStatement)]
+ not isinstance(p, (IDLImplementsStatement,
+ IDLIncludesStatement))]
for production in implementsStatements:
production.finish(self.globalScope())
+ for production in includesStatements:
+ production.finish(self.globalScope())
for production in otherStatements:
production.finish(self.globalScope())
@@ -7185,14 +7565,14 @@ def main():
f = open(fullPath, 'rb')
lines = f.readlines()
f.close()
- print fullPath
+ print(fullPath)
parser.parse(''.join(lines), fullPath)
parser.finish()
- except WebIDLError, e:
+ except WebIDLError as e:
if options.verbose_errors:
traceback.print_exc()
else:
- print e
+ print(e)
if __name__ == '__main__':
main()