dom/bindings/parser/WebIDL.py

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 """ A WebIDL parser. """
     7 from ply import lex, yacc
     8 import re
     9 import os
    10 import traceback
    11 import math
    13 # Machinery
    15 def parseInt(literal):
    16     string = literal
    17     sign = 0
    18     base = 0
    20     if string[0] == '-':
    21         sign = -1
    22         string = string[1:]
    23     else:
    24         sign = 1
    26     if string[0] == '0' and len(string) > 1:
    27         if string[1] == 'x' or string[1] == 'X':
    28             base = 16
    29             string = string[2:]
    30         else:
    31             base = 8
    32             string = string[1:]
    33     else:
    34         base = 10
    36     value = int(string, base)
    37     return value * sign
    39 # Magic for creating enums
    40 def M_add_class_attribs(attribs, start):
    41     def foo(name, bases, dict_):
    42         for v, k in enumerate(attribs):
    43             dict_[k] = start + v
    44         assert 'length' not in dict_
    45         dict_['length'] = start + len(attribs)
    46         return type(name, bases, dict_)
    47     return foo
    49 def enum(*names, **kw):
    50     if len(kw) == 1:
    51         base = kw['base'].__class__
    52         start = base.length
    53     else:
    54         assert len(kw) == 0
    55         base = object
    56         start = 0
    57     class Foo(base):
    58         __metaclass__ = M_add_class_attribs(names, start)
    59         def __setattr__(self, name, value):  # this makes it read-only
    60             raise NotImplementedError
    61     return Foo()
    63 class WebIDLError(Exception):
    64     def __init__(self, message, locations, warning=False):
    65         self.message = message
    66         self.locations = [str(loc) for loc in locations]
    67         self.warning = warning
    69     def __str__(self):
    70         return "%s: %s%s%s" % (self.warning and 'warning' or 'error',
    71                                  self.message,
    72                                  ", " if len(self.locations) != 0 else "",
    73                                  "\n".join(self.locations))
    75 class Location(object):
    76     def __init__(self, lexer, lineno, lexpos, filename):
    77         self._line = None
    78         self._lineno = lineno
    79         self._lexpos = lexpos
    80         self._lexdata = lexer.lexdata
    81         self._file = filename if filename else "<unknown>"
    83     def __eq__(self, other):
    84         return self._lexpos == other._lexpos and \
    85                self._file == other._file
    87     def filename(self):
    88         return self._file
    90     def resolve(self):
    91         if self._line:
    92             return
    94         startofline = self._lexdata.rfind('\n', 0, self._lexpos) + 1
    95         endofline = self._lexdata.find('\n', self._lexpos, self._lexpos + 80)
    96         if endofline != -1:
    97             self._line = self._lexdata[startofline:endofline]
    98         else:
    99             self._line = self._lexdata[startofline:]
   100         self._colno = self._lexpos - startofline
   102         # Our line number seems to point to the start of self._lexdata
   103         self._lineno += self._lexdata.count('\n', 0, startofline)
   105     def get(self):
   106         self.resolve()
   107         return "%s line %s:%s" % (self._file, self._lineno, self._colno)
   109     def _pointerline(self):
   110         return " " * self._colno + "^"
   112     def __str__(self):
   113         self.resolve()
   114         return "%s line %s:%s\n%s\n%s" % (self._file, self._lineno, self._colno,
   115                                           self._line, self._pointerline())
   117 class BuiltinLocation(object):
   118     def __init__(self, text):
   119         self.msg = text + "\n"
   121     def __eq__(self, other):
   122         return isinstance(other, BuiltinLocation) and \
   123                self.msg == other.msg
   125     def filename(self):
   126         return '<builtin>'
   128     def resolve(self):
   129         pass
   131     def get(self):
   132         return self.msg
   134     def __str__(self):
   135         return self.get()
   138 # Data Model
   140 class IDLObject(object):
   141     def __init__(self, location):
   142         self.location = location
   143         self.userData = dict()
   145     def filename(self):
   146         return self.location.filename()
   148     def isInterface(self):
   149         return False
   151     def isEnum(self):
   152         return False
   154     def isCallback(self):
   155         return False
   157     def isType(self):
   158         return False
   160     def isDictionary(self):
   161         return False;
   163     def isUnion(self):
   164         return False
   166     def getUserData(self, key, default):
   167         return self.userData.get(key, default)
   169     def setUserData(self, key, value):
   170         self.userData[key] = value
   172     def addExtendedAttributes(self, attrs):
   173         assert False # Override me!
   175     def handleExtendedAttribute(self, attr):
   176         assert False # Override me!
   178     def _getDependentObjects(self):
   179         assert False # Override me!
   181     def getDeps(self, visited=None):
   182         """ Return a set of files that this object depends on.  If any of
   183             these files are changed the parser needs to be rerun to regenerate
   184             a new IDLObject.
   186             The visited argument is a set of all the objects already visited.
   187             We must test to see if we are in it, and if so, do nothing.  This
   188             prevents infinite recursion."""
   190         # NB: We can't use visited=set() above because the default value is
   191         # evaluated when the def statement is evaluated, not when the function
   192         # is executed, so there would be one set for all invocations.
   193         if visited == None:
   194             visited = set()
   196         if self in visited:
   197             return set()
   199         visited.add(self)
   201         deps = set()
   202         if self.filename() != "<builtin>":
   203             deps.add(self.filename())
   205         for d in self._getDependentObjects():
   206             deps = deps.union(d.getDeps(visited))
   208         return deps
   210 class IDLScope(IDLObject):
   211     def __init__(self, location, parentScope, identifier):
   212         IDLObject.__init__(self, location)
   214         self.parentScope = parentScope
   215         if identifier:
   216             assert isinstance(identifier, IDLIdentifier)
   217             self._name = identifier
   218         else:
   219             self._name = None
   221         self._dict = {}
   223     def __str__(self):
   224         return self.QName()
   226     def QName(self):
   227         if self._name:
   228             return self._name.QName() + "::"
   229         return "::"
   231     def ensureUnique(self, identifier, object):
   232         """
   233             Ensure that there is at most one 'identifier' in scope ('self').
   234             Note that object can be None.  This occurs if we end up here for an
   235             interface type we haven't seen yet.
   236         """
   237         assert isinstance(identifier, IDLUnresolvedIdentifier)
   238         assert not object or isinstance(object, IDLObjectWithIdentifier)
   239         assert not object or object.identifier == identifier
   241         if identifier.name in self._dict:
   242             if not object:
   243                 return
   245             # ensureUnique twice with the same object is not allowed
   246             assert id(object) != id(self._dict[identifier.name])
   248             replacement = self.resolveIdentifierConflict(self, identifier,
   249                                                          self._dict[identifier.name],
   250                                                          object)
   251             self._dict[identifier.name] = replacement
   252             return
   254         assert object
   256         self._dict[identifier.name] = object
   258     def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
   259         if isinstance(originalObject, IDLExternalInterface) and \
   260            isinstance(newObject, IDLExternalInterface) and \
   261            originalObject.identifier.name == newObject.identifier.name:
   262             return originalObject
   264         if (isinstance(originalObject, IDLExternalInterface) or
   265             isinstance(newObject, IDLExternalInterface)):
   266             raise WebIDLError(
   267                 "Name collision between "
   268                 "interface declarations for identifier '%s' at '%s' and '%s'"
   269                 % (identifier.name,
   270                     originalObject.location, newObject.location), [])
   272         # We do the merging of overloads here as opposed to in IDLInterface
   273         # because we need to merge overloads of NamedConstructors and we need to
   274         # detect conflicts in those across interfaces. See also the comment in
   275         # IDLInterface.addExtendedAttributes for "NamedConstructor".
   276         if originalObject.tag == IDLInterfaceMember.Tags.Method and \
   277            newObject.tag == IDLInterfaceMember.Tags.Method:
   278             return originalObject.addOverload(newObject)
   280         # Default to throwing, derived classes can override.
   281         conflictdesc = "\n\t%s at %s\n\t%s at %s" % \
   282           (originalObject, originalObject.location, newObject, newObject.location)
   284         raise WebIDLError(
   285             "Multiple unresolvable definitions of identifier '%s' in scope '%s%s"
   286             % (identifier.name, str(self), conflictdesc), [])
   288     def _lookupIdentifier(self, identifier):
   289         return self._dict[identifier.name]
   291     def lookupIdentifier(self, identifier):
   292         assert isinstance(identifier, IDLIdentifier)
   293         assert identifier.scope == self
   294         return self._lookupIdentifier(identifier)
   296 class IDLIdentifier(IDLObject):
   297     def __init__(self, location, scope, name):
   298         IDLObject.__init__(self, location)
   300         self.name = name
   301         assert isinstance(scope, IDLScope)
   302         self.scope = scope
   304     def __str__(self):
   305         return self.QName()
   307     def QName(self):
   308         return self.scope.QName() + self.name
   310     def __hash__(self):
   311         return self.QName().__hash__()
   313     def __eq__(self, other):
   314         return self.QName() == other.QName()
   316     def object(self):
   317         return self.scope.lookupIdentifier(self)
   319 class IDLUnresolvedIdentifier(IDLObject):
   320     def __init__(self, location, name, allowDoubleUnderscore = False,
   321                  allowForbidden = False):
   322         IDLObject.__init__(self, location)
   324         assert len(name) > 0
   326         if name[:2] == "__" and name != "__content" and name != "___noSuchMethod__"  and not allowDoubleUnderscore:
   327             raise WebIDLError("Identifiers beginning with __ are reserved",
   328                               [location])
   329         if name[0] == '_' and not allowDoubleUnderscore:
   330             name = name[1:]
   331         # TODO: Bug 872377, Restore "toJSON" to below list.
   332         # We sometimes need custom serialization, so allow toJSON for now.
   333         if (name in ["constructor", "toString"] and
   334             not allowForbidden):
   335             raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
   336                               [location])
   338         self.name = name
   340     def __str__(self):
   341         return self.QName()
   343     def QName(self):
   344         return "<unresolved scope>::" + self.name
   346     def resolve(self, scope, object):
   347         assert isinstance(scope, IDLScope)
   348         assert not object or isinstance(object, IDLObjectWithIdentifier)
   349         assert not object or object.identifier == self
   351         scope.ensureUnique(self, object)
   353         identifier = IDLIdentifier(self.location, scope, self.name)
   354         if object:
   355             object.identifier = identifier
   356         return identifier
   358     def finish(self):
   359         assert False # Should replace with a resolved identifier first.
   361 class IDLObjectWithIdentifier(IDLObject):
   362     def __init__(self, location, parentScope, identifier):
   363         IDLObject.__init__(self, location)
   365         assert isinstance(identifier, IDLUnresolvedIdentifier)
   367         self.identifier = identifier
   369         if parentScope:
   370             self.resolve(parentScope)
   372         self.treatNullAs = "Default"
   374     def resolve(self, parentScope):
   375         assert isinstance(parentScope, IDLScope)
   376         assert isinstance(self.identifier, IDLUnresolvedIdentifier)
   377         self.identifier.resolve(parentScope, self)
   379     def checkForStringHandlingExtendedAttributes(self, attrs,
   380                                                  isDictionaryMember=False,
   381                                                  isOptional=False):
   382         """
   383         A helper function to deal with TreatNullAs.  Returns the list
   384         of attrs it didn't handle itself.
   385         """
   386         assert isinstance(self, IDLArgument) or isinstance(self, IDLAttribute)
   387         unhandledAttrs = list()
   388         for attr in attrs:
   389             if not attr.hasValue():
   390                 unhandledAttrs.append(attr)
   391                 continue
   393             identifier = attr.identifier()
   394             value = attr.value()
   395             if identifier == "TreatNullAs":
   396                 if not self.type.isDOMString() or self.type.nullable():
   397                     raise WebIDLError("[TreatNullAs] is only allowed on "
   398                                       "arguments or attributes whose type is "
   399                                       "DOMString",
   400                                       [self.location])
   401                 if isDictionaryMember:
   402                     raise WebIDLError("[TreatNullAs] is not allowed for "
   403                                       "dictionary members", [self.location])
   404                 if value != 'EmptyString':
   405                     raise WebIDLError("[TreatNullAs] must take the identifier "
   406                                       "'EmptyString', not '%s'" % value,
   407                                       [self.location])
   408                 self.treatNullAs = value
   409             else:
   410                 unhandledAttrs.append(attr)
   412         return unhandledAttrs
   414 class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope):
   415     def __init__(self, location, parentScope, identifier):
   416         assert isinstance(identifier, IDLUnresolvedIdentifier)
   418         IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
   419         IDLScope.__init__(self, location, parentScope, self.identifier)
   421 class IDLIdentifierPlaceholder(IDLObjectWithIdentifier):
   422     def __init__(self, location, identifier):
   423         assert isinstance(identifier, IDLUnresolvedIdentifier)
   424         IDLObjectWithIdentifier.__init__(self, location, None, identifier)
   426     def finish(self, scope):
   427         try:
   428             scope._lookupIdentifier(self.identifier)
   429         except:
   430             raise WebIDLError("Unresolved type '%s'." % self.identifier,
   431                               [self.location])
   433         obj = self.identifier.resolve(scope, None)
   434         return scope.lookupIdentifier(obj)
   436 class IDLExternalInterface(IDLObjectWithIdentifier):
   437     def __init__(self, location, parentScope, identifier):
   438         assert isinstance(identifier, IDLUnresolvedIdentifier)
   439         assert isinstance(parentScope, IDLScope)
   440         self.parent = None
   441         IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
   442         IDLObjectWithIdentifier.resolve(self, parentScope)
   444     def finish(self, scope):
   445         pass
   447     def validate(self):
   448         pass
   450     def isExternal(self):
   451         return True
   453     def isInterface(self):
   454         return True
   456     def isConsequential(self):
   457         return False
   459     def addExtendedAttributes(self, attrs):
   460         assert len(attrs) == 0
   462     def resolve(self, parentScope):
   463         pass
   465     def getJSImplementation(self):
   466         return None
   468     def isJSImplemented(self):
   469         return False
   471     def getNavigatorProperty(self):
   472         return None
   474     def _getDependentObjects(self):
   475         return set()
   477 class IDLInterface(IDLObjectWithScope):
   478     def __init__(self, location, parentScope, name, parent, members,
   479                  isPartial):
   480         assert isinstance(parentScope, IDLScope)
   481         assert isinstance(name, IDLUnresolvedIdentifier)
   482         assert not isPartial or not parent
   484         self.parent = None
   485         self._callback = False
   486         self._finished = False
   487         self.members = []
   488         # namedConstructors needs deterministic ordering because bindings code
   489         # outputs the constructs in the order that namedConstructors enumerates
   490         # them.
   491         self.namedConstructors = list()
   492         self.implementedInterfaces = set()
   493         self._consequential = False
   494         self._isPartial = True
   495         # self.interfacesBasedOnSelf is the set of interfaces that inherit from
   496         # self or have self as a consequential interface, including self itself.
   497         # Used for distinguishability checking.
   498         self.interfacesBasedOnSelf = set([self])
   499         # self.interfacesImplementingSelf is the set of interfaces that directly
   500         # have self as a consequential interface
   501         self.interfacesImplementingSelf = set()
   502         self._hasChildInterfaces = False
   503         self._isOnGlobalProtoChain = False
   504         # Tracking of the number of reserved slots we need for our
   505         # members and those of ancestor interfaces.
   506         self.totalMembersInSlots = 0
   507         # Tracking of the number of own own members we have in slots
   508         self._ownMembersInSlots = 0
   510         IDLObjectWithScope.__init__(self, location, parentScope, name)
   512         if not isPartial:
   513             self.setNonPartial(location, parent, members)
   514         else:
   515             # Just remember our members for now
   516             self.members = members
   518     def __str__(self):
   519         return "Interface '%s'" % self.identifier.name
   521     def ctor(self):
   522         identifier = IDLUnresolvedIdentifier(self.location, "constructor",
   523                                              allowForbidden=True)
   524         try:
   525             return self._lookupIdentifier(identifier)
   526         except:
   527             return None
   529     def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
   530         assert isinstance(scope, IDLScope)
   531         assert isinstance(originalObject, IDLInterfaceMember)
   532         assert isinstance(newObject, IDLInterfaceMember)
   534         retval = IDLScope.resolveIdentifierConflict(self, scope, identifier,
   535                                                     originalObject, newObject)
   537         # Might be a ctor, which isn't in self.members
   538         if newObject in self.members:
   539             self.members.remove(newObject)
   540         return retval
   542     def finish(self, scope):
   543         if self._finished:
   544             return
   546         self._finished = True
   548         if self._isPartial:
   549             raise WebIDLError("Interface %s does not have a non-partial "
   550                               "declaration" % self.identifier.name,
   551                               [self.location])
   553         assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
   554         parent = self.parent.finish(scope) if self.parent else None
   555         if parent and isinstance(parent, IDLExternalInterface):
   556             raise WebIDLError("%s inherits from %s which does not have "
   557                               "a definition" %
   558                               (self.identifier.name,
   559                                self.parent.identifier.name),
   560                               [self.location])
   561         assert not parent or isinstance(parent, IDLInterface)
   563         self.parent = parent
   565         assert iter(self.members)
   567         if self.parent:
   568             self.parent.finish(scope)
   570             self.parent._hasChildInterfaces = True
   572             self.totalMembersInSlots = self.parent.totalMembersInSlots
   574             # Interfaces with [Global] must not have anything inherit from them
   575             if self.parent.getExtendedAttribute("Global"):
   576                 # Note: This is not a self.parent.isOnGlobalProtoChain() check
   577                 # because ancestors of a [Global] interface can have other
   578                 # descendants.
   579                 raise WebIDLError("[Global] interface has another interface "
   580                                   "inheriting from it",
   581                                   [self.location, self.parent.location])
   583             # Callbacks must not inherit from non-callbacks or inherit from
   584             # anything that has consequential interfaces.
   585             # XXXbz Can non-callbacks inherit from callbacks?  Spec issue pending.
   586             # XXXbz Can callbacks have consequential interfaces?  Spec issue pending
   587             if self.isCallback():
   588                 if not self.parent.isCallback():
   589                     raise WebIDLError("Callback interface %s inheriting from "
   590                                       "non-callback interface %s" %
   591                                       (self.identifier.name,
   592                                        self.parent.identifier.name),
   593                                       [self.location, self.parent.location])
   594             elif self.parent.isCallback():
   595                 raise WebIDLError("Non-callback interface %s inheriting from "
   596                                   "callback interface %s" %
   597                                   (self.identifier.name,
   598                                    self.parent.identifier.name),
   599                                   [self.location, self.parent.location])
   601         for iface in self.implementedInterfaces:
   602             iface.finish(scope)
   604         cycleInGraph = self.findInterfaceLoopPoint(self)
   605         if cycleInGraph:
   606             raise WebIDLError("Interface %s has itself as ancestor or "
   607                               "implemented interface" % self.identifier.name,
   608                               [self.location, cycleInGraph.location])
   610         if self.isCallback():
   611             # "implements" should have made sure we have no
   612             # consequential interfaces.
   613             assert len(self.getConsequentialInterfaces()) == 0
   614             # And that we're not consequential.
   615             assert not self.isConsequential()
   617         # Now resolve() and finish() our members before importing the
   618         # ones from our implemented interfaces.
   620         # resolve() will modify self.members, so we need to iterate
   621         # over a copy of the member list here.
   622         for member in list(self.members):
   623             member.resolve(self)
   625         for member in self.members:
   626             member.finish(scope)
   628         ctor = self.ctor()
   629         if ctor is not None:
   630             ctor.finish(scope)
   632         for ctor in self.namedConstructors:
   633             ctor.finish(scope)
   635         # Make a copy of our member list, so things that implement us
   636         # can get those without all the stuff we implement ourselves
   637         # admixed.
   638         self.originalMembers = list(self.members)
   640         # Import everything from our consequential interfaces into
   641         # self.members.  Sort our consequential interfaces by name
   642         # just so we have a consistent order.
   643         for iface in sorted(self.getConsequentialInterfaces(),
   644                             cmp=cmp,
   645                             key=lambda x: x.identifier.name):
   646             # Flag the interface as being someone's consequential interface
   647             iface.setIsConsequentialInterfaceOf(self)
   648             additionalMembers = iface.originalMembers;
   649             for additionalMember in additionalMembers:
   650                 for member in self.members:
   651                     if additionalMember.identifier.name == member.identifier.name:
   652                         raise WebIDLError(
   653                             "Multiple definitions of %s on %s coming from 'implements' statements" %
   654                             (member.identifier.name, self),
   655                             [additionalMember.location, member.location])
   656             self.members.extend(additionalMembers)
   657             iface.interfacesImplementingSelf.add(self)
   659         for ancestor in self.getInheritedInterfaces():
   660             ancestor.interfacesBasedOnSelf.add(self)
   661             for ancestorConsequential in ancestor.getConsequentialInterfaces():
   662                 ancestorConsequential.interfacesBasedOnSelf.add(self)
   664         for member in self.members:
   665             if (member.isAttr() and member.isUnforgeable() and
   666                 not hasattr(member, "originatingInterface")):
   667                 member.originatingInterface = self
   669         # Compute slot indices for our members before we pull in
   670         # unforgeable members from our parent.
   671         for member in self.members:
   672             if (member.isAttr() and
   673                 (member.getExtendedAttribute("StoreInSlot") or
   674                  member.getExtendedAttribute("Cached"))):
   675                 member.slotIndex = self.totalMembersInSlots
   676                 self.totalMembersInSlots += 1
   677                 if member.getExtendedAttribute("StoreInSlot"):
   678                     self._ownMembersInSlots += 1
   680         if self.parent:
   681             # Make sure we don't shadow any of the [Unforgeable] attributes on
   682             # our ancestor interfaces.  We don't have to worry about
   683             # consequential interfaces here, because those have already been
   684             # imported into the relevant .members lists.  And we don't have to
   685             # worry about anything other than our parent, because it has already
   686             # imported its ancestors unforgeable attributes into its member
   687             # list.
   688             for unforgeableAttr in (attr for attr in self.parent.members if
   689                                     attr.isAttr() and not attr.isStatic() and
   690                                     attr.isUnforgeable()):
   691                 shadows = [ m for m in self.members if
   692                             (m.isAttr() or m.isMethod()) and
   693                             not m.isStatic() and
   694                             m.identifier.name == unforgeableAttr.identifier.name ]
   695                 if len(shadows) != 0:
   696                     locs = [unforgeableAttr.location] + [ s.location for s
   697                                                           in shadows ]
   698                     raise WebIDLError("Interface %s shadows [Unforgeable] "
   699                                       "members of %s" %
   700                                       (self.identifier.name,
   701                                        ancestor.identifier.name),
   702                                       locs)
   703                 # And now just stick it in our members, since we won't be
   704                 # inheriting this down the proto chain.  If we really cared we
   705                 # could try to do something where we set up the unforgeable
   706                 # attributes of ancestor interfaces, with their corresponding
   707                 # getters, on our interface, but that gets pretty complicated
   708                 # and seems unnecessary.
   709                 self.members.append(unforgeableAttr)
   711         # Ensure that there's at most one of each {named,indexed}
   712         # {getter,setter,creator,deleter}, at most one stringifier,
   713         # and at most one legacycaller.  Note that this last is not
   714         # quite per spec, but in practice no one overloads
   715         # legacycallers.
   716         specialMembersSeen = {}
   717         for member in self.members:
   718             if not member.isMethod():
   719                 continue
   721             if member.isGetter():
   722                 memberType = "getters"
   723             elif member.isSetter():
   724                 memberType = "setters"
   725             elif member.isCreator():
   726                 memberType = "creators"
   727             elif member.isDeleter():
   728                 memberType = "deleters"
   729             elif member.isStringifier():
   730                 memberType = "stringifiers"
   731             elif member.isJsonifier():
   732                 memberType = "jsonifiers"
   733             elif member.isLegacycaller():
   734                 memberType = "legacycallers"
   735             else:
   736                 continue
   738             if (memberType != "stringifiers" and memberType != "legacycallers" and
   739                 memberType != "jsonifiers"):
   740                 if member.isNamed():
   741                     memberType = "named " + memberType
   742                 else:
   743                     assert member.isIndexed()
   744                     memberType = "indexed " + memberType
   746             if memberType in specialMembersSeen:
   747                 raise WebIDLError("Multiple " + memberType + " on %s" % (self),
   748                                    [self.location,
   749                                     specialMembersSeen[memberType].location,
   750                                     member.location])
   752             specialMembersSeen[memberType] = member
   754         if self._isOnGlobalProtoChain:
   755             # Make sure we have no named setters, creators, or deleters
   756             for memberType in ["setter", "creator", "deleter"]:
   757                 memberId = "named " + memberType + "s"
   758                 if memberId in specialMembersSeen:
   759                     raise WebIDLError("Interface with [Global] has a named %s" %
   760                                       memberType,
   761                                       [self.location,
   762                                        specialMembersSeen[memberId].location])
   763             # Make sure we're not [OverrideBuiltins]
   764             if self.getExtendedAttribute("OverrideBuiltins"):
   765                 raise WebIDLError("Interface with [Global] also has "
   766                                   "[OverrideBuiltins]",
   767                                   [self.location])
   768             # Mark all of our ancestors as being on the global's proto chain too
   769             parent = self.parent
   770             while parent:
   771                 # Must not inherit from an interface with [OverrideBuiltins]
   772                 if parent.getExtendedAttribute("OverrideBuiltins"):
   773                     raise WebIDLError("Interface with [Global] inherits from "
   774                                       "interface with [OverrideBuiltins]",
   775                                       [self.location, parent.location])
   776                 parent._isOnGlobalProtoChain = True
   777                 parent = parent.parent
   779     def validate(self):
   780         for member in self.members:
   781             member.validate()
   783             # Check that PutForwards refers to another attribute and that no
   784             # cycles exist in forwarded assignments.
   785             if member.isAttr():
   786                 iface = self
   787                 attr = member
   788                 putForwards = attr.getExtendedAttribute("PutForwards")
   789                 if putForwards and self.isCallback():
   790                     raise WebIDLError("[PutForwards] used on an attribute "
   791                                       "on interface %s which is a callback "
   792                                       "interface" % self.identifier.name,
   793                                       [self.location, member.location])
   795                 while putForwards is not None:
   796                     forwardIface = attr.type.unroll().inner
   797                     fowardAttr = None
   799                     for forwardedMember in forwardIface.members:
   800                         if (not forwardedMember.isAttr() or
   801                             forwardedMember.identifier.name != putForwards[0]):
   802                             continue
   803                         if forwardedMember == member:
   804                             raise WebIDLError("Cycle detected in forwarded "
   805                                               "assignments for attribute %s on "
   806                                               "%s" %
   807                                               (member.identifier.name, self),
   808                                               [member.location])
   809                         fowardAttr = forwardedMember
   810                         break
   812                     if fowardAttr is None:
   813                         raise WebIDLError("Attribute %s on %s forwards to "
   814                                           "missing attribute %s" %
   815                               (attr.identifier.name, iface, putForwards),
   816                               [attr.location])
   818                     iface = forwardIface
   819                     attr = fowardAttr
   820                     putForwards = attr.getExtendedAttribute("PutForwards")
   823     def isInterface(self):
   824         return True
   826     def isExternal(self):
   827         return False
   829     def setIsConsequentialInterfaceOf(self, other):
   830         self._consequential = True
   831         self.interfacesBasedOnSelf.add(other)
   833     def isConsequential(self):
   834         return self._consequential
   836     def setCallback(self, value):
   837         self._callback = value
   839     def isCallback(self):
   840         return self._callback
   842     def isSingleOperationInterface(self):
   843         assert self.isCallback() or self.isJSImplemented()
   844         return (
   845             # JS-implemented things should never need the
   846             # this-handling weirdness of single-operation interfaces.
   847             not self.isJSImplemented() and
   848             # Not inheriting from another interface
   849             not self.parent and
   850             # No consequential interfaces
   851             len(self.getConsequentialInterfaces()) == 0 and
   852             # No attributes of any kinds
   853             not any(m.isAttr() for m in self.members) and
   854             # There is at least one regular operation, and all regular
   855             # operations have the same identifier
   856             len(set(m.identifier.name for m in self.members if
   857                     m.isMethod() and not m.isStatic())) == 1)
   859     def inheritanceDepth(self):
   860         depth = 0
   861         parent = self.parent
   862         while parent:
   863             depth = depth + 1
   864             parent = parent.parent
   865         return depth
   867     def hasConstants(self):
   868         return any(m.isConst() for m in self.members)
   870     def hasInterfaceObject(self):
   871         if self.isCallback():
   872             return self.hasConstants()
   873         return not hasattr(self, "_noInterfaceObject")
   875     def hasInterfacePrototypeObject(self):
   876         return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
   878     def addExtendedAttributes(self, attrs):
   879         self._extendedAttrDict = {}
   880         for attr in attrs:
   881             identifier = attr.identifier()
   883             # Special cased attrs
   884             if identifier == "TreatNonCallableAsNull":
   885                 raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces",
   886                                   [attr.location, self.location])
   887             if identifier == "TreatNonObjectAsNull":
   888                 raise WebIDLError("TreatNonObjectAsNull cannot be specified on interfaces",
   889                                   [attr.location, self.location])
   890             elif identifier == "NoInterfaceObject":
   891                 if not attr.noArguments():
   892                     raise WebIDLError("[NoInterfaceObject] must take no arguments",
   893                                       [attr.location])
   895                 if self.ctor():
   896                     raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
   897                                       [self.location])
   899                 self._noInterfaceObject = True
   900             elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
   901                 if identifier == "Constructor" and not self.hasInterfaceObject():
   902                     raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
   903                                       [self.location])
   905                 if identifier == "NamedConstructor" and not attr.hasValue():
   906                     raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
   907                                       [attr.location])
   909                 if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
   910                     raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
   911                                       [self.location])
   913                 args = attr.args() if attr.hasArgs() else []
   915                 retType = IDLWrapperType(self.location, self)
   917                 if identifier == "Constructor" or identifier == "ChromeConstructor":
   918                     name = "constructor"
   919                     allowForbidden = True
   920                 else:
   921                     name = attr.value()
   922                     allowForbidden = False
   924                 methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
   925                                                            allowForbidden=allowForbidden)
   927                 method = IDLMethod(self.location, methodIdentifier, retType,
   928                                    args, static=True)
   929                 # Constructors are always NewObject and are always
   930                 # assumed to be able to throw (since there's no way to
   931                 # indicate otherwise) and never have any other
   932                 # extended attributes.
   933                 method.addExtendedAttributes(
   934                     [IDLExtendedAttribute(self.location, ("NewObject",)),
   935                      IDLExtendedAttribute(self.location, ("Throws",))])
   936                 if identifier == "ChromeConstructor":
   937                     method.addExtendedAttributes(
   938                         [IDLExtendedAttribute(self.location, ("ChromeOnly",))])
   940                 if identifier == "Constructor" or identifier == "ChromeConstructor":
   941                     method.resolve(self)
   942                 else:
   943                     # We need to detect conflicts for NamedConstructors across
   944                     # interfaces. We first call resolve on the parentScope,
   945                     # which will merge all NamedConstructors with the same
   946                     # identifier accross interfaces as overloads.
   947                     method.resolve(self.parentScope)
   949                     # Then we look up the identifier on the parentScope. If the
   950                     # result is the same as the method we're adding then it
   951                     # hasn't been added as an overload and it's the first time
   952                     # we've encountered a NamedConstructor with that identifier.
   953                     # If the result is not the same as the method we're adding
   954                     # then it has been added as an overload and we need to check
   955                     # whether the result is actually one of our existing
   956                     # NamedConstructors.
   957                     newMethod = self.parentScope.lookupIdentifier(method.identifier)
   958                     if newMethod == method:
   959                         self.namedConstructors.append(method)
   960                     elif not newMethod in self.namedConstructors:
   961                         raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
   962                                           [method.location, newMethod.location])
   963             elif (identifier == "ArrayClass"):
   964                 if not attr.noArguments():
   965                     raise WebIDLError("[ArrayClass] must take no arguments",
   966                                       [attr.location])
   967                 if self.parent:
   968                     raise WebIDLError("[ArrayClass] must not be specified on "
   969                                       "an interface with inherited interfaces",
   970                                       [attr.location, self.location])
   971             elif identifier == "Global":
   972                 if not attr.noArguments():
   973                     raise WebIDLError("[Global] must take no arguments",
   974                                       [attr.location])
   975                 self._isOnGlobalProtoChain = True
   976             elif (identifier == "NeedNewResolve" or
   977                   identifier == "OverrideBuiltins" or
   978                   identifier == "ChromeOnly"):
   979                 # Known extended attributes that do not take values
   980                 if not attr.noArguments():
   981                     raise WebIDLError("[%s] must take no arguments" % identifier,
   982                                       [attr.location])
   983             elif (identifier == "Pref" or
   984                   identifier == "JSImplementation" or
   985                   identifier == "HeaderFile" or
   986                   identifier == "NavigatorProperty" or
   987                   identifier == "AvailableIn" or
   988                   identifier == "Func"):
   989                 # Known extended attributes that take a string value
   990                 if not attr.hasValue():
   991                     raise WebIDLError("[%s] must have a value" % identifier,
   992                                       [attr.location])
   993             else:
   994                 raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
   995                                   [attr.location])
   997             attrlist = attr.listValue()
   998             self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
  1000     def addImplementedInterface(self, implementedInterface):
  1001         assert(isinstance(implementedInterface, IDLInterface))
  1002         self.implementedInterfaces.add(implementedInterface)
  1004     def getInheritedInterfaces(self):
  1005         """
  1006         Returns a list of the interfaces this interface inherits from
  1007         (not including this interface itself).  The list is in order
  1008         from most derived to least derived.
  1009         """
  1010         assert(self._finished)
  1011         if not self.parent:
  1012             return []
  1013         parentInterfaces = self.parent.getInheritedInterfaces()
  1014         parentInterfaces.insert(0, self.parent)
  1015         return parentInterfaces
  1017     def getConsequentialInterfaces(self):
  1018         assert(self._finished)
  1019         # The interfaces we implement directly
  1020         consequentialInterfaces = set(self.implementedInterfaces)
  1022         # And their inherited interfaces
  1023         for iface in self.implementedInterfaces:
  1024             consequentialInterfaces |= set(iface.getInheritedInterfaces())
  1026         # And now collect up the consequential interfaces of all of those
  1027         temp = set()
  1028         for iface in consequentialInterfaces:
  1029             temp |= iface.getConsequentialInterfaces()
  1031         return consequentialInterfaces | temp
  1033     def findInterfaceLoopPoint(self, otherInterface):
  1034         """
  1035         Finds an interface, amongst our ancestors and consequential interfaces,
  1036         that inherits from otherInterface or implements otherInterface
  1037         directly.  If there is no such interface, returns None.
  1038         """
  1039         if self.parent:
  1040             if self.parent == otherInterface:
  1041                 return self
  1042             loopPoint = self.parent.findInterfaceLoopPoint(otherInterface)
  1043             if loopPoint:
  1044                 return loopPoint
  1045         if otherInterface in self.implementedInterfaces:
  1046             return self
  1047         for iface in self.implementedInterfaces:
  1048             loopPoint = iface.findInterfaceLoopPoint(otherInterface)
  1049             if loopPoint:
  1050                 return loopPoint
  1051         return None
  1053     def getExtendedAttribute(self, name):
  1054         return self._extendedAttrDict.get(name, None)
  1056     def setNonPartial(self, location, parent, members):
  1057         assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
  1058         if not self._isPartial:
  1059             raise WebIDLError("Two non-partial definitions for the "
  1060                               "same interface",
  1061                               [location, self.location])
  1062         self._isPartial = False
  1063         # Now make it look like we were parsed at this new location, since
  1064         # that's the place where the interface is "really" defined
  1065         self.location = location
  1066         assert not self.parent
  1067         self.parent = parent
  1068         # Put the new members at the beginning
  1069         self.members = members + self.members
  1071     def getJSImplementation(self):
  1072         classId = self.getExtendedAttribute("JSImplementation")
  1073         if not classId:
  1074             return classId
  1075         assert isinstance(classId, list)
  1076         assert len(classId) == 1
  1077         return classId[0]
  1079     def isJSImplemented(self):
  1080         return bool(self.getJSImplementation())
  1082     def getNavigatorProperty(self):
  1083         naviProp = self.getExtendedAttribute("NavigatorProperty")
  1084         if not naviProp:
  1085             return None
  1086         assert len(naviProp) == 1
  1087         assert isinstance(naviProp, list)
  1088         assert len(naviProp[0]) != 0
  1089         return naviProp[0]
  1091     def hasChildInterfaces(self):
  1092         return self._hasChildInterfaces
  1094     def isOnGlobalProtoChain(self):
  1095         return self._isOnGlobalProtoChain
  1097     def _getDependentObjects(self):
  1098         deps = set(self.members)
  1099         deps.union(self.implementedInterfaces)
  1100         if self.parent:
  1101             deps.add(self.parent)
  1102         return deps
  1104     def hasMembersInSlots(self):
  1105         return self._ownMembersInSlots != 0
  1107 class IDLDictionary(IDLObjectWithScope):
  1108     def __init__(self, location, parentScope, name, parent, members):
  1109         assert isinstance(parentScope, IDLScope)
  1110         assert isinstance(name, IDLUnresolvedIdentifier)
  1111         assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
  1113         self.parent = parent
  1114         self._finished = False
  1115         self.members = list(members)
  1117         IDLObjectWithScope.__init__(self, location, parentScope, name)
  1119     def __str__(self):
  1120         return "Dictionary '%s'" % self.identifier.name
  1122     def isDictionary(self):
  1123         return True;
  1125     def finish(self, scope):
  1126         if self._finished:
  1127             return
  1129         self._finished = True
  1131         if self.parent:
  1132             assert isinstance(self.parent, IDLIdentifierPlaceholder)
  1133             oldParent = self.parent
  1134             self.parent = self.parent.finish(scope)
  1135             if not isinstance(self.parent, IDLDictionary):
  1136                 raise WebIDLError("Dictionary %s has parent that is not a dictionary" %
  1137                                   self.identifier.name,
  1138                                   [oldParent.location, self.parent.location])
  1140             # Make sure the parent resolves all its members before we start
  1141             # looking at them.
  1142             self.parent.finish(scope)
  1144         for member in self.members:
  1145             member.resolve(self)
  1146             if not member.isComplete():
  1147                 member.complete(scope)
  1148                 assert member.type.isComplete()
  1150         # Members of a dictionary are sorted in lexicographic order
  1151         self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
  1153         inheritedMembers = []
  1154         ancestor = self.parent
  1155         while ancestor:
  1156             if ancestor == self:
  1157                 raise WebIDLError("Dictionary %s has itself as an ancestor" %
  1158                                   self.identifier.name,
  1159                                   [self.identifier.location])
  1160             inheritedMembers.extend(ancestor.members)
  1161             ancestor = ancestor.parent
  1163         # Catch name duplication
  1164         for inheritedMember in inheritedMembers:
  1165             for member in self.members:
  1166                 if member.identifier.name == inheritedMember.identifier.name:
  1167                     raise WebIDLError("Dictionary %s has two members with name %s" %
  1168                                       (self.identifier.name, member.identifier.name),
  1169                                       [member.location, inheritedMember.location])
  1171     def validate(self):
  1172         def typeContainsDictionary(memberType, dictionary):
  1173             """
  1174             Returns a tuple whose:
  1176                 - First element is a Boolean value indicating whether
  1177                   memberType contains dictionary.
  1179                 - Second element is:
  1180                     A list of locations that leads from the type that was passed in
  1181                     the memberType argument, to the dictionary being validated,
  1182                     if the boolean value in the first element is True.
  1184                     None, if the boolean value in the first element is False.
  1185             """
  1187             if (memberType.nullable() or
  1188                 memberType.isArray() or
  1189                 memberType.isSequence() or
  1190                 memberType.isMozMap()):
  1191                 return typeContainsDictionary(memberType.inner, dictionary)
  1193             if memberType.isDictionary():
  1194                 if memberType.inner == dictionary:
  1195                     return (True, [memberType.location])
  1197                 (contains, locations) = dictionaryContainsDictionary(memberType.inner, \
  1198                                                                      dictionary)
  1199                 if contains:
  1200                     return (True, [memberType.location] + locations)
  1202             if memberType.isUnion():
  1203                 for member in memberType.flatMemberTypes:
  1204                     (contains, locations) = typeContainsDictionary(member, dictionary)
  1205                     if contains:
  1206                         return (True, locations)
  1208             return (False, None)
  1210         def dictionaryContainsDictionary(dictMember, dictionary):
  1211             for member in dictMember.members:
  1212                 (contains, locations) = typeContainsDictionary(member.type, dictionary)
  1213                 if contains:
  1214                     return (True, [member.location] + locations)
  1216             if dictMember.parent:
  1217                 if dictMember.parent == dictionary:
  1218                     return (True, [dictMember.location])
  1219                 else:
  1220                     (contains, locations) = dictionaryContainsDictionary(dictMember.parent, dictionary)
  1221                     if contains:
  1222                         return (True, [dictMember.location] + locations)
  1224             return (False, None)
  1226         for member in self.members:
  1227             if member.type.isDictionary() and member.type.nullable():
  1228                 raise WebIDLError("Dictionary %s has member with nullable "
  1229                                   "dictionary type" % self.identifier.name,
  1230                                   [member.location])
  1231             (contains, locations) = typeContainsDictionary(member.type, self)
  1232             if contains:
  1233                 raise WebIDLError("Dictionary %s has member with itself as type." %
  1234                                   self.identifier.name,
  1235                                   [member.location] + locations)
  1237     def addExtendedAttributes(self, attrs):
  1238         assert len(attrs) == 0
  1240     def _getDependentObjects(self):
  1241         deps = set(self.members)
  1242         if (self.parent):
  1243             deps.add(self.parent)
  1244         return deps
  1246 class IDLEnum(IDLObjectWithIdentifier):
  1247     def __init__(self, location, parentScope, name, values):
  1248         assert isinstance(parentScope, IDLScope)
  1249         assert isinstance(name, IDLUnresolvedIdentifier)
  1251         if len(values) != len(set(values)):
  1252             raise WebIDLError("Enum %s has multiple identical strings" % name.name,
  1253                               [location])
  1255         IDLObjectWithIdentifier.__init__(self, location, parentScope, name)
  1256         self._values = values
  1258     def values(self):
  1259         return self._values
  1261     def finish(self, scope):
  1262         pass
  1264     def validate(self):
  1265         pass
  1267     def isEnum(self):
  1268         return True
  1270     def addExtendedAttributes(self, attrs):
  1271         assert len(attrs) == 0
  1273     def _getDependentObjects(self):
  1274         return set()
  1276 class IDLType(IDLObject):
  1277     Tags = enum(
  1278         # The integer types
  1279         'int8',
  1280         'uint8',
  1281         'int16',
  1282         'uint16',
  1283         'int32',
  1284         'uint32',
  1285         'int64',
  1286         'uint64',
  1287         # Additional primitive types
  1288         'bool',
  1289         'unrestricted_float',
  1290         'float',
  1291         'unrestricted_double',
  1292         # "double" last primitive type to match IDLBuiltinType
  1293         'double',
  1294         # Other types
  1295         'any',
  1296         'domstring',
  1297         'bytestring',
  1298         'object',
  1299         'date',
  1300         'void',
  1301         # Funny stuff
  1302         'interface',
  1303         'dictionary',
  1304         'enum',
  1305         'callback',
  1306         'union',
  1307         'sequence',
  1308         'mozmap',
  1309         'array'
  1312     def __init__(self, location, name):
  1313         IDLObject.__init__(self, location)
  1314         self.name = name
  1315         self.builtin = False
  1317     def __eq__(self, other):
  1318         return other and self.builtin == other.builtin and self.name == other.name
  1320     def __ne__(self, other):
  1321         return not self == other
  1323     def __str__(self):
  1324         return str(self.name)
  1326     def isType(self):
  1327         return True
  1329     def nullable(self):
  1330         return False
  1332     def isPrimitive(self):
  1333         return False
  1335     def isBoolean(self):
  1336         return False
  1338     def isNumeric(self):
  1339         return False
  1341     def isString(self):
  1342         return False
  1344     def isByteString(self):
  1345         return False
  1347     def isDOMString(self):
  1348         return False
  1350     def isVoid(self):
  1351         return self.name == "Void"
  1353     def isSequence(self):
  1354         return False
  1356     def isMozMap(self):
  1357         return False
  1359     def isArray(self):
  1360         return False
  1362     def isArrayBuffer(self):
  1363         return False
  1365     def isArrayBufferView(self):
  1366         return False
  1368     def isTypedArray(self):
  1369         return False
  1371     def isCallbackInterface(self):
  1372         return False
  1374     def isNonCallbackInterface(self):
  1375         return False
  1377     def isGeckoInterface(self):
  1378         """ Returns a boolean indicating whether this type is an 'interface'
  1379             type that is implemented in Gecko. At the moment, this returns
  1380             true for all interface types that are not types from the TypedArray
  1381             spec."""
  1382         return self.isInterface() and not self.isSpiderMonkeyInterface()
  1384     def isSpiderMonkeyInterface(self):
  1385         """ Returns a boolean indicating whether this type is an 'interface'
  1386             type that is implemented in Spidermonkey.  At the moment, this
  1387             only returns true for the types from the TypedArray spec. """
  1388         return self.isInterface() and (self.isArrayBuffer() or \
  1389                                        self.isArrayBufferView() or \
  1390                                        self.isTypedArray())
  1392     def isDictionary(self):
  1393         return False
  1395     def isInterface(self):
  1396         return False
  1398     def isAny(self):
  1399         return self.tag() == IDLType.Tags.any
  1401     def isDate(self):
  1402         return self.tag() == IDLType.Tags.date
  1404     def isObject(self):
  1405         return self.tag() == IDLType.Tags.object
  1407     def isPromise(self):
  1408         return False
  1410     def isComplete(self):
  1411         return True
  1413     def includesRestrictedFloat(self):
  1414         return False
  1416     def isFloat(self):
  1417         return False
  1419     def isUnrestricted(self):
  1420         # Should only call this on float types
  1421         assert self.isFloat()
  1423     def isSerializable(self):
  1424         return False
  1426     def tag(self):
  1427         assert False # Override me!
  1429     def treatNonCallableAsNull(self):
  1430         assert self.tag() == IDLType.Tags.callback
  1431         return self.nullable() and self.inner._treatNonCallableAsNull
  1433     def treatNonObjectAsNull(self):
  1434         assert self.tag() == IDLType.Tags.callback
  1435         return self.nullable() and self.inner._treatNonObjectAsNull
  1437     def addExtendedAttributes(self, attrs):
  1438         assert len(attrs) == 0
  1440     def resolveType(self, parentScope):
  1441         pass
  1443     def unroll(self):
  1444         return self
  1446     def isDistinguishableFrom(self, other):
  1447         raise TypeError("Can't tell whether a generic type is or is not "
  1448                         "distinguishable from other things")
  1450 class IDLUnresolvedType(IDLType):
  1451     """
  1452         Unresolved types are interface types 
  1453     """
  1455     def __init__(self, location, name):
  1456         IDLType.__init__(self, location, name)
  1458     def isComplete(self):
  1459         return False
  1461     def complete(self, scope):
  1462         obj = None
  1463         try:
  1464             obj = scope._lookupIdentifier(self.name)
  1465         except:
  1466             raise WebIDLError("Unresolved type '%s'." % self.name,
  1467                               [self.location])
  1469         assert obj
  1470         if obj.isType():
  1471             # obj itself might not be complete; deal with that.
  1472             assert obj != self
  1473             if not obj.isComplete():
  1474                 obj = obj.complete(scope)
  1475             return obj
  1477         name = self.name.resolve(scope, None)
  1478         return IDLWrapperType(self.location, obj)
  1480     def isDistinguishableFrom(self, other):
  1481         raise TypeError("Can't tell whether an unresolved type is or is not "
  1482                         "distinguishable from other things")
  1484 class IDLNullableType(IDLType):
  1485     def __init__(self, location, innerType):
  1486         assert not innerType.isVoid()
  1487         assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
  1489         IDLType.__init__(self, location, innerType.name)
  1490         self.inner = innerType
  1491         self.builtin = False
  1493     def __eq__(self, other):
  1494         return isinstance(other, IDLNullableType) and self.inner == other.inner
  1496     def __str__(self):
  1497         return self.inner.__str__() + "OrNull"
  1499     def nullable(self):
  1500         return True
  1502     def isCallback(self):
  1503         return self.inner.isCallback()
  1505     def isPrimitive(self):
  1506         return self.inner.isPrimitive()
  1508     def isBoolean(self):
  1509         return self.inner.isBoolean()
  1511     def isNumeric(self):
  1512         return self.inner.isNumeric()
  1514     def isString(self):
  1515         return self.inner.isString()
  1517     def isByteString(self):
  1518         return self.inner.isByteString()
  1520     def isDOMString(self):
  1521         return self.inner.isDOMString()
  1523     def isFloat(self):
  1524         return self.inner.isFloat()
  1526     def isUnrestricted(self):
  1527         return self.inner.isUnrestricted()
  1529     def includesRestrictedFloat(self):
  1530         return self.inner.includesRestrictedFloat()
  1532     def isInteger(self):
  1533         return self.inner.isInteger()
  1535     def isVoid(self):
  1536         return False
  1538     def isSequence(self):
  1539         return self.inner.isSequence()
  1541     def isMozMap(self):
  1542         return self.inner.isMozMap()
  1544     def isArray(self):
  1545         return self.inner.isArray()
  1547     def isArrayBuffer(self):
  1548         return self.inner.isArrayBuffer()
  1550     def isArrayBufferView(self):
  1551         return self.inner.isArrayBufferView()
  1553     def isTypedArray(self):
  1554         return self.inner.isTypedArray()
  1556     def isDictionary(self):
  1557         return self.inner.isDictionary()
  1559     def isInterface(self):
  1560         return self.inner.isInterface()
  1562     def isCallbackInterface(self):
  1563         return self.inner.isCallbackInterface()
  1565     def isNonCallbackInterface(self):
  1566         return self.inner.isNonCallbackInterface()
  1568     def isEnum(self):
  1569         return self.inner.isEnum()
  1571     def isUnion(self):
  1572         return self.inner.isUnion()
  1574     def isSerializable(self):
  1575         return self.inner.isSerializable()
  1577     def tag(self):
  1578         return self.inner.tag()
  1580     def resolveType(self, parentScope):
  1581         assert isinstance(parentScope, IDLScope)
  1582         self.inner.resolveType(parentScope)
  1584     def isComplete(self):
  1585         return self.inner.isComplete()
  1587     def complete(self, scope):
  1588         self.inner = self.inner.complete(scope)
  1589         if self.inner.nullable():
  1590             raise WebIDLError("The inner type of a nullable type must not be "
  1591                               "a nullable type",
  1592                               [self.location, self.inner.location])
  1593         if self.inner.isUnion():
  1594             if self.inner.hasNullableType:
  1595                 raise WebIDLError("The inner type of a nullable type must not "
  1596                                   "be a union type that itself has a nullable "
  1597                                   "type as a member type", [self.location])
  1599         self.name = self.inner.name
  1600         return self
  1602     def unroll(self):
  1603         return self.inner.unroll()
  1605     def isDistinguishableFrom(self, other):
  1606         if (other.nullable() or (other.isUnion() and other.hasNullableType) or
  1607             other.isDictionary()):
  1608             # Can't tell which type null should become
  1609             return False
  1610         return self.inner.isDistinguishableFrom(other)
  1612     def _getDependentObjects(self):
  1613         return self.inner._getDependentObjects()
  1615 class IDLSequenceType(IDLType):
  1616     def __init__(self, location, parameterType):
  1617         assert not parameterType.isVoid()
  1619         IDLType.__init__(self, location, parameterType.name)
  1620         self.inner = parameterType
  1621         self.builtin = False
  1623     def __eq__(self, other):
  1624         return isinstance(other, IDLSequenceType) and self.inner == other.inner
  1626     def __str__(self):
  1627         return self.inner.__str__() + "Sequence"
  1629     def nullable(self):
  1630         return False
  1632     def isPrimitive(self):
  1633         return False;
  1635     def isString(self):
  1636         return False;
  1638     def isByteString(self):
  1639         return False
  1641     def isDOMString(self):
  1642         return False
  1644     def isVoid(self):
  1645         return False
  1647     def isSequence(self):
  1648         return True
  1650     def isArray(self):
  1651         return False
  1653     def isDictionary(self):
  1654         return False
  1656     def isInterface(self):
  1657         return False
  1659     def isEnum(self):
  1660         return False
  1662     def isSerializable(self):
  1663         return self.inner.isSerializable()
  1665     def includesRestrictedFloat(self):
  1666         return self.inner.includesRestrictedFloat()
  1668     def tag(self):
  1669         return IDLType.Tags.sequence
  1671     def resolveType(self, parentScope):
  1672         assert isinstance(parentScope, IDLScope)
  1673         self.inner.resolveType(parentScope)
  1675     def isComplete(self):
  1676         return self.inner.isComplete()
  1678     def complete(self, scope):
  1679         self.inner = self.inner.complete(scope)
  1680         self.name = self.inner.name
  1681         return self
  1683     def unroll(self):
  1684         return self.inner.unroll()
  1686     def isDistinguishableFrom(self, other):
  1687         if other.isUnion():
  1688             # Just forward to the union; it'll deal
  1689             return other.isDistinguishableFrom(self)
  1690         return (other.isPrimitive() or other.isString() or other.isEnum() or
  1691                 other.isDate() or other.isNonCallbackInterface())
  1693     def _getDependentObjects(self):
  1694         return self.inner._getDependentObjects()
  1696 class IDLMozMapType(IDLType):
  1697     # XXXbz This is pretty similar to IDLSequenceType in various ways.
  1698     # And maybe to IDLNullableType.  Should we have a superclass for
  1699     # "type containing this other type"?  Bug 1015318.
  1700     def __init__(self, location, parameterType):
  1701         assert not parameterType.isVoid()
  1703         IDLType.__init__(self, location, parameterType.name)
  1704         self.inner = parameterType
  1705         self.builtin = False
  1707     def __eq__(self, other):
  1708         return isinstance(other, IDLMozMapType) and self.inner == other.inner
  1710     def __str__(self):
  1711         return self.inner.__str__() + "MozMap"
  1713     def isMozMap(self):
  1714         return True
  1716     def includesRestrictedFloat(self):
  1717         return self.inner.includesRestrictedFloat()
  1719     def tag(self):
  1720         return IDLType.Tags.mozmap
  1722     def resolveType(self, parentScope):
  1723         assert isinstance(parentScope, IDLScope)
  1724         self.inner.resolveType(parentScope)
  1726     def isComplete(self):
  1727         return self.inner.isComplete()
  1729     def complete(self, scope):
  1730         self.inner = self.inner.complete(scope)
  1731         self.name = self.inner.name
  1732         return self
  1734     def unroll(self):
  1735         # We do not unroll our inner.  Just stop at ourselves.  That
  1736         # lets us add headers for both ourselves and our inner as
  1737         # needed.
  1738         return self
  1740     def isDistinguishableFrom(self, other):
  1741         if other.isUnion():
  1742             # Just forward to the union; it'll deal
  1743             return other.isDistinguishableFrom(self)
  1744         return (other.isPrimitive() or other.isString() or other.isEnum() or
  1745                 other.isDate() or other.isNonCallbackInterface())
  1747     def _getDependentObjects(self):
  1748         return self.inner._getDependentObjects()
  1750 class IDLUnionType(IDLType):
  1751     def __init__(self, location, memberTypes):
  1752         IDLType.__init__(self, location, "")
  1753         self.memberTypes = memberTypes
  1754         self.hasNullableType = False
  1755         self.hasDictionaryType = False
  1756         self.flatMemberTypes = None
  1757         self.builtin = False
  1759     def __eq__(self, other):
  1760         return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes
  1762     def isVoid(self):
  1763         return False
  1765     def isUnion(self):
  1766         return True
  1768     def isSerializable(self):
  1769         return all(m.isSerializable() for m in self.memberTypes)
  1771     def includesRestrictedFloat(self):
  1772         return any(t.includesRestrictedFloat() for t in self.memberTypes)
  1774     def tag(self):
  1775         return IDLType.Tags.union
  1777     def resolveType(self, parentScope):
  1778         assert isinstance(parentScope, IDLScope)
  1779         for t in self.memberTypes:
  1780             t.resolveType(parentScope)
  1782     def isComplete(self):
  1783         return self.flatMemberTypes is not None
  1785     def complete(self, scope):
  1786         def typeName(type):
  1787             if isinstance(type, IDLNullableType):
  1788                 return typeName(type.inner) + "OrNull"
  1789             if isinstance(type, IDLWrapperType):
  1790                 return typeName(type._identifier.object())
  1791             if isinstance(type, IDLObjectWithIdentifier):
  1792                 return typeName(type.identifier)
  1793             if (isinstance(type, IDLType) and
  1794                 (type.isArray() or type.isSequence() or type.isMozMap)):
  1795                 return str(type)
  1796             return type.name
  1798         for (i, type) in enumerate(self.memberTypes):
  1799             if not type.isComplete():
  1800                 self.memberTypes[i] = type.complete(scope)
  1802         self.name = "Or".join(typeName(type) for type in self.memberTypes)
  1803         self.flatMemberTypes = list(self.memberTypes)
  1804         i = 0
  1805         while i < len(self.flatMemberTypes):
  1806             if self.flatMemberTypes[i].nullable():
  1807                 if self.hasNullableType:
  1808                     raise WebIDLError("Can't have more than one nullable types in a union",
  1809                                       [nullableType.location, self.flatMemberTypes[i].location])
  1810                 if self.hasDictionaryType:
  1811                     raise WebIDLError("Can't have a nullable type and a "
  1812                                       "dictionary type in a union",
  1813                                       [dictionaryType.location,
  1814                                        self.flatMemberTypes[i].location])
  1815                 self.hasNullableType = True
  1816                 nullableType = self.flatMemberTypes[i]
  1817                 self.flatMemberTypes[i] = self.flatMemberTypes[i].inner
  1818                 continue
  1819             if self.flatMemberTypes[i].isDictionary():
  1820                 if self.hasNullableType:
  1821                     raise WebIDLError("Can't have a nullable type and a "
  1822                                       "dictionary type in a union",
  1823                                       [nullableType.location,
  1824                                        self.flatMemberTypes[i].location])
  1825                 self.hasDictionaryType = True
  1826                 dictionaryType = self.flatMemberTypes[i]
  1827             elif self.flatMemberTypes[i].isUnion():
  1828                 self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes
  1829                 continue
  1830             i += 1
  1832         for (i, t) in enumerate(self.flatMemberTypes[:-1]):
  1833             for u in self.flatMemberTypes[i + 1:]:
  1834                 if not t.isDistinguishableFrom(u):
  1835                     raise WebIDLError("Flat member types of a union should be "
  1836                                       "distinguishable, " + str(t) + " is not "
  1837                                       "distinguishable from " + str(u),
  1838                                       [self.location, t.location, u.location])
  1840         return self
  1842     def isDistinguishableFrom(self, other):
  1843         if self.hasNullableType and other.nullable():
  1844             # Can't tell which type null should become
  1845             return False
  1846         if other.isUnion():
  1847             otherTypes = other.unroll().memberTypes
  1848         else:
  1849             otherTypes = [other]
  1850         # For every type in otherTypes, check that it's distinguishable from
  1851         # every type in our types
  1852         for u in otherTypes:
  1853             if any(not t.isDistinguishableFrom(u) for t in self.memberTypes):
  1854                 return False
  1855         return True
  1857     def _getDependentObjects(self):
  1858         return set(self.memberTypes)
  1860 class IDLArrayType(IDLType):
  1861     def __init__(self, location, parameterType):
  1862         assert not parameterType.isVoid()
  1863         if parameterType.isSequence():
  1864             raise WebIDLError("Array type cannot parameterize over a sequence type",
  1865                               [location])
  1866         if parameterType.isMozMap():
  1867             raise WebIDLError("Array type cannot parameterize over a MozMap type",
  1868                               [location])
  1869         if parameterType.isDictionary():
  1870             raise WebIDLError("Array type cannot parameterize over a dictionary type",
  1871                               [location])
  1873         IDLType.__init__(self, location, parameterType.name)
  1874         self.inner = parameterType
  1875         self.builtin = False
  1877     def __eq__(self, other):
  1878         return isinstance(other, IDLArrayType) and self.inner == other.inner
  1880     def __str__(self):
  1881         return self.inner.__str__() + "Array"
  1883     def nullable(self):
  1884         return False
  1886     def isPrimitive(self):
  1887         return False
  1889     def isString(self):
  1890         return False
  1892     def isByteString(self):
  1893         return False
  1895     def isDOMString(self):
  1896         return False
  1898     def isVoid(self):
  1899         return False
  1901     def isSequence(self):
  1902         assert not self.inner.isSequence()
  1903         return False
  1905     def isArray(self):
  1906         return True
  1908     def isDictionary(self):
  1909         assert not self.inner.isDictionary()
  1910         return False
  1912     def isInterface(self):
  1913         return False
  1915     def isEnum(self):
  1916         return False
  1918     def tag(self):
  1919         return IDLType.Tags.array
  1921     def resolveType(self, parentScope):
  1922         assert isinstance(parentScope, IDLScope)
  1923         self.inner.resolveType(parentScope)
  1925     def isComplete(self):
  1926         return self.inner.isComplete()
  1928     def complete(self, scope):
  1929         self.inner = self.inner.complete(scope)
  1930         self.name = self.inner.name
  1932         if self.inner.isDictionary():
  1933             raise WebIDLError("Array type must not contain "
  1934                               "dictionary as element type.",
  1935                               [self.inner.location])
  1937         assert not self.inner.isSequence()
  1939         return self
  1941     def unroll(self):
  1942         return self.inner.unroll()
  1944     def isDistinguishableFrom(self, other):
  1945         if other.isUnion():
  1946             # Just forward to the union; it'll deal
  1947             return other.isDistinguishableFrom(self)
  1948         return (other.isPrimitive() or other.isString() or other.isEnum() or
  1949                 other.isDate() or other.isNonCallbackInterface())
  1951     def _getDependentObjects(self):
  1952         return self.inner._getDependentObjects()
  1954 class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
  1955     def __init__(self, location, innerType, name):
  1956         IDLType.__init__(self, location, innerType.name)
  1958         identifier = IDLUnresolvedIdentifier(location, name)
  1960         IDLObjectWithIdentifier.__init__(self, location, None, identifier)
  1962         self.inner = innerType
  1963         self.name = name
  1964         self.builtin = False
  1966     def __eq__(self, other):
  1967         return isinstance(other, IDLTypedefType) and self.inner == other.inner
  1969     def __str__(self):
  1970         return self.identifier.name
  1972     def nullable(self):
  1973         return self.inner.nullable()
  1975     def isPrimitive(self):
  1976         return self.inner.isPrimitive()
  1978     def isBoolean(self):
  1979         return self.inner.isBoolean()
  1981     def isNumeric(self):
  1982         return self.inner.isNumeric()
  1984     def isString(self):
  1985         return self.inner.isString()
  1987     def isByteString(self):
  1988         return self.inner.isByteString()
  1990     def isDOMString(self):
  1991         return self.inner.isDOMString()
  1993     def isVoid(self):
  1994         return self.inner.isVoid()
  1996     def isSequence(self):
  1997         return self.inner.isSequence()
  1999     def isMozMap(self):
  2000         return self.inner.isMozMap()
  2002     def isArray(self):
  2003         return self.inner.isArray()
  2005     def isDictionary(self):
  2006         return self.inner.isDictionary()
  2008     def isArrayBuffer(self):
  2009         return self.inner.isArrayBuffer()
  2011     def isArrayBufferView(self):
  2012         return self.inner.isArrayBufferView()
  2014     def isTypedArray(self):
  2015         return self.inner.isTypedArray()
  2017     def isInterface(self):
  2018         return self.inner.isInterface()
  2020     def isCallbackInterface(self):
  2021         return self.inner.isCallbackInterface()
  2023     def isNonCallbackInterface(self):
  2024         return self.inner.isNonCallbackInterface()
  2026     def isComplete(self):
  2027         return False
  2029     def complete(self, parentScope):
  2030         if not self.inner.isComplete():
  2031             self.inner = self.inner.complete(parentScope)
  2032         assert self.inner.isComplete()
  2033         return self.inner
  2035     def finish(self, parentScope):
  2036         # Maybe the IDLObjectWithIdentifier for the typedef should be
  2037         # a separate thing from the type?  If that happens, we can
  2038         # remove some hackery around avoiding isInterface() in
  2039         # Configuration.py.
  2040         self.complete(parentScope)
  2042     def validate(self):
  2043         pass
  2045     # Do we need a resolveType impl?  I don't think it's particularly useful....
  2047     def tag(self):
  2048         return self.inner.tag()
  2050     def unroll(self):
  2051         return self.inner.unroll()
  2053     def isDistinguishableFrom(self, other):
  2054         return self.inner.isDistinguishableFrom(other)
  2056     def _getDependentObjects(self):
  2057         return self.inner._getDependentObjects()
  2059 class IDLWrapperType(IDLType):
  2060     def __init__(self, location, inner):
  2061         IDLType.__init__(self, location, inner.identifier.name)
  2062         self.inner = inner
  2063         self._identifier = inner.identifier
  2064         self.builtin = False
  2066     def __eq__(self, other):
  2067         return isinstance(other, IDLWrapperType) and \
  2068                self._identifier == other._identifier and \
  2069                self.builtin == other.builtin
  2071     def __str__(self):
  2072         return str(self.name) + " (Wrapper)"
  2074     def nullable(self):
  2075         return False
  2077     def isPrimitive(self):
  2078         return False
  2080     def isString(self):
  2081         return False
  2083     def isByteString(self):
  2084         return False
  2086     def isDOMString(self):
  2087         return False
  2089     def isVoid(self):
  2090         return False
  2092     def isSequence(self):
  2093         return False
  2095     def isArray(self):
  2096         return False
  2098     def isDictionary(self):
  2099         return isinstance(self.inner, IDLDictionary)
  2101     def isInterface(self):
  2102         return isinstance(self.inner, IDLInterface) or \
  2103                isinstance(self.inner, IDLExternalInterface)
  2105     def isCallbackInterface(self):
  2106         return self.isInterface() and self.inner.isCallback()
  2108     def isNonCallbackInterface(self):
  2109         return self.isInterface() and not self.inner.isCallback()
  2111     def isEnum(self):
  2112         return isinstance(self.inner, IDLEnum)
  2114     def isPromise(self):
  2115         return isinstance(self.inner, IDLInterface) and \
  2116                self.inner.identifier.name == "Promise"
  2118     def isSerializable(self):
  2119         if self.isInterface():
  2120             if self.inner.isExternal():
  2121                 return False
  2122             return any(m.isMethod() and m.isJsonifier() for m in self.inner.members)
  2123         elif self.isEnum():
  2124             return True
  2125         elif self.isDictionary():
  2126             return all(m.type.isSerializable() for m in self.inner.members)
  2127         else:
  2128             raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
  2129                               "is serializable" % type(self.inner), [self.location])
  2131     def resolveType(self, parentScope):
  2132         assert isinstance(parentScope, IDLScope)
  2133         self.inner.resolve(parentScope)
  2135     def isComplete(self):
  2136         return True
  2138     def tag(self):
  2139         if self.isInterface():
  2140             return IDLType.Tags.interface
  2141         elif self.isEnum():
  2142             return IDLType.Tags.enum
  2143         elif self.isDictionary():
  2144             return IDLType.Tags.dictionary
  2145         else:
  2146             assert False
  2148     def isDistinguishableFrom(self, other):
  2149         if other.isUnion():
  2150             # Just forward to the union; it'll deal
  2151             return other.isDistinguishableFrom(self)
  2152         assert self.isInterface() or self.isEnum() or self.isDictionary()
  2153         if self.isEnum():
  2154             return (other.isPrimitive() or other.isInterface() or other.isObject() or
  2155                     other.isCallback() or other.isDictionary() or
  2156                     other.isSequence() or other.isMozMap() or other.isArray() or
  2157                     other.isDate())
  2158         if self.isDictionary() and other.nullable():
  2159             return False
  2160         if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate():
  2161             return True
  2162         if self.isDictionary():
  2163             return other.isNonCallbackInterface()
  2165         assert self.isInterface()
  2166         if other.isInterface():
  2167             if other.isSpiderMonkeyInterface():
  2168                 # Just let |other| handle things
  2169                 return other.isDistinguishableFrom(self)
  2170             assert self.isGeckoInterface() and other.isGeckoInterface()
  2171             if self.inner.isExternal() or other.unroll().inner.isExternal():
  2172                 return self != other
  2173             return (len(self.inner.interfacesBasedOnSelf &
  2174                         other.unroll().inner.interfacesBasedOnSelf) == 0 and
  2175                     (self.isNonCallbackInterface() or
  2176                      other.isNonCallbackInterface()))
  2177         if (other.isDictionary() or other.isCallback() or
  2178             other.isSequence() or other.isMozMap() or other.isArray()):
  2179             return self.isNonCallbackInterface()
  2181         # Not much else |other| can be
  2182         assert other.isObject()
  2183         return False
  2185     def _getDependentObjects(self):
  2186         # NB: The codegen for an interface type depends on
  2187         #  a) That the identifier is in fact an interface (as opposed to
  2188         #     a dictionary or something else).
  2189         #  b) The native type of the interface.
  2190         #  If we depend on the interface object we will also depend on
  2191         #  anything the interface depends on which is undesirable.  We
  2192         #  considered implementing a dependency just on the interface type
  2193         #  file, but then every modification to an interface would cause this
  2194         #  to be regenerated which is still undesirable.  We decided not to
  2195         #  depend on anything, reasoning that:
  2196         #  1) Changing the concrete type of the interface requires modifying
  2197         #     Bindings.conf, which is still a global dependency.
  2198         #  2) Changing an interface to a dictionary (or vice versa) with the
  2199         #     same identifier should be incredibly rare.
  2200         return set()
  2202 class IDLBuiltinType(IDLType):
  2204     Types = enum(
  2205         # The integer types
  2206         'byte',
  2207         'octet',
  2208         'short',
  2209         'unsigned_short',
  2210         'long',
  2211         'unsigned_long',
  2212         'long_long',
  2213         'unsigned_long_long',
  2214         # Additional primitive types
  2215         'boolean',
  2216         'unrestricted_float',
  2217         'float',
  2218         'unrestricted_double',
  2219         # IMPORTANT: "double" must be the last primitive type listed
  2220         'double',
  2221         # Other types
  2222         'any',
  2223         'domstring',
  2224         'bytestring',
  2225         'object',
  2226         'date',
  2227         'void',
  2228         # Funny stuff
  2229         'ArrayBuffer',
  2230         'ArrayBufferView',
  2231         'Int8Array',
  2232         'Uint8Array',
  2233         'Uint8ClampedArray',
  2234         'Int16Array',
  2235         'Uint16Array',
  2236         'Int32Array',
  2237         'Uint32Array',
  2238         'Float32Array',
  2239         'Float64Array'
  2242     TagLookup = {
  2243             Types.byte: IDLType.Tags.int8,
  2244             Types.octet: IDLType.Tags.uint8,
  2245             Types.short: IDLType.Tags.int16,
  2246             Types.unsigned_short: IDLType.Tags.uint16,
  2247             Types.long: IDLType.Tags.int32,
  2248             Types.unsigned_long: IDLType.Tags.uint32,
  2249             Types.long_long: IDLType.Tags.int64,
  2250             Types.unsigned_long_long: IDLType.Tags.uint64,
  2251             Types.boolean: IDLType.Tags.bool,
  2252             Types.unrestricted_float: IDLType.Tags.unrestricted_float,
  2253             Types.float: IDLType.Tags.float,
  2254             Types.unrestricted_double: IDLType.Tags.unrestricted_double,
  2255             Types.double: IDLType.Tags.double,
  2256             Types.any: IDLType.Tags.any,
  2257             Types.domstring: IDLType.Tags.domstring,
  2258             Types.bytestring: IDLType.Tags.bytestring,
  2259             Types.object: IDLType.Tags.object,
  2260             Types.date: IDLType.Tags.date,
  2261             Types.void: IDLType.Tags.void,
  2262             Types.ArrayBuffer: IDLType.Tags.interface,
  2263             Types.ArrayBufferView: IDLType.Tags.interface,
  2264             Types.Int8Array: IDLType.Tags.interface,
  2265             Types.Uint8Array: IDLType.Tags.interface,
  2266             Types.Uint8ClampedArray: IDLType.Tags.interface,
  2267             Types.Int16Array: IDLType.Tags.interface,
  2268             Types.Uint16Array: IDLType.Tags.interface,
  2269             Types.Int32Array: IDLType.Tags.interface,
  2270             Types.Uint32Array: IDLType.Tags.interface,
  2271             Types.Float32Array: IDLType.Tags.interface,
  2272             Types.Float64Array: IDLType.Tags.interface
  2275     def __init__(self, location, name, type):
  2276         IDLType.__init__(self, location, name)
  2277         self.builtin = True
  2278         self._typeTag = type
  2280     def isPrimitive(self):
  2281         return self._typeTag <= IDLBuiltinType.Types.double
  2283     def isBoolean(self):
  2284         return self._typeTag == IDLBuiltinType.Types.boolean
  2286     def isNumeric(self):
  2287         return self.isPrimitive() and not self.isBoolean()
  2289     def isString(self):
  2290         return self._typeTag == IDLBuiltinType.Types.domstring or \
  2291                self._typeTag == IDLBuiltinType.Types.bytestring
  2293     def isByteString(self):
  2294         return self._typeTag == IDLBuiltinType.Types.bytestring
  2296     def isDOMString(self):
  2297         return self._typeTag == IDLBuiltinType.Types.domstring
  2299     def isInteger(self):
  2300         return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long
  2302     def isArrayBuffer(self):
  2303         return self._typeTag == IDLBuiltinType.Types.ArrayBuffer
  2305     def isArrayBufferView(self):
  2306         return self._typeTag == IDLBuiltinType.Types.ArrayBufferView
  2308     def isTypedArray(self):
  2309         return self._typeTag >= IDLBuiltinType.Types.Int8Array and \
  2310                self._typeTag <= IDLBuiltinType.Types.Float64Array
  2312     def isInterface(self):
  2313         # TypedArray things are interface types per the TypedArray spec,
  2314         # but we handle them as builtins because SpiderMonkey implements
  2315         # all of it internally.
  2316         return self.isArrayBuffer() or \
  2317                self.isArrayBufferView() or \
  2318                self.isTypedArray()
  2320     def isNonCallbackInterface(self):
  2321         # All the interfaces we can be are non-callback
  2322         return self.isInterface()
  2324     def isFloat(self):
  2325         return self._typeTag == IDLBuiltinType.Types.float or \
  2326                self._typeTag == IDLBuiltinType.Types.double or \
  2327                self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
  2328                self._typeTag == IDLBuiltinType.Types.unrestricted_double
  2330     def isUnrestricted(self):
  2331         assert self.isFloat()
  2332         return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
  2333                self._typeTag == IDLBuiltinType.Types.unrestricted_double
  2335     def isSerializable(self):
  2336         return self.isPrimitive() or self.isDOMString() or self.isDate()
  2338     def includesRestrictedFloat(self):
  2339         return self.isFloat() and not self.isUnrestricted()
  2341     def tag(self):
  2342         return IDLBuiltinType.TagLookup[self._typeTag]
  2344     def isDistinguishableFrom(self, other):
  2345         if other.isUnion():
  2346             # Just forward to the union; it'll deal
  2347             return other.isDistinguishableFrom(self)
  2348         if self.isBoolean():
  2349             return (other.isNumeric() or other.isString() or other.isEnum() or
  2350                     other.isInterface() or other.isObject() or
  2351                     other.isCallback() or other.isDictionary() or
  2352                     other.isSequence() or other.isMozMap() or other.isArray() or
  2353                     other.isDate())
  2354         if self.isNumeric():
  2355             return (other.isBoolean() or other.isString() or other.isEnum() or
  2356                     other.isInterface() or other.isObject() or
  2357                     other.isCallback() or other.isDictionary() or
  2358                     other.isSequence() or other.isMozMap() or other.isArray() or
  2359                     other.isDate())
  2360         if self.isString():
  2361             return (other.isPrimitive() or other.isInterface() or
  2362                     other.isObject() or
  2363                     other.isCallback() or other.isDictionary() or
  2364                     other.isSequence() or other.isMozMap() or other.isArray() or
  2365                     other.isDate())
  2366         if self.isAny():
  2367             # Can't tell "any" apart from anything
  2368             return False
  2369         if self.isObject():
  2370             return other.isPrimitive() or other.isString() or other.isEnum()
  2371         if self.isDate():
  2372             return (other.isPrimitive() or other.isString() or other.isEnum() or
  2373                     other.isInterface() or other.isCallback() or
  2374                     other.isDictionary() or other.isSequence() or
  2375                     other.isMozMap() or other.isArray())
  2376         if self.isVoid():
  2377             return not other.isVoid()
  2378         # Not much else we could be!
  2379         assert self.isSpiderMonkeyInterface()
  2380         # Like interfaces, but we know we're not a callback
  2381         return (other.isPrimitive() or other.isString() or other.isEnum() or
  2382                 other.isCallback() or other.isDictionary() or
  2383                 other.isSequence() or other.isMozMap() or other.isArray() or
  2384                 other.isDate() or
  2385                 (other.isInterface() and (
  2386                  # ArrayBuffer is distinguishable from everything
  2387                  # that's not an ArrayBuffer or a callback interface
  2388                  (self.isArrayBuffer() and not other.isArrayBuffer()) or
  2389                  # ArrayBufferView is distinguishable from everything
  2390                  # that's not an ArrayBufferView or typed array.
  2391                  (self.isArrayBufferView() and not other.isArrayBufferView() and
  2392                   not other.isTypedArray()) or
  2393                  # Typed arrays are distinguishable from everything
  2394                  # except ArrayBufferView and the same type of typed
  2395                  # array
  2396                  (self.isTypedArray() and not other.isArrayBufferView() and not
  2397                   (other.isTypedArray() and other.name == self.name)))))
  2399     def _getDependentObjects(self):
  2400         return set()
  2402 BuiltinTypes = {
  2403       IDLBuiltinType.Types.byte:
  2404           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte",
  2405                          IDLBuiltinType.Types.byte),
  2406       IDLBuiltinType.Types.octet:
  2407           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Octet",
  2408                          IDLBuiltinType.Types.octet),
  2409       IDLBuiltinType.Types.short:
  2410           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Short",
  2411                          IDLBuiltinType.Types.short),
  2412       IDLBuiltinType.Types.unsigned_short:
  2413           IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedShort",
  2414                          IDLBuiltinType.Types.unsigned_short),
  2415       IDLBuiltinType.Types.long:
  2416           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Long",
  2417                          IDLBuiltinType.Types.long),
  2418       IDLBuiltinType.Types.unsigned_long:
  2419           IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLong",
  2420                          IDLBuiltinType.Types.unsigned_long),
  2421       IDLBuiltinType.Types.long_long:
  2422           IDLBuiltinType(BuiltinLocation("<builtin type>"), "LongLong",
  2423                          IDLBuiltinType.Types.long_long),
  2424       IDLBuiltinType.Types.unsigned_long_long:
  2425           IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLongLong",
  2426                          IDLBuiltinType.Types.unsigned_long_long),
  2427       IDLBuiltinType.Types.boolean:
  2428           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Boolean",
  2429                          IDLBuiltinType.Types.boolean),
  2430       IDLBuiltinType.Types.float:
  2431           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float",
  2432                          IDLBuiltinType.Types.float),
  2433       IDLBuiltinType.Types.unrestricted_float:
  2434           IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedFloat",
  2435                          IDLBuiltinType.Types.unrestricted_float),
  2436       IDLBuiltinType.Types.double:
  2437           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Double",
  2438                          IDLBuiltinType.Types.double),
  2439       IDLBuiltinType.Types.unrestricted_double:
  2440           IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedDouble",
  2441                          IDLBuiltinType.Types.unrestricted_double),
  2442       IDLBuiltinType.Types.any:
  2443           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Any",
  2444                          IDLBuiltinType.Types.any),
  2445       IDLBuiltinType.Types.domstring:
  2446           IDLBuiltinType(BuiltinLocation("<builtin type>"), "String",
  2447                          IDLBuiltinType.Types.domstring),
  2448       IDLBuiltinType.Types.bytestring:
  2449           IDLBuiltinType(BuiltinLocation("<builtin type>"), "ByteString",
  2450                          IDLBuiltinType.Types.bytestring),
  2451       IDLBuiltinType.Types.object:
  2452           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
  2453                          IDLBuiltinType.Types.object),
  2454       IDLBuiltinType.Types.date:
  2455           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date",
  2456                          IDLBuiltinType.Types.date),
  2457       IDLBuiltinType.Types.void:
  2458           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void",
  2459                          IDLBuiltinType.Types.void),
  2460       IDLBuiltinType.Types.ArrayBuffer:
  2461           IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBuffer",
  2462                          IDLBuiltinType.Types.ArrayBuffer),
  2463       IDLBuiltinType.Types.ArrayBufferView:
  2464           IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView",
  2465                          IDLBuiltinType.Types.ArrayBufferView),
  2466       IDLBuiltinType.Types.Int8Array:
  2467           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
  2468                          IDLBuiltinType.Types.Int8Array),
  2469       IDLBuiltinType.Types.Uint8Array:
  2470           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8Array",
  2471                          IDLBuiltinType.Types.Uint8Array),
  2472       IDLBuiltinType.Types.Uint8ClampedArray:
  2473           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8ClampedArray",
  2474                          IDLBuiltinType.Types.Uint8ClampedArray),
  2475       IDLBuiltinType.Types.Int16Array:
  2476           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int16Array",
  2477                          IDLBuiltinType.Types.Int16Array),
  2478       IDLBuiltinType.Types.Uint16Array:
  2479           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint16Array",
  2480                          IDLBuiltinType.Types.Uint16Array),
  2481       IDLBuiltinType.Types.Int32Array:
  2482           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int32Array",
  2483                          IDLBuiltinType.Types.Int32Array),
  2484       IDLBuiltinType.Types.Uint32Array:
  2485           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint32Array",
  2486                          IDLBuiltinType.Types.Uint32Array),
  2487       IDLBuiltinType.Types.Float32Array:
  2488           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float32Array",
  2489                          IDLBuiltinType.Types.Float32Array),
  2490       IDLBuiltinType.Types.Float64Array:
  2491           IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array",
  2492                          IDLBuiltinType.Types.Float64Array)
  2496 integerTypeSizes = {
  2497         IDLBuiltinType.Types.byte: (-128, 127),
  2498         IDLBuiltinType.Types.octet:  (0, 255),
  2499         IDLBuiltinType.Types.short: (-32768, 32767),
  2500         IDLBuiltinType.Types.unsigned_short: (0, 65535),
  2501         IDLBuiltinType.Types.long: (-2147483648, 2147483647),
  2502         IDLBuiltinType.Types.unsigned_long: (0, 4294967295),
  2503         IDLBuiltinType.Types.long_long: (-9223372036854775808,
  2504                                          9223372036854775807),
  2505         IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615)
  2508 def matchIntegerValueToType(value):
  2509     for type, extremes in integerTypeSizes.items():
  2510         (min, max) = extremes
  2511         if value <= max and value >= min:
  2512             return BuiltinTypes[type]
  2514     return None
  2516 class IDLValue(IDLObject):
  2517     def __init__(self, location, type, value):
  2518         IDLObject.__init__(self, location)
  2519         self.type = type
  2520         assert isinstance(type, IDLType)
  2522         self.value = value
  2524     def coerceToType(self, type, location):
  2525         if type == self.type:
  2526             return self # Nothing to do
  2528         # We first check for unions to ensure that even if the union is nullable
  2529         # we end up with the right flat member type, not the union's type.
  2530         if type.isUnion():
  2531             # We use the flat member types here, because if we have a nullable
  2532             # member type, or a nested union, we want the type the value
  2533             # actually coerces to, not the nullable or nested union type.
  2534             for subtype in type.unroll().flatMemberTypes:
  2535                 try:
  2536                     coercedValue = self.coerceToType(subtype, location)
  2537                     # Create a new IDLValue to make sure that we have the
  2538                     # correct float/double type.  This is necessary because we
  2539                     # use the value's type when it is a default value of a
  2540                     # union, and the union cares about the exact float type.
  2541                     return IDLValue(self.location, subtype, coercedValue.value)
  2542                 except:
  2543                     pass
  2544         # If the type allows null, rerun this matching on the inner type, except
  2545         # nullable enums.  We handle those specially, because we want our
  2546         # default string values to stay strings even when assigned to a nullable
  2547         # enum.
  2548         elif type.nullable() and not type.isEnum():
  2549             innerValue = self.coerceToType(type.inner, location)
  2550             return IDLValue(self.location, type, innerValue.value)
  2552         elif self.type.isInteger() and type.isInteger():
  2553             # We're both integer types.  See if we fit.
  2555             (min, max) = integerTypeSizes[type._typeTag]
  2556             if self.value <= max and self.value >= min:
  2557                 # Promote
  2558                 return IDLValue(self.location, type, self.value)
  2559             else:
  2560                 raise WebIDLError("Value %s is out of range for type %s." %
  2561                                   (self.value, type), [location])
  2562         elif self.type.isInteger() and type.isFloat():
  2563             # Convert an integer literal into float
  2564             if -2**24 <= self.value <= 2**24:
  2565                 floatType = BuiltinTypes[IDLBuiltinType.Types.float]
  2566                 return IDLValue(self.location, floatType, float(self.value))
  2567             else:
  2568                 raise WebIDLError("Converting value %s to %s will lose precision." %
  2569                                   (self.value, type), [location])
  2570         elif self.type.isString() and type.isEnum():
  2571             # Just keep our string, but make sure it's a valid value for this enum
  2572             enum = type.unroll().inner
  2573             if self.value not in enum.values():
  2574                 raise WebIDLError("'%s' is not a valid default value for enum %s"
  2575                                   % (self.value, enum.identifier.name),
  2576                                   [location, enum.location])
  2577             return self
  2578         elif self.type.isFloat() and type.isFloat():
  2579             if (not type.isUnrestricted() and
  2580                 (self.value == float("inf") or self.value == float("-inf") or
  2581                  math.isnan(self.value))):
  2582                 raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted"
  2583                                   % self.value, [location]);
  2584             return self
  2585         raise WebIDLError("Cannot coerce type %s to type %s." %
  2586                           (self.type, type), [location])
  2588     def _getDependentObjects(self):
  2589         return set()
  2591 class IDLNullValue(IDLObject):
  2592     def __init__(self, location):
  2593         IDLObject.__init__(self, location)
  2594         self.type = None
  2595         self.value = None
  2597     def coerceToType(self, type, location):
  2598         if (not isinstance(type, IDLNullableType) and
  2599             not (type.isUnion() and type.hasNullableType) and
  2600             not (type.isUnion() and type.hasDictionaryType) and
  2601             not type.isDictionary() and
  2602             not type.isAny()):
  2603             raise WebIDLError("Cannot coerce null value to type %s." % type,
  2604                               [location])
  2606         nullValue = IDLNullValue(self.location)
  2607         if type.isUnion() and not type.nullable() and type.hasDictionaryType:
  2608             # We're actually a default value for the union's dictionary member.
  2609             # Use its type.
  2610             for t in type.flatMemberTypes:
  2611                 if t.isDictionary():
  2612                     nullValue.type = t
  2613                     return nullValue
  2614         nullValue.type = type
  2615         return nullValue
  2617     def _getDependentObjects(self):
  2618         return set()
  2620 class IDLUndefinedValue(IDLObject):
  2621     def __init__(self, location):
  2622         IDLObject.__init__(self, location)
  2623         self.type = None
  2624         self.value = None
  2626     def coerceToType(self, type, location):
  2627         if not type.isAny():
  2628             raise WebIDLError("Cannot coerce undefined value to type %s." % type,
  2629                               [location])
  2631         undefinedValue = IDLUndefinedValue(self.location)
  2632         undefinedValue.type = type
  2633         return undefinedValue
  2635     def _getDependentObjects(self):
  2636         return set()
  2638 class IDLInterfaceMember(IDLObjectWithIdentifier):
  2640     Tags = enum(
  2641         'Const',
  2642         'Attr',
  2643         'Method'
  2646     Special = enum(
  2647         'Static',
  2648         'Stringifier'
  2651     def __init__(self, location, identifier, tag):
  2652         IDLObjectWithIdentifier.__init__(self, location, None, identifier)
  2653         self.tag = tag
  2654         self._extendedAttrDict = {}
  2656     def isMethod(self):
  2657         return self.tag == IDLInterfaceMember.Tags.Method
  2659     def isAttr(self):
  2660         return self.tag == IDLInterfaceMember.Tags.Attr
  2662     def isConst(self):
  2663         return self.tag == IDLInterfaceMember.Tags.Const
  2665     def addExtendedAttributes(self, attrs):
  2666         for attr in attrs:
  2667             self.handleExtendedAttribute(attr)
  2668             attrlist = attr.listValue()
  2669             self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True
  2671     def handleExtendedAttribute(self, attr):
  2672         pass
  2674     def getExtendedAttribute(self, name):
  2675         return self._extendedAttrDict.get(name, None)
  2677 class IDLConst(IDLInterfaceMember):
  2678     def __init__(self, location, identifier, type, value):
  2679         IDLInterfaceMember.__init__(self, location, identifier,
  2680                                     IDLInterfaceMember.Tags.Const)
  2682         assert isinstance(type, IDLType)
  2683         if type.isDictionary():
  2684             raise WebIDLError("A constant cannot be of a dictionary type",
  2685                               [self.location])
  2686         self.type = type
  2687         self.value = value
  2689         if identifier.name == "prototype":
  2690             raise WebIDLError("The identifier of a constant must not be 'prototype'",
  2691                               [location])
  2693     def __str__(self):
  2694         return "'%s' const '%s'" % (self.type, self.identifier)
  2696     def finish(self, scope):
  2697         if not self.type.isComplete():
  2698             type = self.type.complete(scope)
  2699             if not type.isPrimitive() and not type.isString():
  2700                 locations = [self.type.location, type.location]
  2701                 try:
  2702                     locations.append(type.inner.location)
  2703                 except:
  2704                     pass
  2705                 raise WebIDLError("Incorrect type for constant", locations)
  2706             self.type = type
  2708         # The value might not match the type
  2709         coercedValue = self.value.coerceToType(self.type, self.location)
  2710         assert coercedValue
  2712         self.value = coercedValue
  2714     def validate(self):
  2715         pass
  2717     def _getDependentObjects(self):
  2718         return set([self.type, self.value])
  2720 class IDLAttribute(IDLInterfaceMember):
  2721     def __init__(self, location, identifier, type, readonly, inherit=False,
  2722                  static=False, stringifier=False):
  2723         IDLInterfaceMember.__init__(self, location, identifier,
  2724                                     IDLInterfaceMember.Tags.Attr)
  2726         assert isinstance(type, IDLType)
  2727         self.type = type
  2728         self.readonly = readonly
  2729         self.inherit = inherit
  2730         self.static = static
  2731         self.lenientThis = False
  2732         self._unforgeable = False
  2733         self.stringifier = stringifier
  2734         self.enforceRange = False
  2735         self.clamp = False
  2736         self.slotIndex = None
  2738         if static and identifier.name == "prototype":
  2739             raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
  2740                               [location])
  2742         if readonly and inherit:
  2743             raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
  2744                               [self.location])
  2746     def isStatic(self):
  2747         return self.static
  2749     def __str__(self):
  2750         return "'%s' attribute '%s'" % (self.type, self.identifier)
  2752     def finish(self, scope):
  2753         if not self.type.isComplete():
  2754             t = self.type.complete(scope)
  2756             assert not isinstance(t, IDLUnresolvedType)
  2757             assert not isinstance(t, IDLTypedefType)
  2758             assert not isinstance(t.name, IDLUnresolvedIdentifier)
  2759             self.type = t
  2761         if self.type.isDictionary() and not self.getExtendedAttribute("Cached"):
  2762             raise WebIDLError("An attribute cannot be of a dictionary type",
  2763                               [self.location])
  2764         if self.type.isSequence() and not self.getExtendedAttribute("Cached"):
  2765             raise WebIDLError("A non-cached attribute cannot be of a sequence "
  2766                               "type", [self.location])
  2767         if self.type.isMozMap() and not self.getExtendedAttribute("Cached"):
  2768             raise WebIDLError("A non-cached attribute cannot be of a MozMap "
  2769                               "type", [self.location])
  2770         if self.type.isUnion():
  2771             for f in self.type.unroll().flatMemberTypes:
  2772                 if f.isDictionary():
  2773                     raise WebIDLError("An attribute cannot be of a union "
  2774                                       "type if one of its member types (or "
  2775                                       "one of its member types's member "
  2776                                       "types, and so on) is a dictionary "
  2777                                       "type", [self.location, f.location])
  2778                 if f.isSequence():
  2779                     raise WebIDLError("An attribute cannot be of a union "
  2780                                       "type if one of its member types (or "
  2781                                       "one of its member types's member "
  2782                                       "types, and so on) is a sequence "
  2783                                       "type", [self.location, f.location])
  2784                 if f.isMozMap():
  2785                     raise WebIDLError("An attribute cannot be of a union "
  2786                                       "type if one of its member types (or "
  2787                                       "one of its member types's member "
  2788                                       "types, and so on) is a MozMap "
  2789                                       "type", [self.location, f.location])
  2790         if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"):
  2791             raise WebIDLError("An attribute with [PutForwards] must have an "
  2792                               "interface type as its type", [self.location])
  2794         if not self.type.isInterface() and self.getExtendedAttribute("SameObject"):
  2795             raise WebIDLError("An attribute with [SameObject] must have an "
  2796                               "interface type as its type", [self.location])
  2798     def validate(self):
  2799         if ((self.getExtendedAttribute("Cached") or
  2800              self.getExtendedAttribute("StoreInSlot")) and
  2801             not self.getExtendedAttribute("Constant") and
  2802             not self.getExtendedAttribute("Pure")):
  2803             raise WebIDLError("Cached attributes and attributes stored in "
  2804                               "slots must be constant or pure, since the "
  2805                               "getter won't always be called.",
  2806                               [self.location])
  2807         if self.getExtendedAttribute("Frozen"):
  2808             if (not self.type.isSequence() and not self.type.isDictionary() and
  2809                 not self.type.isMozMap()):
  2810                 raise WebIDLError("[Frozen] is only allowed on "
  2811                                   "sequence-valued, dictionary-valued, and "
  2812                                   "MozMap-valued attributes",
  2813                                   [self.location])
  2815     def handleExtendedAttribute(self, attr):
  2816         identifier = attr.identifier()
  2817         if identifier == "SetterThrows" and self.readonly:
  2818             raise WebIDLError("Readonly attributes must not be flagged as "
  2819                               "[SetterThrows]",
  2820                               [self.location])
  2821         elif (((identifier == "Throws" or identifier == "GetterThrows") and
  2822                self.getExtendedAttribute("StoreInSlot")) or
  2823               (identifier == "StoreInSlot" and
  2824                (self.getExtendedAttribute("Throws") or
  2825                 self.getExtendedAttribute("GetterThrows")))):
  2826             raise WebIDLError("Throwing things can't be [Pure] or [Constant] "
  2827                               "or [SameObject] or [StoreInSlot]",
  2828                               [attr.location])
  2829         elif identifier == "LenientThis":
  2830             if not attr.noArguments():
  2831                 raise WebIDLError("[LenientThis] must take no arguments",
  2832                                   [attr.location])
  2833             if self.isStatic():
  2834                 raise WebIDLError("[LenientThis] is only allowed on non-static "
  2835                                   "attributes", [attr.location, self.location])
  2836             if self.getExtendedAttribute("CrossOriginReadable"):
  2837                 raise WebIDLError("[LenientThis] is not allowed in combination "
  2838                                   "with [CrossOriginReadable]",
  2839                                   [attr.location, self.location])
  2840             if self.getExtendedAttribute("CrossOriginWritable"):
  2841                 raise WebIDLError("[LenientThis] is not allowed in combination "
  2842                                   "with [CrossOriginWritable]",
  2843                                   [attr.location, self.location])
  2844             self.lenientThis = True
  2845         elif identifier == "Unforgeable":
  2846             if not self.readonly:
  2847                 raise WebIDLError("[Unforgeable] is only allowed on readonly "
  2848                                   "attributes", [attr.location, self.location])
  2849             if self.isStatic():
  2850                 raise WebIDLError("[Unforgeable] is only allowed on non-static "
  2851                                   "attributes", [attr.location, self.location])
  2852             self._unforgeable = True
  2853         elif identifier == "SameObject" and not self.readonly:
  2854             raise WebIDLError("[SameObject] only allowed on readonly attributes",
  2855                               [attr.location, self.location])
  2856         elif identifier == "Constant" and not self.readonly:
  2857             raise WebIDLError("[Constant] only allowed on readonly attributes",
  2858                               [attr.location, self.location])
  2859         elif identifier == "PutForwards":
  2860             if not self.readonly:
  2861                 raise WebIDLError("[PutForwards] is only allowed on readonly "
  2862                                   "attributes", [attr.location, self.location])
  2863             if self.isStatic():
  2864                 raise WebIDLError("[PutForwards] is only allowed on non-static "
  2865                                   "attributes", [attr.location, self.location])
  2866             if self.getExtendedAttribute("Replaceable") is not None:
  2867                 raise WebIDLError("[PutForwards] and [Replaceable] can't both "
  2868                                   "appear on the same attribute",
  2869                                   [attr.location, self.location])
  2870             if not attr.hasValue():
  2871                 raise WebIDLError("[PutForwards] takes an identifier",
  2872                                   [attr.location, self.location])
  2873         elif identifier == "Replaceable":
  2874             if self.getExtendedAttribute("PutForwards") is not None:
  2875                 raise WebIDLError("[PutForwards] and [Replaceable] can't both "
  2876                                   "appear on the same attribute",
  2877                                   [attr.location, self.location])
  2878         elif identifier == "LenientFloat":
  2879             if self.readonly:
  2880                 raise WebIDLError("[LenientFloat] used on a readonly attribute",
  2881                                   [attr.location, self.location])
  2882             if not self.type.includesRestrictedFloat():
  2883                 raise WebIDLError("[LenientFloat] used on an attribute with a "
  2884                                   "non-restricted-float type",
  2885                                   [attr.location, self.location])
  2886         elif identifier == "EnforceRange":
  2887             if self.readonly:
  2888                 raise WebIDLError("[EnforceRange] used on a readonly attribute",
  2889                                   [attr.location, self.location])
  2890             self.enforceRange = True
  2891         elif identifier == "Clamp":
  2892             if self.readonly:
  2893                 raise WebIDLError("[Clamp] used on a readonly attribute",
  2894                                   [attr.location, self.location])
  2895             self.clamp = True
  2896         elif identifier == "StoreInSlot":
  2897             if self.getExtendedAttribute("Cached"):
  2898                 raise WebIDLError("[StoreInSlot] and [Cached] must not be "
  2899                                   "specified on the same attribute",
  2900                                   [attr.location, self.location])
  2901         elif identifier == "Cached":
  2902             if self.getExtendedAttribute("StoreInSlot"):
  2903                 raise WebIDLError("[Cached] and [StoreInSlot] must not be "
  2904                                   "specified on the same attribute",
  2905                                   [attr.location, self.location])
  2906         elif (identifier == "CrossOriginReadable" or
  2907               identifier == "CrossOriginWritable"):
  2908             if not attr.noArguments():
  2909                 raise WebIDLError("[%s] must take no arguments" % identifier,
  2910                                   [attr.location])
  2911             if self.isStatic():
  2912                 raise WebIDLError("[%s] is only allowed on non-static "
  2913                                   "attributes" % identifier,
  2914                                   [attr.location, self.location])
  2915             if self.getExtendedAttribute("LenientThis"):
  2916                 raise WebIDLError("[LenientThis] is not allowed in combination "
  2917                                   "with [%s]" % identifier,
  2918                                   [attr.location, self.location])
  2919         elif (identifier == "Pref" or
  2920               identifier == "SetterThrows" or
  2921               identifier == "Pure" or
  2922               identifier == "Throws" or
  2923               identifier == "GetterThrows" or
  2924               identifier == "ChromeOnly" or
  2925               identifier == "SameObject" or
  2926               identifier == "Constant" or
  2927               identifier == "Func" or
  2928               identifier == "Frozen" or
  2929               identifier == "AvailableIn" or
  2930               identifier == "NewObject"):
  2931             # Known attributes that we don't need to do anything with here
  2932             pass
  2933         else:
  2934             raise WebIDLError("Unknown extended attribute %s on attribute" % identifier,
  2935                               [attr.location])
  2936         IDLInterfaceMember.handleExtendedAttribute(self, attr)
  2938     def resolve(self, parentScope):
  2939         assert isinstance(parentScope, IDLScope)
  2940         self.type.resolveType(parentScope)
  2941         IDLObjectWithIdentifier.resolve(self, parentScope)
  2943     def addExtendedAttributes(self, attrs):
  2944         attrs = self.checkForStringHandlingExtendedAttributes(attrs)
  2945         IDLInterfaceMember.addExtendedAttributes(self, attrs)
  2947     def hasLenientThis(self):
  2948         return self.lenientThis
  2950     def isUnforgeable(self):
  2951         return self._unforgeable
  2953     def _getDependentObjects(self):
  2954         return set([self.type])
  2956 class IDLArgument(IDLObjectWithIdentifier):
  2957     def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
  2958         IDLObjectWithIdentifier.__init__(self, location, None, identifier)
  2960         assert isinstance(type, IDLType)
  2961         self.type = type
  2963         self.optional = optional
  2964         self.defaultValue = defaultValue
  2965         self.variadic = variadic
  2966         self.dictionaryMember = dictionaryMember
  2967         self._isComplete = False
  2968         self.enforceRange = False
  2969         self.clamp = False
  2970         self._allowTreatNonCallableAsNull = False
  2972         assert not variadic or optional
  2974     def addExtendedAttributes(self, attrs):
  2975         attrs = self.checkForStringHandlingExtendedAttributes(
  2976             attrs,
  2977             isDictionaryMember=self.dictionaryMember,
  2978             isOptional=self.optional)
  2979         for attribute in attrs:
  2980             identifier = attribute.identifier()
  2981             if identifier == "Clamp":
  2982                 if not attribute.noArguments():
  2983                     raise WebIDLError("[Clamp] must take no arguments",
  2984                                       [attribute.location])
  2985                 if self.enforceRange:
  2986                     raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
  2987                                       [self.location]);
  2988                 self.clamp = True
  2989             elif identifier == "EnforceRange":
  2990                 if not attribute.noArguments():
  2991                     raise WebIDLError("[EnforceRange] must take no arguments",
  2992                                       [attribute.location])
  2993                 if self.clamp:
  2994                     raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
  2995                                       [self.location]);
  2996                 self.enforceRange = True
  2997             elif identifier == "TreatNonCallableAsNull":
  2998                 self._allowTreatNonCallableAsNull = True
  2999             else:
  3000                 raise WebIDLError("Unhandled extended attribute on an argument",
  3001                                   [attribute.location])
  3003     def isComplete(self):
  3004         return self._isComplete
  3006     def complete(self, scope):
  3007         if self._isComplete:
  3008             return
  3010         self._isComplete = True
  3012         if not self.type.isComplete():
  3013             type = self.type.complete(scope)
  3014             assert not isinstance(type, IDLUnresolvedType)
  3015             assert not isinstance(type, IDLTypedefType)
  3016             assert not isinstance(type.name, IDLUnresolvedIdentifier)
  3017             self.type = type
  3019         if ((self.type.isDictionary() or
  3020              self.type.isUnion() and self.type.unroll().hasDictionaryType) and
  3021             self.optional and not self.defaultValue):
  3022             # Default optional dictionaries to null, for simplicity,
  3023             # so the codegen doesn't have to special-case this.
  3024             self.defaultValue = IDLNullValue(self.location)
  3025         elif self.type.isAny():
  3026             assert (self.defaultValue is None or
  3027                     isinstance(self.defaultValue, IDLNullValue))
  3028             # optional 'any' values always have a default value
  3029             if self.optional and not self.defaultValue and not self.variadic:
  3030                 # Set the default value to undefined, for simplicity, so the
  3031                 # codegen doesn't have to special-case this.
  3032                 self.defaultValue = IDLUndefinedValue(self.location)
  3034         # Now do the coercing thing; this needs to happen after the
  3035         # above creation of a default value.
  3036         if self.defaultValue:
  3037             self.defaultValue = self.defaultValue.coerceToType(self.type,
  3038                                                                self.location)
  3039             assert self.defaultValue
  3041     def allowTreatNonCallableAsNull(self):
  3042         return self._allowTreatNonCallableAsNull
  3044     def _getDependentObjects(self):
  3045         deps = set([self.type])
  3046         if self.defaultValue:
  3047             deps.add(self.defaultValue)
  3048         return deps
  3050 class IDLCallbackType(IDLType, IDLObjectWithScope):
  3051     def __init__(self, location, parentScope, identifier, returnType, arguments):
  3052         assert isinstance(returnType, IDLType)
  3054         IDLType.__init__(self, location, identifier.name)
  3056         self._returnType = returnType
  3057         # Clone the list
  3058         self._arguments = list(arguments)
  3060         IDLObjectWithScope.__init__(self, location, parentScope, identifier)
  3062         for (returnType, arguments) in self.signatures():
  3063             for argument in arguments:
  3064                 argument.resolve(self)
  3066         self._treatNonCallableAsNull = False
  3067         self._treatNonObjectAsNull = False
  3069     def isCallback(self):
  3070         return True
  3072     def signatures(self):
  3073         return [(self._returnType, self._arguments)]
  3075     def tag(self):
  3076         return IDLType.Tags.callback
  3078     def finish(self, scope):
  3079         if not self._returnType.isComplete():
  3080             type = self._returnType.complete(scope)
  3082             assert not isinstance(type, IDLUnresolvedType)
  3083             assert not isinstance(type, IDLTypedefType)
  3084             assert not isinstance(type.name, IDLUnresolvedIdentifier)
  3085             self._returnType = type
  3087         for argument in self._arguments:
  3088             if argument.type.isComplete():
  3089                 continue
  3091             type = argument.type.complete(scope)
  3093             assert not isinstance(type, IDLUnresolvedType)
  3094             assert not isinstance(type, IDLTypedefType)
  3095             assert not isinstance(type.name, IDLUnresolvedIdentifier)
  3096             argument.type = type
  3098     def validate(self):
  3099         pass
  3101     def isDistinguishableFrom(self, other):
  3102         if other.isUnion():
  3103             # Just forward to the union; it'll deal
  3104             return other.isDistinguishableFrom(self)
  3105         return (other.isPrimitive() or other.isString() or other.isEnum() or
  3106                 other.isNonCallbackInterface() or other.isDate())
  3108     def addExtendedAttributes(self, attrs):
  3109         unhandledAttrs = []
  3110         for attr in attrs:
  3111             if attr.identifier() == "TreatNonCallableAsNull":
  3112                 self._treatNonCallableAsNull = True
  3113             elif attr.identifier() == "TreatNonObjectAsNull":
  3114                 self._treatNonObjectAsNull = True
  3115             else:
  3116                 unhandledAttrs.append(attr)
  3117         if self._treatNonCallableAsNull and self._treatNonObjectAsNull:
  3118             raise WebIDLError("Cannot specify both [TreatNonCallableAsNull] "
  3119                               "and [TreatNonObjectAsNull]", [self.location])
  3120         if len(unhandledAttrs) != 0:
  3121             IDLType.addExtendedAttributes(self, unhandledAttrs)
  3123     def _getDependentObjects(self):
  3124         return set([self._returnType] + self._arguments)
  3126 class IDLMethodOverload:
  3127     """
  3128     A class that represents a single overload of a WebIDL method.  This is not
  3129     quite the same as an element of the "effective overload set" in the spec,
  3130     because separate IDLMethodOverloads are not created based on arguments being
  3131     optional.  Rather, when multiple methods have the same name, there is an
  3132     IDLMethodOverload for each one, all hanging off an IDLMethod representing
  3133     the full set of overloads.
  3134     """
  3135     def __init__(self, returnType, arguments, location):
  3136         self.returnType = returnType
  3137         # Clone the list of arguments, just in case
  3138         self.arguments = list(arguments)
  3139         self.location = location
  3141     def _getDependentObjects(self):
  3142         deps = set(self.arguments)
  3143         deps.add(self.returnType)
  3144         return deps
  3146 class IDLMethod(IDLInterfaceMember, IDLScope):
  3148     Special = enum(
  3149         'Getter',
  3150         'Setter',
  3151         'Creator',
  3152         'Deleter',
  3153         'LegacyCaller',
  3154         base=IDLInterfaceMember.Special
  3157     TypeSuffixModifier = enum(
  3158         'None',
  3159         'QMark',
  3160         'Brackets'
  3163     NamedOrIndexed = enum(
  3164         'Neither',
  3165         'Named',
  3166         'Indexed'
  3169     def __init__(self, location, identifier, returnType, arguments,
  3170                  static=False, getter=False, setter=False, creator=False,
  3171                  deleter=False, specialType=NamedOrIndexed.Neither,
  3172                  legacycaller=False, stringifier=False, jsonifier=False):
  3173         # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
  3174         IDLInterfaceMember.__init__(self, location, identifier,
  3175                                     IDLInterfaceMember.Tags.Method)
  3177         self._hasOverloads = False
  3179         assert isinstance(returnType, IDLType)
  3181         # self._overloads is a list of IDLMethodOverloads
  3182         self._overloads = [IDLMethodOverload(returnType, arguments, location)]
  3184         assert isinstance(static, bool)
  3185         self._static = static
  3186         assert isinstance(getter, bool)
  3187         self._getter = getter
  3188         assert isinstance(setter, bool)
  3189         self._setter = setter
  3190         assert isinstance(creator, bool)
  3191         self._creator = creator
  3192         assert isinstance(deleter, bool)
  3193         self._deleter = deleter
  3194         assert isinstance(legacycaller, bool)
  3195         self._legacycaller = legacycaller
  3196         assert isinstance(stringifier, bool)
  3197         self._stringifier = stringifier
  3198         assert isinstance(jsonifier, bool)
  3199         self._jsonifier = jsonifier
  3200         self._specialType = specialType
  3202         if static and identifier.name == "prototype":
  3203             raise WebIDLError("The identifier of a static operation must not be 'prototype'",
  3204                               [location])
  3206         self.assertSignatureConstraints()
  3208     def __str__(self):
  3209         return "Method '%s'" % self.identifier
  3211     def assertSignatureConstraints(self):
  3212         if self._getter or self._deleter:
  3213             assert len(self._overloads) == 1
  3214             overload = self._overloads[0]
  3215             arguments =  overload.arguments
  3216             assert len(arguments) == 1
  3217             assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \
  3218                    arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]
  3219             assert not arguments[0].optional and not arguments[0].variadic
  3220             assert not self._getter or not overload.returnType.isVoid()
  3222         if self._setter or self._creator:
  3223             assert len(self._overloads) == 1
  3224             arguments = self._overloads[0].arguments
  3225             assert len(arguments) == 2
  3226             assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \
  3227                    arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]
  3228             assert not arguments[0].optional and not arguments[0].variadic
  3229             assert not arguments[1].optional and not arguments[1].variadic
  3231         if self._stringifier:
  3232             assert len(self._overloads) == 1
  3233             overload = self._overloads[0]
  3234             assert len(overload.arguments) == 0
  3235             assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
  3237         if self._jsonifier:
  3238             assert len(self._overloads) == 1
  3239             overload = self._overloads[0]
  3240             assert len(overload.arguments) == 0
  3241             assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
  3243     def isStatic(self):
  3244         return self._static
  3246     def isGetter(self):
  3247         return self._getter
  3249     def isSetter(self):
  3250         return self._setter
  3252     def isCreator(self):
  3253         return self._creator
  3255     def isDeleter(self):
  3256         return self._deleter
  3258     def isNamed(self):
  3259         assert self._specialType == IDLMethod.NamedOrIndexed.Named or \
  3260                self._specialType == IDLMethod.NamedOrIndexed.Indexed
  3261         return self._specialType == IDLMethod.NamedOrIndexed.Named
  3263     def isIndexed(self):
  3264         assert self._specialType == IDLMethod.NamedOrIndexed.Named or \
  3265                self._specialType == IDLMethod.NamedOrIndexed.Indexed
  3266         return self._specialType == IDLMethod.NamedOrIndexed.Indexed
  3268     def isLegacycaller(self):
  3269         return self._legacycaller
  3271     def isStringifier(self):
  3272         return self._stringifier
  3274     def isJsonifier(self):
  3275         return self._jsonifier
  3277     def hasOverloads(self):
  3278         return self._hasOverloads
  3280     def isIdentifierLess(self):
  3281         return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__"
  3283     def resolve(self, parentScope):
  3284         assert isinstance(parentScope, IDLScope)
  3285         IDLObjectWithIdentifier.resolve(self, parentScope)
  3286         IDLScope.__init__(self, self.location, parentScope, self.identifier)
  3287         for (returnType, arguments) in self.signatures():
  3288             for argument in arguments:
  3289                 argument.resolve(self)
  3291     def addOverload(self, method):
  3292         assert len(method._overloads) == 1
  3294         if self._extendedAttrDict != method ._extendedAttrDict:
  3295             raise WebIDLError("Extended attributes differ on different "
  3296                               "overloads of %s" % method.identifier,
  3297                               [self.location, method.location])
  3299         self._overloads.extend(method._overloads)
  3301         self._hasOverloads = True
  3303         if self.isStatic() != method.isStatic():
  3304             raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method.identifier,
  3305                               [method.location])
  3307         if self.isLegacycaller() != method.isLegacycaller():
  3308             raise WebIDLError("Overloaded identifier %s appears with different values of the 'legacycaller' attribute" % method.identifier,
  3309                               [method.location])
  3311         # Can't overload special things!
  3312         assert not self.isGetter()
  3313         assert not method.isGetter()
  3314         assert not self.isSetter()
  3315         assert not method.isSetter()
  3316         assert not self.isCreator()
  3317         assert not method.isCreator()
  3318         assert not self.isDeleter()
  3319         assert not method.isDeleter()
  3320         assert not self.isStringifier()
  3321         assert not method.isStringifier()
  3322         assert not self.isJsonifier()
  3323         assert not method.isJsonifier()
  3325         return self
  3327     def signatures(self):
  3328         return [(overload.returnType, overload.arguments) for overload in
  3329                 self._overloads]
  3331     def finish(self, scope):
  3332         overloadWithPromiseReturnType = None
  3333         overloadWithoutPromiseReturnType = None
  3334         for overload in self._overloads:
  3335             variadicArgument = None
  3337             arguments = overload.arguments
  3338             for (idx, argument) in enumerate(arguments):
  3339                 if not argument.isComplete():
  3340                     argument.complete(scope)
  3341                 assert argument.type.isComplete()
  3343                 if (argument.type.isDictionary() or
  3344                     (argument.type.isUnion() and
  3345                      argument.type.unroll().hasDictionaryType)):
  3346                     # Dictionaries and unions containing dictionaries at the
  3347                     # end of the list or followed by optional arguments must be
  3348                     # optional.
  3349                     if (not argument.optional and
  3350                         all(arg.optional for arg in arguments[idx+1:])):
  3351                         raise WebIDLError("Dictionary argument or union "
  3352                                           "argument containing a dictionary "
  3353                                           "not followed by a required argument "
  3354                                           "must be optional",
  3355                                           [argument.location])
  3357                     # An argument cannot be a Nullable Dictionary
  3358                     if argument.type.nullable():
  3359                         raise WebIDLError("An argument cannot be a nullable "
  3360                                           "dictionary or nullable union "
  3361                                           "containing a dictionary",
  3362                                           [argument.location])
  3364                 # Only the last argument can be variadic
  3365                 if variadicArgument:
  3366                     raise WebIDLError("Variadic argument is not last argument",
  3367                                       [variadicArgument.location])
  3368                 if argument.variadic:
  3369                     variadicArgument = argument
  3371             returnType = overload.returnType
  3372             if not returnType.isComplete():
  3373                 returnType = returnType.complete(scope)
  3374                 assert not isinstance(returnType, IDLUnresolvedType)
  3375                 assert not isinstance(returnType, IDLTypedefType)
  3376                 assert not isinstance(returnType.name, IDLUnresolvedIdentifier)
  3377                 overload.returnType = returnType
  3379             if returnType.isPromise():
  3380                 overloadWithPromiseReturnType = overload
  3381             else:
  3382                 overloadWithoutPromiseReturnType = overload
  3384         # Make sure either all our overloads return Promises or none do
  3385         if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType:
  3386             raise WebIDLError("We have overloads with both Promise and "
  3387                               "non-Promise return types",
  3388                               [overloadWithPromiseReturnType.location,
  3389                                overloadWithoutPromiseReturnType.location])
  3391         if overloadWithPromiseReturnType and self._legacycaller:
  3392             raise WebIDLError("May not have a Promise return type for a "
  3393                               "legacycaller.",
  3394                               [overloadWithPromiseReturnType.location])
  3396         # Now compute various information that will be used by the
  3397         # WebIDL overload resolution algorithm.
  3398         self.maxArgCount = max(len(s[1]) for s in self.signatures())
  3399         self.allowedArgCounts = [ i for i in range(self.maxArgCount+1)
  3400                                   if len(self.signaturesForArgCount(i)) != 0 ]
  3402     def validate(self):
  3403         # Make sure our overloads are properly distinguishable and don't have
  3404         # different argument types before the distinguishing args.
  3405         for argCount in self.allowedArgCounts:
  3406             possibleOverloads = self.overloadsForArgCount(argCount)
  3407             if len(possibleOverloads) == 1:
  3408                 continue
  3409             distinguishingIndex = self.distinguishingIndexForArgCount(argCount)
  3410             for idx in range(distinguishingIndex):
  3411                 firstSigType = possibleOverloads[0].arguments[idx].type
  3412                 for overload in possibleOverloads[1:]:
  3413                     if overload.arguments[idx].type != firstSigType:
  3414                         raise WebIDLError(
  3415                             "Signatures for method '%s' with %d arguments have "
  3416                             "different types of arguments at index %d, which "
  3417                             "is before distinguishing index %d" %
  3418                             (self.identifier.name, argCount, idx,
  3419                              distinguishingIndex),
  3420                             [self.location, overload.location])
  3422     def overloadsForArgCount(self, argc):
  3423         return [overload for overload in self._overloads if
  3424                 len(overload.arguments) == argc or
  3425                 (len(overload.arguments) > argc and
  3426                  all(arg.optional for arg in overload.arguments[argc:])) or
  3427                 (len(overload.arguments) < argc and
  3428                  len(overload.arguments) > 0 and
  3429                  overload.arguments[-1].variadic)]
  3431     def signaturesForArgCount(self, argc):
  3432         return [(overload.returnType, overload.arguments) for overload
  3433                 in self.overloadsForArgCount(argc)]
  3435     def locationsForArgCount(self, argc):
  3436         return [overload.location for overload in self.overloadsForArgCount(argc)]
  3438     def distinguishingIndexForArgCount(self, argc):
  3439         def isValidDistinguishingIndex(idx, signatures):
  3440             for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]):
  3441                 for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]:
  3442                     if idx < len(firstArgs):
  3443                         firstType = firstArgs[idx].type
  3444                     else:
  3445                         assert(firstArgs[-1].variadic)
  3446                         firstType = firstArgs[-1].type
  3447                     if idx < len(secondArgs):
  3448                         secondType = secondArgs[idx].type
  3449                     else:
  3450                         assert(secondArgs[-1].variadic)
  3451                         secondType = secondArgs[-1].type
  3452                     if not firstType.isDistinguishableFrom(secondType):
  3453                         return False
  3454             return True
  3455         signatures = self.signaturesForArgCount(argc)
  3456         for idx in range(argc):
  3457             if isValidDistinguishingIndex(idx, signatures):
  3458                 return idx
  3459         # No valid distinguishing index.  Time to throw
  3460         locations = self.locationsForArgCount(argc)
  3461         raise WebIDLError("Signatures with %d arguments for method '%s' are not "
  3462                           "distinguishable" % (argc, self.identifier.name),
  3463                           locations)
  3465     def handleExtendedAttribute(self, attr):
  3466         identifier = attr.identifier()
  3467         if identifier == "GetterThrows":
  3468             raise WebIDLError("Methods must not be flagged as "
  3469                               "[GetterThrows]",
  3470                               [attr.location, self.location])
  3471         elif identifier == "SetterThrows":
  3472             raise WebIDLError("Methods must not be flagged as "
  3473                               "[SetterThrows]",
  3474                               [attr.location, self.location])
  3475         elif identifier == "Unforgeable":
  3476             raise WebIDLError("Methods must not be flagged as "
  3477                               "[Unforgeable]",
  3478                               [attr.location, self.location])
  3479         elif identifier == "SameObject":
  3480             raise WebIDLError("Methods must not be flagged as [SameObject]",
  3481                               [attr.location, self.location]);
  3482         elif identifier == "Constant":
  3483             raise WebIDLError("Methods must not be flagged as [Constant]",
  3484                               [attr.location, self.location]);
  3485         elif identifier == "PutForwards":
  3486             raise WebIDLError("Only attributes support [PutForwards]",
  3487                               [attr.location, self.location])
  3488         elif identifier == "LenientFloat":
  3489             # This is called before we've done overload resolution
  3490             assert len(self.signatures()) == 1
  3491             sig = self.signatures()[0]
  3492             if not sig[0].isVoid():
  3493                 raise WebIDLError("[LenientFloat] used on a non-void method",
  3494                                   [attr.location, self.location])
  3495             if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
  3496                 raise WebIDLError("[LenientFloat] used on an operation with no "
  3497                                   "restricted float type arguments",
  3498                                   [attr.location, self.location])
  3499         elif (identifier == "Throws" or
  3500               identifier == "NewObject" or
  3501               identifier == "ChromeOnly" or
  3502               identifier == "Pref" or
  3503               identifier == "Func" or
  3504               identifier == "AvailableIn" or
  3505               identifier == "Pure" or
  3506               identifier == "CrossOriginCallable" or
  3507               identifier == "WebGLHandlesContextLoss"):
  3508             # Known attributes that we don't need to do anything with here
  3509             pass
  3510         else:
  3511             raise WebIDLError("Unknown extended attribute %s on method" % identifier,
  3512                               [attr.location])
  3513         IDLInterfaceMember.handleExtendedAttribute(self, attr)
  3515     def returnsPromise(self):
  3516         return self._overloads[0].returnType.isPromise()
  3518     def _getDependentObjects(self):
  3519         deps = set()
  3520         for overload in self._overloads:
  3521             deps.union(overload._getDependentObjects())
  3522         return deps
  3524 class IDLImplementsStatement(IDLObject):
  3525     def __init__(self, location, implementor, implementee):
  3526         IDLObject.__init__(self, location)
  3527         self.implementor = implementor;
  3528         self.implementee = implementee
  3530     def finish(self, scope):
  3531         assert(isinstance(self.implementor, IDLIdentifierPlaceholder))
  3532         assert(isinstance(self.implementee, IDLIdentifierPlaceholder))
  3533         implementor = self.implementor.finish(scope)
  3534         implementee = self.implementee.finish(scope)
  3535         # NOTE: we depend on not setting self.implementor and
  3536         # self.implementee here to keep track of the original
  3537         # locations.
  3538         if not isinstance(implementor, IDLInterface):
  3539             raise WebIDLError("Left-hand side of 'implements' is not an "
  3540                               "interface",
  3541                               [self.implementor.location])
  3542         if implementor.isCallback():
  3543             raise WebIDLError("Left-hand side of 'implements' is a callback "
  3544                               "interface",
  3545                               [self.implementor.location])
  3546         if not isinstance(implementee, IDLInterface):
  3547             raise WebIDLError("Right-hand side of 'implements' is not an "
  3548                               "interface",
  3549                               [self.implementee.location])
  3550         if implementee.isCallback():
  3551             raise WebIDLError("Right-hand side of 'implements' is a callback "
  3552                               "interface",
  3553                               [self.implementee.location])
  3554         implementor.addImplementedInterface(implementee)
  3556     def validate(self):
  3557         pass
  3559     def addExtendedAttributes(self, attrs):
  3560         assert len(attrs) == 0
  3562 class IDLExtendedAttribute(IDLObject):
  3563     """
  3564     A class to represent IDL extended attributes so we can give them locations
  3565     """
  3566     def __init__(self, location, tuple):
  3567         IDLObject.__init__(self, location)
  3568         self._tuple = tuple
  3570     def identifier(self):
  3571         return self._tuple[0]
  3573     def noArguments(self):
  3574         return len(self._tuple) == 1
  3576     def hasValue(self):
  3577         return len(self._tuple) >= 2 and isinstance(self._tuple[1], str)
  3579     def value(self):
  3580         assert(self.hasValue())
  3581         return self._tuple[1]
  3583     def hasArgs(self):
  3584         return (len(self._tuple) == 2 and isinstance(self._tuple[1], list) or
  3585                 len(self._tuple) == 3)
  3587     def args(self):
  3588         assert(self.hasArgs())
  3589         # Our args are our last element
  3590         return self._tuple[-1]
  3592     def listValue(self):
  3593         """
  3594         Backdoor for storing random data in _extendedAttrDict
  3595         """
  3596         return list(self._tuple)[1:]
  3598 # Parser
  3600 class Tokenizer(object):
  3601     tokens = [
  3602         "INTEGER",
  3603         "FLOATLITERAL",
  3604         "IDENTIFIER",
  3605         "STRING",
  3606         "WHITESPACE",
  3607         "OTHER"
  3610     def t_FLOATLITERAL(self, t):
  3611         r'(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN'
  3612         t.value = float(t.value)
  3613         return t
  3615     def t_INTEGER(self, t):
  3616         r'-?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*)'
  3617         try:
  3618             # Can't use int(), because that doesn't handle octal properly.
  3619             t.value = parseInt(t.value)
  3620         except:
  3621             raise WebIDLError("Invalid integer literal",
  3622                               [Location(lexer=self.lexer,
  3623                                         lineno=self.lexer.lineno,
  3624                                         lexpos=self.lexer.lexpos,
  3625                                         filename=self._filename)])
  3626         return t
  3628     def t_IDENTIFIER(self, t):
  3629         r'[A-Z_a-z][0-9A-Z_a-z]*'
  3630         t.type = self.keywords.get(t.value, 'IDENTIFIER')
  3631         return t
  3633     def t_STRING(self, t):
  3634         r'"[^"]*"'
  3635         t.value = t.value[1:-1]
  3636         return t
  3638     def t_WHITESPACE(self, t):
  3639         r'[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+'
  3640         pass
  3642     def t_ELLIPSIS(self, t):
  3643         r'\.\.\.'
  3644         t.type = self.keywords.get(t.value)
  3645         return t
  3647     def t_OTHER(self, t):
  3648         r'[^\t\n\r 0-9A-Z_a-z]'
  3649         t.type = self.keywords.get(t.value, 'OTHER')
  3650         return t
  3652     keywords = {
  3653         "module": "MODULE",
  3654         "interface": "INTERFACE",
  3655         "partial": "PARTIAL",
  3656         "dictionary": "DICTIONARY",
  3657         "exception": "EXCEPTION",
  3658         "enum": "ENUM",
  3659         "callback": "CALLBACK",
  3660         "typedef": "TYPEDEF",
  3661         "implements": "IMPLEMENTS",
  3662         "const": "CONST",
  3663         "null": "NULL",
  3664         "true": "TRUE",
  3665         "false": "FALSE",
  3666         "serializer": "SERIALIZER",
  3667         "stringifier": "STRINGIFIER",
  3668         "jsonifier": "JSONIFIER",
  3669         "unrestricted": "UNRESTRICTED",
  3670         "attribute": "ATTRIBUTE",
  3671         "readonly": "READONLY",
  3672         "inherit": "INHERIT",
  3673         "static": "STATIC",
  3674         "getter": "GETTER",
  3675         "setter": "SETTER",
  3676         "creator": "CREATOR",
  3677         "deleter": "DELETER",
  3678         "legacycaller": "LEGACYCALLER",
  3679         "optional": "OPTIONAL",
  3680         "...": "ELLIPSIS",
  3681         "::": "SCOPE",
  3682         "Date": "DATE",
  3683         "DOMString": "DOMSTRING",
  3684         "ByteString": "BYTESTRING",
  3685         "any": "ANY",
  3686         "boolean": "BOOLEAN",
  3687         "byte": "BYTE",
  3688         "double": "DOUBLE",
  3689         "float": "FLOAT",
  3690         "long": "LONG",
  3691         "object": "OBJECT",
  3692         "octet": "OCTET",
  3693         "optional": "OPTIONAL",
  3694         "sequence": "SEQUENCE",
  3695         "MozMap": "MOZMAP",
  3696         "short": "SHORT",
  3697         "unsigned": "UNSIGNED",
  3698         "void": "VOID",
  3699         ":": "COLON",
  3700         ";": "SEMICOLON",
  3701         "{": "LBRACE",
  3702         "}": "RBRACE",
  3703         "(": "LPAREN",
  3704         ")": "RPAREN",
  3705         "[": "LBRACKET",
  3706         "]": "RBRACKET",
  3707         "?": "QUESTIONMARK",
  3708         ",": "COMMA",
  3709         "=": "EQUALS",
  3710         "<": "LT",
  3711         ">": "GT",
  3712         "ArrayBuffer": "ARRAYBUFFER",
  3713         "or": "OR"
  3716     tokens.extend(keywords.values())
  3718     def t_error(self, t):
  3719         raise WebIDLError("Unrecognized Input",
  3720                [Location(lexer=self.lexer,
  3721                          lineno=self.lexer.lineno,
  3722                          lexpos=self.lexer.lexpos,
  3723                          filename = self.filename)])
  3725     def __init__(self, outputdir, lexer=None):
  3726         if lexer:
  3727             self.lexer = lexer
  3728         else:
  3729             self.lexer = lex.lex(object=self,
  3730                                  outputdir=outputdir,
  3731                                  lextab='webidllex',
  3732                                  reflags=re.DOTALL)
  3734 class Parser(Tokenizer):
  3735     def getLocation(self, p, i):
  3736         return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
  3738     def globalScope(self):
  3739         return self._globalScope
  3741     # The p_Foo functions here must match the WebIDL spec's grammar.
  3742     # It's acceptable to split things at '|' boundaries.
  3743     def p_Definitions(self, p):
  3744         """ 
  3745             Definitions : ExtendedAttributeList Definition Definitions
  3746         """
  3747         if p[2]:
  3748             p[0] = [p[2]]
  3749             p[2].addExtendedAttributes(p[1])
  3750         else:
  3751             assert not p[1]
  3752             p[0] = []
  3754         p[0].extend(p[3])
  3756     def p_DefinitionsEmpty(self, p):
  3757         """
  3758             Definitions :
  3759         """
  3760         p[0] = []
  3762     def p_Definition(self, p):
  3763         """
  3764             Definition : CallbackOrInterface
  3765                        | PartialInterface
  3766                        | Dictionary
  3767                        | Exception
  3768                        | Enum
  3769                        | Typedef
  3770                        | ImplementsStatement
  3771         """
  3772         p[0] = p[1]
  3773         assert p[1] # We might not have implemented something ...
  3775     def p_CallbackOrInterfaceCallback(self, p):
  3776         """
  3777             CallbackOrInterface : CALLBACK CallbackRestOrInterface
  3778         """
  3779         if p[2].isInterface():
  3780             assert isinstance(p[2], IDLInterface)
  3781             p[2].setCallback(True)
  3783         p[0] = p[2]
  3785     def p_CallbackOrInterfaceInterface(self, p):
  3786         """
  3787             CallbackOrInterface : Interface
  3788         """
  3789         p[0] = p[1]
  3791     def p_CallbackRestOrInterface(self, p):
  3792         """
  3793             CallbackRestOrInterface : CallbackRest
  3794                                     | Interface
  3795         """
  3796         assert p[1]
  3797         p[0] = p[1]
  3799     def p_Interface(self, p):
  3800         """
  3801             Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
  3802         """
  3803         location = self.getLocation(p, 1)
  3804         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
  3805         members = p[5]
  3806         parent = p[3]
  3808         try:
  3809             if self.globalScope()._lookupIdentifier(identifier):
  3810                 p[0] = self.globalScope()._lookupIdentifier(identifier)
  3811                 if not isinstance(p[0], IDLInterface):
  3812                     raise WebIDLError("Partial interface has the same name as "
  3813                                       "non-interface object",
  3814                                       [location, p[0].location])
  3815                 p[0].setNonPartial(location, parent, members)
  3816                 return
  3817         except Exception, ex:
  3818             if isinstance(ex, WebIDLError):
  3819                 raise ex
  3820             pass
  3822         p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
  3823                             members, isPartial=False)
  3825     def p_InterfaceForwardDecl(self, p):
  3826         """
  3827             Interface : INTERFACE IDENTIFIER SEMICOLON
  3828         """
  3829         location = self.getLocation(p, 1)
  3830         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
  3832         try:
  3833             if self.globalScope()._lookupIdentifier(identifier):
  3834                 p[0] = self.globalScope()._lookupIdentifier(identifier)
  3835                 if not isinstance(p[0], IDLExternalInterface):
  3836                     raise WebIDLError("Name collision between external "
  3837                                       "interface declaration for identifier "
  3838                                       "%s and %s" % (identifier.name, p[0]),
  3839                                       [location, p[0].location])
  3840                 return
  3841         except Exception, ex:
  3842             if isinstance(ex, WebIDLError):
  3843                 raise ex
  3844             pass
  3846         p[0] = IDLExternalInterface(location, self.globalScope(), identifier)
  3848     def p_PartialInterface(self, p):
  3849         """
  3850             PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
  3851         """
  3852         location = self.getLocation(p, 2)
  3853         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
  3854         members = p[5]
  3856         try:
  3857             if self.globalScope()._lookupIdentifier(identifier):
  3858                 p[0] = self.globalScope()._lookupIdentifier(identifier)
  3859                 if not isinstance(p[0], IDLInterface):
  3860                     raise WebIDLError("Partial interface has the same name as "
  3861                                       "non-interface object",
  3862                                       [location, p[0].location])
  3863                 # Just throw our members into the existing IDLInterface.  If we
  3864                 # have extended attributes, those will get added to it
  3865                 # automatically.
  3866                 p[0].members.extend(members)
  3867                 return
  3868         except Exception, ex:
  3869             if isinstance(ex, WebIDLError):
  3870                 raise ex
  3871             pass
  3873         p[0] = IDLInterface(location, self.globalScope(), identifier, None,
  3874                             members, isPartial=True)
  3875         pass
  3877     def p_Inheritance(self, p):
  3878         """
  3879             Inheritance : COLON ScopedName
  3880         """
  3881         p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2])
  3883     def p_InheritanceEmpty(self, p):
  3884         """
  3885             Inheritance :
  3886         """
  3887         pass
  3889     def p_InterfaceMembers(self, p):
  3890         """
  3891             InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
  3892         """
  3893         p[0] = [p[2]] if p[2] else []
  3895         assert not p[1] or p[2]
  3896         p[2].addExtendedAttributes(p[1])
  3898         p[0].extend(p[3])
  3900     def p_InterfaceMembersEmpty(self, p):
  3901         """
  3902             InterfaceMembers :
  3903         """
  3904         p[0] = []
  3906     def p_InterfaceMember(self, p):
  3907         """
  3908             InterfaceMember : Const
  3909                             | AttributeOrOperation
  3910         """
  3911         p[0] = p[1]
  3913     def p_Dictionary(self, p):
  3914         """
  3915             Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
  3916         """
  3917         location = self.getLocation(p, 1)
  3918         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
  3919         members = p[5]
  3920         p[0] = IDLDictionary(location, self.globalScope(), identifier, p[3], members)
  3922     def p_DictionaryMembers(self, p):
  3923         """
  3924             DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
  3926         """
  3927         if len(p) == 1:
  3928             # We're at the end of the list
  3929             p[0] = []
  3930             return
  3931         # Add our extended attributes
  3932         p[2].addExtendedAttributes(p[1])
  3933         p[0] = [p[2]]
  3934         p[0].extend(p[3])
  3936     def p_DictionaryMember(self, p):
  3937         """
  3938             DictionaryMember : Type IDENTIFIER DefaultValue SEMICOLON
  3939         """
  3940         # These quack a lot like optional arguments, so just treat them that way.
  3941         t = p[1]
  3942         assert isinstance(t, IDLType)
  3943         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
  3944         defaultValue = p[3]
  3946         p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
  3947                            defaultValue=defaultValue, variadic=False,
  3948                            dictionaryMember=True)
  3950     def p_DefaultValue(self, p):
  3951         """
  3952             DefaultValue : EQUALS ConstValue
  3954         """
  3955         if len(p) > 1:
  3956             p[0] = p[2]
  3957         else:
  3958             p[0] = None
  3960     def p_Exception(self, p):
  3961         """
  3962             Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON
  3963         """
  3964         pass
  3966     def p_Enum(self, p):
  3967         """
  3968             Enum : ENUM IDENTIFIER LBRACE EnumValueList RBRACE SEMICOLON
  3969         """
  3970         location = self.getLocation(p, 1)
  3971         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
  3973         values = p[4]
  3974         assert values
  3975         p[0] = IDLEnum(location, self.globalScope(), identifier, values)
  3977     def p_EnumValueList(self, p):
  3978         """
  3979             EnumValueList : STRING EnumValueListComma
  3980         """
  3981         p[0] = [p[1]]
  3982         p[0].extend(p[2])
  3984     def p_EnumValueListComma(self, p):
  3985         """
  3986             EnumValueListComma : COMMA EnumValueListString
  3987         """
  3988         p[0] = p[2]
  3990     def p_EnumValueListCommaEmpty(self, p):
  3991         """
  3992             EnumValueListComma :
  3993         """
  3994         p[0] = []
  3996     def p_EnumValueListString(self, p):
  3997         """
  3998             EnumValueListString : STRING EnumValueListComma
  3999         """
  4000         p[0] = [p[1]]
  4001         p[0].extend(p[2])
  4003     def p_EnumValueListStringEmpty(self, p):
  4004         """
  4005             EnumValueListString :
  4006         """
  4007         p[0] = []
  4009     def p_CallbackRest(self, p):
  4010         """
  4011             CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
  4012         """
  4013         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
  4014         p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(),
  4015                                identifier, p[3], p[5])
  4017     def p_ExceptionMembers(self, p):
  4018         """
  4019             ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
  4021         """
  4022         pass
  4024     def p_Typedef(self, p):
  4025         """
  4026             Typedef : TYPEDEF Type IDENTIFIER SEMICOLON
  4027         """
  4028         typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3])
  4029         typedef.resolve(self.globalScope())
  4030         p[0] = typedef
  4032     def p_ImplementsStatement(self, p):
  4033         """
  4034             ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON
  4035         """
  4036         assert(p[2] == "implements")
  4037         implementor = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1])
  4038         implementee = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3])
  4039         p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor,
  4040                                       implementee)
  4042     def p_Const(self, p):
  4043         """
  4044             Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON
  4045         """
  4046         location = self.getLocation(p, 1)
  4047         type = p[2]
  4048         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
  4049         value = p[5]
  4050         p[0] = IDLConst(location, identifier, type, value)
  4052     def p_ConstValueBoolean(self, p):
  4053         """
  4054             ConstValue : BooleanLiteral
  4055         """
  4056         location = self.getLocation(p, 1)
  4057         booleanType = BuiltinTypes[IDLBuiltinType.Types.boolean]
  4058         p[0] = IDLValue(location, booleanType, p[1])
  4060     def p_ConstValueInteger(self, p):
  4061         """
  4062             ConstValue : INTEGER
  4063         """
  4064         location = self.getLocation(p, 1)
  4066         # We don't know ahead of time what type the integer literal is.
  4067         # Determine the smallest type it could possibly fit in and use that.
  4068         integerType = matchIntegerValueToType(p[1])
  4069         if integerType == None:
  4070             raise WebIDLError("Integer literal out of range", [location])
  4072         p[0] = IDLValue(location, integerType, p[1])
  4074     def p_ConstValueFloat(self, p):
  4075         """
  4076             ConstValue : FLOATLITERAL
  4077         """
  4078         location = self.getLocation(p, 1)
  4079         p[0] = IDLValue(location, BuiltinTypes[IDLBuiltinType.Types.unrestricted_float], p[1])
  4081     def p_ConstValueString(self, p):
  4082         """
  4083             ConstValue : STRING
  4084         """
  4085         location = self.getLocation(p, 1)
  4086         stringType = BuiltinTypes[IDLBuiltinType.Types.domstring]
  4087         p[0] = IDLValue(location, stringType, p[1])
  4089     def p_ConstValueNull(self, p):
  4090         """
  4091             ConstValue : NULL
  4092         """
  4093         p[0] = IDLNullValue(self.getLocation(p, 1))
  4095     def p_BooleanLiteralTrue(self, p):
  4096         """
  4097             BooleanLiteral : TRUE
  4098         """
  4099         p[0] = True
  4101     def p_BooleanLiteralFalse(self, p):
  4102         """
  4103             BooleanLiteral : FALSE
  4104         """
  4105         p[0] = False
  4107     def p_AttributeOrOperation(self, p):
  4108         """
  4109             AttributeOrOperation : Attribute
  4110                                  | Operation
  4111         """
  4112         p[0] = p[1]
  4114     def p_AttributeWithQualifier(self, p):
  4115         """
  4116             Attribute : Qualifier AttributeRest
  4117         """
  4118         static = IDLInterfaceMember.Special.Static in p[1]
  4119         stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
  4120         (location, identifier, type, readonly) = p[2]
  4121         p[0] = IDLAttribute(location, identifier, type, readonly, static=static,
  4122                             stringifier=stringifier)
  4124     def p_Attribute(self, p):
  4125         """
  4126             Attribute : Inherit AttributeRest
  4127         """
  4128         (location, identifier, type, readonly) = p[2]
  4129         p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1])
  4131     def p_AttributeRest(self, p):
  4132         """
  4133             AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
  4134         """
  4135         location = self.getLocation(p, 2)
  4136         readonly = p[1]
  4137         t = p[3]
  4138         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4])
  4139         p[0] = (location, identifier, t, readonly)
  4141     def p_ReadOnly(self, p):
  4142         """
  4143             ReadOnly : READONLY
  4144         """
  4145         p[0] = True
  4147     def p_ReadOnlyEmpty(self, p):
  4148         """
  4149             ReadOnly :
  4150         """
  4151         p[0] = False
  4153     def p_Inherit(self, p):
  4154         """
  4155             Inherit : INHERIT
  4156         """
  4157         p[0] = True
  4159     def p_InheritEmpty(self, p):
  4160         """
  4161             Inherit :
  4162         """
  4163         p[0] = False
  4165     def p_Operation(self, p):
  4166         """
  4167             Operation : Qualifiers OperationRest
  4168         """
  4169         qualifiers = p[1]
  4171         # Disallow duplicates in the qualifier set
  4172         if not len(set(qualifiers)) == len(qualifiers):
  4173             raise WebIDLError("Duplicate qualifiers are not allowed",
  4174                               [self.getLocation(p, 1)])
  4176         static = IDLInterfaceMember.Special.Static in p[1]
  4177         # If static is there that's all that's allowed.  This is disallowed
  4178         # by the parser, so we can assert here.
  4179         assert not static or len(qualifiers) == 1
  4181         stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
  4182         # If stringifier is there that's all that's allowed.  This is disallowed
  4183         # by the parser, so we can assert here.
  4184         assert not stringifier or len(qualifiers) == 1
  4186         getter = True if IDLMethod.Special.Getter in p[1] else False
  4187         setter = True if IDLMethod.Special.Setter in p[1] else False
  4188         creator = True if IDLMethod.Special.Creator in p[1] else False
  4189         deleter = True if IDLMethod.Special.Deleter in p[1] else False
  4190         legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False
  4192         if getter or deleter:
  4193             if setter or creator:
  4194                 raise WebIDLError("getter and deleter are incompatible with setter and creator",
  4195                                   [self.getLocation(p, 1)])
  4197         (returnType, identifier, arguments) = p[2]
  4199         assert isinstance(returnType, IDLType)
  4201         specialType = IDLMethod.NamedOrIndexed.Neither
  4203         if getter or deleter:
  4204             if len(arguments) != 1:
  4205                 raise WebIDLError("%s has wrong number of arguments" %
  4206                                   ("getter" if getter else "deleter"),
  4207                                   [self.getLocation(p, 2)])
  4208             argType = arguments[0].type
  4209             if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
  4210                 specialType = IDLMethod.NamedOrIndexed.Named
  4211             elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
  4212                 specialType = IDLMethod.NamedOrIndexed.Indexed
  4213             else:
  4214                 raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
  4215                                   ("getter" if getter else "deleter"),
  4216                                   [arguments[0].location])
  4217             if arguments[0].optional or arguments[0].variadic:
  4218                 raise WebIDLError("%s cannot have %s argument" %
  4219                                   ("getter" if getter else "deleter",
  4220                                    "optional" if arguments[0].optional else "variadic"),
  4221                                    [arguments[0].location])
  4222         if getter:
  4223             if returnType.isVoid():
  4224                 raise WebIDLError("getter cannot have void return type",
  4225                                   [self.getLocation(p, 2)])
  4226         if setter or creator:
  4227             if len(arguments) != 2:
  4228                 raise WebIDLError("%s has wrong number of arguments" %
  4229                                   ("setter" if setter else "creator"),
  4230                                   [self.getLocation(p, 2)])
  4231             argType = arguments[0].type
  4232             if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
  4233                 specialType = IDLMethod.NamedOrIndexed.Named
  4234             elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
  4235                 specialType = IDLMethod.NamedOrIndexed.Indexed
  4236             else:
  4237                 raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
  4238                                   ("setter" if setter else "creator"),
  4239                                   [arguments[0].location])
  4240             if arguments[0].optional or arguments[0].variadic:
  4241                 raise WebIDLError("%s cannot have %s argument" %
  4242                                   ("setter" if setter else "creator",
  4243                                    "optional" if arguments[0].optional else "variadic"),
  4244                                   [arguments[0].location])
  4245             if arguments[1].optional or arguments[1].variadic:
  4246                 raise WebIDLError("%s cannot have %s argument" %
  4247                                   ("setter" if setter else "creator",
  4248                                    "optional" if arguments[1].optional else "variadic"),
  4249                                   [arguments[1].location])
  4251         if stringifier:
  4252             if len(arguments) != 0:
  4253                 raise WebIDLError("stringifier has wrong number of arguments",
  4254                                   [self.getLocation(p, 2)])
  4255             if not returnType.isDOMString():
  4256                 raise WebIDLError("stringifier must have DOMString return type",
  4257                                   [self.getLocation(p, 2)])
  4259         # identifier might be None.  This is only permitted for special methods.
  4260         if not identifier:
  4261             if not getter and not setter and not creator and \
  4262                not deleter and not legacycaller and not stringifier:
  4263                 raise WebIDLError("Identifier required for non-special methods",
  4264                                   [self.getLocation(p, 2)])
  4266             location = BuiltinLocation("<auto-generated-identifier>")
  4267             identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" %
  4268                 ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \
  4269                  "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "",
  4270                  "getter" if getter else "",
  4271                  "setter" if setter else "",
  4272                  "deleter" if deleter else "",
  4273                  "creator" if creator else "",
  4274                  "legacycaller" if legacycaller else "",
  4275                  "stringifier" if stringifier else ""), allowDoubleUnderscore=True)
  4277         method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments,
  4278                            static=static, getter=getter, setter=setter, creator=creator,
  4279                            deleter=deleter, specialType=specialType,
  4280                            legacycaller=legacycaller, stringifier=stringifier)
  4281         p[0] = method
  4283     def p_Stringifier(self, p):
  4284         """
  4285             Operation : STRINGIFIER SEMICOLON
  4286         """
  4287         identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
  4288                                              "__stringifier",
  4289                                              allowDoubleUnderscore=True)
  4290         method = IDLMethod(self.getLocation(p, 1),
  4291                            identifier,
  4292                            returnType=BuiltinTypes[IDLBuiltinType.Types.domstring],
  4293                            arguments=[],
  4294                            stringifier=True)
  4295         p[0] = method
  4297     def p_Jsonifier(self, p):
  4298         """
  4299             Operation : JSONIFIER SEMICOLON
  4300         """
  4301         identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
  4302                                              "__jsonifier", allowDoubleUnderscore=True)
  4303         method = IDLMethod(self.getLocation(p, 1),
  4304                            identifier,
  4305                            returnType=BuiltinTypes[IDLBuiltinType.Types.object],
  4306                            arguments=[],
  4307                            jsonifier=True)
  4308         p[0] = method
  4310     def p_QualifierStatic(self, p):
  4311         """
  4312             Qualifier : STATIC
  4313         """
  4314         p[0] = [IDLInterfaceMember.Special.Static]
  4316     def p_QualifierStringifier(self, p):
  4317         """
  4318             Qualifier : STRINGIFIER
  4319         """
  4320         p[0] = [IDLInterfaceMember.Special.Stringifier]
  4322     def p_Qualifiers(self, p):
  4323         """
  4324             Qualifiers : Qualifier
  4325                        | Specials
  4326         """
  4327         p[0] = p[1]
  4329     def p_Specials(self, p):
  4330         """
  4331             Specials : Special Specials
  4332         """
  4333         p[0] = [p[1]]
  4334         p[0].extend(p[2])
  4336     def p_SpecialsEmpty(self, p):
  4337         """
  4338             Specials :
  4339         """
  4340         p[0] = []
  4342     def p_SpecialGetter(self, p):
  4343         """
  4344             Special : GETTER
  4345         """
  4346         p[0] = IDLMethod.Special.Getter
  4348     def p_SpecialSetter(self, p):
  4349         """
  4350             Special : SETTER
  4351         """
  4352         p[0] = IDLMethod.Special.Setter
  4354     def p_SpecialCreator(self, p):
  4355         """
  4356             Special : CREATOR
  4357         """
  4358         p[0] = IDLMethod.Special.Creator
  4360     def p_SpecialDeleter(self, p):
  4361         """
  4362             Special : DELETER
  4363         """
  4364         p[0] = IDLMethod.Special.Deleter
  4366     def p_SpecialLegacyCaller(self, p):
  4367         """
  4368             Special : LEGACYCALLER
  4369         """
  4370         p[0] = IDLMethod.Special.LegacyCaller
  4372     def p_OperationRest(self, p):
  4373         """
  4374             OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON
  4375         """
  4376         p[0] = (p[1], p[2], p[4])
  4378     def p_OptionalIdentifier(self, p):
  4379         """
  4380             OptionalIdentifier : IDENTIFIER
  4381         """
  4382         p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
  4384     def p_OptionalIdentifierEmpty(self, p):
  4385         """
  4386             OptionalIdentifier :
  4387         """
  4388         pass
  4390     def p_ArgumentList(self, p):
  4391         """
  4392             ArgumentList : Argument Arguments
  4393         """
  4394         p[0] = [p[1]] if p[1] else []
  4395         p[0].extend(p[2])
  4397     def p_ArgumentListEmpty(self, p):
  4398         """
  4399             ArgumentList :
  4400         """
  4401         p[0] = []
  4403     def p_Arguments(self, p):
  4404         """
  4405             Arguments : COMMA Argument Arguments
  4406         """
  4407         p[0] = [p[2]] if p[2] else []
  4408         p[0].extend(p[3])
  4410     def p_ArgumentsEmpty(self, p):
  4411         """
  4412             Arguments :
  4413         """
  4414         p[0] = []
  4416     def p_Argument(self, p):
  4417         """
  4418             Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName DefaultValue
  4419         """
  4420         t = p[3]
  4421         assert isinstance(t, IDLType)
  4422         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5])
  4424         optional = p[2]
  4425         variadic = p[4]
  4426         defaultValue = p[6]
  4428         if not optional and defaultValue:
  4429             raise WebIDLError("Mandatory arguments can't have a default value.",
  4430                               [self.getLocation(p, 6)])
  4432         # We can't test t.isAny() here and give it a default value as needed,
  4433         # since at this point t is not a fully resolved type yet (e.g. it might
  4434         # be a typedef).  We'll handle the 'any' case in IDLArgument.complete.
  4436         if variadic:
  4437             if optional:
  4438                 raise WebIDLError("Variadic arguments should not be marked optional.",
  4439                                   [self.getLocation(p, 2)])
  4440             optional = variadic
  4442         p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
  4443         p[0].addExtendedAttributes(p[1])
  4445     def p_ArgumentName(self, p):
  4446         """
  4447             ArgumentName : IDENTIFIER
  4448                          | ATTRIBUTE
  4449                          | CALLBACK
  4450                          | CONST
  4451                          | CREATOR
  4452                          | DELETER
  4453                          | DICTIONARY
  4454                          | ENUM
  4455                          | EXCEPTION
  4456                          | GETTER
  4457                          | IMPLEMENTS
  4458                          | INHERIT
  4459                          | INTERFACE
  4460                          | LEGACYCALLER
  4461                          | PARTIAL
  4462                          | SERIALIZER
  4463                          | SETTER
  4464                          | STATIC
  4465                          | STRINGIFIER
  4466                          | JSONIFIER
  4467                          | TYPEDEF
  4468                          | UNRESTRICTED
  4469         """
  4470         p[0] = p[1]
  4472     def p_Optional(self, p):
  4473         """
  4474             Optional : OPTIONAL
  4475         """
  4476         p[0] = True
  4478     def p_OptionalEmpty(self, p):
  4479         """
  4480             Optional :
  4481         """
  4482         p[0] = False
  4484     def p_Ellipsis(self, p):
  4485         """
  4486             Ellipsis : ELLIPSIS
  4487         """
  4488         p[0] = True
  4490     def p_EllipsisEmpty(self, p):
  4491         """
  4492             Ellipsis :
  4493         """
  4494         p[0] = False
  4496     def p_ExceptionMember(self, p):
  4497         """
  4498             ExceptionMember : Const
  4499                             | ExceptionField
  4500         """
  4501         pass
  4503     def p_ExceptionField(self, p):
  4504         """
  4505             ExceptionField : Type IDENTIFIER SEMICOLON
  4506         """
  4507         pass
  4509     def p_ExtendedAttributeList(self, p):
  4510         """
  4511             ExtendedAttributeList : LBRACKET ExtendedAttribute ExtendedAttributes RBRACKET
  4512         """
  4513         p[0] = [p[2]]
  4514         if p[3]:
  4515             p[0].extend(p[3])
  4517     def p_ExtendedAttributeListEmpty(self, p):
  4518         """
  4519             ExtendedAttributeList :
  4520         """
  4521         p[0] = []
  4523     def p_ExtendedAttribute(self, p):
  4524         """
  4525             ExtendedAttribute : ExtendedAttributeNoArgs
  4526                               | ExtendedAttributeArgList
  4527                               | ExtendedAttributeIdent
  4528                               | ExtendedAttributeNamedArgList
  4529         """
  4530         p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1])
  4532     def p_ExtendedAttributeEmpty(self, p):
  4533         """
  4534             ExtendedAttribute :
  4535         """
  4536         pass
  4538     def p_ExtendedAttributes(self, p):
  4539         """
  4540             ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes
  4541         """
  4542         p[0] = [p[2]] if p[2] else []
  4543         p[0].extend(p[3])
  4545     def p_ExtendedAttributesEmpty(self, p):
  4546         """
  4547             ExtendedAttributes :
  4548         """
  4549         p[0] = []
  4551     def p_Other(self, p):
  4552         """
  4553             Other : INTEGER
  4554                   | FLOATLITERAL
  4555                   | IDENTIFIER
  4556                   | STRING
  4557                   | OTHER
  4558                   | ELLIPSIS
  4559                   | COLON
  4560                   | SCOPE
  4561                   | SEMICOLON
  4562                   | LT
  4563                   | EQUALS
  4564                   | GT
  4565                   | QUESTIONMARK
  4566                   | DATE
  4567                   | DOMSTRING
  4568                   | BYTESTRING
  4569                   | ANY
  4570                   | ATTRIBUTE
  4571                   | BOOLEAN
  4572                   | BYTE
  4573                   | LEGACYCALLER
  4574                   | CONST
  4575                   | CREATOR
  4576                   | DELETER
  4577                   | DOUBLE
  4578                   | EXCEPTION
  4579                   | FALSE
  4580                   | FLOAT
  4581                   | GETTER
  4582                   | IMPLEMENTS
  4583                   | INHERIT
  4584                   | INTERFACE
  4585                   | LONG
  4586                   | MODULE
  4587                   | NULL
  4588                   | OBJECT
  4589                   | OCTET
  4590                   | OPTIONAL
  4591                   | SEQUENCE
  4592                   | MOZMAP
  4593                   | SETTER
  4594                   | SHORT
  4595                   | STATIC
  4596                   | STRINGIFIER
  4597                   | JSONIFIER
  4598                   | TRUE
  4599                   | TYPEDEF
  4600                   | UNSIGNED
  4601                   | VOID
  4602         """
  4603         pass
  4605     def p_OtherOrComma(self, p):
  4606         """
  4607             OtherOrComma : Other
  4608                          | COMMA
  4609         """
  4610         pass
  4612     def p_TypeSingleType(self, p):
  4613         """
  4614             Type : SingleType
  4615         """
  4616         p[0] = p[1]
  4618     def p_TypeUnionType(self, p):
  4619         """
  4620             Type : UnionType TypeSuffix
  4621         """
  4622         p[0] = self.handleModifiers(p[1], p[2])
  4624     def p_SingleTypeNonAnyType(self, p):
  4625         """
  4626             SingleType : NonAnyType
  4627         """
  4628         p[0] = p[1]
  4630     def p_SingleTypeAnyType(self, p):
  4631         """
  4632             SingleType : ANY TypeSuffixStartingWithArray
  4633         """
  4634         p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.any], p[2])
  4636     def p_UnionType(self, p):
  4637         """
  4638             UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN
  4639         """
  4640         types = [p[2], p[4]]
  4641         types.extend(p[5])
  4642         p[0] = IDLUnionType(self.getLocation(p, 1), types)
  4644     def p_UnionMemberTypeNonAnyType(self, p):
  4645         """
  4646             UnionMemberType : NonAnyType
  4647         """
  4648         p[0] = p[1]
  4650     def p_UnionMemberTypeArrayOfAny(self, p):
  4651         """
  4652             UnionMemberTypeArrayOfAny : ANY LBRACKET RBRACKET
  4653         """
  4654         p[0] = IDLArrayType(self.getLocation(p, 2),
  4655                             BuiltinTypes[IDLBuiltinType.Types.any])
  4657     def p_UnionMemberType(self, p):
  4658         """
  4659             UnionMemberType : UnionType TypeSuffix
  4660                             | UnionMemberTypeArrayOfAny TypeSuffix
  4661         """
  4662         p[0] = self.handleModifiers(p[1], p[2])
  4664     def p_UnionMemberTypes(self, p):
  4665         """
  4666             UnionMemberTypes : OR UnionMemberType UnionMemberTypes
  4667         """
  4668         p[0] = [p[2]]
  4669         p[0].extend(p[3])
  4671     def p_UnionMemberTypesEmpty(self, p):
  4672         """
  4673             UnionMemberTypes : 
  4674         """
  4675         p[0] = []
  4677     def p_NonAnyType(self, p):
  4678         """
  4679             NonAnyType : PrimitiveOrStringType TypeSuffix
  4680                        | ARRAYBUFFER TypeSuffix
  4681                        | OBJECT TypeSuffix
  4682         """
  4683         if p[1] == "object":
  4684             type = BuiltinTypes[IDLBuiltinType.Types.object]
  4685         elif p[1] == "ArrayBuffer":
  4686             type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
  4687         else:
  4688             type = BuiltinTypes[p[1]]
  4690         p[0] = self.handleModifiers(type, p[2])
  4692     def p_NonAnyTypeSequenceType(self, p):
  4693         """
  4694             NonAnyType : SEQUENCE LT Type GT Null
  4695         """
  4696         innerType = p[3]
  4697         type = IDLSequenceType(self.getLocation(p, 1), innerType)
  4698         if p[5]:
  4699             type = IDLNullableType(self.getLocation(p, 5), type)
  4700         p[0] = type
  4702     def p_NonAnyTypeMozMapType(self, p):
  4703         """
  4704             NonAnyType : MOZMAP LT Type GT Null
  4705         """
  4706         innerType = p[3]
  4707         type = IDLMozMapType(self.getLocation(p, 1), innerType)
  4708         if p[5]:
  4709             type = IDLNullableType(self.getLocation(p, 5), type)
  4710         p[0] = type
  4712     def p_NonAnyTypeScopedName(self, p):
  4713         """
  4714             NonAnyType : ScopedName TypeSuffix
  4715         """
  4716         assert isinstance(p[1], IDLUnresolvedIdentifier)
  4718         type = None
  4720         try:
  4721             if self.globalScope()._lookupIdentifier(p[1]):
  4722                 obj = self.globalScope()._lookupIdentifier(p[1])
  4723                 if obj.isType():
  4724                     type = obj
  4725                 else:
  4726                     type = IDLWrapperType(self.getLocation(p, 1), p[1])
  4727                 p[0] = self.handleModifiers(type, p[2])
  4728                 return
  4729         except:
  4730             pass
  4732         type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
  4733         p[0] = self.handleModifiers(type, p[2])
  4735     def p_NonAnyTypeDate(self, p):
  4736         """
  4737             NonAnyType : DATE TypeSuffix
  4738         """
  4739         p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.date],
  4740                                     p[2])
  4742     def p_ConstType(self, p):
  4743         """
  4744             ConstType : PrimitiveOrStringType Null
  4745         """
  4746         type = BuiltinTypes[p[1]]
  4747         if p[2]:
  4748             type = IDLNullableType(self.getLocation(p, 1), type)
  4749         p[0] = type
  4751     def p_ConstTypeIdentifier(self, p):
  4752         """
  4753             ConstType : IDENTIFIER Null
  4754         """
  4755         identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
  4757         type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
  4758         if p[2]:
  4759             type = IDLNullableType(self.getLocation(p, 1), type)
  4760         p[0] = type
  4762     def p_PrimitiveOrStringTypeUint(self, p):
  4763         """
  4764             PrimitiveOrStringType : UnsignedIntegerType
  4765         """
  4766         p[0] = p[1]
  4768     def p_PrimitiveOrStringTypeBoolean(self, p):
  4769         """
  4770             PrimitiveOrStringType : BOOLEAN
  4771         """
  4772         p[0] = IDLBuiltinType.Types.boolean
  4774     def p_PrimitiveOrStringTypeByte(self, p):
  4775         """
  4776             PrimitiveOrStringType : BYTE
  4777         """
  4778         p[0] = IDLBuiltinType.Types.byte
  4780     def p_PrimitiveOrStringTypeOctet(self, p):
  4781         """
  4782             PrimitiveOrStringType : OCTET
  4783         """
  4784         p[0] = IDLBuiltinType.Types.octet
  4786     def p_PrimitiveOrStringTypeFloat(self, p):
  4787         """
  4788             PrimitiveOrStringType : FLOAT
  4789         """
  4790         p[0] = IDLBuiltinType.Types.float
  4792     def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
  4793         """
  4794             PrimitiveOrStringType : UNRESTRICTED FLOAT
  4795         """
  4796         p[0] = IDLBuiltinType.Types.unrestricted_float
  4798     def p_PrimitiveOrStringTypeDouble(self, p):
  4799         """
  4800             PrimitiveOrStringType : DOUBLE
  4801         """
  4802         p[0] = IDLBuiltinType.Types.double
  4804     def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
  4805         """
  4806             PrimitiveOrStringType : UNRESTRICTED DOUBLE
  4807         """
  4808         p[0] = IDLBuiltinType.Types.unrestricted_double
  4810     def p_PrimitiveOrStringTypeDOMString(self, p):
  4811         """
  4812             PrimitiveOrStringType : DOMSTRING
  4813         """
  4814         p[0] = IDLBuiltinType.Types.domstring
  4816     def p_PrimitiveOrStringTypeBytestring(self, p):
  4817         """
  4818             PrimitiveOrStringType : BYTESTRING
  4819         """
  4820         p[0] = IDLBuiltinType.Types.bytestring
  4822     def p_UnsignedIntegerTypeUnsigned(self, p):
  4823         """
  4824             UnsignedIntegerType : UNSIGNED IntegerType
  4825         """
  4826         p[0] = p[2] + 1 # Adding one to a given signed integer type
  4827                         # gets you the unsigned type.
  4829     def p_UnsignedIntegerType(self, p):
  4830         """
  4831             UnsignedIntegerType : IntegerType
  4832         """
  4833         p[0] = p[1]
  4835     def p_IntegerTypeShort(self, p):
  4836         """
  4837             IntegerType : SHORT
  4838         """
  4839         p[0] = IDLBuiltinType.Types.short
  4841     def p_IntegerTypeLong(self, p):
  4842         """
  4843             IntegerType : LONG OptionalLong
  4844         """
  4845         if p[2]:
  4846             p[0] = IDLBuiltinType.Types.long_long
  4847         else:
  4848             p[0] = IDLBuiltinType.Types.long
  4850     def p_OptionalLong(self, p):
  4851         """
  4852             OptionalLong : LONG
  4853         """
  4854         p[0] = True
  4856     def p_OptionalLongEmpty(self, p):
  4857         """
  4858             OptionalLong :
  4859         """
  4860         p[0] = False
  4862     def p_TypeSuffixBrackets(self, p):
  4863         """
  4864             TypeSuffix : LBRACKET RBRACKET TypeSuffix
  4865         """
  4866         p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))]
  4867         p[0].extend(p[3])
  4869     def p_TypeSuffixQMark(self, p):
  4870         """
  4871             TypeSuffix : QUESTIONMARK TypeSuffixStartingWithArray
  4872         """
  4873         p[0] = [(IDLMethod.TypeSuffixModifier.QMark, self.getLocation(p, 1))]
  4874         p[0].extend(p[2])
  4876     def p_TypeSuffixEmpty(self, p):
  4877         """
  4878             TypeSuffix :
  4879         """
  4880         p[0] = []
  4882     def p_TypeSuffixStartingWithArray(self, p):
  4883         """
  4884             TypeSuffixStartingWithArray : LBRACKET RBRACKET TypeSuffix
  4885         """
  4886         p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))]
  4887         p[0].extend(p[3])
  4889     def p_TypeSuffixStartingWithArrayEmpty(self, p):
  4890         """
  4891             TypeSuffixStartingWithArray :
  4892         """
  4893         p[0] = []
  4895     def p_Null(self, p):
  4896         """
  4897             Null : QUESTIONMARK
  4899         """
  4900         if len(p) > 1:
  4901             p[0] = True
  4902         else:
  4903             p[0] = False
  4905     def p_ReturnTypeType(self, p):
  4906         """
  4907             ReturnType : Type
  4908         """
  4909         p[0] = p[1]
  4911     def p_ReturnTypeVoid(self, p):
  4912         """
  4913             ReturnType : VOID
  4914         """
  4915         p[0] = BuiltinTypes[IDLBuiltinType.Types.void]
  4917     def p_ScopedName(self, p):
  4918         """
  4919             ScopedName : AbsoluteScopedName
  4920                        | RelativeScopedName
  4921         """
  4922         p[0] = p[1]
  4924     def p_AbsoluteScopedName(self, p):
  4925         """
  4926             AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts
  4927         """
  4928         assert False
  4929         pass
  4931     def p_RelativeScopedName(self, p):
  4932         """
  4933             RelativeScopedName : IDENTIFIER ScopedNameParts
  4934         """
  4935         assert not p[2] # Not implemented!
  4937         p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
  4939     def p_ScopedNameParts(self, p):
  4940         """
  4941             ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts
  4942         """
  4943         assert False
  4944         pass
  4946     def p_ScopedNamePartsEmpty(self, p):
  4947         """
  4948             ScopedNameParts :
  4949         """
  4950         p[0] = None
  4952     def p_ExtendedAttributeNoArgs(self, p):
  4953         """
  4954             ExtendedAttributeNoArgs : IDENTIFIER
  4955         """
  4956         p[0] = (p[1],)
  4958     def p_ExtendedAttributeArgList(self, p):
  4959         """
  4960             ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN
  4961         """
  4962         p[0] = (p[1], p[3])
  4964     def p_ExtendedAttributeIdent(self, p):
  4965         """
  4966             ExtendedAttributeIdent : IDENTIFIER EQUALS STRING
  4967                                    | IDENTIFIER EQUALS IDENTIFIER
  4968         """
  4969         p[0] = (p[1], p[3])
  4971     def p_ExtendedAttributeNamedArgList(self, p):
  4972         """
  4973             ExtendedAttributeNamedArgList : IDENTIFIER EQUALS IDENTIFIER LPAREN ArgumentList RPAREN
  4974         """
  4975         p[0] = (p[1], p[3], p[5])
  4977     def p_error(self, p):
  4978         if not p:
  4979             raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both",
  4980                               [self._filename])
  4981         else:
  4982             raise WebIDLError("invalid syntax", [Location(self.lexer, p.lineno, p.lexpos, self._filename)])
  4984     def __init__(self, outputdir='', lexer=None):
  4985         Tokenizer.__init__(self, outputdir, lexer)
  4986         self.parser = yacc.yacc(module=self,
  4987                                 outputdir=outputdir,
  4988                                 tabmodule='webidlyacc',
  4989                                 errorlog=yacc.NullLogger(),
  4990                                 picklefile='WebIDLGrammar.pkl')
  4991         self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
  4992         self._installBuiltins(self._globalScope)
  4993         self._productions = []
  4995         self._filename = "<builtin>"
  4996         self.lexer.input(Parser._builtins)
  4997         self._filename = None
  4999         self.parser.parse(lexer=self.lexer,tracking=True)
  5001     def _installBuiltins(self, scope):
  5002         assert isinstance(scope, IDLScope)
  5004         # xrange omits the last value.
  5005         for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
  5006             builtin = BuiltinTypes[x]
  5007             name = builtin.name
  5009             typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name)
  5010             typedef.resolve(scope)
  5012     @ staticmethod
  5013     def handleModifiers(type, modifiers):
  5014         for (modifier, modifierLocation) in modifiers:
  5015             assert modifier == IDLMethod.TypeSuffixModifier.QMark or \
  5016                    modifier == IDLMethod.TypeSuffixModifier.Brackets
  5018             if modifier == IDLMethod.TypeSuffixModifier.QMark:
  5019                 type = IDLNullableType(modifierLocation, type)
  5020             elif modifier == IDLMethod.TypeSuffixModifier.Brackets:
  5021                 type = IDLArrayType(modifierLocation, type)
  5023         return type
  5025     def parse(self, t, filename=None):
  5026         self.lexer.input(t)
  5028         #for tok in iter(self.lexer.token, None):
  5029         #    print tok
  5031         self._filename = filename
  5032         self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True))
  5033         self._filename = None
  5035     def finish(self):
  5036         # First, finish all the IDLImplementsStatements.  In particular, we
  5037         # have to make sure we do those before we do the IDLInterfaces.
  5038         # XXX khuey hates this bit and wants to nuke it from orbit.
  5039         implementsStatements = [ p for p in self._productions if
  5040                                  isinstance(p, IDLImplementsStatement)]
  5041         otherStatements = [ p for p in self._productions if
  5042                             not isinstance(p, IDLImplementsStatement)]
  5043         for production in implementsStatements:
  5044             production.finish(self.globalScope())
  5045         for production in otherStatements:
  5046             production.finish(self.globalScope())
  5048         # Do any post-finish validation we need to do
  5049         for production in self._productions:
  5050             production.validate()
  5052         # De-duplicate self._productions, without modifying its order.
  5053         seen = set()
  5054         result = []
  5055         for p in self._productions:
  5056             if p not in seen:
  5057                 seen.add(p)
  5058                 result.append(p)
  5059         return result
  5061     def reset(self):
  5062         return Parser(lexer=self.lexer)
  5064     # Builtin IDL defined by WebIDL
  5065     _builtins = """
  5066         typedef unsigned long long DOMTimeStamp;
  5067     """
  5069 def main():
  5070     # Parse arguments.
  5071     from optparse import OptionParser
  5072     usageString = "usage: %prog [options] files"
  5073     o = OptionParser(usage=usageString)
  5074     o.add_option("--cachedir", dest='cachedir', default=None,
  5075                  help="Directory in which to cache lex/parse tables.")
  5076     o.add_option("--verbose-errors", action='store_true', default=False,
  5077                  help="When an error happens, display the Python traceback.")
  5078     (options, args) = o.parse_args()
  5080     if len(args) < 1:
  5081         o.error(usageString)
  5083     fileList = args
  5084     baseDir = os.getcwd()
  5086     # Parse the WebIDL.
  5087     parser = Parser(options.cachedir)
  5088     try:
  5089         for filename in fileList:
  5090             fullPath = os.path.normpath(os.path.join(baseDir, filename))
  5091             f = open(fullPath, 'rb')
  5092             lines = f.readlines()
  5093             f.close()
  5094             print fullPath
  5095             parser.parse(''.join(lines), fullPath)
  5096         parser.finish()
  5097     except WebIDLError, e:
  5098         if options.verbose_errors:
  5099             traceback.print_exc()
  5100         else:
  5101             print e
  5103 if __name__ == '__main__':
  5104     main()

mercurial