Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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'
1310 )
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'
2240 )
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
2273 }
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)
2493 }
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)
2506 }
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'
2644 )
2646 Special = enum(
2647 'Static',
2648 'Stringifier'
2649 )
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
3155 )
3157 TypeSuffixModifier = enum(
3158 'None',
3159 'QMark',
3160 'Brackets'
3161 )
3163 NamedOrIndexed = enum(
3164 'Neither',
3165 'Named',
3166 'Indexed'
3167 )
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"
3608 ]
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"
3714 }
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
3925 |
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
3953 |
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
4020 |
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
4898 |
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()