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