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