dom/bindings/parser/WebIDL.py

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:5dcd37b36cbe
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/.
4
5 """ A WebIDL parser. """
6
7 from ply import lex, yacc
8 import re
9 import os
10 import traceback
11 import math
12
13 # Machinery
14
15 def parseInt(literal):
16 string = literal
17 sign = 0
18 base = 0
19
20 if string[0] == '-':
21 sign = -1
22 string = string[1:]
23 else:
24 sign = 1
25
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
35
36 value = int(string, base)
37 return value * sign
38
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
48
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()
62
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
68
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))
74
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>"
82
83 def __eq__(self, other):
84 return self._lexpos == other._lexpos and \
85 self._file == other._file
86
87 def filename(self):
88 return self._file
89
90 def resolve(self):
91 if self._line:
92 return
93
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
101
102 # Our line number seems to point to the start of self._lexdata
103 self._lineno += self._lexdata.count('\n', 0, startofline)
104
105 def get(self):
106 self.resolve()
107 return "%s line %s:%s" % (self._file, self._lineno, self._colno)
108
109 def _pointerline(self):
110 return " " * self._colno + "^"
111
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())
116
117 class BuiltinLocation(object):
118 def __init__(self, text):
119 self.msg = text + "\n"
120
121 def __eq__(self, other):
122 return isinstance(other, BuiltinLocation) and \
123 self.msg == other.msg
124
125 def filename(self):
126 return '<builtin>'
127
128 def resolve(self):
129 pass
130
131 def get(self):
132 return self.msg
133
134 def __str__(self):
135 return self.get()
136
137
138 # Data Model
139
140 class IDLObject(object):
141 def __init__(self, location):
142 self.location = location
143 self.userData = dict()
144
145 def filename(self):
146 return self.location.filename()
147
148 def isInterface(self):
149 return False
150
151 def isEnum(self):
152 return False
153
154 def isCallback(self):
155 return False
156
157 def isType(self):
158 return False
159
160 def isDictionary(self):
161 return False;
162
163 def isUnion(self):
164 return False
165
166 def getUserData(self, key, default):
167 return self.userData.get(key, default)
168
169 def setUserData(self, key, value):
170 self.userData[key] = value
171
172 def addExtendedAttributes(self, attrs):
173 assert False # Override me!
174
175 def handleExtendedAttribute(self, attr):
176 assert False # Override me!
177
178 def _getDependentObjects(self):
179 assert False # Override me!
180
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.
185
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."""
189
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()
195
196 if self in visited:
197 return set()
198
199 visited.add(self)
200
201 deps = set()
202 if self.filename() != "<builtin>":
203 deps.add(self.filename())
204
205 for d in self._getDependentObjects():
206 deps = deps.union(d.getDeps(visited))
207
208 return deps
209
210 class IDLScope(IDLObject):
211 def __init__(self, location, parentScope, identifier):
212 IDLObject.__init__(self, location)
213
214 self.parentScope = parentScope
215 if identifier:
216 assert isinstance(identifier, IDLIdentifier)
217 self._name = identifier
218 else:
219 self._name = None
220
221 self._dict = {}
222
223 def __str__(self):
224 return self.QName()
225
226 def QName(self):
227 if self._name:
228 return self._name.QName() + "::"
229 return "::"
230
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
240
241 if identifier.name in self._dict:
242 if not object:
243 return
244
245 # ensureUnique twice with the same object is not allowed
246 assert id(object) != id(self._dict[identifier.name])
247
248 replacement = self.resolveIdentifierConflict(self, identifier,
249 self._dict[identifier.name],
250 object)
251 self._dict[identifier.name] = replacement
252 return
253
254 assert object
255
256 self._dict[identifier.name] = object
257
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
263
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), [])
271
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)
279
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)
283
284 raise WebIDLError(
285 "Multiple unresolvable definitions of identifier '%s' in scope '%s%s"
286 % (identifier.name, str(self), conflictdesc), [])
287
288 def _lookupIdentifier(self, identifier):
289 return self._dict[identifier.name]
290
291 def lookupIdentifier(self, identifier):
292 assert isinstance(identifier, IDLIdentifier)
293 assert identifier.scope == self
294 return self._lookupIdentifier(identifier)
295
296 class IDLIdentifier(IDLObject):
297 def __init__(self, location, scope, name):
298 IDLObject.__init__(self, location)
299
300 self.name = name
301 assert isinstance(scope, IDLScope)
302 self.scope = scope
303
304 def __str__(self):
305 return self.QName()
306
307 def QName(self):
308 return self.scope.QName() + self.name
309
310 def __hash__(self):
311 return self.QName().__hash__()
312
313 def __eq__(self, other):
314 return self.QName() == other.QName()
315
316 def object(self):
317 return self.scope.lookupIdentifier(self)
318
319 class IDLUnresolvedIdentifier(IDLObject):
320 def __init__(self, location, name, allowDoubleUnderscore = False,
321 allowForbidden = False):
322 IDLObject.__init__(self, location)
323
324 assert len(name) > 0
325
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])
337
338 self.name = name
339
340 def __str__(self):
341 return self.QName()
342
343 def QName(self):
344 return "<unresolved scope>::" + self.name
345
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
350
351 scope.ensureUnique(self, object)
352
353 identifier = IDLIdentifier(self.location, scope, self.name)
354 if object:
355 object.identifier = identifier
356 return identifier
357
358 def finish(self):
359 assert False # Should replace with a resolved identifier first.
360
361 class IDLObjectWithIdentifier(IDLObject):
362 def __init__(self, location, parentScope, identifier):
363 IDLObject.__init__(self, location)
364
365 assert isinstance(identifier, IDLUnresolvedIdentifier)
366
367 self.identifier = identifier
368
369 if parentScope:
370 self.resolve(parentScope)
371
372 self.treatNullAs = "Default"
373
374 def resolve(self, parentScope):
375 assert isinstance(parentScope, IDLScope)
376 assert isinstance(self.identifier, IDLUnresolvedIdentifier)
377 self.identifier.resolve(parentScope, self)
378
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
392
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)
411
412 return unhandledAttrs
413
414 class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope):
415 def __init__(self, location, parentScope, identifier):
416 assert isinstance(identifier, IDLUnresolvedIdentifier)
417
418 IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
419 IDLScope.__init__(self, location, parentScope, self.identifier)
420
421 class IDLIdentifierPlaceholder(IDLObjectWithIdentifier):
422 def __init__(self, location, identifier):
423 assert isinstance(identifier, IDLUnresolvedIdentifier)
424 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
425
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])
432
433 obj = self.identifier.resolve(scope, None)
434 return scope.lookupIdentifier(obj)
435
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)
443
444 def finish(self, scope):
445 pass
446
447 def validate(self):
448 pass
449
450 def isExternal(self):
451 return True
452
453 def isInterface(self):
454 return True
455
456 def isConsequential(self):
457 return False
458
459 def addExtendedAttributes(self, attrs):
460 assert len(attrs) == 0
461
462 def resolve(self, parentScope):
463 pass
464
465 def getJSImplementation(self):
466 return None
467
468 def isJSImplemented(self):
469 return False
470
471 def getNavigatorProperty(self):
472 return None
473
474 def _getDependentObjects(self):
475 return set()
476
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
483
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
509
510 IDLObjectWithScope.__init__(self, location, parentScope, name)
511
512 if not isPartial:
513 self.setNonPartial(location, parent, members)
514 else:
515 # Just remember our members for now
516 self.members = members
517
518 def __str__(self):
519 return "Interface '%s'" % self.identifier.name
520
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
528
529 def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
530 assert isinstance(scope, IDLScope)
531 assert isinstance(originalObject, IDLInterfaceMember)
532 assert isinstance(newObject, IDLInterfaceMember)
533
534 retval = IDLScope.resolveIdentifierConflict(self, scope, identifier,
535 originalObject, newObject)
536
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
541
542 def finish(self, scope):
543 if self._finished:
544 return
545
546 self._finished = True
547
548 if self._isPartial:
549 raise WebIDLError("Interface %s does not have a non-partial "
550 "declaration" % self.identifier.name,
551 [self.location])
552
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)
562
563 self.parent = parent
564
565 assert iter(self.members)
566
567 if self.parent:
568 self.parent.finish(scope)
569
570 self.parent._hasChildInterfaces = True
571
572 self.totalMembersInSlots = self.parent.totalMembersInSlots
573
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])
582
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])
600
601 for iface in self.implementedInterfaces:
602 iface.finish(scope)
603
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])
609
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()
616
617 # Now resolve() and finish() our members before importing the
618 # ones from our implemented interfaces.
619
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)
624
625 for member in self.members:
626 member.finish(scope)
627
628 ctor = self.ctor()
629 if ctor is not None:
630 ctor.finish(scope)
631
632 for ctor in self.namedConstructors:
633 ctor.finish(scope)
634
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)
639
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)
658
659 for ancestor in self.getInheritedInterfaces():
660 ancestor.interfacesBasedOnSelf.add(self)
661 for ancestorConsequential in ancestor.getConsequentialInterfaces():
662 ancestorConsequential.interfacesBasedOnSelf.add(self)
663
664 for member in self.members:
665 if (member.isAttr() and member.isUnforgeable() and
666 not hasattr(member, "originatingInterface")):
667 member.originatingInterface = self
668
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
679
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)
710
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
720
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
737
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
745
746 if memberType in specialMembersSeen:
747 raise WebIDLError("Multiple " + memberType + " on %s" % (self),
748 [self.location,
749 specialMembersSeen[memberType].location,
750 member.location])
751
752 specialMembersSeen[memberType] = member
753
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
778
779 def validate(self):
780 for member in self.members:
781 member.validate()
782
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])
794
795 while putForwards is not None:
796 forwardIface = attr.type.unroll().inner
797 fowardAttr = None
798
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
811
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])
817
818 iface = forwardIface
819 attr = fowardAttr
820 putForwards = attr.getExtendedAttribute("PutForwards")
821
822
823 def isInterface(self):
824 return True
825
826 def isExternal(self):
827 return False
828
829 def setIsConsequentialInterfaceOf(self, other):
830 self._consequential = True
831 self.interfacesBasedOnSelf.add(other)
832
833 def isConsequential(self):
834 return self._consequential
835
836 def setCallback(self, value):
837 self._callback = value
838
839 def isCallback(self):
840 return self._callback
841
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)
858
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
866
867 def hasConstants(self):
868 return any(m.isConst() for m in self.members)
869
870 def hasInterfaceObject(self):
871 if self.isCallback():
872 return self.hasConstants()
873 return not hasattr(self, "_noInterfaceObject")
874
875 def hasInterfacePrototypeObject(self):
876 return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
877
878 def addExtendedAttributes(self, attrs):
879 self._extendedAttrDict = {}
880 for attr in attrs:
881 identifier = attr.identifier()
882
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])
894
895 if self.ctor():
896 raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
897 [self.location])
898
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])
904
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])
908
909 if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
910 raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
911 [self.location])
912
913 args = attr.args() if attr.hasArgs() else []
914
915 retType = IDLWrapperType(self.location, self)
916
917 if identifier == "Constructor" or identifier == "ChromeConstructor":
918 name = "constructor"
919 allowForbidden = True
920 else:
921 name = attr.value()
922 allowForbidden = False
923
924 methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
925 allowForbidden=allowForbidden)
926
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",))])
939
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)
948
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])
996
997 attrlist = attr.listValue()
998 self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
999
1000 def addImplementedInterface(self, implementedInterface):
1001 assert(isinstance(implementedInterface, IDLInterface))
1002 self.implementedInterfaces.add(implementedInterface)
1003
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
1016
1017 def getConsequentialInterfaces(self):
1018 assert(self._finished)
1019 # The interfaces we implement directly
1020 consequentialInterfaces = set(self.implementedInterfaces)
1021
1022 # And their inherited interfaces
1023 for iface in self.implementedInterfaces:
1024 consequentialInterfaces |= set(iface.getInheritedInterfaces())
1025
1026 # And now collect up the consequential interfaces of all of those
1027 temp = set()
1028 for iface in consequentialInterfaces:
1029 temp |= iface.getConsequentialInterfaces()
1030
1031 return consequentialInterfaces | temp
1032
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
1052
1053 def getExtendedAttribute(self, name):
1054 return self._extendedAttrDict.get(name, None)
1055
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
1070
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]
1078
1079 def isJSImplemented(self):
1080 return bool(self.getJSImplementation())
1081
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]
1090
1091 def hasChildInterfaces(self):
1092 return self._hasChildInterfaces
1093
1094 def isOnGlobalProtoChain(self):
1095 return self._isOnGlobalProtoChain
1096
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
1103
1104 def hasMembersInSlots(self):
1105 return self._ownMembersInSlots != 0
1106
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)
1112
1113 self.parent = parent
1114 self._finished = False
1115 self.members = list(members)
1116
1117 IDLObjectWithScope.__init__(self, location, parentScope, name)
1118
1119 def __str__(self):
1120 return "Dictionary '%s'" % self.identifier.name
1121
1122 def isDictionary(self):
1123 return True;
1124
1125 def finish(self, scope):
1126 if self._finished:
1127 return
1128
1129 self._finished = True
1130
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])
1139
1140 # Make sure the parent resolves all its members before we start
1141 # looking at them.
1142 self.parent.finish(scope)
1143
1144 for member in self.members:
1145 member.resolve(self)
1146 if not member.isComplete():
1147 member.complete(scope)
1148 assert member.type.isComplete()
1149
1150 # Members of a dictionary are sorted in lexicographic order
1151 self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
1152
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
1162
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])
1170
1171 def validate(self):
1172 def typeContainsDictionary(memberType, dictionary):
1173 """
1174 Returns a tuple whose:
1175
1176 - First element is a Boolean value indicating whether
1177 memberType contains dictionary.
1178
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.
1183
1184 None, if the boolean value in the first element is False.
1185 """
1186
1187 if (memberType.nullable() or
1188 memberType.isArray() or
1189 memberType.isSequence() or
1190 memberType.isMozMap()):
1191 return typeContainsDictionary(memberType.inner, dictionary)
1192
1193 if memberType.isDictionary():
1194 if memberType.inner == dictionary:
1195 return (True, [memberType.location])
1196
1197 (contains, locations) = dictionaryContainsDictionary(memberType.inner, \
1198 dictionary)
1199 if contains:
1200 return (True, [memberType.location] + locations)
1201
1202 if memberType.isUnion():
1203 for member in memberType.flatMemberTypes:
1204 (contains, locations) = typeContainsDictionary(member, dictionary)
1205 if contains:
1206 return (True, locations)
1207
1208 return (False, None)
1209
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)
1215
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)
1223
1224 return (False, None)
1225
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)
1236
1237 def addExtendedAttributes(self, attrs):
1238 assert len(attrs) == 0
1239
1240 def _getDependentObjects(self):
1241 deps = set(self.members)
1242 if (self.parent):
1243 deps.add(self.parent)
1244 return deps
1245
1246 class IDLEnum(IDLObjectWithIdentifier):
1247 def __init__(self, location, parentScope, name, values):
1248 assert isinstance(parentScope, IDLScope)
1249 assert isinstance(name, IDLUnresolvedIdentifier)
1250
1251 if len(values) != len(set(values)):
1252 raise WebIDLError("Enum %s has multiple identical strings" % name.name,
1253 [location])
1254
1255 IDLObjectWithIdentifier.__init__(self, location, parentScope, name)
1256 self._values = values
1257
1258 def values(self):
1259 return self._values
1260
1261 def finish(self, scope):
1262 pass
1263
1264 def validate(self):
1265 pass
1266
1267 def isEnum(self):
1268 return True
1269
1270 def addExtendedAttributes(self, attrs):
1271 assert len(attrs) == 0
1272
1273 def _getDependentObjects(self):
1274 return set()
1275
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 )
1311
1312 def __init__(self, location, name):
1313 IDLObject.__init__(self, location)
1314 self.name = name
1315 self.builtin = False
1316
1317 def __eq__(self, other):
1318 return other and self.builtin == other.builtin and self.name == other.name
1319
1320 def __ne__(self, other):
1321 return not self == other
1322
1323 def __str__(self):
1324 return str(self.name)
1325
1326 def isType(self):
1327 return True
1328
1329 def nullable(self):
1330 return False
1331
1332 def isPrimitive(self):
1333 return False
1334
1335 def isBoolean(self):
1336 return False
1337
1338 def isNumeric(self):
1339 return False
1340
1341 def isString(self):
1342 return False
1343
1344 def isByteString(self):
1345 return False
1346
1347 def isDOMString(self):
1348 return False
1349
1350 def isVoid(self):
1351 return self.name == "Void"
1352
1353 def isSequence(self):
1354 return False
1355
1356 def isMozMap(self):
1357 return False
1358
1359 def isArray(self):
1360 return False
1361
1362 def isArrayBuffer(self):
1363 return False
1364
1365 def isArrayBufferView(self):
1366 return False
1367
1368 def isTypedArray(self):
1369 return False
1370
1371 def isCallbackInterface(self):
1372 return False
1373
1374 def isNonCallbackInterface(self):
1375 return False
1376
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()
1383
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())
1391
1392 def isDictionary(self):
1393 return False
1394
1395 def isInterface(self):
1396 return False
1397
1398 def isAny(self):
1399 return self.tag() == IDLType.Tags.any
1400
1401 def isDate(self):
1402 return self.tag() == IDLType.Tags.date
1403
1404 def isObject(self):
1405 return self.tag() == IDLType.Tags.object
1406
1407 def isPromise(self):
1408 return False
1409
1410 def isComplete(self):
1411 return True
1412
1413 def includesRestrictedFloat(self):
1414 return False
1415
1416 def isFloat(self):
1417 return False
1418
1419 def isUnrestricted(self):
1420 # Should only call this on float types
1421 assert self.isFloat()
1422
1423 def isSerializable(self):
1424 return False
1425
1426 def tag(self):
1427 assert False # Override me!
1428
1429 def treatNonCallableAsNull(self):
1430 assert self.tag() == IDLType.Tags.callback
1431 return self.nullable() and self.inner._treatNonCallableAsNull
1432
1433 def treatNonObjectAsNull(self):
1434 assert self.tag() == IDLType.Tags.callback
1435 return self.nullable() and self.inner._treatNonObjectAsNull
1436
1437 def addExtendedAttributes(self, attrs):
1438 assert len(attrs) == 0
1439
1440 def resolveType(self, parentScope):
1441 pass
1442
1443 def unroll(self):
1444 return self
1445
1446 def isDistinguishableFrom(self, other):
1447 raise TypeError("Can't tell whether a generic type is or is not "
1448 "distinguishable from other things")
1449
1450 class IDLUnresolvedType(IDLType):
1451 """
1452 Unresolved types are interface types
1453 """
1454
1455 def __init__(self, location, name):
1456 IDLType.__init__(self, location, name)
1457
1458 def isComplete(self):
1459 return False
1460
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])
1468
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
1476
1477 name = self.name.resolve(scope, None)
1478 return IDLWrapperType(self.location, obj)
1479
1480 def isDistinguishableFrom(self, other):
1481 raise TypeError("Can't tell whether an unresolved type is or is not "
1482 "distinguishable from other things")
1483
1484 class IDLNullableType(IDLType):
1485 def __init__(self, location, innerType):
1486 assert not innerType.isVoid()
1487 assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
1488
1489 IDLType.__init__(self, location, innerType.name)
1490 self.inner = innerType
1491 self.builtin = False
1492
1493 def __eq__(self, other):
1494 return isinstance(other, IDLNullableType) and self.inner == other.inner
1495
1496 def __str__(self):
1497 return self.inner.__str__() + "OrNull"
1498
1499 def nullable(self):
1500 return True
1501
1502 def isCallback(self):
1503 return self.inner.isCallback()
1504
1505 def isPrimitive(self):
1506 return self.inner.isPrimitive()
1507
1508 def isBoolean(self):
1509 return self.inner.isBoolean()
1510
1511 def isNumeric(self):
1512 return self.inner.isNumeric()
1513
1514 def isString(self):
1515 return self.inner.isString()
1516
1517 def isByteString(self):
1518 return self.inner.isByteString()
1519
1520 def isDOMString(self):
1521 return self.inner.isDOMString()
1522
1523 def isFloat(self):
1524 return self.inner.isFloat()
1525
1526 def isUnrestricted(self):
1527 return self.inner.isUnrestricted()
1528
1529 def includesRestrictedFloat(self):
1530 return self.inner.includesRestrictedFloat()
1531
1532 def isInteger(self):
1533 return self.inner.isInteger()
1534
1535 def isVoid(self):
1536 return False
1537
1538 def isSequence(self):
1539 return self.inner.isSequence()
1540
1541 def isMozMap(self):
1542 return self.inner.isMozMap()
1543
1544 def isArray(self):
1545 return self.inner.isArray()
1546
1547 def isArrayBuffer(self):
1548 return self.inner.isArrayBuffer()
1549
1550 def isArrayBufferView(self):
1551 return self.inner.isArrayBufferView()
1552
1553 def isTypedArray(self):
1554 return self.inner.isTypedArray()
1555
1556 def isDictionary(self):
1557 return self.inner.isDictionary()
1558
1559 def isInterface(self):
1560 return self.inner.isInterface()
1561
1562 def isCallbackInterface(self):
1563 return self.inner.isCallbackInterface()
1564
1565 def isNonCallbackInterface(self):
1566 return self.inner.isNonCallbackInterface()
1567
1568 def isEnum(self):
1569 return self.inner.isEnum()
1570
1571 def isUnion(self):
1572 return self.inner.isUnion()
1573
1574 def isSerializable(self):
1575 return self.inner.isSerializable()
1576
1577 def tag(self):
1578 return self.inner.tag()
1579
1580 def resolveType(self, parentScope):
1581 assert isinstance(parentScope, IDLScope)
1582 self.inner.resolveType(parentScope)
1583
1584 def isComplete(self):
1585 return self.inner.isComplete()
1586
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])
1598
1599 self.name = self.inner.name
1600 return self
1601
1602 def unroll(self):
1603 return self.inner.unroll()
1604
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)
1611
1612 def _getDependentObjects(self):
1613 return self.inner._getDependentObjects()
1614
1615 class IDLSequenceType(IDLType):
1616 def __init__(self, location, parameterType):
1617 assert not parameterType.isVoid()
1618
1619 IDLType.__init__(self, location, parameterType.name)
1620 self.inner = parameterType
1621 self.builtin = False
1622
1623 def __eq__(self, other):
1624 return isinstance(other, IDLSequenceType) and self.inner == other.inner
1625
1626 def __str__(self):
1627 return self.inner.__str__() + "Sequence"
1628
1629 def nullable(self):
1630 return False
1631
1632 def isPrimitive(self):
1633 return False;
1634
1635 def isString(self):
1636 return False;
1637
1638 def isByteString(self):
1639 return False
1640
1641 def isDOMString(self):
1642 return False
1643
1644 def isVoid(self):
1645 return False
1646
1647 def isSequence(self):
1648 return True
1649
1650 def isArray(self):
1651 return False
1652
1653 def isDictionary(self):
1654 return False
1655
1656 def isInterface(self):
1657 return False
1658
1659 def isEnum(self):
1660 return False
1661
1662 def isSerializable(self):
1663 return self.inner.isSerializable()
1664
1665 def includesRestrictedFloat(self):
1666 return self.inner.includesRestrictedFloat()
1667
1668 def tag(self):
1669 return IDLType.Tags.sequence
1670
1671 def resolveType(self, parentScope):
1672 assert isinstance(parentScope, IDLScope)
1673 self.inner.resolveType(parentScope)
1674
1675 def isComplete(self):
1676 return self.inner.isComplete()
1677
1678 def complete(self, scope):
1679 self.inner = self.inner.complete(scope)
1680 self.name = self.inner.name
1681 return self
1682
1683 def unroll(self):
1684 return self.inner.unroll()
1685
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())
1692
1693 def _getDependentObjects(self):
1694 return self.inner._getDependentObjects()
1695
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()
1702
1703 IDLType.__init__(self, location, parameterType.name)
1704 self.inner = parameterType
1705 self.builtin = False
1706
1707 def __eq__(self, other):
1708 return isinstance(other, IDLMozMapType) and self.inner == other.inner
1709
1710 def __str__(self):
1711 return self.inner.__str__() + "MozMap"
1712
1713 def isMozMap(self):
1714 return True
1715
1716 def includesRestrictedFloat(self):
1717 return self.inner.includesRestrictedFloat()
1718
1719 def tag(self):
1720 return IDLType.Tags.mozmap
1721
1722 def resolveType(self, parentScope):
1723 assert isinstance(parentScope, IDLScope)
1724 self.inner.resolveType(parentScope)
1725
1726 def isComplete(self):
1727 return self.inner.isComplete()
1728
1729 def complete(self, scope):
1730 self.inner = self.inner.complete(scope)
1731 self.name = self.inner.name
1732 return self
1733
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
1739
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())
1746
1747 def _getDependentObjects(self):
1748 return self.inner._getDependentObjects()
1749
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
1758
1759 def __eq__(self, other):
1760 return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes
1761
1762 def isVoid(self):
1763 return False
1764
1765 def isUnion(self):
1766 return True
1767
1768 def isSerializable(self):
1769 return all(m.isSerializable() for m in self.memberTypes)
1770
1771 def includesRestrictedFloat(self):
1772 return any(t.includesRestrictedFloat() for t in self.memberTypes)
1773
1774 def tag(self):
1775 return IDLType.Tags.union
1776
1777 def resolveType(self, parentScope):
1778 assert isinstance(parentScope, IDLScope)
1779 for t in self.memberTypes:
1780 t.resolveType(parentScope)
1781
1782 def isComplete(self):
1783 return self.flatMemberTypes is not None
1784
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
1797
1798 for (i, type) in enumerate(self.memberTypes):
1799 if not type.isComplete():
1800 self.memberTypes[i] = type.complete(scope)
1801
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
1831
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])
1839
1840 return self
1841
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
1856
1857 def _getDependentObjects(self):
1858 return set(self.memberTypes)
1859
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])
1872
1873 IDLType.__init__(self, location, parameterType.name)
1874 self.inner = parameterType
1875 self.builtin = False
1876
1877 def __eq__(self, other):
1878 return isinstance(other, IDLArrayType) and self.inner == other.inner
1879
1880 def __str__(self):
1881 return self.inner.__str__() + "Array"
1882
1883 def nullable(self):
1884 return False
1885
1886 def isPrimitive(self):
1887 return False
1888
1889 def isString(self):
1890 return False
1891
1892 def isByteString(self):
1893 return False
1894
1895 def isDOMString(self):
1896 return False
1897
1898 def isVoid(self):
1899 return False
1900
1901 def isSequence(self):
1902 assert not self.inner.isSequence()
1903 return False
1904
1905 def isArray(self):
1906 return True
1907
1908 def isDictionary(self):
1909 assert not self.inner.isDictionary()
1910 return False
1911
1912 def isInterface(self):
1913 return False
1914
1915 def isEnum(self):
1916 return False
1917
1918 def tag(self):
1919 return IDLType.Tags.array
1920
1921 def resolveType(self, parentScope):
1922 assert isinstance(parentScope, IDLScope)
1923 self.inner.resolveType(parentScope)
1924
1925 def isComplete(self):
1926 return self.inner.isComplete()
1927
1928 def complete(self, scope):
1929 self.inner = self.inner.complete(scope)
1930 self.name = self.inner.name
1931
1932 if self.inner.isDictionary():
1933 raise WebIDLError("Array type must not contain "
1934 "dictionary as element type.",
1935 [self.inner.location])
1936
1937 assert not self.inner.isSequence()
1938
1939 return self
1940
1941 def unroll(self):
1942 return self.inner.unroll()
1943
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())
1950
1951 def _getDependentObjects(self):
1952 return self.inner._getDependentObjects()
1953
1954 class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
1955 def __init__(self, location, innerType, name):
1956 IDLType.__init__(self, location, innerType.name)
1957
1958 identifier = IDLUnresolvedIdentifier(location, name)
1959
1960 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
1961
1962 self.inner = innerType
1963 self.name = name
1964 self.builtin = False
1965
1966 def __eq__(self, other):
1967 return isinstance(other, IDLTypedefType) and self.inner == other.inner
1968
1969 def __str__(self):
1970 return self.identifier.name
1971
1972 def nullable(self):
1973 return self.inner.nullable()
1974
1975 def isPrimitive(self):
1976 return self.inner.isPrimitive()
1977
1978 def isBoolean(self):
1979 return self.inner.isBoolean()
1980
1981 def isNumeric(self):
1982 return self.inner.isNumeric()
1983
1984 def isString(self):
1985 return self.inner.isString()
1986
1987 def isByteString(self):
1988 return self.inner.isByteString()
1989
1990 def isDOMString(self):
1991 return self.inner.isDOMString()
1992
1993 def isVoid(self):
1994 return self.inner.isVoid()
1995
1996 def isSequence(self):
1997 return self.inner.isSequence()
1998
1999 def isMozMap(self):
2000 return self.inner.isMozMap()
2001
2002 def isArray(self):
2003 return self.inner.isArray()
2004
2005 def isDictionary(self):
2006 return self.inner.isDictionary()
2007
2008 def isArrayBuffer(self):
2009 return self.inner.isArrayBuffer()
2010
2011 def isArrayBufferView(self):
2012 return self.inner.isArrayBufferView()
2013
2014 def isTypedArray(self):
2015 return self.inner.isTypedArray()
2016
2017 def isInterface(self):
2018 return self.inner.isInterface()
2019
2020 def isCallbackInterface(self):
2021 return self.inner.isCallbackInterface()
2022
2023 def isNonCallbackInterface(self):
2024 return self.inner.isNonCallbackInterface()
2025
2026 def isComplete(self):
2027 return False
2028
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
2034
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)
2041
2042 def validate(self):
2043 pass
2044
2045 # Do we need a resolveType impl? I don't think it's particularly useful....
2046
2047 def tag(self):
2048 return self.inner.tag()
2049
2050 def unroll(self):
2051 return self.inner.unroll()
2052
2053 def isDistinguishableFrom(self, other):
2054 return self.inner.isDistinguishableFrom(other)
2055
2056 def _getDependentObjects(self):
2057 return self.inner._getDependentObjects()
2058
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
2065
2066 def __eq__(self, other):
2067 return isinstance(other, IDLWrapperType) and \
2068 self._identifier == other._identifier and \
2069 self.builtin == other.builtin
2070
2071 def __str__(self):
2072 return str(self.name) + " (Wrapper)"
2073
2074 def nullable(self):
2075 return False
2076
2077 def isPrimitive(self):
2078 return False
2079
2080 def isString(self):
2081 return False
2082
2083 def isByteString(self):
2084 return False
2085
2086 def isDOMString(self):
2087 return False
2088
2089 def isVoid(self):
2090 return False
2091
2092 def isSequence(self):
2093 return False
2094
2095 def isArray(self):
2096 return False
2097
2098 def isDictionary(self):
2099 return isinstance(self.inner, IDLDictionary)
2100
2101 def isInterface(self):
2102 return isinstance(self.inner, IDLInterface) or \
2103 isinstance(self.inner, IDLExternalInterface)
2104
2105 def isCallbackInterface(self):
2106 return self.isInterface() and self.inner.isCallback()
2107
2108 def isNonCallbackInterface(self):
2109 return self.isInterface() and not self.inner.isCallback()
2110
2111 def isEnum(self):
2112 return isinstance(self.inner, IDLEnum)
2113
2114 def isPromise(self):
2115 return isinstance(self.inner, IDLInterface) and \
2116 self.inner.identifier.name == "Promise"
2117
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])
2130
2131 def resolveType(self, parentScope):
2132 assert isinstance(parentScope, IDLScope)
2133 self.inner.resolve(parentScope)
2134
2135 def isComplete(self):
2136 return True
2137
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
2147
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()
2164
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()
2180
2181 # Not much else |other| can be
2182 assert other.isObject()
2183 return False
2184
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()
2201
2202 class IDLBuiltinType(IDLType):
2203
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 )
2241
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 }
2274
2275 def __init__(self, location, name, type):
2276 IDLType.__init__(self, location, name)
2277 self.builtin = True
2278 self._typeTag = type
2279
2280 def isPrimitive(self):
2281 return self._typeTag <= IDLBuiltinType.Types.double
2282
2283 def isBoolean(self):
2284 return self._typeTag == IDLBuiltinType.Types.boolean
2285
2286 def isNumeric(self):
2287 return self.isPrimitive() and not self.isBoolean()
2288
2289 def isString(self):
2290 return self._typeTag == IDLBuiltinType.Types.domstring or \
2291 self._typeTag == IDLBuiltinType.Types.bytestring
2292
2293 def isByteString(self):
2294 return self._typeTag == IDLBuiltinType.Types.bytestring
2295
2296 def isDOMString(self):
2297 return self._typeTag == IDLBuiltinType.Types.domstring
2298
2299 def isInteger(self):
2300 return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long
2301
2302 def isArrayBuffer(self):
2303 return self._typeTag == IDLBuiltinType.Types.ArrayBuffer
2304
2305 def isArrayBufferView(self):
2306 return self._typeTag == IDLBuiltinType.Types.ArrayBufferView
2307
2308 def isTypedArray(self):
2309 return self._typeTag >= IDLBuiltinType.Types.Int8Array and \
2310 self._typeTag <= IDLBuiltinType.Types.Float64Array
2311
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()
2319
2320 def isNonCallbackInterface(self):
2321 # All the interfaces we can be are non-callback
2322 return self.isInterface()
2323
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
2329
2330 def isUnrestricted(self):
2331 assert self.isFloat()
2332 return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
2333 self._typeTag == IDLBuiltinType.Types.unrestricted_double
2334
2335 def isSerializable(self):
2336 return self.isPrimitive() or self.isDOMString() or self.isDate()
2337
2338 def includesRestrictedFloat(self):
2339 return self.isFloat() and not self.isUnrestricted()
2340
2341 def tag(self):
2342 return IDLBuiltinType.TagLookup[self._typeTag]
2343
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)))))
2398
2399 def _getDependentObjects(self):
2400 return set()
2401
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 }
2494
2495
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 }
2507
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]
2513
2514 return None
2515
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)
2521
2522 self.value = value
2523
2524 def coerceToType(self, type, location):
2525 if type == self.type:
2526 return self # Nothing to do
2527
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)
2551
2552 elif self.type.isInteger() and type.isInteger():
2553 # We're both integer types. See if we fit.
2554
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])
2587
2588 def _getDependentObjects(self):
2589 return set()
2590
2591 class IDLNullValue(IDLObject):
2592 def __init__(self, location):
2593 IDLObject.__init__(self, location)
2594 self.type = None
2595 self.value = None
2596
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])
2605
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
2616
2617 def _getDependentObjects(self):
2618 return set()
2619
2620 class IDLUndefinedValue(IDLObject):
2621 def __init__(self, location):
2622 IDLObject.__init__(self, location)
2623 self.type = None
2624 self.value = None
2625
2626 def coerceToType(self, type, location):
2627 if not type.isAny():
2628 raise WebIDLError("Cannot coerce undefined value to type %s." % type,
2629 [location])
2630
2631 undefinedValue = IDLUndefinedValue(self.location)
2632 undefinedValue.type = type
2633 return undefinedValue
2634
2635 def _getDependentObjects(self):
2636 return set()
2637
2638 class IDLInterfaceMember(IDLObjectWithIdentifier):
2639
2640 Tags = enum(
2641 'Const',
2642 'Attr',
2643 'Method'
2644 )
2645
2646 Special = enum(
2647 'Static',
2648 'Stringifier'
2649 )
2650
2651 def __init__(self, location, identifier, tag):
2652 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
2653 self.tag = tag
2654 self._extendedAttrDict = {}
2655
2656 def isMethod(self):
2657 return self.tag == IDLInterfaceMember.Tags.Method
2658
2659 def isAttr(self):
2660 return self.tag == IDLInterfaceMember.Tags.Attr
2661
2662 def isConst(self):
2663 return self.tag == IDLInterfaceMember.Tags.Const
2664
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
2670
2671 def handleExtendedAttribute(self, attr):
2672 pass
2673
2674 def getExtendedAttribute(self, name):
2675 return self._extendedAttrDict.get(name, None)
2676
2677 class IDLConst(IDLInterfaceMember):
2678 def __init__(self, location, identifier, type, value):
2679 IDLInterfaceMember.__init__(self, location, identifier,
2680 IDLInterfaceMember.Tags.Const)
2681
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
2688
2689 if identifier.name == "prototype":
2690 raise WebIDLError("The identifier of a constant must not be 'prototype'",
2691 [location])
2692
2693 def __str__(self):
2694 return "'%s' const '%s'" % (self.type, self.identifier)
2695
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
2707
2708 # The value might not match the type
2709 coercedValue = self.value.coerceToType(self.type, self.location)
2710 assert coercedValue
2711
2712 self.value = coercedValue
2713
2714 def validate(self):
2715 pass
2716
2717 def _getDependentObjects(self):
2718 return set([self.type, self.value])
2719
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)
2725
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
2737
2738 if static and identifier.name == "prototype":
2739 raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
2740 [location])
2741
2742 if readonly and inherit:
2743 raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
2744 [self.location])
2745
2746 def isStatic(self):
2747 return self.static
2748
2749 def __str__(self):
2750 return "'%s' attribute '%s'" % (self.type, self.identifier)
2751
2752 def finish(self, scope):
2753 if not self.type.isComplete():
2754 t = self.type.complete(scope)
2755
2756 assert not isinstance(t, IDLUnresolvedType)
2757 assert not isinstance(t, IDLTypedefType)
2758 assert not isinstance(t.name, IDLUnresolvedIdentifier)
2759 self.type = t
2760
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])
2793
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])
2797
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])
2814
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)
2937
2938 def resolve(self, parentScope):
2939 assert isinstance(parentScope, IDLScope)
2940 self.type.resolveType(parentScope)
2941 IDLObjectWithIdentifier.resolve(self, parentScope)
2942
2943 def addExtendedAttributes(self, attrs):
2944 attrs = self.checkForStringHandlingExtendedAttributes(attrs)
2945 IDLInterfaceMember.addExtendedAttributes(self, attrs)
2946
2947 def hasLenientThis(self):
2948 return self.lenientThis
2949
2950 def isUnforgeable(self):
2951 return self._unforgeable
2952
2953 def _getDependentObjects(self):
2954 return set([self.type])
2955
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)
2959
2960 assert isinstance(type, IDLType)
2961 self.type = type
2962
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
2971
2972 assert not variadic or optional
2973
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])
3002
3003 def isComplete(self):
3004 return self._isComplete
3005
3006 def complete(self, scope):
3007 if self._isComplete:
3008 return
3009
3010 self._isComplete = True
3011
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
3018
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)
3033
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
3040
3041 def allowTreatNonCallableAsNull(self):
3042 return self._allowTreatNonCallableAsNull
3043
3044 def _getDependentObjects(self):
3045 deps = set([self.type])
3046 if self.defaultValue:
3047 deps.add(self.defaultValue)
3048 return deps
3049
3050 class IDLCallbackType(IDLType, IDLObjectWithScope):
3051 def __init__(self, location, parentScope, identifier, returnType, arguments):
3052 assert isinstance(returnType, IDLType)
3053
3054 IDLType.__init__(self, location, identifier.name)
3055
3056 self._returnType = returnType
3057 # Clone the list
3058 self._arguments = list(arguments)
3059
3060 IDLObjectWithScope.__init__(self, location, parentScope, identifier)
3061
3062 for (returnType, arguments) in self.signatures():
3063 for argument in arguments:
3064 argument.resolve(self)
3065
3066 self._treatNonCallableAsNull = False
3067 self._treatNonObjectAsNull = False
3068
3069 def isCallback(self):
3070 return True
3071
3072 def signatures(self):
3073 return [(self._returnType, self._arguments)]
3074
3075 def tag(self):
3076 return IDLType.Tags.callback
3077
3078 def finish(self, scope):
3079 if not self._returnType.isComplete():
3080 type = self._returnType.complete(scope)
3081
3082 assert not isinstance(type, IDLUnresolvedType)
3083 assert not isinstance(type, IDLTypedefType)
3084 assert not isinstance(type.name, IDLUnresolvedIdentifier)
3085 self._returnType = type
3086
3087 for argument in self._arguments:
3088 if argument.type.isComplete():
3089 continue
3090
3091 type = argument.type.complete(scope)
3092
3093 assert not isinstance(type, IDLUnresolvedType)
3094 assert not isinstance(type, IDLTypedefType)
3095 assert not isinstance(type.name, IDLUnresolvedIdentifier)
3096 argument.type = type
3097
3098 def validate(self):
3099 pass
3100
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())
3107
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)
3122
3123 def _getDependentObjects(self):
3124 return set([self._returnType] + self._arguments)
3125
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
3140
3141 def _getDependentObjects(self):
3142 deps = set(self.arguments)
3143 deps.add(self.returnType)
3144 return deps
3145
3146 class IDLMethod(IDLInterfaceMember, IDLScope):
3147
3148 Special = enum(
3149 'Getter',
3150 'Setter',
3151 'Creator',
3152 'Deleter',
3153 'LegacyCaller',
3154 base=IDLInterfaceMember.Special
3155 )
3156
3157 TypeSuffixModifier = enum(
3158 'None',
3159 'QMark',
3160 'Brackets'
3161 )
3162
3163 NamedOrIndexed = enum(
3164 'Neither',
3165 'Named',
3166 'Indexed'
3167 )
3168
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)
3176
3177 self._hasOverloads = False
3178
3179 assert isinstance(returnType, IDLType)
3180
3181 # self._overloads is a list of IDLMethodOverloads
3182 self._overloads = [IDLMethodOverload(returnType, arguments, location)]
3183
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
3201
3202 if static and identifier.name == "prototype":
3203 raise WebIDLError("The identifier of a static operation must not be 'prototype'",
3204 [location])
3205
3206 self.assertSignatureConstraints()
3207
3208 def __str__(self):
3209 return "Method '%s'" % self.identifier
3210
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()
3221
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
3230
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]
3236
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]
3242
3243 def isStatic(self):
3244 return self._static
3245
3246 def isGetter(self):
3247 return self._getter
3248
3249 def isSetter(self):
3250 return self._setter
3251
3252 def isCreator(self):
3253 return self._creator
3254
3255 def isDeleter(self):
3256 return self._deleter
3257
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
3262
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
3267
3268 def isLegacycaller(self):
3269 return self._legacycaller
3270
3271 def isStringifier(self):
3272 return self._stringifier
3273
3274 def isJsonifier(self):
3275 return self._jsonifier
3276
3277 def hasOverloads(self):
3278 return self._hasOverloads
3279
3280 def isIdentifierLess(self):
3281 return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__"
3282
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)
3290
3291 def addOverload(self, method):
3292 assert len(method._overloads) == 1
3293
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])
3298
3299 self._overloads.extend(method._overloads)
3300
3301 self._hasOverloads = True
3302
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])
3306
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])
3310
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()
3324
3325 return self
3326
3327 def signatures(self):
3328 return [(overload.returnType, overload.arguments) for overload in
3329 self._overloads]
3330
3331 def finish(self, scope):
3332 overloadWithPromiseReturnType = None
3333 overloadWithoutPromiseReturnType = None
3334 for overload in self._overloads:
3335 variadicArgument = None
3336
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()
3342
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])
3356
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])
3363
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
3370
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
3378
3379 if returnType.isPromise():
3380 overloadWithPromiseReturnType = overload
3381 else:
3382 overloadWithoutPromiseReturnType = overload
3383
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])
3390
3391 if overloadWithPromiseReturnType and self._legacycaller:
3392 raise WebIDLError("May not have a Promise return type for a "
3393 "legacycaller.",
3394 [overloadWithPromiseReturnType.location])
3395
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 ]
3401
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])
3421
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)]
3430
3431 def signaturesForArgCount(self, argc):
3432 return [(overload.returnType, overload.arguments) for overload
3433 in self.overloadsForArgCount(argc)]
3434
3435 def locationsForArgCount(self, argc):
3436 return [overload.location for overload in self.overloadsForArgCount(argc)]
3437
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)
3464
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)
3514
3515 def returnsPromise(self):
3516 return self._overloads[0].returnType.isPromise()
3517
3518 def _getDependentObjects(self):
3519 deps = set()
3520 for overload in self._overloads:
3521 deps.union(overload._getDependentObjects())
3522 return deps
3523
3524 class IDLImplementsStatement(IDLObject):
3525 def __init__(self, location, implementor, implementee):
3526 IDLObject.__init__(self, location)
3527 self.implementor = implementor;
3528 self.implementee = implementee
3529
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)
3555
3556 def validate(self):
3557 pass
3558
3559 def addExtendedAttributes(self, attrs):
3560 assert len(attrs) == 0
3561
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
3569
3570 def identifier(self):
3571 return self._tuple[0]
3572
3573 def noArguments(self):
3574 return len(self._tuple) == 1
3575
3576 def hasValue(self):
3577 return len(self._tuple) >= 2 and isinstance(self._tuple[1], str)
3578
3579 def value(self):
3580 assert(self.hasValue())
3581 return self._tuple[1]
3582
3583 def hasArgs(self):
3584 return (len(self._tuple) == 2 and isinstance(self._tuple[1], list) or
3585 len(self._tuple) == 3)
3586
3587 def args(self):
3588 assert(self.hasArgs())
3589 # Our args are our last element
3590 return self._tuple[-1]
3591
3592 def listValue(self):
3593 """
3594 Backdoor for storing random data in _extendedAttrDict
3595 """
3596 return list(self._tuple)[1:]
3597
3598 # Parser
3599
3600 class Tokenizer(object):
3601 tokens = [
3602 "INTEGER",
3603 "FLOATLITERAL",
3604 "IDENTIFIER",
3605 "STRING",
3606 "WHITESPACE",
3607 "OTHER"
3608 ]
3609
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
3614
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
3627
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
3632
3633 def t_STRING(self, t):
3634 r'"[^"]*"'
3635 t.value = t.value[1:-1]
3636 return t
3637
3638 def t_WHITESPACE(self, t):
3639 r'[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+'
3640 pass
3641
3642 def t_ELLIPSIS(self, t):
3643 r'\.\.\.'
3644 t.type = self.keywords.get(t.value)
3645 return t
3646
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
3651
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 }
3715
3716 tokens.extend(keywords.values())
3717
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)])
3724
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)
3733
3734 class Parser(Tokenizer):
3735 def getLocation(self, p, i):
3736 return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
3737
3738 def globalScope(self):
3739 return self._globalScope
3740
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] = []
3753
3754 p[0].extend(p[3])
3755
3756 def p_DefinitionsEmpty(self, p):
3757 """
3758 Definitions :
3759 """
3760 p[0] = []
3761
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 ...
3774
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)
3782
3783 p[0] = p[2]
3784
3785 def p_CallbackOrInterfaceInterface(self, p):
3786 """
3787 CallbackOrInterface : Interface
3788 """
3789 p[0] = p[1]
3790
3791 def p_CallbackRestOrInterface(self, p):
3792 """
3793 CallbackRestOrInterface : CallbackRest
3794 | Interface
3795 """
3796 assert p[1]
3797 p[0] = p[1]
3798
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]
3807
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
3821
3822 p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
3823 members, isPartial=False)
3824
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])
3831
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
3845
3846 p[0] = IDLExternalInterface(location, self.globalScope(), identifier)
3847
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]
3855
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
3872
3873 p[0] = IDLInterface(location, self.globalScope(), identifier, None,
3874 members, isPartial=True)
3875 pass
3876
3877 def p_Inheritance(self, p):
3878 """
3879 Inheritance : COLON ScopedName
3880 """
3881 p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2])
3882
3883 def p_InheritanceEmpty(self, p):
3884 """
3885 Inheritance :
3886 """
3887 pass
3888
3889 def p_InterfaceMembers(self, p):
3890 """
3891 InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
3892 """
3893 p[0] = [p[2]] if p[2] else []
3894
3895 assert not p[1] or p[2]
3896 p[2].addExtendedAttributes(p[1])
3897
3898 p[0].extend(p[3])
3899
3900 def p_InterfaceMembersEmpty(self, p):
3901 """
3902 InterfaceMembers :
3903 """
3904 p[0] = []
3905
3906 def p_InterfaceMember(self, p):
3907 """
3908 InterfaceMember : Const
3909 | AttributeOrOperation
3910 """
3911 p[0] = p[1]
3912
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)
3921
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])
3935
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]
3945
3946 p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
3947 defaultValue=defaultValue, variadic=False,
3948 dictionaryMember=True)
3949
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
3959
3960 def p_Exception(self, p):
3961 """
3962 Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON
3963 """
3964 pass
3965
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])
3972
3973 values = p[4]
3974 assert values
3975 p[0] = IDLEnum(location, self.globalScope(), identifier, values)
3976
3977 def p_EnumValueList(self, p):
3978 """
3979 EnumValueList : STRING EnumValueListComma
3980 """
3981 p[0] = [p[1]]
3982 p[0].extend(p[2])
3983
3984 def p_EnumValueListComma(self, p):
3985 """
3986 EnumValueListComma : COMMA EnumValueListString
3987 """
3988 p[0] = p[2]
3989
3990 def p_EnumValueListCommaEmpty(self, p):
3991 """
3992 EnumValueListComma :
3993 """
3994 p[0] = []
3995
3996 def p_EnumValueListString(self, p):
3997 """
3998 EnumValueListString : STRING EnumValueListComma
3999 """
4000 p[0] = [p[1]]
4001 p[0].extend(p[2])
4002
4003 def p_EnumValueListStringEmpty(self, p):
4004 """
4005 EnumValueListString :
4006 """
4007 p[0] = []
4008
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])
4016
4017 def p_ExceptionMembers(self, p):
4018 """
4019 ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
4020 |
4021 """
4022 pass
4023
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
4031
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)
4041
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)
4051
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])
4059
4060 def p_ConstValueInteger(self, p):
4061 """
4062 ConstValue : INTEGER
4063 """
4064 location = self.getLocation(p, 1)
4065
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])
4071
4072 p[0] = IDLValue(location, integerType, p[1])
4073
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])
4080
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])
4088
4089 def p_ConstValueNull(self, p):
4090 """
4091 ConstValue : NULL
4092 """
4093 p[0] = IDLNullValue(self.getLocation(p, 1))
4094
4095 def p_BooleanLiteralTrue(self, p):
4096 """
4097 BooleanLiteral : TRUE
4098 """
4099 p[0] = True
4100
4101 def p_BooleanLiteralFalse(self, p):
4102 """
4103 BooleanLiteral : FALSE
4104 """
4105 p[0] = False
4106
4107 def p_AttributeOrOperation(self, p):
4108 """
4109 AttributeOrOperation : Attribute
4110 | Operation
4111 """
4112 p[0] = p[1]
4113
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)
4123
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])
4130
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)
4140
4141 def p_ReadOnly(self, p):
4142 """
4143 ReadOnly : READONLY
4144 """
4145 p[0] = True
4146
4147 def p_ReadOnlyEmpty(self, p):
4148 """
4149 ReadOnly :
4150 """
4151 p[0] = False
4152
4153 def p_Inherit(self, p):
4154 """
4155 Inherit : INHERIT
4156 """
4157 p[0] = True
4158
4159 def p_InheritEmpty(self, p):
4160 """
4161 Inherit :
4162 """
4163 p[0] = False
4164
4165 def p_Operation(self, p):
4166 """
4167 Operation : Qualifiers OperationRest
4168 """
4169 qualifiers = p[1]
4170
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)])
4175
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
4180
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
4185
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
4191
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)])
4196
4197 (returnType, identifier, arguments) = p[2]
4198
4199 assert isinstance(returnType, IDLType)
4200
4201 specialType = IDLMethod.NamedOrIndexed.Neither
4202
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])
4250
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)])
4258
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)])
4265
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)
4276
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
4282
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
4296
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
4309
4310 def p_QualifierStatic(self, p):
4311 """
4312 Qualifier : STATIC
4313 """
4314 p[0] = [IDLInterfaceMember.Special.Static]
4315
4316 def p_QualifierStringifier(self, p):
4317 """
4318 Qualifier : STRINGIFIER
4319 """
4320 p[0] = [IDLInterfaceMember.Special.Stringifier]
4321
4322 def p_Qualifiers(self, p):
4323 """
4324 Qualifiers : Qualifier
4325 | Specials
4326 """
4327 p[0] = p[1]
4328
4329 def p_Specials(self, p):
4330 """
4331 Specials : Special Specials
4332 """
4333 p[0] = [p[1]]
4334 p[0].extend(p[2])
4335
4336 def p_SpecialsEmpty(self, p):
4337 """
4338 Specials :
4339 """
4340 p[0] = []
4341
4342 def p_SpecialGetter(self, p):
4343 """
4344 Special : GETTER
4345 """
4346 p[0] = IDLMethod.Special.Getter
4347
4348 def p_SpecialSetter(self, p):
4349 """
4350 Special : SETTER
4351 """
4352 p[0] = IDLMethod.Special.Setter
4353
4354 def p_SpecialCreator(self, p):
4355 """
4356 Special : CREATOR
4357 """
4358 p[0] = IDLMethod.Special.Creator
4359
4360 def p_SpecialDeleter(self, p):
4361 """
4362 Special : DELETER
4363 """
4364 p[0] = IDLMethod.Special.Deleter
4365
4366 def p_SpecialLegacyCaller(self, p):
4367 """
4368 Special : LEGACYCALLER
4369 """
4370 p[0] = IDLMethod.Special.LegacyCaller
4371
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])
4377
4378 def p_OptionalIdentifier(self, p):
4379 """
4380 OptionalIdentifier : IDENTIFIER
4381 """
4382 p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
4383
4384 def p_OptionalIdentifierEmpty(self, p):
4385 """
4386 OptionalIdentifier :
4387 """
4388 pass
4389
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])
4396
4397 def p_ArgumentListEmpty(self, p):
4398 """
4399 ArgumentList :
4400 """
4401 p[0] = []
4402
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])
4409
4410 def p_ArgumentsEmpty(self, p):
4411 """
4412 Arguments :
4413 """
4414 p[0] = []
4415
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])
4423
4424 optional = p[2]
4425 variadic = p[4]
4426 defaultValue = p[6]
4427
4428 if not optional and defaultValue:
4429 raise WebIDLError("Mandatory arguments can't have a default value.",
4430 [self.getLocation(p, 6)])
4431
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.
4435
4436 if variadic:
4437 if optional:
4438 raise WebIDLError("Variadic arguments should not be marked optional.",
4439 [self.getLocation(p, 2)])
4440 optional = variadic
4441
4442 p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
4443 p[0].addExtendedAttributes(p[1])
4444
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]
4471
4472 def p_Optional(self, p):
4473 """
4474 Optional : OPTIONAL
4475 """
4476 p[0] = True
4477
4478 def p_OptionalEmpty(self, p):
4479 """
4480 Optional :
4481 """
4482 p[0] = False
4483
4484 def p_Ellipsis(self, p):
4485 """
4486 Ellipsis : ELLIPSIS
4487 """
4488 p[0] = True
4489
4490 def p_EllipsisEmpty(self, p):
4491 """
4492 Ellipsis :
4493 """
4494 p[0] = False
4495
4496 def p_ExceptionMember(self, p):
4497 """
4498 ExceptionMember : Const
4499 | ExceptionField
4500 """
4501 pass
4502
4503 def p_ExceptionField(self, p):
4504 """
4505 ExceptionField : Type IDENTIFIER SEMICOLON
4506 """
4507 pass
4508
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])
4516
4517 def p_ExtendedAttributeListEmpty(self, p):
4518 """
4519 ExtendedAttributeList :
4520 """
4521 p[0] = []
4522
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])
4531
4532 def p_ExtendedAttributeEmpty(self, p):
4533 """
4534 ExtendedAttribute :
4535 """
4536 pass
4537
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])
4544
4545 def p_ExtendedAttributesEmpty(self, p):
4546 """
4547 ExtendedAttributes :
4548 """
4549 p[0] = []
4550
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
4604
4605 def p_OtherOrComma(self, p):
4606 """
4607 OtherOrComma : Other
4608 | COMMA
4609 """
4610 pass
4611
4612 def p_TypeSingleType(self, p):
4613 """
4614 Type : SingleType
4615 """
4616 p[0] = p[1]
4617
4618 def p_TypeUnionType(self, p):
4619 """
4620 Type : UnionType TypeSuffix
4621 """
4622 p[0] = self.handleModifiers(p[1], p[2])
4623
4624 def p_SingleTypeNonAnyType(self, p):
4625 """
4626 SingleType : NonAnyType
4627 """
4628 p[0] = p[1]
4629
4630 def p_SingleTypeAnyType(self, p):
4631 """
4632 SingleType : ANY TypeSuffixStartingWithArray
4633 """
4634 p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.any], p[2])
4635
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)
4643
4644 def p_UnionMemberTypeNonAnyType(self, p):
4645 """
4646 UnionMemberType : NonAnyType
4647 """
4648 p[0] = p[1]
4649
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])
4656
4657 def p_UnionMemberType(self, p):
4658 """
4659 UnionMemberType : UnionType TypeSuffix
4660 | UnionMemberTypeArrayOfAny TypeSuffix
4661 """
4662 p[0] = self.handleModifiers(p[1], p[2])
4663
4664 def p_UnionMemberTypes(self, p):
4665 """
4666 UnionMemberTypes : OR UnionMemberType UnionMemberTypes
4667 """
4668 p[0] = [p[2]]
4669 p[0].extend(p[3])
4670
4671 def p_UnionMemberTypesEmpty(self, p):
4672 """
4673 UnionMemberTypes :
4674 """
4675 p[0] = []
4676
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]]
4689
4690 p[0] = self.handleModifiers(type, p[2])
4691
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
4701
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
4711
4712 def p_NonAnyTypeScopedName(self, p):
4713 """
4714 NonAnyType : ScopedName TypeSuffix
4715 """
4716 assert isinstance(p[1], IDLUnresolvedIdentifier)
4717
4718 type = None
4719
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
4731
4732 type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
4733 p[0] = self.handleModifiers(type, p[2])
4734
4735 def p_NonAnyTypeDate(self, p):
4736 """
4737 NonAnyType : DATE TypeSuffix
4738 """
4739 p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.date],
4740 p[2])
4741
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
4750
4751 def p_ConstTypeIdentifier(self, p):
4752 """
4753 ConstType : IDENTIFIER Null
4754 """
4755 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
4756
4757 type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
4758 if p[2]:
4759 type = IDLNullableType(self.getLocation(p, 1), type)
4760 p[0] = type
4761
4762 def p_PrimitiveOrStringTypeUint(self, p):
4763 """
4764 PrimitiveOrStringType : UnsignedIntegerType
4765 """
4766 p[0] = p[1]
4767
4768 def p_PrimitiveOrStringTypeBoolean(self, p):
4769 """
4770 PrimitiveOrStringType : BOOLEAN
4771 """
4772 p[0] = IDLBuiltinType.Types.boolean
4773
4774 def p_PrimitiveOrStringTypeByte(self, p):
4775 """
4776 PrimitiveOrStringType : BYTE
4777 """
4778 p[0] = IDLBuiltinType.Types.byte
4779
4780 def p_PrimitiveOrStringTypeOctet(self, p):
4781 """
4782 PrimitiveOrStringType : OCTET
4783 """
4784 p[0] = IDLBuiltinType.Types.octet
4785
4786 def p_PrimitiveOrStringTypeFloat(self, p):
4787 """
4788 PrimitiveOrStringType : FLOAT
4789 """
4790 p[0] = IDLBuiltinType.Types.float
4791
4792 def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
4793 """
4794 PrimitiveOrStringType : UNRESTRICTED FLOAT
4795 """
4796 p[0] = IDLBuiltinType.Types.unrestricted_float
4797
4798 def p_PrimitiveOrStringTypeDouble(self, p):
4799 """
4800 PrimitiveOrStringType : DOUBLE
4801 """
4802 p[0] = IDLBuiltinType.Types.double
4803
4804 def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
4805 """
4806 PrimitiveOrStringType : UNRESTRICTED DOUBLE
4807 """
4808 p[0] = IDLBuiltinType.Types.unrestricted_double
4809
4810 def p_PrimitiveOrStringTypeDOMString(self, p):
4811 """
4812 PrimitiveOrStringType : DOMSTRING
4813 """
4814 p[0] = IDLBuiltinType.Types.domstring
4815
4816 def p_PrimitiveOrStringTypeBytestring(self, p):
4817 """
4818 PrimitiveOrStringType : BYTESTRING
4819 """
4820 p[0] = IDLBuiltinType.Types.bytestring
4821
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.
4828
4829 def p_UnsignedIntegerType(self, p):
4830 """
4831 UnsignedIntegerType : IntegerType
4832 """
4833 p[0] = p[1]
4834
4835 def p_IntegerTypeShort(self, p):
4836 """
4837 IntegerType : SHORT
4838 """
4839 p[0] = IDLBuiltinType.Types.short
4840
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
4849
4850 def p_OptionalLong(self, p):
4851 """
4852 OptionalLong : LONG
4853 """
4854 p[0] = True
4855
4856 def p_OptionalLongEmpty(self, p):
4857 """
4858 OptionalLong :
4859 """
4860 p[0] = False
4861
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])
4868
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])
4875
4876 def p_TypeSuffixEmpty(self, p):
4877 """
4878 TypeSuffix :
4879 """
4880 p[0] = []
4881
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])
4888
4889 def p_TypeSuffixStartingWithArrayEmpty(self, p):
4890 """
4891 TypeSuffixStartingWithArray :
4892 """
4893 p[0] = []
4894
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
4904
4905 def p_ReturnTypeType(self, p):
4906 """
4907 ReturnType : Type
4908 """
4909 p[0] = p[1]
4910
4911 def p_ReturnTypeVoid(self, p):
4912 """
4913 ReturnType : VOID
4914 """
4915 p[0] = BuiltinTypes[IDLBuiltinType.Types.void]
4916
4917 def p_ScopedName(self, p):
4918 """
4919 ScopedName : AbsoluteScopedName
4920 | RelativeScopedName
4921 """
4922 p[0] = p[1]
4923
4924 def p_AbsoluteScopedName(self, p):
4925 """
4926 AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts
4927 """
4928 assert False
4929 pass
4930
4931 def p_RelativeScopedName(self, p):
4932 """
4933 RelativeScopedName : IDENTIFIER ScopedNameParts
4934 """
4935 assert not p[2] # Not implemented!
4936
4937 p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
4938
4939 def p_ScopedNameParts(self, p):
4940 """
4941 ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts
4942 """
4943 assert False
4944 pass
4945
4946 def p_ScopedNamePartsEmpty(self, p):
4947 """
4948 ScopedNameParts :
4949 """
4950 p[0] = None
4951
4952 def p_ExtendedAttributeNoArgs(self, p):
4953 """
4954 ExtendedAttributeNoArgs : IDENTIFIER
4955 """
4956 p[0] = (p[1],)
4957
4958 def p_ExtendedAttributeArgList(self, p):
4959 """
4960 ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN
4961 """
4962 p[0] = (p[1], p[3])
4963
4964 def p_ExtendedAttributeIdent(self, p):
4965 """
4966 ExtendedAttributeIdent : IDENTIFIER EQUALS STRING
4967 | IDENTIFIER EQUALS IDENTIFIER
4968 """
4969 p[0] = (p[1], p[3])
4970
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])
4976
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)])
4983
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 = []
4994
4995 self._filename = "<builtin>"
4996 self.lexer.input(Parser._builtins)
4997 self._filename = None
4998
4999 self.parser.parse(lexer=self.lexer,tracking=True)
5000
5001 def _installBuiltins(self, scope):
5002 assert isinstance(scope, IDLScope)
5003
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
5008
5009 typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name)
5010 typedef.resolve(scope)
5011
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
5017
5018 if modifier == IDLMethod.TypeSuffixModifier.QMark:
5019 type = IDLNullableType(modifierLocation, type)
5020 elif modifier == IDLMethod.TypeSuffixModifier.Brackets:
5021 type = IDLArrayType(modifierLocation, type)
5022
5023 return type
5024
5025 def parse(self, t, filename=None):
5026 self.lexer.input(t)
5027
5028 #for tok in iter(self.lexer.token, None):
5029 # print tok
5030
5031 self._filename = filename
5032 self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True))
5033 self._filename = None
5034
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())
5047
5048 # Do any post-finish validation we need to do
5049 for production in self._productions:
5050 production.validate()
5051
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
5060
5061 def reset(self):
5062 return Parser(lexer=self.lexer)
5063
5064 # Builtin IDL defined by WebIDL
5065 _builtins = """
5066 typedef unsigned long long DOMTimeStamp;
5067 """
5068
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()
5079
5080 if len(args) < 1:
5081 o.error(usageString)
5082
5083 fileList = args
5084 baseDir = os.getcwd()
5085
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
5102
5103 if __name__ == '__main__':
5104 main()

mercurial