2012-05-21 11:12:37 +00:00
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
2012-03-31 04:42:20 +00:00
""" A WebIDL parser. """
from ply import lex , yacc
import re
2012-08-24 18:51:45 +00:00
import os
import traceback
2013-04-18 16:58:01 +00:00
import math
2014-08-05 02:20:33 +00:00
from collections import defaultdict
2012-03-31 04:42:20 +00:00
# Machinery
def parseInt ( literal ) :
string = literal
sign = 0
base = 0
if string [ 0 ] == ' - ' :
sign = - 1
string = string [ 1 : ]
else :
sign = 1
if string [ 0 ] == ' 0 ' and len ( string ) > 1 :
if string [ 1 ] == ' x ' or string [ 1 ] == ' X ' :
base = 16
string = string [ 2 : ]
else :
base = 8
string = string [ 1 : ]
else :
base = 10
value = int ( string , base )
return value * sign
# Magic for creating enums
2012-10-19 07:34:28 +00:00
def M_add_class_attribs ( attribs , start ) :
2012-03-31 04:42:20 +00:00
def foo ( name , bases , dict_ ) :
2012-04-12 22:14:10 +00:00
for v , k in enumerate ( attribs ) :
2012-10-19 07:34:28 +00:00
dict_ [ k ] = start + v
2012-04-12 22:14:10 +00:00
assert ' length ' not in dict_
2012-10-19 07:34:28 +00:00
dict_ [ ' length ' ] = start + len ( attribs )
2012-03-31 04:42:20 +00:00
return type ( name , bases , dict_ )
return foo
2012-10-19 07:34:28 +00:00
def enum ( * names , * * kw ) :
if len ( kw ) == 1 :
base = kw [ ' base ' ] . __class__
start = base . length
else :
assert len ( kw ) == 0
base = object
start = 0
class Foo ( base ) :
__metaclass__ = M_add_class_attribs ( names , start )
2012-03-31 04:42:20 +00:00
def __setattr__ ( self , name , value ) : # this makes it read-only
raise NotImplementedError
return Foo ( )
class WebIDLError ( Exception ) :
2012-06-30 05:53:28 +00:00
def __init__ ( self , message , locations , warning = False ) :
2012-03-31 04:42:20 +00:00
self . message = message
2012-06-30 05:53:28 +00:00
self . locations = [ str ( loc ) for loc in locations ]
2012-03-31 04:42:20 +00:00
self . warning = warning
def __str__ ( self ) :
2012-06-30 05:53:28 +00:00
return " %s : %s %s %s " % ( self . warning and ' warning ' or ' error ' ,
2012-06-22 20:18:50 +00:00
self . message ,
2012-06-30 05:53:28 +00:00
" , " if len ( self . locations ) != 0 else " " ,
" \n " . join ( self . locations ) )
2012-03-31 04:42:20 +00:00
class Location ( object ) :
def __init__ ( self , lexer , lineno , lexpos , filename ) :
2012-04-12 22:14:10 +00:00
self . _line = None
2012-03-31 04:42:20 +00:00
self . _lineno = lineno
self . _lexpos = lexpos
self . _lexdata = lexer . lexdata
self . _file = filename if filename else " <unknown> "
def __eq__ ( self , other ) :
return self . _lexpos == other . _lexpos and \
self . _file == other . _file
2012-04-12 22:14:10 +00:00
def filename ( self ) :
return self . _file
2012-03-31 04:42:20 +00:00
def resolve ( self ) :
if self . _line :
return
startofline = self . _lexdata . rfind ( ' \n ' , 0 , self . _lexpos ) + 1
endofline = self . _lexdata . find ( ' \n ' , self . _lexpos , self . _lexpos + 80 )
2012-04-12 22:14:10 +00:00
if endofline != - 1 :
self . _line = self . _lexdata [ startofline : endofline ]
else :
self . _line = self . _lexdata [ startofline : ]
2012-03-31 04:42:20 +00:00
self . _colno = self . _lexpos - startofline
2012-06-05 01:30:03 +00:00
# Our line number seems to point to the start of self._lexdata
self . _lineno + = self . _lexdata . count ( ' \n ' , 0 , startofline )
2012-03-31 04:42:20 +00:00
def get ( self ) :
self . resolve ( )
return " %s line %s : %s " % ( self . _file , self . _lineno , self . _colno )
2012-04-12 22:14:10 +00:00
def _pointerline ( self ) :
return " " * self . _colno + " ^ "
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
self . resolve ( )
return " %s line %s : %s \n %s \n %s " % ( self . _file , self . _lineno , self . _colno ,
2012-04-12 22:14:10 +00:00
self . _line , self . _pointerline ( ) )
2012-03-31 04:42:20 +00:00
class BuiltinLocation ( object ) :
def __init__ ( self , text ) :
2012-06-30 05:53:28 +00:00
self . msg = text + " \n "
2012-03-31 04:42:20 +00:00
2012-04-12 22:14:10 +00:00
def __eq__ ( self , other ) :
return isinstance ( other , BuiltinLocation ) and \
self . msg == other . msg
def filename ( self ) :
return ' <builtin> '
def resolve ( self ) :
pass
2012-03-31 04:42:20 +00:00
def get ( self ) :
return self . msg
def __str__ ( self ) :
return self . get ( )
# Data Model
class IDLObject ( object ) :
def __init__ ( self , location ) :
self . location = location
self . userData = dict ( )
def filename ( self ) :
2012-04-12 22:14:10 +00:00
return self . location . filename ( )
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
return False
def isEnum ( self ) :
return False
def isCallback ( self ) :
return False
def isType ( self ) :
return False
2012-06-12 14:22:05 +00:00
def isDictionary ( self ) :
return False ;
2012-05-18 21:25:47 +00:00
def isUnion ( self ) :
return False
2012-03-31 04:42:20 +00:00
def getUserData ( self , key , default ) :
return self . userData . get ( key , default )
def setUserData ( self , key , value ) :
self . userData [ key ] = value
def addExtendedAttributes ( self , attrs ) :
assert False # Override me!
2012-09-12 16:24:58 +00:00
def handleExtendedAttribute ( self , attr ) :
2012-03-31 04:42:20 +00:00
assert False # Override me!
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
assert False # Override me!
def getDeps ( self , visited = None ) :
""" Return a set of files that this object depends on. If any of
these files are changed the parser needs to be rerun to regenerate
a new IDLObject .
The visited argument is a set of all the objects already visited .
We must test to see if we are in it , and if so , do nothing . This
prevents infinite recursion . """
# NB: We can't use visited=set() above because the default value is
# evaluated when the def statement is evaluated, not when the function
# is executed, so there would be one set for all invocations.
if visited == None :
visited = set ( )
if self in visited :
return set ( )
visited . add ( self )
deps = set ( )
if self . filename ( ) != " <builtin> " :
deps . add ( self . filename ( ) )
for d in self . _getDependentObjects ( ) :
2014-12-01 20:17:58 +00:00
deps . update ( d . getDeps ( visited ) )
2013-02-24 20:36:44 +00:00
return deps
2012-03-31 04:42:20 +00:00
class IDLScope ( IDLObject ) :
def __init__ ( self , location , parentScope , identifier ) :
IDLObject . __init__ ( self , location )
self . parentScope = parentScope
if identifier :
assert isinstance ( identifier , IDLIdentifier )
self . _name = identifier
else :
self . _name = None
self . _dict = { }
2014-08-05 02:20:33 +00:00
self . globalNames = set ( )
# A mapping from global name to the set of global interfaces
# that have that global name.
self . globalNameMapping = defaultdict ( set )
2014-08-05 02:20:34 +00:00
self . primaryGlobalAttr = None
self . primaryGlobalName = None
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
return self . QName ( )
def QName ( self ) :
if self . _name :
return self . _name . QName ( ) + " :: "
return " :: "
def ensureUnique ( self , identifier , object ) :
2012-04-12 22:14:10 +00:00
"""
Ensure that there is at most one ' identifier ' in scope ( ' self ' ) .
Note that object can be None . This occurs if we end up here for an
interface type we haven ' t seen yet.
"""
2012-03-31 04:42:20 +00:00
assert isinstance ( identifier , IDLUnresolvedIdentifier )
assert not object or isinstance ( object , IDLObjectWithIdentifier )
assert not object or object . identifier == identifier
if identifier . name in self . _dict :
if not object :
return
# ensureUnique twice with the same object is not allowed
2013-08-29 04:30:05 +00:00
assert id ( object ) != id ( self . _dict [ identifier . name ] )
2012-03-31 04:42:20 +00:00
replacement = self . resolveIdentifierConflict ( self , identifier ,
self . _dict [ identifier . name ] ,
object )
self . _dict [ identifier . name ] = replacement
return
assert object
self . _dict [ identifier . name ] = object
def resolveIdentifierConflict ( self , scope , identifier , originalObject , newObject ) :
if isinstance ( originalObject , IDLExternalInterface ) and \
isinstance ( newObject , IDLExternalInterface ) and \
originalObject . identifier . name == newObject . identifier . name :
return originalObject
2014-03-22 04:25:40 +00:00
if ( isinstance ( originalObject , IDLExternalInterface ) or
isinstance ( newObject , IDLExternalInterface ) ) :
raise WebIDLError (
" Name collision between "
" interface declarations for identifier ' %s ' at ' %s ' and ' %s ' "
% ( identifier . name ,
originalObject . location , newObject . location ) , [ ] )
2014-05-05 19:50:00 +00:00
if ( isinstance ( originalObject , IDLDictionary ) or
isinstance ( newObject , IDLDictionary ) ) :
raise WebIDLError (
" Name collision between dictionary declarations for "
" identifier ' %s ' . \n %s \n %s "
% ( identifier . name ,
originalObject . location , newObject . location ) , [ ] )
2013-01-22 10:51:15 +00:00
# We do the merging of overloads here as opposed to in IDLInterface
# because we need to merge overloads of NamedConstructors and we need to
# detect conflicts in those across interfaces. See also the comment in
# IDLInterface.addExtendedAttributes for "NamedConstructor".
if originalObject . tag == IDLInterfaceMember . Tags . Method and \
newObject . tag == IDLInterfaceMember . Tags . Method :
return originalObject . addOverload ( newObject )
2012-03-31 04:42:20 +00:00
# Default to throwing, derived classes can override.
conflictdesc = " \n \t %s at %s \n \t %s at %s " % \
( originalObject , originalObject . location , newObject , newObject . location )
raise WebIDLError (
" Multiple unresolvable definitions of identifier ' %s ' in scope ' %s %s "
2012-06-30 05:53:28 +00:00
% ( identifier . name , str ( self ) , conflictdesc ) , [ ] )
2012-03-31 04:42:20 +00:00
def _lookupIdentifier ( self , identifier ) :
return self . _dict [ identifier . name ]
def lookupIdentifier ( self , identifier ) :
assert isinstance ( identifier , IDLIdentifier )
assert identifier . scope == self
return self . _lookupIdentifier ( identifier )
class IDLIdentifier ( IDLObject ) :
def __init__ ( self , location , scope , name ) :
IDLObject . __init__ ( self , location )
self . name = name
assert isinstance ( scope , IDLScope )
self . scope = scope
def __str__ ( self ) :
return self . QName ( )
def QName ( self ) :
return self . scope . QName ( ) + self . name
def __hash__ ( self ) :
return self . QName ( ) . __hash__ ( )
def __eq__ ( self , other ) :
return self . QName ( ) == other . QName ( )
def object ( self ) :
return self . scope . lookupIdentifier ( self )
class IDLUnresolvedIdentifier ( IDLObject ) :
def __init__ ( self , location , name , allowDoubleUnderscore = False ,
allowForbidden = False ) :
IDLObject . __init__ ( self , location )
assert len ( name ) > 0
2014-01-26 12:35:10 +00:00
if name [ : 2 ] == " __ " and name != " __content " and name != " ___noSuchMethod__ " and not allowDoubleUnderscore :
2012-03-31 04:42:20 +00:00
raise WebIDLError ( " Identifiers beginning with __ are reserved " ,
2012-06-30 05:53:28 +00:00
[ location ] )
2012-03-31 04:42:20 +00:00
if name [ 0 ] == ' _ ' and not allowDoubleUnderscore :
name = name [ 1 : ]
2013-11-01 16:01:00 +00:00
# TODO: Bug 872377, Restore "toJSON" to below list.
# We sometimes need custom serialization, so allow toJSON for now.
if ( name in [ " constructor " , " toString " ] and
2013-07-29 16:39:18 +00:00
not allowForbidden ) :
2012-03-31 04:42:20 +00:00
raise WebIDLError ( " Cannot use reserved identifier ' %s ' " % ( name ) ,
2012-06-30 05:53:28 +00:00
[ location ] )
2012-03-31 04:42:20 +00:00
self . name = name
def __str__ ( self ) :
return self . QName ( )
def QName ( self ) :
return " <unresolved scope>:: " + self . name
def resolve ( self , scope , object ) :
assert isinstance ( scope , IDLScope )
assert not object or isinstance ( object , IDLObjectWithIdentifier )
assert not object or object . identifier == self
scope . ensureUnique ( self , object )
identifier = IDLIdentifier ( self . location , scope , self . name )
if object :
object . identifier = identifier
return identifier
2012-04-12 22:14:10 +00:00
def finish ( self ) :
assert False # Should replace with a resolved identifier first.
2012-03-31 04:42:20 +00:00
class IDLObjectWithIdentifier ( IDLObject ) :
def __init__ ( self , location , parentScope , identifier ) :
IDLObject . __init__ ( self , location )
assert isinstance ( identifier , IDLUnresolvedIdentifier )
self . identifier = identifier
if parentScope :
self . resolve ( parentScope )
2012-09-01 00:59:46 +00:00
self . treatNullAs = " Default "
2012-03-31 04:42:20 +00:00
def resolve ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
assert isinstance ( self . identifier , IDLUnresolvedIdentifier )
self . identifier . resolve ( parentScope , self )
2012-09-01 00:59:46 +00:00
def checkForStringHandlingExtendedAttributes ( self , attrs ,
isDictionaryMember = False ,
isOptional = False ) :
"""
2013-11-17 05:10:18 +00:00
A helper function to deal with TreatNullAs . Returns the list
2012-09-01 00:59:46 +00:00
of attrs it didn ' t handle itself.
"""
assert isinstance ( self , IDLArgument ) or isinstance ( self , IDLAttribute )
unhandledAttrs = list ( )
2012-09-12 16:24:58 +00:00
for attr in attrs :
if not attr . hasValue ( ) :
unhandledAttrs . append ( attr )
2012-09-01 00:59:46 +00:00
continue
2012-09-12 16:24:58 +00:00
identifier = attr . identifier ( )
value = attr . value ( )
if identifier == " TreatNullAs " :
2013-06-13 05:15:35 +00:00
if not self . type . isDOMString ( ) or self . type . nullable ( ) :
2012-09-01 00:59:46 +00:00
raise WebIDLError ( " [TreatNullAs] is only allowed on "
" arguments or attributes whose type is "
" DOMString " ,
[ self . location ] )
if isDictionaryMember :
raise WebIDLError ( " [TreatNullAs] is not allowed for "
" dictionary members " , [ self . location ] )
if value != ' EmptyString ' :
raise WebIDLError ( " [TreatNullAs] must take the identifier "
2012-09-12 16:24:58 +00:00
" ' EmptyString ' , not ' %s ' " % value ,
[ self . location ] )
2012-09-01 00:59:46 +00:00
self . treatNullAs = value
else :
2012-09-12 16:24:58 +00:00
unhandledAttrs . append ( attr )
2012-09-01 00:59:46 +00:00
return unhandledAttrs
2012-03-31 04:42:20 +00:00
class IDLObjectWithScope ( IDLObjectWithIdentifier , IDLScope ) :
def __init__ ( self , location , parentScope , identifier ) :
assert isinstance ( identifier , IDLUnresolvedIdentifier )
IDLObjectWithIdentifier . __init__ ( self , location , parentScope , identifier )
IDLScope . __init__ ( self , location , parentScope , self . identifier )
2012-06-12 14:22:05 +00:00
class IDLIdentifierPlaceholder ( IDLObjectWithIdentifier ) :
2012-03-31 04:42:20 +00:00
def __init__ ( self , location , identifier ) :
assert isinstance ( identifier , IDLUnresolvedIdentifier )
IDLObjectWithIdentifier . __init__ ( self , location , None , identifier )
def finish ( self , scope ) :
try :
scope . _lookupIdentifier ( self . identifier )
except :
2012-06-30 05:53:28 +00:00
raise WebIDLError ( " Unresolved type ' %s ' . " % self . identifier ,
[ self . location ] )
2012-03-31 04:42:20 +00:00
2012-06-12 14:22:05 +00:00
obj = self . identifier . resolve ( scope , None )
return scope . lookupIdentifier ( obj )
2012-03-31 04:42:20 +00:00
class IDLExternalInterface ( IDLObjectWithIdentifier ) :
def __init__ ( self , location , parentScope , identifier ) :
assert isinstance ( identifier , IDLUnresolvedIdentifier )
assert isinstance ( parentScope , IDLScope )
self . parent = None
IDLObjectWithIdentifier . __init__ ( self , location , parentScope , identifier )
IDLObjectWithIdentifier . resolve ( self , parentScope )
def finish ( self , scope ) :
pass
2012-06-22 20:18:50 +00:00
def validate ( self ) :
pass
2012-03-31 04:42:20 +00:00
def isExternal ( self ) :
return True
def isInterface ( self ) :
return True
2012-06-22 20:18:50 +00:00
def isConsequential ( self ) :
return False
2012-03-31 04:42:20 +00:00
def addExtendedAttributes ( self , attrs ) :
assert len ( attrs ) == 0
def resolve ( self , parentScope ) :
pass
2013-03-18 23:04:24 +00:00
def getJSImplementation ( self ) :
return None
def isJSImplemented ( self ) :
return False
2013-04-30 20:30:25 +00:00
def getNavigatorProperty ( self ) :
return None
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( )
2014-08-05 02:20:33 +00:00
class IDLPartialInterface ( IDLObject ) :
def __init__ ( self , location , name , members , nonPartialInterface ) :
assert isinstance ( name , IDLUnresolvedIdentifier )
IDLObject . __init__ ( self , location )
self . identifier = name
self . members = members
# propagatedExtendedAttrs are the ones that should get
# propagated to our non-partial interface.
self . propagatedExtendedAttrs = [ ]
self . _nonPartialInterface = nonPartialInterface
self . _finished = False
nonPartialInterface . addPartialInterface ( self )
def addExtendedAttributes ( self , attrs ) :
for attr in attrs :
identifier = attr . identifier ( )
if identifier in [ " Constructor " , " NamedConstructor " ] :
self . propagatedExtendedAttrs . append ( attr )
2014-08-05 02:20:34 +00:00
elif identifier == " Exposed " :
# This just gets propagated to all our members.
for member in self . members :
if len ( member . _exposureGlobalNames ) != 0 :
raise WebIDLError ( " [Exposed] specified on both a "
" partial interface member and on the "
" partial interface itself " ,
[ member . location , attr . location ] )
member . addExtendedAttributes ( [ attr ] )
2014-08-05 02:20:33 +00:00
else :
raise WebIDLError ( " Unknown extended attribute %s on partial "
" interface " % identifier ,
[ attr . location ] )
def finish ( self , scope ) :
if self . _finished :
return
self . _finished = True
# Need to make sure our non-partial interface gets finished so it can
# report cases when we only have partial interfaces.
self . _nonPartialInterface . finish ( scope )
def validate ( self ) :
pass
2014-08-05 02:20:34 +00:00
def convertExposedAttrToGlobalNameSet ( exposedAttr , targetSet ) :
assert len ( targetSet ) == 0
if exposedAttr . hasValue ( ) :
targetSet . add ( exposedAttr . value ( ) )
else :
assert exposedAttr . hasArgs ( )
targetSet . update ( exposedAttr . args ( ) )
def globalNameSetToExposureSet ( globalScope , nameSet , exposureSet ) :
for name in nameSet :
exposureSet . update ( globalScope . globalNameMapping [ name ] )
2012-03-31 04:42:20 +00:00
class IDLInterface ( IDLObjectWithScope ) :
2013-01-10 15:49:07 +00:00
def __init__ ( self , location , parentScope , name , parent , members ,
2014-08-05 02:20:33 +00:00
isKnownNonPartial ) :
2012-03-31 04:42:20 +00:00
assert isinstance ( parentScope , IDLScope )
assert isinstance ( name , IDLUnresolvedIdentifier )
2014-08-05 02:20:33 +00:00
assert isKnownNonPartial or not parent
assert isKnownNonPartial or len ( members ) == 0
2012-03-31 04:42:20 +00:00
2013-01-10 15:49:07 +00:00
self . parent = None
2012-03-31 04:42:20 +00:00
self . _callback = False
2012-04-12 22:14:10 +00:00
self . _finished = False
2013-01-10 15:49:07 +00:00
self . members = [ ]
2014-08-05 02:20:33 +00:00
self . _partialInterfaces = [ ]
self . _extendedAttrDict = { }
2013-06-13 05:12:33 +00:00
# namedConstructors needs deterministic ordering because bindings code
# outputs the constructs in the order that namedConstructors enumerates
# them.
self . namedConstructors = list ( )
2012-06-11 22:21:35 +00:00
self . implementedInterfaces = set ( )
2012-06-22 20:18:50 +00:00
self . _consequential = False
2014-08-05 02:20:33 +00:00
self . _isKnownNonPartial = False
2012-06-22 20:18:50 +00:00
# self.interfacesBasedOnSelf is the set of interfaces that inherit from
# self or have self as a consequential interface, including self itself.
# Used for distinguishability checking.
self . interfacesBasedOnSelf = set ( [ self ] )
2013-03-18 23:14:39 +00:00
# self.interfacesImplementingSelf is the set of interfaces that directly
# have self as a consequential interface
self . interfacesImplementingSelf = set ( )
2013-04-04 02:22:15 +00:00
self . _hasChildInterfaces = False
2013-09-25 18:38:30 +00:00
self . _isOnGlobalProtoChain = False
2013-11-26 01:59:38 +00:00
# Tracking of the number of reserved slots we need for our
# members and those of ancestor interfaces.
self . totalMembersInSlots = 0
2013-11-26 01:59:38 +00:00
# Tracking of the number of own own members we have in slots
self . _ownMembersInSlots = 0
2014-08-05 02:20:34 +00:00
# _exposureGlobalNames are the global names listed in our [Exposed]
# extended attribute. exposureSet is the exposure set as defined in the
# Web IDL spec: it contains interface names.
self . _exposureGlobalNames = set ( )
self . exposureSet = set ( )
2012-03-31 04:42:20 +00:00
IDLObjectWithScope . __init__ ( self , location , parentScope , name )
2014-08-05 02:20:33 +00:00
if isKnownNonPartial :
2013-01-10 15:49:07 +00:00
self . setNonPartial ( location , parent , members )
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
return " Interface ' %s ' " % self . identifier . name
def ctor ( self ) :
identifier = IDLUnresolvedIdentifier ( self . location , " constructor " ,
allowForbidden = True )
try :
return self . _lookupIdentifier ( identifier )
except :
return None
def resolveIdentifierConflict ( self , scope , identifier , originalObject , newObject ) :
assert isinstance ( scope , IDLScope )
assert isinstance ( originalObject , IDLInterfaceMember )
assert isinstance ( newObject , IDLInterfaceMember )
2013-01-22 10:51:15 +00:00
retval = IDLScope . resolveIdentifierConflict ( self , scope , identifier ,
originalObject , newObject )
2012-03-31 04:42:20 +00:00
# Might be a ctor, which isn't in self.members
if newObject in self . members :
self . members . remove ( newObject )
return retval
def finish ( self , scope ) :
2012-04-12 22:14:10 +00:00
if self . _finished :
2012-03-31 04:42:20 +00:00
return
self . _finished = True
2014-08-05 02:20:33 +00:00
if not self . _isKnownNonPartial :
2013-01-10 15:49:07 +00:00
raise WebIDLError ( " Interface %s does not have a non-partial "
" declaration " % self . identifier . name ,
[ self . location ] )
2014-08-05 02:20:34 +00:00
# Verify that our [Exposed] value, if any, makes sense.
for globalName in self . _exposureGlobalNames :
if globalName not in scope . globalNames :
raise WebIDLError ( " Unknown [Exposed] value %s " % globalName ,
[ self . location ] )
if len ( self . _exposureGlobalNames ) == 0 :
self . _exposureGlobalNames . add ( scope . primaryGlobalName )
globalNameSetToExposureSet ( scope , self . _exposureGlobalNames ,
self . exposureSet )
2014-08-05 02:20:33 +00:00
# Now go ahead and merge in our partial interfaces.
for partial in self . _partialInterfaces :
partial . finish ( scope )
self . addExtendedAttributes ( partial . propagatedExtendedAttrs )
self . members . extend ( partial . members )
2014-08-05 02:20:34 +00:00
# Now that we've merged in our partial interfaces, set the
# _exposureGlobalNames on any members that don't have it set yet. Note
# that any partial interfaces that had [Exposed] set have already set up
# _exposureGlobalNames on all the members coming from them, so this is
# just implementing the "members default to interface that defined them"
# and "partial interfaces default to interface they're a partial for"
# rules from the spec.
for m in self . members :
# If m, or the partial interface m came from, had [Exposed]
# specified, it already has a nonempty exposure global names set.
if len ( m . _exposureGlobalNames ) == 0 :
m . _exposureGlobalNames . update ( self . _exposureGlobalNames )
2012-06-12 14:22:05 +00:00
assert not self . parent or isinstance ( self . parent , IDLIdentifierPlaceholder )
2012-03-31 04:42:20 +00:00
parent = self . parent . finish ( scope ) if self . parent else None
2012-08-24 19:23:21 +00:00
if parent and isinstance ( parent , IDLExternalInterface ) :
raise WebIDLError ( " %s inherits from %s which does not have "
" a definition " %
( self . identifier . name ,
self . parent . identifier . name ) ,
[ self . location ] )
2012-03-31 04:42:20 +00:00
assert not parent or isinstance ( parent , IDLInterface )
self . parent = parent
assert iter ( self . members )
if self . parent :
self . parent . finish ( scope )
2013-04-04 02:22:15 +00:00
self . parent . _hasChildInterfaces = True
2013-11-26 01:59:38 +00:00
self . totalMembersInSlots = self . parent . totalMembersInSlots
2014-08-05 02:20:34 +00:00
# Interfaces with [Global] or [PrimaryGlobal] must not
# have anything inherit from them
if ( self . parent . getExtendedAttribute ( " Global " ) or
self . parent . getExtendedAttribute ( " PrimaryGlobal " ) ) :
2013-09-25 18:38:30 +00:00
# Note: This is not a self.parent.isOnGlobalProtoChain() check
# because ancestors of a [Global] interface can have other
# descendants.
raise WebIDLError ( " [Global] interface has another interface "
" inheriting from it " ,
[ self . location , self . parent . location ] )
2014-08-05 02:20:34 +00:00
# Make sure that we're not exposed in places where our parent is not
if not self . exposureSet . issubset ( self . parent . exposureSet ) :
raise WebIDLError ( " Interface %s is exposed in globals where its "
" parent interface %s is not exposed. " %
( self . identifier . name ,
self . parent . identifier . name ) ,
[ self . location , self . parent . location ] )
2012-06-11 22:21:35 +00:00
# Callbacks must not inherit from non-callbacks or inherit from
# anything that has consequential interfaces.
2012-06-22 20:18:50 +00:00
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
# XXXbz Can callbacks have consequential interfaces? Spec issue pending
2012-06-11 22:21:35 +00:00
if self . isCallback ( ) :
2012-06-22 20:18:50 +00:00
if not self . parent . isCallback ( ) :
raise WebIDLError ( " Callback interface %s inheriting from "
" non-callback interface %s " %
( self . identifier . name ,
self . parent . identifier . name ) ,
2012-06-30 05:53:28 +00:00
[ self . location , self . parent . location ] )
2012-06-22 20:18:51 +00:00
elif self . parent . isCallback ( ) :
raise WebIDLError ( " Non-callback interface %s inheriting from "
" callback interface %s " %
( self . identifier . name ,
self . parent . identifier . name ) ,
2012-06-30 05:53:28 +00:00
[ self . location , self . parent . location ] )
2012-06-11 22:21:35 +00:00
for iface in self . implementedInterfaces :
iface . finish ( scope )
2012-06-21 16:29:11 +00:00
cycleInGraph = self . findInterfaceLoopPoint ( self )
if cycleInGraph :
raise WebIDLError ( " Interface %s has itself as ancestor or "
" implemented interface " % self . identifier . name ,
2012-06-30 05:53:28 +00:00
[ self . location , cycleInGraph . location ] )
2012-06-21 16:29:11 +00:00
2012-06-22 20:18:51 +00:00
if self . isCallback ( ) :
# "implements" should have made sure we have no
# consequential interfaces.
assert len ( self . getConsequentialInterfaces ( ) ) == 0
# And that we're not consequential.
assert not self . isConsequential ( )
2012-06-11 22:21:35 +00:00
# Now resolve() and finish() our members before importing the
# ones from our implemented interfaces.
2012-03-31 04:42:20 +00:00
2012-06-11 22:21:35 +00:00
# resolve() will modify self.members, so we need to iterate
# over a copy of the member list here.
for member in list ( self . members ) :
member . resolve ( self )
2012-03-31 04:42:20 +00:00
2012-06-11 22:21:35 +00:00
for member in self . members :
member . finish ( scope )
2014-08-05 02:20:34 +00:00
# Now that we've finished our members, which has updated their exposure
# sets, make sure they aren't exposed in places where we are not.
for member in self . members :
if not member . exposureSet . issubset ( self . exposureSet ) :
raise WebIDLError ( " Interface member has larger exposure set "
" than the interface itself " ,
[ member . location , self . location ] )
2012-06-11 22:21:35 +00:00
ctor = self . ctor ( )
if ctor is not None :
ctor . finish ( scope )
2012-03-31 04:42:20 +00:00
2013-01-22 10:51:15 +00:00
for ctor in self . namedConstructors :
ctor . finish ( scope )
2012-12-14 19:10:50 +00:00
# Make a copy of our member list, so things that implement us
2012-06-11 22:21:35 +00:00
# can get those without all the stuff we implement ourselves
# admixed.
self . originalMembers = list ( self . members )
# Import everything from our consequential interfaces into
# self.members. Sort our consequential interfaces by name
# just so we have a consistent order.
for iface in sorted ( self . getConsequentialInterfaces ( ) ,
cmp = cmp ,
key = lambda x : x . identifier . name ) :
2012-06-22 20:18:50 +00:00
# Flag the interface as being someone's consequential interface
2012-06-22 20:18:50 +00:00
iface . setIsConsequentialInterfaceOf ( self )
2014-08-05 02:20:34 +00:00
# Verify that we're not exposed somewhere where iface is not exposed
if not self . exposureSet . issubset ( iface . exposureSet ) :
raise WebIDLError ( " Interface %s is exposed in globals where its "
" consequential interface %s is not exposed. " %
( self . identifier . name , iface . identifier . name ) ,
[ self . location , iface . location ] )
2012-06-11 22:21:35 +00:00
additionalMembers = iface . originalMembers ;
for additionalMember in additionalMembers :
for member in self . members :
if additionalMember . identifier . name == member . identifier . name :
raise WebIDLError (
" Multiple definitions of %s on %s coming from ' implements ' statements " %
( member . identifier . name , self ) ,
2012-06-30 05:53:28 +00:00
[ additionalMember . location , member . location ] )
2012-06-11 22:21:35 +00:00
self . members . extend ( additionalMembers )
2013-03-18 23:14:39 +00:00
iface . interfacesImplementingSelf . add ( self )
2012-03-31 04:42:20 +00:00
2012-06-22 20:18:50 +00:00
for ancestor in self . getInheritedInterfaces ( ) :
ancestor . interfacesBasedOnSelf . add ( self )
for ancestorConsequential in ancestor . getConsequentialInterfaces ( ) :
ancestorConsequential . interfacesBasedOnSelf . add ( self )
2014-07-11 23:30:26 +00:00
# Deal with interfaces marked [Unforgeable], now that we have our full
# member list, except unforgeables pulled in from parents. We want to
# do this before we set "originatingInterface" on our unforgeable
# members.
if self . getExtendedAttribute ( " Unforgeable " ) :
# Check that the interface already has all the things the
# spec would otherwise require us to synthesize and is
# missing the ones we plan to synthesize.
if not any ( m . isMethod ( ) and m . isStringifier ( ) for m in self . members ) :
raise WebIDLError ( " Unforgeable interface %s does not have a "
" stringifier " % self . identifier . name ,
[ self . location ] )
for m in self . members :
if ( ( m . isMethod ( ) and m . isJsonifier ( ) ) or
m . identifier . name == " toJSON " ) :
raise WebIDLError ( " Unforgeable interface %s has a "
" jsonifier so we won ' t be able to add "
" one ourselves " % self . identifier . name ,
[ self . location , m . location ] )
if m . identifier . name == " valueOf " and not m . isStatic ( ) :
raise WebIDLError ( " Unforgeable interface %s has a valueOf "
" member so we won ' t be able to add one "
" ourselves " % self . identifier . name ,
[ self . location , m . location ] )
2013-09-28 10:27:29 +00:00
for member in self . members :
2014-07-11 23:30:26 +00:00
if ( ( member . isAttr ( ) or member . isMethod ( ) ) and
member . isUnforgeable ( ) and
2013-09-28 10:27:29 +00:00
not hasattr ( member , " originatingInterface " ) ) :
member . originatingInterface = self
2013-11-26 01:59:38 +00:00
# Compute slot indices for our members before we pull in
# unforgeable members from our parent.
for member in self . members :
2013-12-04 13:02:17 +00:00
if ( member . isAttr ( ) and
( member . getExtendedAttribute ( " StoreInSlot " ) or
member . getExtendedAttribute ( " Cached " ) ) ) :
2013-11-26 01:59:38 +00:00
member . slotIndex = self . totalMembersInSlots
self . totalMembersInSlots + = 1
2013-12-04 13:02:17 +00:00
if member . getExtendedAttribute ( " StoreInSlot " ) :
self . _ownMembersInSlots + = 1
2013-11-26 01:59:38 +00:00
2012-12-14 19:10:50 +00:00
if self . parent :
# Make sure we don't shadow any of the [Unforgeable] attributes on
# our ancestor interfaces. We don't have to worry about
# consequential interfaces here, because those have already been
# imported into the relevant .members lists. And we don't have to
# worry about anything other than our parent, because it has already
# imported its ancestors unforgeable attributes into its member
# list.
2014-07-11 23:30:26 +00:00
for unforgeableMember in ( member for member in self . parent . members if
( member . isAttr ( ) or member . isMethod ( ) ) and
member . isUnforgeable ( ) ) :
2012-12-14 19:10:50 +00:00
shadows = [ m for m in self . members if
( m . isAttr ( ) or m . isMethod ( ) ) and
not m . isStatic ( ) and
2014-07-11 23:30:26 +00:00
m . identifier . name == unforgeableMember . identifier . name ]
2012-12-14 19:10:50 +00:00
if len ( shadows ) != 0 :
2014-07-11 23:30:26 +00:00
locs = [ unforgeableMember . location ] + [ s . location for s
in shadows ]
2012-12-14 19:10:50 +00:00
raise WebIDLError ( " Interface %s shadows [Unforgeable] "
" members of %s " %
( self . identifier . name ,
ancestor . identifier . name ) ,
locs )
# And now just stick it in our members, since we won't be
# inheriting this down the proto chain. If we really cared we
# could try to do something where we set up the unforgeable
2014-07-11 23:30:26 +00:00
# attributes/methods of ancestor interfaces, with their
# corresponding getters, on our interface, but that gets pretty
# complicated and seems unnecessary.
self . members . append ( unforgeableMember )
2012-12-14 19:10:50 +00:00
2012-04-12 22:14:10 +00:00
# Ensure that there's at most one of each {named,indexed}
2013-03-04 19:08:24 +00:00
# {getter,setter,creator,deleter}, at most one stringifier,
# and at most one legacycaller. Note that this last is not
# quite per spec, but in practice no one overloads
# legacycallers.
2012-11-05 19:40:32 +00:00
specialMembersSeen = { }
2012-06-11 22:21:35 +00:00
for member in self . members :
2012-08-13 12:20:49 +00:00
if not member . isMethod ( ) :
2012-04-12 22:14:10 +00:00
continue
if member . isGetter ( ) :
memberType = " getters "
elif member . isSetter ( ) :
memberType = " setters "
elif member . isCreator ( ) :
memberType = " creators "
elif member . isDeleter ( ) :
memberType = " deleters "
2012-11-05 19:40:32 +00:00
elif member . isStringifier ( ) :
memberType = " stringifiers "
2013-07-26 16:00:49 +00:00
elif member . isJsonifier ( ) :
memberType = " jsonifiers "
2013-03-04 19:08:24 +00:00
elif member . isLegacycaller ( ) :
memberType = " legacycallers "
2012-04-12 22:14:10 +00:00
else :
continue
2013-07-26 16:00:49 +00:00
if ( memberType != " stringifiers " and memberType != " legacycallers " and
memberType != " jsonifiers " ) :
2012-11-05 19:40:32 +00:00
if member . isNamed ( ) :
memberType = " named " + memberType
else :
assert member . isIndexed ( )
memberType = " indexed " + memberType
2012-04-12 22:14:10 +00:00
if memberType in specialMembersSeen :
raise WebIDLError ( " Multiple " + memberType + " on %s " % ( self ) ,
2012-11-05 19:40:32 +00:00
[ self . location ,
specialMembersSeen [ memberType ] . location ,
member . location ] )
2012-04-12 22:14:10 +00:00
2012-11-05 19:40:32 +00:00
specialMembersSeen [ memberType ] = member
2012-03-31 04:42:20 +00:00
2013-09-25 18:38:30 +00:00
if self . _isOnGlobalProtoChain :
# Make sure we have no named setters, creators, or deleters
for memberType in [ " setter " , " creator " , " deleter " ] :
memberId = " named " + memberType + " s "
if memberId in specialMembersSeen :
raise WebIDLError ( " Interface with [Global] has a named %s " %
memberType ,
[ self . location ,
specialMembersSeen [ memberId ] . location ] )
# Make sure we're not [OverrideBuiltins]
if self . getExtendedAttribute ( " OverrideBuiltins " ) :
raise WebIDLError ( " Interface with [Global] also has "
" [OverrideBuiltins] " ,
[ self . location ] )
# Mark all of our ancestors as being on the global's proto chain too
parent = self . parent
while parent :
# Must not inherit from an interface with [OverrideBuiltins]
if parent . getExtendedAttribute ( " OverrideBuiltins " ) :
raise WebIDLError ( " Interface with [Global] inherits from "
" interface with [OverrideBuiltins] " ,
[ self . location , parent . location ] )
parent . _isOnGlobalProtoChain = True
parent = parent . parent
2012-06-22 20:18:50 +00:00
def validate ( self ) :
2014-07-11 23:30:26 +00:00
# We don't support consequential unforgeable interfaces. Need to check
# this here, becaue in finish() an interface might not know yet that
# it's consequential.
if self . getExtendedAttribute ( " Unforgeable " ) and self . isConsequential ( ) :
raise WebIDLError (
" %s is an unforgeable consequential interface " %
self . identifier . name ,
[ self . location ] +
list ( i . location for i in
( self . interfacesBasedOnSelf - { self } ) ) )
# We also don't support inheriting from unforgeable interfaces.
if self . getExtendedAttribute ( " Unforgeable " ) and self . hasChildInterfaces ( ) :
raise WebIDLError ( " %s is an unforgeable ancestor interface " %
self . identifier . name ,
[ self . location ] +
list ( i . location for i in
self . interfacesBasedOnSelf if i . parent == self ) )
2012-06-22 20:18:50 +00:00
for member in self . members :
member . validate ( )
2014-08-20 15:31:39 +00:00
if self . isCallback ( ) and member . getExtendedAttribute ( " Replaceable " ) :
raise WebIDLError ( " [Replaceable] used on an attribute on "
" interface %s which is a callback interface " %
self . identifier . name ,
[ self . location , member . location ] )
2012-08-13 12:20:49 +00:00
# Check that PutForwards refers to another attribute and that no
# cycles exist in forwarded assignments.
if member . isAttr ( ) :
iface = self
attr = member
putForwards = attr . getExtendedAttribute ( " PutForwards " )
if putForwards and self . isCallback ( ) :
raise WebIDLError ( " [PutForwards] used on an attribute "
" on interface %s which is a callback "
" interface " % self . identifier . name ,
[ self . location , member . location ] )
while putForwards is not None :
forwardIface = attr . type . unroll ( ) . inner
fowardAttr = None
for forwardedMember in forwardIface . members :
if ( not forwardedMember . isAttr ( ) or
forwardedMember . identifier . name != putForwards [ 0 ] ) :
continue
if forwardedMember == member :
raise WebIDLError ( " Cycle detected in forwarded "
" assignments for attribute %s on "
" %s " %
( member . identifier . name , self ) ,
[ member . location ] )
fowardAttr = forwardedMember
break
if fowardAttr is None :
raise WebIDLError ( " Attribute %s on %s forwards to "
" missing attribute %s " %
( attr . identifier . name , iface , putForwards ) ,
[ attr . location ] )
iface = forwardIface
attr = fowardAttr
putForwards = attr . getExtendedAttribute ( " PutForwards " )
2014-08-05 02:20:35 +00:00
if ( self . getExtendedAttribute ( " Pref " ) and
self . _exposureGlobalNames != set ( [ self . parentScope . primaryGlobalName ] ) ) :
2014-08-25 19:07:44 +00:00
raise WebIDLError ( " [Pref] used on an interface that is not %s -only " %
self . parentScope . primaryGlobalName ,
[ self . location ] )
if ( self . getExtendedAttribute ( " CheckPermissions " ) and
self . _exposureGlobalNames != set ( [ self . parentScope . primaryGlobalName ] ) ) :
raise WebIDLError ( " [CheckPermissions] used on an interface that is "
" not %s -only " %
2014-08-05 02:20:35 +00:00
self . parentScope . primaryGlobalName ,
[ self . location ] )
2014-08-29 23:50:04 +00:00
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
if ( self . isExposedConditionally ( ) and
not self . hasInterfaceObject ( ) and
not self . getNavigatorProperty ( ) ) :
raise WebIDLError ( " Interface with no interface object is "
" exposed conditionally " ,
[ self . location ] )
2012-08-13 12:20:49 +00:00
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
return True
def isExternal ( self ) :
return False
2012-06-22 20:18:50 +00:00
def setIsConsequentialInterfaceOf ( self , other ) :
2012-06-22 20:18:50 +00:00
self . _consequential = True
2012-06-22 20:18:50 +00:00
self . interfacesBasedOnSelf . add ( other )
2012-06-22 20:18:50 +00:00
def isConsequential ( self ) :
return self . _consequential
2012-03-31 04:42:20 +00:00
def setCallback ( self , value ) :
self . _callback = value
def isCallback ( self ) :
return self . _callback
2013-01-28 13:34:30 +00:00
def isSingleOperationInterface ( self ) :
2013-03-18 23:05:51 +00:00
assert self . isCallback ( ) or self . isJSImplemented ( )
2013-01-28 13:34:30 +00:00
return (
2013-09-24 03:11:45 +00:00
# JS-implemented things should never need the
# this-handling weirdness of single-operation interfaces.
not self . isJSImplemented ( ) and
2013-01-28 13:34:30 +00:00
# Not inheriting from another interface
not self . parent and
# No consequential interfaces
len ( self . getConsequentialInterfaces ( ) ) == 0 and
# No attributes of any kinds
not any ( m . isAttr ( ) for m in self . members ) and
# There is at least one regular operation, and all regular
# operations have the same identifier
len ( set ( m . identifier . name for m in self . members if
m . isMethod ( ) and not m . isStatic ( ) ) ) == 1 )
2014-08-27 17:17:36 +00:00
def isExposedInWindow ( self ) :
return ' Window ' in self . exposureSet
def isExposedInAnyWorker ( self ) :
return len ( self . getWorkerExposureSet ( ) ) > 0
2014-10-17 15:30:18 +00:00
def isExposedInSystemGlobals ( self ) :
return ' BackstagePass ' in self . exposureSet
2014-11-16 20:01:32 +00:00
def isExposedInSomeButNotAllWorkers ( self ) :
"""
Returns true if the Exposed extended attribute for this interface
exposes it in some worker globals but not others . The return value does
not depend on whether the interface is exposed in Window or System
globals .
"""
if not self . isExposedInAnyWorker ( ) :
return False
2014-08-27 17:17:36 +00:00
workerScopes = self . parentScope . globalNameMapping [ " Worker " ]
return len ( workerScopes . difference ( self . exposureSet ) ) > 0
def getWorkerExposureSet ( self ) :
workerScopes = self . parentScope . globalNameMapping [ " Worker " ]
return workerScopes . intersection ( self . exposureSet )
2012-03-31 04:42:20 +00:00
def inheritanceDepth ( self ) :
depth = 0
parent = self . parent
while parent :
depth = depth + 1
parent = parent . parent
return depth
def hasConstants ( self ) :
2012-04-12 22:14:10 +00:00
return any ( m . isConst ( ) for m in self . members )
2012-03-31 04:42:20 +00:00
def hasInterfaceObject ( self ) :
if self . isCallback ( ) :
return self . hasConstants ( )
return not hasattr ( self , " _noInterfaceObject " )
def hasInterfacePrototypeObject ( self ) :
2012-07-19 18:48:58 +00:00
return not self . isCallback ( ) and self . getUserData ( ' hasConcreteDescendant ' , False )
2012-03-31 04:42:20 +00:00
def addExtendedAttributes ( self , attrs ) :
for attr in attrs :
2012-09-12 16:24:58 +00:00
identifier = attr . identifier ( )
2012-03-31 04:42:20 +00:00
# Special cased attrs
if identifier == " TreatNonCallableAsNull " :
raise WebIDLError ( " TreatNonCallableAsNull cannot be specified on interfaces " ,
2012-09-12 16:24:58 +00:00
[ attr . location , self . location ] )
2014-01-13 20:08:56 +00:00
if identifier == " TreatNonObjectAsNull " :
raise WebIDLError ( " TreatNonObjectAsNull cannot be specified on interfaces " ,
[ attr . location , self . location ] )
2012-03-31 04:42:20 +00:00
elif identifier == " NoInterfaceObject " :
2012-09-12 16:24:58 +00:00
if not attr . noArguments ( ) :
raise WebIDLError ( " [NoInterfaceObject] must take no arguments " ,
[ attr . location ] )
2012-03-31 04:42:20 +00:00
if self . ctor ( ) :
raise WebIDLError ( " Constructor and NoInterfaceObject are incompatible " ,
2012-06-30 05:53:28 +00:00
[ self . location ] )
2012-03-31 04:42:20 +00:00
self . _noInterfaceObject = True
2013-08-12 14:45:33 +00:00
elif identifier == " Constructor " or identifier == " NamedConstructor " or identifier == " ChromeConstructor " :
2013-04-23 01:05:25 +00:00
if identifier == " Constructor " and not self . hasInterfaceObject ( ) :
2013-01-22 10:51:15 +00:00
raise WebIDLError ( str ( identifier ) + " and NoInterfaceObject are incompatible " ,
2012-06-30 05:53:28 +00:00
[ self . location ] )
2012-03-31 04:42:20 +00:00
2013-01-22 10:51:15 +00:00
if identifier == " NamedConstructor " and not attr . hasValue ( ) :
raise WebIDLError ( " NamedConstructor must either take an identifier or take a named argument list " ,
[ attr . location ] )
2013-08-12 14:45:33 +00:00
if identifier == " ChromeConstructor " and not self . hasInterfaceObject ( ) :
raise WebIDLError ( str ( identifier ) + " and NoInterfaceObject are incompatible " ,
[ self . location ] )
2012-09-12 16:24:58 +00:00
args = attr . args ( ) if attr . hasArgs ( ) else [ ]
2012-03-31 04:42:20 +00:00
retType = IDLWrapperType ( self . location , self )
2014-05-05 19:24:00 +00:00
2013-08-12 14:45:33 +00:00
if identifier == " Constructor " or identifier == " ChromeConstructor " :
2013-01-22 10:51:15 +00:00
name = " constructor "
allowForbidden = True
else :
name = attr . value ( )
allowForbidden = False
methodIdentifier = IDLUnresolvedIdentifier ( self . location , name ,
allowForbidden = allowForbidden )
2012-03-31 04:42:20 +00:00
2013-01-22 10:51:15 +00:00
method = IDLMethod ( self . location , methodIdentifier , retType ,
args , static = True )
2013-09-30 16:32:22 +00:00
# Constructors are always NewObject and are always
2012-09-05 13:21:33 +00:00
# assumed to be able to throw (since there's no way to
# indicate otherwise) and never have any other
# extended attributes.
2012-09-12 16:24:58 +00:00
method . addExtendedAttributes (
2013-09-30 16:32:22 +00:00
[ IDLExtendedAttribute ( self . location , ( " NewObject " , ) ) ,
2012-09-12 16:24:58 +00:00
IDLExtendedAttribute ( self . location , ( " Throws " , ) ) ] )
2013-08-12 14:45:33 +00:00
if identifier == " ChromeConstructor " :
method . addExtendedAttributes (
[ IDLExtendedAttribute ( self . location , ( " ChromeOnly " , ) ) ] )
2013-01-22 10:51:15 +00:00
2013-08-12 14:45:33 +00:00
if identifier == " Constructor " or identifier == " ChromeConstructor " :
2013-01-22 10:51:15 +00:00
method . resolve ( self )
else :
# We need to detect conflicts for NamedConstructors across
# interfaces. We first call resolve on the parentScope,
# which will merge all NamedConstructors with the same
# identifier accross interfaces as overloads.
method . resolve ( self . parentScope )
# Then we look up the identifier on the parentScope. If the
# result is the same as the method we're adding then it
# hasn't been added as an overload and it's the first time
# we've encountered a NamedConstructor with that identifier.
# If the result is not the same as the method we're adding
# then it has been added as an overload and we need to check
# whether the result is actually one of our existing
# NamedConstructors.
newMethod = self . parentScope . lookupIdentifier ( method . identifier )
if newMethod == method :
2013-06-13 05:12:33 +00:00
self . namedConstructors . append ( method )
2013-01-22 10:51:15 +00:00
elif not newMethod in self . namedConstructors :
raise WebIDLError ( " NamedConstructor conflicts with a NamedConstructor of a different interface " ,
[ method . location , newMethod . location ] )
2013-07-31 05:28:30 +00:00
elif ( identifier == " ArrayClass " ) :
if not attr . noArguments ( ) :
raise WebIDLError ( " [ArrayClass] must take no arguments " ,
[ attr . location ] )
if self . parent :
raise WebIDLError ( " [ArrayClass] must not be specified on "
" an interface with inherited interfaces " ,
[ attr . location , self . location ] )
2014-05-05 20:01:57 +00:00
elif ( identifier == " ExceptionClass " ) :
if not attr . noArguments ( ) :
raise WebIDLError ( " [ExceptionClass] must take no arguments " ,
[ attr . location ] )
if self . parent :
raise WebIDLError ( " [ExceptionClass] must not be specified on "
" an interface with inherited interfaces " ,
[ attr . location , self . location ] )
2013-09-25 18:38:30 +00:00
elif identifier == " Global " :
2014-08-05 02:20:33 +00:00
if attr . hasValue ( ) :
self . globalNames = [ attr . value ( ) ]
elif attr . hasArgs ( ) :
self . globalNames = attr . args ( )
else :
self . globalNames = [ self . identifier . name ]
2014-08-05 02:20:33 +00:00
self . parentScope . globalNames . update ( self . globalNames )
for globalName in self . globalNames :
self . parentScope . globalNameMapping [ globalName ] . add ( self . identifier . name )
2013-09-25 18:38:30 +00:00
self . _isOnGlobalProtoChain = True
2014-08-05 02:20:34 +00:00
elif identifier == " PrimaryGlobal " :
if not attr . noArguments ( ) :
raise WebIDLError ( " [PrimaryGlobal] must take no arguments " ,
[ attr . location ] )
if self . parentScope . primaryGlobalAttr is not None :
raise WebIDLError (
" [PrimaryGlobal] specified twice " ,
[ attr . location ,
self . parentScope . primaryGlobalAttr . location ] )
self . parentScope . primaryGlobalAttr = attr
self . parentScope . primaryGlobalName = self . identifier . name
self . parentScope . globalNames . add ( self . identifier . name )
self . parentScope . globalNameMapping [ self . identifier . name ] . add ( self . identifier . name )
self . _isOnGlobalProtoChain = True
2014-11-08 00:07:12 +00:00
elif ( identifier == " NeedResolve " or
2013-06-13 05:12:37 +00:00
identifier == " OverrideBuiltins " or
2014-06-30 23:00:31 +00:00
identifier == " ChromeOnly " or
2014-07-11 23:30:26 +00:00
identifier == " Unforgeable " or
2014-08-20 23:32:19 +00:00
identifier == " UnsafeInPrerendering " or
2014-07-24 19:57:02 +00:00
identifier == " LegacyEventInit " ) :
2013-07-31 05:28:30 +00:00
# Known extended attributes that do not take values
if not attr . noArguments ( ) :
raise WebIDLError ( " [ %s ] must take no arguments " % identifier ,
[ attr . location ] )
2014-08-05 02:20:34 +00:00
elif identifier == " Exposed " :
convertExposedAttrToGlobalNameSet ( attr ,
self . _exposureGlobalNames )
2013-07-31 05:28:30 +00:00
elif ( identifier == " Pref " or
identifier == " JSImplementation " or
identifier == " HeaderFile " or
2013-08-04 03:38:55 +00:00
identifier == " NavigatorProperty " or
2014-02-05 18:38:17 +00:00
identifier == " AvailableIn " or
2014-05-25 18:31:07 +00:00
identifier == " Func " or
identifier == " CheckPermissions " ) :
2013-07-31 05:28:30 +00:00
# Known extended attributes that take a string value
if not attr . hasValue ( ) :
raise WebIDLError ( " [ %s ] must have a value " % identifier ,
[ attr . location ] )
2013-04-10 17:49:06 +00:00
else :
2013-04-30 20:30:25 +00:00
raise WebIDLError ( " Unknown extended attribute %s on interface " % identifier ,
2013-04-10 17:49:06 +00:00
[ attr . location ] )
2012-03-31 04:42:20 +00:00
2012-09-12 16:24:58 +00:00
attrlist = attr . listValue ( )
2012-03-31 04:42:20 +00:00
self . _extendedAttrDict [ identifier ] = attrlist if len ( attrlist ) else True
2012-06-11 22:21:35 +00:00
def addImplementedInterface ( self , implementedInterface ) :
assert ( isinstance ( implementedInterface , IDLInterface ) )
self . implementedInterfaces . add ( implementedInterface )
def getInheritedInterfaces ( self ) :
"""
Returns a list of the interfaces this interface inherits from
( not including this interface itself ) . The list is in order
from most derived to least derived .
"""
assert ( self . _finished )
if not self . parent :
return [ ]
parentInterfaces = self . parent . getInheritedInterfaces ( )
parentInterfaces . insert ( 0 , self . parent )
return parentInterfaces
def getConsequentialInterfaces ( self ) :
assert ( self . _finished )
# The interfaces we implement directly
consequentialInterfaces = set ( self . implementedInterfaces )
# And their inherited interfaces
for iface in self . implementedInterfaces :
consequentialInterfaces | = set ( iface . getInheritedInterfaces ( ) )
# And now collect up the consequential interfaces of all of those
temp = set ( )
for iface in consequentialInterfaces :
temp | = iface . getConsequentialInterfaces ( )
return consequentialInterfaces | temp
2012-06-21 16:29:11 +00:00
def findInterfaceLoopPoint ( self , otherInterface ) :
"""
Finds an interface , amongst our ancestors and consequential interfaces ,
that inherits from otherInterface or implements otherInterface
directly . If there is no such interface , returns None .
"""
if self . parent :
if self . parent == otherInterface :
return self
loopPoint = self . parent . findInterfaceLoopPoint ( otherInterface )
if loopPoint :
return loopPoint
if otherInterface in self . implementedInterfaces :
return self
for iface in self . implementedInterfaces :
loopPoint = iface . findInterfaceLoopPoint ( otherInterface )
if loopPoint :
return loopPoint
return None
2012-09-05 17:37:28 +00:00
def getExtendedAttribute ( self , name ) :
return self . _extendedAttrDict . get ( name , None )
2013-01-10 15:49:07 +00:00
def setNonPartial ( self , location , parent , members ) :
assert not parent or isinstance ( parent , IDLIdentifierPlaceholder )
2014-08-05 02:20:33 +00:00
if self . _isKnownNonPartial :
2013-01-10 15:49:07 +00:00
raise WebIDLError ( " Two non-partial definitions for the "
" same interface " ,
[ location , self . location ] )
2014-08-05 02:20:33 +00:00
self . _isKnownNonPartial = True
2013-01-10 15:49:07 +00:00
# Now make it look like we were parsed at this new location, since
# that's the place where the interface is "really" defined
self . location = location
assert not self . parent
self . parent = parent
# Put the new members at the beginning
self . members = members + self . members
2014-08-05 02:20:33 +00:00
def addPartialInterface ( self , partial ) :
assert self . identifier . name == partial . identifier . name
self . _partialInterfaces . append ( partial )
2013-03-18 23:04:24 +00:00
def getJSImplementation ( self ) :
classId = self . getExtendedAttribute ( " JSImplementation " )
if not classId :
return classId
assert isinstance ( classId , list )
assert len ( classId ) == 1
return classId [ 0 ]
def isJSImplemented ( self ) :
return bool ( self . getJSImplementation ( ) )
2013-04-30 20:30:25 +00:00
def getNavigatorProperty ( self ) :
naviProp = self . getExtendedAttribute ( " NavigatorProperty " )
if not naviProp :
return None
assert len ( naviProp ) == 1
assert isinstance ( naviProp , list )
assert len ( naviProp [ 0 ] ) != 0
return naviProp [ 0 ]
2013-04-04 02:22:15 +00:00
def hasChildInterfaces ( self ) :
return self . _hasChildInterfaces
2013-09-25 18:38:30 +00:00
def isOnGlobalProtoChain ( self ) :
return self . _isOnGlobalProtoChain
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
deps = set ( self . members )
2014-12-01 20:17:58 +00:00
deps . update ( self . implementedInterfaces )
2013-02-24 20:36:44 +00:00
if self . parent :
deps . add ( self . parent )
return deps
2013-11-26 01:59:38 +00:00
def hasMembersInSlots ( self ) :
return self . _ownMembersInSlots != 0
2014-08-29 23:50:04 +00:00
def isExposedConditionally ( self ) :
return ( self . getExtendedAttribute ( " Pref " ) or
self . getExtendedAttribute ( " ChromeOnly " ) or
self . getExtendedAttribute ( " Func " ) or
self . getExtendedAttribute ( " AvailableIn " ) or
self . getExtendedAttribute ( " CheckPermissions " ) )
2012-06-12 14:22:05 +00:00
class IDLDictionary ( IDLObjectWithScope ) :
def __init__ ( self , location , parentScope , name , parent , members ) :
assert isinstance ( parentScope , IDLScope )
assert isinstance ( name , IDLUnresolvedIdentifier )
assert not parent or isinstance ( parent , IDLIdentifierPlaceholder )
self . parent = parent
self . _finished = False
self . members = list ( members )
IDLObjectWithScope . __init__ ( self , location , parentScope , name )
def __str__ ( self ) :
return " Dictionary ' %s ' " % self . identifier . name
2012-06-12 14:22:05 +00:00
def isDictionary ( self ) :
return True ;
2012-06-12 14:22:05 +00:00
def finish ( self , scope ) :
if self . _finished :
return
self . _finished = True
if self . parent :
assert isinstance ( self . parent , IDLIdentifierPlaceholder )
oldParent = self . parent
self . parent = self . parent . finish ( scope )
if not isinstance ( self . parent , IDLDictionary ) :
raise WebIDLError ( " Dictionary %s has parent that is not a dictionary " %
self . identifier . name ,
2012-06-30 05:53:28 +00:00
[ oldParent . location , self . parent . location ] )
2012-06-12 14:22:05 +00:00
# Make sure the parent resolves all its members before we start
# looking at them.
self . parent . finish ( scope )
for member in self . members :
member . resolve ( self )
2012-07-17 16:18:53 +00:00
if not member . isComplete ( ) :
member . complete ( scope )
assert member . type . isComplete ( )
2012-06-12 14:22:05 +00:00
# Members of a dictionary are sorted in lexicographic order
self . members . sort ( cmp = cmp , key = lambda x : x . identifier . name )
inheritedMembers = [ ]
ancestor = self . parent
while ancestor :
if ancestor == self :
raise WebIDLError ( " Dictionary %s has itself as an ancestor " %
self . identifier . name ,
2012-06-30 05:53:28 +00:00
[ self . identifier . location ] )
2012-06-12 14:22:05 +00:00
inheritedMembers . extend ( ancestor . members )
ancestor = ancestor . parent
# Catch name duplication
for inheritedMember in inheritedMembers :
for member in self . members :
if member . identifier . name == inheritedMember . identifier . name :
raise WebIDLError ( " Dictionary %s has two members with name %s " %
( self . identifier . name , member . identifier . name ) ,
2012-06-30 05:53:28 +00:00
[ member . location , inheritedMember . location ] )
2012-06-22 20:18:50 +00:00
def validate ( self ) :
2013-02-27 14:55:56 +00:00
def typeContainsDictionary ( memberType , dictionary ) :
"""
Returns a tuple whose :
- First element is a Boolean value indicating whether
memberType contains dictionary .
- Second element is :
A list of locations that leads from the type that was passed in
the memberType argument , to the dictionary being validated ,
if the boolean value in the first element is True .
None , if the boolean value in the first element is False .
"""
2014-05-23 21:32:38 +00:00
if ( memberType . nullable ( ) or
memberType . isArray ( ) or
memberType . isSequence ( ) or
memberType . isMozMap ( ) ) :
2013-02-27 14:55:56 +00:00
return typeContainsDictionary ( memberType . inner , dictionary )
if memberType . isDictionary ( ) :
if memberType . inner == dictionary :
return ( True , [ memberType . location ] )
( contains , locations ) = dictionaryContainsDictionary ( memberType . inner , \
dictionary )
if contains :
return ( True , [ memberType . location ] + locations )
if memberType . isUnion ( ) :
for member in memberType . flatMemberTypes :
( contains , locations ) = typeContainsDictionary ( member , dictionary )
if contains :
return ( True , locations )
return ( False , None )
def dictionaryContainsDictionary ( dictMember , dictionary ) :
for member in dictMember . members :
( contains , locations ) = typeContainsDictionary ( member . type , dictionary )
if contains :
return ( True , [ member . location ] + locations )
if dictMember . parent :
if dictMember . parent == dictionary :
return ( True , [ dictMember . location ] )
else :
( contains , locations ) = dictionaryContainsDictionary ( dictMember . parent , dictionary )
if contains :
return ( True , [ dictMember . location ] + locations )
return ( False , None )
for member in self . members :
2013-03-14 19:42:59 +00:00
if member . type . isDictionary ( ) and member . type . nullable ( ) :
raise WebIDLError ( " Dictionary %s has member with nullable "
" dictionary type " % self . identifier . name ,
[ member . location ] )
2013-02-27 14:55:56 +00:00
( contains , locations ) = typeContainsDictionary ( member . type , self )
if contains :
raise WebIDLError ( " Dictionary %s has member with itself as type. " %
self . identifier . name ,
[ member . location ] + locations )
2012-06-12 14:22:05 +00:00
def addExtendedAttributes ( self , attrs ) :
assert len ( attrs ) == 0
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
deps = set ( self . members )
if ( self . parent ) :
deps . add ( self . parent )
return deps
2012-06-12 14:22:05 +00:00
2012-03-31 04:42:20 +00:00
class IDLEnum ( IDLObjectWithIdentifier ) :
def __init__ ( self , location , parentScope , name , values ) :
assert isinstance ( parentScope , IDLScope )
assert isinstance ( name , IDLUnresolvedIdentifier )
if len ( values ) != len ( set ( values ) ) :
2012-06-30 05:53:28 +00:00
raise WebIDLError ( " Enum %s has multiple identical strings " % name . name ,
[ location ] )
2012-03-31 04:42:20 +00:00
IDLObjectWithIdentifier . __init__ ( self , location , parentScope , name )
self . _values = values
def values ( self ) :
return self . _values
def finish ( self , scope ) :
pass
2012-06-22 20:18:50 +00:00
def validate ( self ) :
pass
2012-03-31 04:42:20 +00:00
def isEnum ( self ) :
return True
def addExtendedAttributes ( self , attrs ) :
assert len ( attrs ) == 0
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( )
2012-03-31 04:42:20 +00:00
class IDLType ( IDLObject ) :
Tags = enum (
# The integer types
' int8 ' ,
' uint8 ' ,
' int16 ' ,
' uint16 ' ,
' int32 ' ,
' uint32 ' ,
' int64 ' ,
' uint64 ' ,
# Additional primitive types
' bool ' ,
2012-11-27 20:32:05 +00:00
' unrestricted_float ' ,
2012-03-31 04:42:20 +00:00
' float ' ,
2012-11-27 20:32:05 +00:00
' unrestricted_double ' ,
# "double" last primitive type to match IDLBuiltinType
2012-03-31 04:42:20 +00:00
' double ' ,
# Other types
' any ' ,
' domstring ' ,
2013-06-13 05:15:35 +00:00
' bytestring ' ,
2014-11-20 11:58:00 +00:00
' usvstring ' ,
2012-03-31 04:42:20 +00:00
' object ' ,
' date ' ,
' void ' ,
# Funny stuff
' interface ' ,
' dictionary ' ,
' enum ' ,
2012-05-18 21:25:47 +00:00
' callback ' ,
2013-05-02 18:38:19 +00:00
' union ' ,
' sequence ' ,
2014-05-23 21:32:38 +00:00
' mozmap ' ,
2013-05-02 18:38:19 +00:00
' array '
2012-03-31 04:42:20 +00:00
)
def __init__ ( self , location , name ) :
IDLObject . __init__ ( self , location )
self . name = name
self . builtin = False
def __eq__ ( self , other ) :
2012-05-18 21:25:47 +00:00
return other and self . builtin == other . builtin and self . name == other . name
2012-03-31 04:42:20 +00:00
2012-05-25 05:07:30 +00:00
def __ne__ ( self , other ) :
return not self == other
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
return str ( self . name )
def isType ( self ) :
return True
def nullable ( self ) :
return False
def isPrimitive ( self ) :
return False
2013-07-30 17:39:34 +00:00
def isBoolean ( self ) :
return False
def isNumeric ( self ) :
return False
2012-03-31 04:42:20 +00:00
def isString ( self ) :
return False
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return False
def isDOMString ( self ) :
return False
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
2014-08-01 20:23:48 +00:00
return False
2012-03-31 04:42:20 +00:00
def isVoid ( self ) :
return self . name == " Void "
def isSequence ( self ) :
return False
2014-05-23 21:32:38 +00:00
def isMozMap ( self ) :
return False
2012-03-31 04:42:20 +00:00
def isArray ( self ) :
return False
def isArrayBuffer ( self ) :
return False
2012-05-25 04:41:33 +00:00
def isArrayBufferView ( self ) :
return False
def isTypedArray ( self ) :
return False
2012-06-21 16:29:11 +00:00
def isCallbackInterface ( self ) :
return False
def isNonCallbackInterface ( self ) :
return False
2012-05-25 04:41:33 +00:00
def isGeckoInterface ( self ) :
""" Returns a boolean indicating whether this type is an ' interface '
type that is implemented in Gecko . At the moment , this returns
true for all interface types that are not types from the TypedArray
spec . """
return self . isInterface ( ) and not self . isSpiderMonkeyInterface ( )
def isSpiderMonkeyInterface ( self ) :
""" Returns a boolean indicating whether this type is an ' interface '
type that is implemented in Spidermonkey . At the moment , this
only returns true for the types from the TypedArray spec . """
return self . isInterface ( ) and ( self . isArrayBuffer ( ) or \
self . isArrayBufferView ( ) or \
self . isTypedArray ( ) )
2012-03-31 04:42:20 +00:00
def isDictionary ( self ) :
return False
def isInterface ( self ) :
return False
def isAny ( self ) :
2013-05-02 18:38:19 +00:00
return self . tag ( ) == IDLType . Tags . any
2012-03-31 04:42:20 +00:00
def isDate ( self ) :
return self . tag ( ) == IDLType . Tags . date
def isObject ( self ) :
return self . tag ( ) == IDLType . Tags . object
2014-03-21 16:18:24 +00:00
def isPromise ( self ) :
return False
2012-03-31 04:42:20 +00:00
def isComplete ( self ) :
return True
2012-11-27 20:32:05 +00:00
def includesRestrictedFloat ( self ) :
return False
def isFloat ( self ) :
return False
def isUnrestricted ( self ) :
# Should only call this on float types
assert self . isFloat ( )
2013-07-30 14:04:04 +00:00
def isSerializable ( self ) :
return False
2012-03-31 04:42:20 +00:00
def tag ( self ) :
assert False # Override me!
def treatNonCallableAsNull ( self ) :
2012-10-10 19:53:02 +00:00
assert self . tag ( ) == IDLType . Tags . callback
return self . nullable ( ) and self . inner . _treatNonCallableAsNull
2012-03-31 04:42:20 +00:00
2014-01-13 20:08:56 +00:00
def treatNonObjectAsNull ( self ) :
assert self . tag ( ) == IDLType . Tags . callback
return self . nullable ( ) and self . inner . _treatNonObjectAsNull
2012-03-31 04:42:20 +00:00
def addExtendedAttributes ( self , attrs ) :
assert len ( attrs ) == 0
def resolveType ( self , parentScope ) :
pass
def unroll ( self ) :
return self
def isDistinguishableFrom ( self , other ) :
raise TypeError ( " Can ' t tell whether a generic type is or is not "
" distinguishable from other things " )
2014-08-05 02:20:34 +00:00
def isExposedInAllOf ( self , exposureSet ) :
return True
2012-03-31 04:42:20 +00:00
class IDLUnresolvedType ( IDLType ) :
"""
2014-05-05 19:24:00 +00:00
Unresolved types are interface types
2012-03-31 04:42:20 +00:00
"""
2014-08-01 03:50:30 +00:00
def __init__ ( self , location , name , promiseInnerType = None ) :
2012-03-31 04:42:20 +00:00
IDLType . __init__ ( self , location , name )
2014-08-01 03:50:30 +00:00
self . _promiseInnerType = promiseInnerType
2012-03-31 04:42:20 +00:00
def isComplete ( self ) :
return False
def complete ( self , scope ) :
obj = None
try :
obj = scope . _lookupIdentifier ( self . name )
except :
2012-06-30 05:53:28 +00:00
raise WebIDLError ( " Unresolved type ' %s ' . " % self . name ,
[ self . location ] )
2012-03-31 04:42:20 +00:00
assert obj
if obj . isType ( ) :
2012-09-06 14:23:51 +00:00
# obj itself might not be complete; deal with that.
assert obj != self
if not obj . isComplete ( ) :
obj = obj . complete ( scope )
2012-03-31 04:42:20 +00:00
return obj
2014-08-01 03:50:30 +00:00
if self . _promiseInnerType and not self . _promiseInnerType . isComplete ( ) :
self . _promiseInnerType = self . _promiseInnerType . complete ( scope )
2012-03-31 04:42:20 +00:00
name = self . name . resolve ( scope , None )
2014-08-01 03:50:30 +00:00
return IDLWrapperType ( self . location , obj , self . _promiseInnerType )
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
raise TypeError ( " Can ' t tell whether an unresolved type is or is not "
" distinguishable from other things " )
class IDLNullableType ( IDLType ) :
def __init__ ( self , location , innerType ) :
assert not innerType . isVoid ( )
assert not innerType == BuiltinTypes [ IDLBuiltinType . Types . any ]
2014-09-08 15:28:57 +00:00
name = innerType . name
if innerType . isComplete ( ) :
name + = " OrNull "
IDLType . __init__ ( self , location , name )
2012-03-31 04:42:20 +00:00
self . inner = innerType
self . builtin = False
def __eq__ ( self , other ) :
return isinstance ( other , IDLNullableType ) and self . inner == other . inner
def __str__ ( self ) :
return self . inner . __str__ ( ) + " OrNull "
def nullable ( self ) :
return True
def isCallback ( self ) :
return self . inner . isCallback ( )
def isPrimitive ( self ) :
return self . inner . isPrimitive ( )
2013-07-30 17:39:34 +00:00
def isBoolean ( self ) :
return self . inner . isBoolean ( )
def isNumeric ( self ) :
return self . inner . isNumeric ( )
2012-03-31 04:42:20 +00:00
def isString ( self ) :
return self . inner . isString ( )
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return self . inner . isByteString ( )
def isDOMString ( self ) :
return self . inner . isDOMString ( )
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
return self . inner . isUSVString ( )
2014-08-01 20:23:48 +00:00
2012-04-12 22:14:10 +00:00
def isFloat ( self ) :
return self . inner . isFloat ( )
2012-11-27 20:32:05 +00:00
def isUnrestricted ( self ) :
return self . inner . isUnrestricted ( )
def includesRestrictedFloat ( self ) :
return self . inner . includesRestrictedFloat ( )
2012-04-12 22:14:10 +00:00
def isInteger ( self ) :
return self . inner . isInteger ( )
2012-03-31 04:42:20 +00:00
def isVoid ( self ) :
return False
def isSequence ( self ) :
return self . inner . isSequence ( )
2014-05-23 21:32:38 +00:00
def isMozMap ( self ) :
return self . inner . isMozMap ( )
2012-03-31 04:42:20 +00:00
def isArray ( self ) :
return self . inner . isArray ( )
2012-04-12 22:14:10 +00:00
def isArrayBuffer ( self ) :
return self . inner . isArrayBuffer ( )
2012-05-25 04:41:33 +00:00
def isArrayBufferView ( self ) :
return self . inner . isArrayBufferView ( )
def isTypedArray ( self ) :
return self . inner . isTypedArray ( )
2012-03-31 04:42:20 +00:00
def isDictionary ( self ) :
return self . inner . isDictionary ( )
def isInterface ( self ) :
return self . inner . isInterface ( )
2012-06-21 16:29:11 +00:00
def isCallbackInterface ( self ) :
return self . inner . isCallbackInterface ( )
def isNonCallbackInterface ( self ) :
return self . inner . isNonCallbackInterface ( )
2012-03-31 04:42:20 +00:00
def isEnum ( self ) :
return self . inner . isEnum ( )
2012-05-18 21:25:47 +00:00
def isUnion ( self ) :
return self . inner . isUnion ( )
2013-07-30 14:04:04 +00:00
def isSerializable ( self ) :
return self . inner . isSerializable ( )
2012-03-31 04:42:20 +00:00
def tag ( self ) :
return self . inner . tag ( )
def resolveType ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
self . inner . resolveType ( parentScope )
def isComplete ( self ) :
return self . inner . isComplete ( )
def complete ( self , scope ) :
self . inner = self . inner . complete ( scope )
2012-09-06 14:23:51 +00:00
if self . inner . nullable ( ) :
raise WebIDLError ( " The inner type of a nullable type must not be "
" a nullable type " ,
[ self . location , self . inner . location ] )
2012-07-17 16:18:53 +00:00
if self . inner . isUnion ( ) :
if self . inner . hasNullableType :
raise WebIDLError ( " The inner type of a nullable type must not "
" be a union type that itself has a nullable "
" type as a member type " , [ self . location ] )
2014-09-08 15:28:57 +00:00
self . name = self . inner . name + " OrNull "
2012-03-31 04:42:20 +00:00
return self
def unroll ( self ) :
2012-04-12 22:14:10 +00:00
return self . inner . unroll ( )
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
2012-07-17 16:18:53 +00:00
if ( other . nullable ( ) or ( other . isUnion ( ) and other . hasNullableType ) or
other . isDictionary ( ) ) :
2012-03-31 04:42:20 +00:00
# Can't tell which type null should become
return False
return self . inner . isDistinguishableFrom ( other )
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return self . inner . _getDependentObjects ( )
2012-03-31 04:42:20 +00:00
class IDLSequenceType ( IDLType ) :
def __init__ ( self , location , parameterType ) :
assert not parameterType . isVoid ( )
IDLType . __init__ ( self , location , parameterType . name )
self . inner = parameterType
self . builtin = False
2014-09-08 15:28:57 +00:00
# Need to set self.name up front if our inner type is already complete,
# since in that case our .complete() won't be called.
if self . inner . isComplete ( ) :
self . name = self . inner . name + " Sequence "
2012-03-31 04:42:20 +00:00
def __eq__ ( self , other ) :
return isinstance ( other , IDLSequenceType ) and self . inner == other . inner
def __str__ ( self ) :
return self . inner . __str__ ( ) + " Sequence "
def nullable ( self ) :
return False
def isPrimitive ( self ) :
2012-05-15 18:23:29 +00:00
return False ;
2012-03-31 04:42:20 +00:00
def isString ( self ) :
2012-05-15 18:23:29 +00:00
return False ;
2012-03-31 04:42:20 +00:00
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return False
def isDOMString ( self ) :
return False
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
2014-08-01 20:23:48 +00:00
return False
2012-03-31 04:42:20 +00:00
def isVoid ( self ) :
return False
def isSequence ( self ) :
return True
def isArray ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isDictionary ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isEnum ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
2013-07-30 14:04:04 +00:00
def isSerializable ( self ) :
return self . inner . isSerializable ( )
2012-11-27 20:32:05 +00:00
def includesRestrictedFloat ( self ) :
return self . inner . includesRestrictedFloat ( )
2012-03-31 04:42:20 +00:00
def tag ( self ) :
2013-05-02 18:38:19 +00:00
return IDLType . Tags . sequence
2012-03-31 04:42:20 +00:00
def resolveType ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
self . inner . resolveType ( parentScope )
def isComplete ( self ) :
return self . inner . isComplete ( )
def complete ( self , scope ) :
self . inner = self . inner . complete ( scope )
2014-09-08 15:28:57 +00:00
self . name = self . inner . name + " Sequence "
2012-03-31 04:42:20 +00:00
return self
def unroll ( self ) :
2012-04-12 22:14:10 +00:00
return self . inner . unroll ( )
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
2012-07-27 04:09:10 +00:00
if other . isUnion ( ) :
# Just forward to the union; it'll deal
return other . isDistinguishableFrom ( self )
2012-03-31 04:42:20 +00:00
return ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
2014-09-24 13:11:30 +00:00
other . isDate ( ) or other . isInterface ( ) or other . isDictionary ( ) or
other . isCallback ( ) or other . isMozMap ( ) )
2012-03-31 04:42:20 +00:00
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return self . inner . _getDependentObjects ( )
2014-05-23 21:32:38 +00:00
class IDLMozMapType ( IDLType ) :
# XXXbz This is pretty similar to IDLSequenceType in various ways.
# And maybe to IDLNullableType. Should we have a superclass for
# "type containing this other type"? Bug 1015318.
def __init__ ( self , location , parameterType ) :
assert not parameterType . isVoid ( )
IDLType . __init__ ( self , location , parameterType . name )
self . inner = parameterType
self . builtin = False
2014-09-08 15:28:57 +00:00
# Need to set self.name up front if our inner type is already complete,
# since in that case our .complete() won't be called.
if self . inner . isComplete ( ) :
self . name = self . inner . name + " MozMap "
2014-05-23 21:32:38 +00:00
def __eq__ ( self , other ) :
return isinstance ( other , IDLMozMapType ) and self . inner == other . inner
def __str__ ( self ) :
return self . inner . __str__ ( ) + " MozMap "
def isMozMap ( self ) :
return True
def includesRestrictedFloat ( self ) :
return self . inner . includesRestrictedFloat ( )
def tag ( self ) :
return IDLType . Tags . mozmap
def resolveType ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
self . inner . resolveType ( parentScope )
def isComplete ( self ) :
return self . inner . isComplete ( )
def complete ( self , scope ) :
self . inner = self . inner . complete ( scope )
2014-09-08 15:28:57 +00:00
self . name = self . inner . name + " MozMap "
2014-05-23 21:32:38 +00:00
return self
def unroll ( self ) :
# We do not unroll our inner. Just stop at ourselves. That
# lets us add headers for both ourselves and our inner as
# needed.
return self
def isDistinguishableFrom ( self , other ) :
if other . isUnion ( ) :
# Just forward to the union; it'll deal
return other . isDistinguishableFrom ( self )
return ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
2014-06-25 17:25:09 +00:00
other . isDate ( ) or other . isNonCallbackInterface ( ) or other . isSequence ( ) )
2014-05-23 21:32:38 +00:00
2014-08-05 02:20:34 +00:00
def isExposedInAllOf ( self , exposureSet ) :
return self . inner . unroll ( ) . isExposedInAllOf ( exposureSet )
2014-05-23 21:32:38 +00:00
def _getDependentObjects ( self ) :
return self . inner . _getDependentObjects ( )
2012-05-18 21:25:47 +00:00
class IDLUnionType ( IDLType ) :
def __init__ ( self , location , memberTypes ) :
IDLType . __init__ ( self , location , " " )
self . memberTypes = memberTypes
self . hasNullableType = False
2013-01-03 19:03:00 +00:00
self . hasDictionaryType = False
2012-05-18 21:25:47 +00:00
self . flatMemberTypes = None
self . builtin = False
def __eq__ ( self , other ) :
return isinstance ( other , IDLUnionType ) and self . memberTypes == other . memberTypes
2014-10-01 18:43:26 +00:00
def __hash__ ( self ) :
assert self . isComplete ( )
return self . name . __hash__ ( )
2012-05-18 21:25:47 +00:00
def isVoid ( self ) :
return False
def isUnion ( self ) :
return True
2013-07-30 14:04:04 +00:00
def isSerializable ( self ) :
return all ( m . isSerializable ( ) for m in self . memberTypes )
2012-11-27 20:32:05 +00:00
def includesRestrictedFloat ( self ) :
return any ( t . includesRestrictedFloat ( ) for t in self . memberTypes )
2012-05-18 21:25:47 +00:00
def tag ( self ) :
return IDLType . Tags . union
def resolveType ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
for t in self . memberTypes :
t . resolveType ( parentScope )
def isComplete ( self ) :
return self . flatMemberTypes is not None
def complete ( self , scope ) :
def typeName ( type ) :
if isinstance ( type , IDLNullableType ) :
return typeName ( type . inner ) + " OrNull "
if isinstance ( type , IDLWrapperType ) :
return typeName ( type . _identifier . object ( ) )
if isinstance ( type , IDLObjectWithIdentifier ) :
return typeName ( type . identifier )
return type . name
for ( i , type ) in enumerate ( self . memberTypes ) :
if not type . isComplete ( ) :
self . memberTypes [ i ] = type . complete ( scope )
self . name = " Or " . join ( typeName ( type ) for type in self . memberTypes )
self . flatMemberTypes = list ( self . memberTypes )
i = 0
while i < len ( self . flatMemberTypes ) :
if self . flatMemberTypes [ i ] . nullable ( ) :
if self . hasNullableType :
raise WebIDLError ( " Can ' t have more than one nullable types in a union " ,
2012-06-30 05:53:28 +00:00
[ nullableType . location , self . flatMemberTypes [ i ] . location ] )
2013-01-03 19:03:00 +00:00
if self . hasDictionaryType :
raise WebIDLError ( " Can ' t have a nullable type and a "
" dictionary type in a union " ,
[ dictionaryType . location ,
self . flatMemberTypes [ i ] . location ] )
2012-05-18 21:25:47 +00:00
self . hasNullableType = True
nullableType = self . flatMemberTypes [ i ]
self . flatMemberTypes [ i ] = self . flatMemberTypes [ i ] . inner
continue
2013-01-03 19:03:00 +00:00
if self . flatMemberTypes [ i ] . isDictionary ( ) :
if self . hasNullableType :
raise WebIDLError ( " Can ' t have a nullable type and a "
" dictionary type in a union " ,
[ nullableType . location ,
self . flatMemberTypes [ i ] . location ] )
self . hasDictionaryType = True
dictionaryType = self . flatMemberTypes [ i ]
elif self . flatMemberTypes [ i ] . isUnion ( ) :
2012-05-18 21:25:47 +00:00
self . flatMemberTypes [ i : i + 1 ] = self . flatMemberTypes [ i ] . memberTypes
continue
i + = 1
for ( i , t ) in enumerate ( self . flatMemberTypes [ : - 1 ] ) :
for u in self . flatMemberTypes [ i + 1 : ] :
if not t . isDistinguishableFrom ( u ) :
raise WebIDLError ( " Flat member types of a union should be "
" distinguishable, " + str ( t ) + " is not "
" distinguishable from " + str ( u ) ,
2012-06-30 05:53:28 +00:00
[ self . location , t . location , u . location ] )
2012-05-18 21:25:47 +00:00
return self
def isDistinguishableFrom ( self , other ) :
if self . hasNullableType and other . nullable ( ) :
# Can't tell which type null should become
return False
if other . isUnion ( ) :
otherTypes = other . unroll ( ) . memberTypes
else :
otherTypes = [ other ]
# For every type in otherTypes, check that it's distinguishable from
# every type in our types
for u in otherTypes :
if any ( not t . isDistinguishableFrom ( u ) for t in self . memberTypes ) :
return False
return True
2014-08-05 02:20:34 +00:00
def isExposedInAllOf ( self , exposureSet ) :
# We could have different member types in different globals. Just make sure that each thing in exposureSet has one of our member types exposed in it.
for globalName in exposureSet :
if not any ( t . unroll ( ) . isExposedInAllOf ( set ( [ globalName ] ) ) for t
in self . flatMemberTypes ) :
return False
return True
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( self . memberTypes )
2012-03-31 04:42:20 +00:00
class IDLArrayType ( IDLType ) :
def __init__ ( self , location , parameterType ) :
assert not parameterType . isVoid ( )
if parameterType . isSequence ( ) :
raise WebIDLError ( " Array type cannot parameterize over a sequence type " ,
2012-06-30 05:53:28 +00:00
[ location ] )
2014-05-23 21:32:38 +00:00
if parameterType . isMozMap ( ) :
raise WebIDLError ( " Array type cannot parameterize over a MozMap type " ,
[ location ] )
2012-03-31 04:42:20 +00:00
if parameterType . isDictionary ( ) :
raise WebIDLError ( " Array type cannot parameterize over a dictionary type " ,
2012-06-30 05:53:28 +00:00
[ location ] )
2012-03-31 04:42:20 +00:00
IDLType . __init__ ( self , location , parameterType . name )
self . inner = parameterType
self . builtin = False
def __eq__ ( self , other ) :
return isinstance ( other , IDLArrayType ) and self . inner == other . inner
def __str__ ( self ) :
return self . inner . __str__ ( ) + " Array "
def nullable ( self ) :
return False
def isPrimitive ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isString ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return False
def isDOMString ( self ) :
return False
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
2014-08-01 20:23:48 +00:00
return False
2012-03-31 04:42:20 +00:00
def isVoid ( self ) :
return False
def isSequence ( self ) :
assert not self . inner . isSequence ( )
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isArray ( self ) :
return True
def isDictionary ( self ) :
assert not self . inner . isDictionary ( )
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def isEnum ( self ) :
2012-04-12 22:14:10 +00:00
return False
2012-03-31 04:42:20 +00:00
def tag ( self ) :
2013-05-02 18:38:19 +00:00
return IDLType . Tags . array
2012-03-31 04:42:20 +00:00
def resolveType ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
self . inner . resolveType ( parentScope )
def isComplete ( self ) :
return self . inner . isComplete ( )
def complete ( self , scope ) :
self . inner = self . inner . complete ( scope )
2012-04-12 22:14:10 +00:00
self . name = self . inner . name
2013-03-06 18:06:23 +00:00
if self . inner . isDictionary ( ) :
raise WebIDLError ( " Array type must not contain "
" dictionary as element type. " ,
[ self . inner . location ] )
assert not self . inner . isSequence ( )
2012-03-31 04:42:20 +00:00
return self
def unroll ( self ) :
2012-04-12 22:14:10 +00:00
return self . inner . unroll ( )
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
2012-07-27 04:09:10 +00:00
if other . isUnion ( ) :
# Just forward to the union; it'll deal
return other . isDistinguishableFrom ( self )
2012-03-31 04:42:20 +00:00
return ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
2013-01-03 03:03:25 +00:00
other . isDate ( ) or other . isNonCallbackInterface ( ) )
2012-03-31 04:42:20 +00:00
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return self . inner . _getDependentObjects ( )
2012-03-31 04:42:20 +00:00
class IDLTypedefType ( IDLType , IDLObjectWithIdentifier ) :
def __init__ ( self , location , innerType , name ) :
IDLType . __init__ ( self , location , innerType . name )
identifier = IDLUnresolvedIdentifier ( location , name )
IDLObjectWithIdentifier . __init__ ( self , location , None , identifier )
self . inner = innerType
self . name = name
self . builtin = False
def __eq__ ( self , other ) :
return isinstance ( other , IDLTypedefType ) and self . inner == other . inner
def __str__ ( self ) :
return self . identifier . name
def nullable ( self ) :
return self . inner . nullable ( )
def isPrimitive ( self ) :
return self . inner . isPrimitive ( )
2013-07-30 17:39:34 +00:00
def isBoolean ( self ) :
return self . inner . isBoolean ( )
def isNumeric ( self ) :
return self . inner . isNumeric ( )
2012-03-31 04:42:20 +00:00
def isString ( self ) :
return self . inner . isString ( )
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return self . inner . isByteString ( )
def isDOMString ( self ) :
return self . inner . isDOMString ( )
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
return self . inner . isUSVString ( )
2014-08-01 20:23:48 +00:00
2012-03-31 04:42:20 +00:00
def isVoid ( self ) :
return self . inner . isVoid ( )
def isSequence ( self ) :
return self . inner . isSequence ( )
2014-05-23 21:32:38 +00:00
def isMozMap ( self ) :
return self . inner . isMozMap ( )
2012-03-31 04:42:20 +00:00
def isArray ( self ) :
return self . inner . isArray ( )
def isDictionary ( self ) :
return self . inner . isDictionary ( )
2012-05-25 04:41:33 +00:00
def isArrayBuffer ( self ) :
return self . inner . isArrayBuffer ( )
def isArrayBufferView ( self ) :
return self . inner . isArrayBufferView ( )
def isTypedArray ( self ) :
return self . inner . isTypedArray ( )
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
return self . inner . isInterface ( )
2012-06-21 16:29:11 +00:00
def isCallbackInterface ( self ) :
return self . inner . isCallbackInterface ( )
def isNonCallbackInterface ( self ) :
return self . inner . isNonCallbackInterface ( )
2012-09-06 14:23:51 +00:00
def isComplete ( self ) :
return False
def complete ( self , parentScope ) :
if not self . inner . isComplete ( ) :
self . inner = self . inner . complete ( parentScope )
assert self . inner . isComplete ( )
return self . inner
def finish ( self , parentScope ) :
# Maybe the IDLObjectWithIdentifier for the typedef should be
2012-10-01 12:56:31 +00:00
# a separate thing from the type? If that happens, we can
# remove some hackery around avoiding isInterface() in
# Configuration.py.
2012-09-06 14:23:51 +00:00
self . complete ( parentScope )
def validate ( self ) :
pass
# Do we need a resolveType impl? I don't think it's particularly useful....
2012-03-31 04:42:20 +00:00
def tag ( self ) :
return self . inner . tag ( )
def unroll ( self ) :
2012-04-12 22:14:10 +00:00
return self . inner . unroll ( )
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
return self . inner . isDistinguishableFrom ( other )
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return self . inner . _getDependentObjects ( )
2012-03-31 04:42:20 +00:00
class IDLWrapperType ( IDLType ) :
2014-08-01 03:50:30 +00:00
def __init__ ( self , location , inner , promiseInnerType = None ) :
2012-03-31 04:42:20 +00:00
IDLType . __init__ ( self , location , inner . identifier . name )
self . inner = inner
2012-05-25 04:41:33 +00:00
self . _identifier = inner . identifier
2012-03-31 04:42:20 +00:00
self . builtin = False
2014-08-01 03:50:30 +00:00
assert not promiseInnerType or inner . identifier . name == " Promise "
self . _promiseInnerType = promiseInnerType
2012-03-31 04:42:20 +00:00
def __eq__ ( self , other ) :
2012-05-25 05:07:30 +00:00
return isinstance ( other , IDLWrapperType ) and \
self . _identifier == other . _identifier and \
2012-05-25 04:41:33 +00:00
self . builtin == other . builtin
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
2012-05-25 04:41:33 +00:00
return str ( self . name ) + " (Wrapper) "
2012-03-31 04:42:20 +00:00
def nullable ( self ) :
return False
def isPrimitive ( self ) :
return False
def isString ( self ) :
return False
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return False
def isDOMString ( self ) :
return False
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
2014-08-01 20:23:48 +00:00
return False
2012-03-31 04:42:20 +00:00
def isVoid ( self ) :
return False
def isSequence ( self ) :
return False
def isArray ( self ) :
return False
def isDictionary ( self ) :
2012-06-12 14:22:05 +00:00
return isinstance ( self . inner , IDLDictionary )
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
return isinstance ( self . inner , IDLInterface ) or \
isinstance ( self . inner , IDLExternalInterface )
2012-06-21 16:29:11 +00:00
def isCallbackInterface ( self ) :
return self . isInterface ( ) and self . inner . isCallback ( )
def isNonCallbackInterface ( self ) :
return self . isInterface ( ) and not self . inner . isCallback ( )
2012-03-31 04:42:20 +00:00
def isEnum ( self ) :
return isinstance ( self . inner , IDLEnum )
2014-03-21 16:18:24 +00:00
def isPromise ( self ) :
return isinstance ( self . inner , IDLInterface ) and \
self . inner . identifier . name == " Promise "
2013-07-30 14:04:04 +00:00
def isSerializable ( self ) :
if self . isInterface ( ) :
if self . inner . isExternal ( ) :
return False
return any ( m . isMethod ( ) and m . isJsonifier ( ) for m in self . inner . members )
elif self . isEnum ( ) :
return True
elif self . isDictionary ( ) :
2013-12-05 16:39:50 +00:00
return all ( m . type . isSerializable ( ) for m in self . inner . members )
2013-07-30 14:04:04 +00:00
else :
raise WebIDLError ( " IDLWrapperType wraps type %s that we don ' t know if "
" is serializable " % type ( self . inner ) , [ self . location ] )
2012-04-12 22:14:10 +00:00
def resolveType ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
self . inner . resolve ( parentScope )
2012-03-31 04:42:20 +00:00
def isComplete ( self ) :
return True
def tag ( self ) :
if self . isInterface ( ) :
return IDLType . Tags . interface
elif self . isEnum ( ) :
return IDLType . Tags . enum
2012-06-12 14:22:05 +00:00
elif self . isDictionary ( ) :
return IDLType . Tags . dictionary
2012-03-31 04:42:20 +00:00
else :
assert False
def isDistinguishableFrom ( self , other ) :
2012-07-27 04:09:10 +00:00
if other . isUnion ( ) :
# Just forward to the union; it'll deal
return other . isDistinguishableFrom ( self )
2012-06-21 16:29:11 +00:00
assert self . isInterface ( ) or self . isEnum ( ) or self . isDictionary ( )
2012-03-31 04:42:20 +00:00
if self . isEnum ( ) :
2013-07-30 17:39:34 +00:00
return ( other . isPrimitive ( ) or other . isInterface ( ) or other . isObject ( ) or
2012-03-31 04:42:20 +00:00
other . isCallback ( ) or other . isDictionary ( ) or
2014-05-23 21:32:38 +00:00
other . isSequence ( ) or other . isMozMap ( ) or other . isArray ( ) or
2012-03-31 04:42:20 +00:00
other . isDate ( ) )
2013-01-03 03:03:25 +00:00
if self . isDictionary ( ) and other . nullable ( ) :
return False
2014-09-24 13:11:30 +00:00
if ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
other . isDate ( ) or other . isSequence ( ) ) :
2012-03-31 04:42:20 +00:00
return True
2012-06-21 16:29:11 +00:00
if self . isDictionary ( ) :
2013-01-03 03:03:25 +00:00
return other . isNonCallbackInterface ( )
2012-06-21 16:29:11 +00:00
assert self . isInterface ( )
2012-03-31 04:42:20 +00:00
if other . isInterface ( ) :
2012-06-22 20:18:50 +00:00
if other . isSpiderMonkeyInterface ( ) :
# Just let |other| handle things
return other . isDistinguishableFrom ( self )
assert self . isGeckoInterface ( ) and other . isGeckoInterface ( )
if self . inner . isExternal ( ) or other . unroll ( ) . inner . isExternal ( ) :
return self != other
return ( len ( self . inner . interfacesBasedOnSelf &
other . unroll ( ) . inner . interfacesBasedOnSelf ) == 0 and
2012-06-21 16:29:11 +00:00
( self . isNonCallbackInterface ( ) or
other . isNonCallbackInterface ( ) ) )
if ( other . isDictionary ( ) or other . isCallback ( ) or
2014-09-24 13:11:30 +00:00
other . isMozMap ( ) or other . isArray ( ) ) :
2012-06-21 16:29:11 +00:00
return self . isNonCallbackInterface ( )
2012-03-31 04:42:20 +00:00
2012-06-22 20:18:50 +00:00
# Not much else |other| can be
assert other . isObject ( )
return False
2014-08-05 02:20:34 +00:00
def isExposedInAllOf ( self , exposureSet ) :
if not self . isInterface ( ) :
return True
iface = self . inner
if iface . isExternal ( ) :
# Let's say true, though ideally we'd only do this when
# exposureSet contains the primary global's name.
return True
if ( iface . identifier . name == " Promise " and
# Check the internal type
not self . _promiseInnerType . unroll ( ) . isExposedInAllOf ( exposureSet ) ) :
return False
return iface . exposureSet . issuperset ( exposureSet )
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
# NB: The codegen for an interface type depends on
# a) That the identifier is in fact an interface (as opposed to
# a dictionary or something else).
# b) The native type of the interface.
# If we depend on the interface object we will also depend on
# anything the interface depends on which is undesirable. We
# considered implementing a dependency just on the interface type
# file, but then every modification to an interface would cause this
# to be regenerated which is still undesirable. We decided not to
# depend on anything, reasoning that:
# 1) Changing the concrete type of the interface requires modifying
# Bindings.conf, which is still a global dependency.
# 2) Changing an interface to a dictionary (or vice versa) with the
# same identifier should be incredibly rare.
2014-12-01 20:17:58 +00:00
#
# On the other hand, if our type is a dictionary, we should
# depend on it, because the member types of a dictionary
# affect whether a method taking the dictionary as an argument
# takes a JSContext* argument or not.
if self . isDictionary ( ) :
return set ( [ self . inner ] )
2013-02-24 20:36:44 +00:00
return set ( )
2012-03-31 04:42:20 +00:00
class IDLBuiltinType ( IDLType ) :
Types = enum (
# The integer types
' byte ' ,
' octet ' ,
' short ' ,
' unsigned_short ' ,
' long ' ,
' unsigned_long ' ,
' long_long ' ,
' unsigned_long_long ' ,
# Additional primitive types
' boolean ' ,
2012-11-27 20:32:05 +00:00
' unrestricted_float ' ,
2012-03-31 04:42:20 +00:00
' float ' ,
2012-11-27 20:32:05 +00:00
' unrestricted_double ' ,
# IMPORTANT: "double" must be the last primitive type listed
2012-03-31 04:42:20 +00:00
' double ' ,
# Other types
' any ' ,
' domstring ' ,
2013-06-13 05:15:35 +00:00
' bytestring ' ,
2014-11-20 11:58:00 +00:00
' usvstring ' ,
2012-03-31 04:42:20 +00:00
' object ' ,
' date ' ,
' void ' ,
# Funny stuff
2012-05-25 04:41:33 +00:00
' ArrayBuffer ' ,
' ArrayBufferView ' ,
' Int8Array ' ,
' Uint8Array ' ,
' Uint8ClampedArray ' ,
' Int16Array ' ,
' Uint16Array ' ,
' Int32Array ' ,
' Uint32Array ' ,
' Float32Array ' ,
' Float64Array '
2012-03-31 04:42:20 +00:00
)
TagLookup = {
Types . byte : IDLType . Tags . int8 ,
Types . octet : IDLType . Tags . uint8 ,
Types . short : IDLType . Tags . int16 ,
Types . unsigned_short : IDLType . Tags . uint16 ,
Types . long : IDLType . Tags . int32 ,
Types . unsigned_long : IDLType . Tags . uint32 ,
Types . long_long : IDLType . Tags . int64 ,
Types . unsigned_long_long : IDLType . Tags . uint64 ,
Types . boolean : IDLType . Tags . bool ,
2012-11-27 20:32:05 +00:00
Types . unrestricted_float : IDLType . Tags . unrestricted_float ,
2012-03-31 04:42:20 +00:00
Types . float : IDLType . Tags . float ,
2012-11-27 20:32:05 +00:00
Types . unrestricted_double : IDLType . Tags . unrestricted_double ,
2012-03-31 04:42:20 +00:00
Types . double : IDLType . Tags . double ,
Types . any : IDLType . Tags . any ,
Types . domstring : IDLType . Tags . domstring ,
2013-06-13 05:15:35 +00:00
Types . bytestring : IDLType . Tags . bytestring ,
2014-11-20 11:58:00 +00:00
Types . usvstring : IDLType . Tags . usvstring ,
2012-03-31 04:42:20 +00:00
Types . object : IDLType . Tags . object ,
Types . date : IDLType . Tags . date ,
Types . void : IDLType . Tags . void ,
2012-05-25 04:41:33 +00:00
Types . ArrayBuffer : IDLType . Tags . interface ,
Types . ArrayBufferView : IDLType . Tags . interface ,
Types . Int8Array : IDLType . Tags . interface ,
Types . Uint8Array : IDLType . Tags . interface ,
Types . Uint8ClampedArray : IDLType . Tags . interface ,
Types . Int16Array : IDLType . Tags . interface ,
Types . Uint16Array : IDLType . Tags . interface ,
Types . Int32Array : IDLType . Tags . interface ,
Types . Uint32Array : IDLType . Tags . interface ,
Types . Float32Array : IDLType . Tags . interface ,
Types . Float64Array : IDLType . Tags . interface
2012-03-31 04:42:20 +00:00
}
def __init__ ( self , location , name , type ) :
IDLType . __init__ ( self , location , name )
self . builtin = True
2012-04-12 22:14:10 +00:00
self . _typeTag = type
2012-03-31 04:42:20 +00:00
def isPrimitive ( self ) :
2012-04-12 22:14:10 +00:00
return self . _typeTag < = IDLBuiltinType . Types . double
2012-03-31 04:42:20 +00:00
2013-07-30 17:39:34 +00:00
def isBoolean ( self ) :
return self . _typeTag == IDLBuiltinType . Types . boolean
def isNumeric ( self ) :
return self . isPrimitive ( ) and not self . isBoolean ( )
2012-03-31 04:42:20 +00:00
def isString ( self ) :
2013-06-13 05:15:35 +00:00
return self . _typeTag == IDLBuiltinType . Types . domstring or \
2014-08-01 20:23:48 +00:00
self . _typeTag == IDLBuiltinType . Types . bytestring or \
2014-11-20 11:58:00 +00:00
self . _typeTag == IDLBuiltinType . Types . usvstring
2013-06-13 05:15:35 +00:00
def isByteString ( self ) :
return self . _typeTag == IDLBuiltinType . Types . bytestring
def isDOMString ( self ) :
2012-04-12 22:14:10 +00:00
return self . _typeTag == IDLBuiltinType . Types . domstring
2012-03-31 04:42:20 +00:00
2014-11-20 11:58:00 +00:00
def isUSVString ( self ) :
return self . _typeTag == IDLBuiltinType . Types . usvstring
2014-08-01 20:23:48 +00:00
2012-03-31 04:42:20 +00:00
def isInteger ( self ) :
2012-04-12 22:14:10 +00:00
return self . _typeTag < = IDLBuiltinType . Types . unsigned_long_long
2012-03-31 04:42:20 +00:00
def isArrayBuffer ( self ) :
2012-04-12 22:14:10 +00:00
return self . _typeTag == IDLBuiltinType . Types . ArrayBuffer
2012-03-31 04:42:20 +00:00
2012-05-25 04:41:33 +00:00
def isArrayBufferView ( self ) :
return self . _typeTag == IDLBuiltinType . Types . ArrayBufferView
def isTypedArray ( self ) :
return self . _typeTag > = IDLBuiltinType . Types . Int8Array and \
self . _typeTag < = IDLBuiltinType . Types . Float64Array
2012-03-31 04:42:20 +00:00
def isInterface ( self ) :
2012-05-25 04:41:33 +00:00
# TypedArray things are interface types per the TypedArray spec,
2012-03-31 04:42:20 +00:00
# but we handle them as builtins because SpiderMonkey implements
2012-05-25 04:41:33 +00:00
# all of it internally.
return self . isArrayBuffer ( ) or \
self . isArrayBufferView ( ) or \
self . isTypedArray ( )
2012-03-31 04:42:20 +00:00
2012-06-21 16:29:11 +00:00
def isNonCallbackInterface ( self ) :
# All the interfaces we can be are non-callback
return self . isInterface ( )
2012-03-31 04:42:20 +00:00
def isFloat ( self ) :
2012-04-12 22:14:10 +00:00
return self . _typeTag == IDLBuiltinType . Types . float or \
2012-11-27 20:32:05 +00:00
self . _typeTag == IDLBuiltinType . Types . double or \
self . _typeTag == IDLBuiltinType . Types . unrestricted_float or \
self . _typeTag == IDLBuiltinType . Types . unrestricted_double
def isUnrestricted ( self ) :
assert self . isFloat ( )
return self . _typeTag == IDLBuiltinType . Types . unrestricted_float or \
self . _typeTag == IDLBuiltinType . Types . unrestricted_double
2013-07-30 14:04:04 +00:00
def isSerializable ( self ) :
return self . isPrimitive ( ) or self . isDOMString ( ) or self . isDate ( )
2012-11-27 20:32:05 +00:00
def includesRestrictedFloat ( self ) :
return self . isFloat ( ) and not self . isUnrestricted ( )
2012-03-31 04:42:20 +00:00
def tag ( self ) :
2012-04-12 22:14:10 +00:00
return IDLBuiltinType . TagLookup [ self . _typeTag ]
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
2012-07-27 04:09:10 +00:00
if other . isUnion ( ) :
# Just forward to the union; it'll deal
return other . isDistinguishableFrom ( self )
2013-07-30 17:39:34 +00:00
if self . isBoolean ( ) :
return ( other . isNumeric ( ) or other . isString ( ) or other . isEnum ( ) or
other . isInterface ( ) or other . isObject ( ) or
other . isCallback ( ) or other . isDictionary ( ) or
2014-05-23 21:32:38 +00:00
other . isSequence ( ) or other . isMozMap ( ) or other . isArray ( ) or
2013-07-30 17:39:34 +00:00
other . isDate ( ) )
if self . isNumeric ( ) :
return ( other . isBoolean ( ) or other . isString ( ) or other . isEnum ( ) or
other . isInterface ( ) or other . isObject ( ) or
other . isCallback ( ) or other . isDictionary ( ) or
2014-05-23 21:32:38 +00:00
other . isSequence ( ) or other . isMozMap ( ) or other . isArray ( ) or
2013-07-30 17:39:34 +00:00
other . isDate ( ) )
if self . isString ( ) :
return ( other . isPrimitive ( ) or other . isInterface ( ) or
other . isObject ( ) or
2012-03-31 04:42:20 +00:00
other . isCallback ( ) or other . isDictionary ( ) or
2014-05-23 21:32:38 +00:00
other . isSequence ( ) or other . isMozMap ( ) or other . isArray ( ) or
2012-03-31 04:42:20 +00:00
other . isDate ( ) )
if self . isAny ( ) :
# Can't tell "any" apart from anything
return False
if self . isObject ( ) :
return other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( )
if self . isDate ( ) :
return ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
other . isInterface ( ) or other . isCallback ( ) or
other . isDictionary ( ) or other . isSequence ( ) or
2014-05-23 21:32:38 +00:00
other . isMozMap ( ) or other . isArray ( ) )
2012-03-31 04:42:20 +00:00
if self . isVoid ( ) :
return not other . isVoid ( )
# Not much else we could be!
2012-05-25 04:41:33 +00:00
assert self . isSpiderMonkeyInterface ( )
2012-04-13 17:52:21 +00:00
# Like interfaces, but we know we're not a callback
2012-03-31 04:42:20 +00:00
return ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
2012-04-13 17:52:21 +00:00
other . isCallback ( ) or other . isDictionary ( ) or
2014-05-23 21:32:38 +00:00
other . isSequence ( ) or other . isMozMap ( ) or other . isArray ( ) or
other . isDate ( ) or
2012-05-25 04:41:33 +00:00
( other . isInterface ( ) and (
# ArrayBuffer is distinguishable from everything
2012-06-21 16:29:11 +00:00
# that's not an ArrayBuffer or a callback interface
2012-05-25 04:41:33 +00:00
( self . isArrayBuffer ( ) and not other . isArrayBuffer ( ) ) or
# ArrayBufferView is distinguishable from everything
# that's not an ArrayBufferView or typed array.
( self . isArrayBufferView ( ) and not other . isArrayBufferView ( ) and
not other . isTypedArray ( ) ) or
# Typed arrays are distinguishable from everything
# except ArrayBufferView and the same type of typed
# array
( self . isTypedArray ( ) and not other . isArrayBufferView ( ) and not
( other . isTypedArray ( ) and other . name == self . name ) ) ) ) )
2012-03-31 04:42:20 +00:00
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( )
2012-03-31 04:42:20 +00:00
BuiltinTypes = {
IDLBuiltinType . Types . byte :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Byte " ,
IDLBuiltinType . Types . byte ) ,
IDLBuiltinType . Types . octet :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Octet " ,
IDLBuiltinType . Types . octet ) ,
IDLBuiltinType . Types . short :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Short " ,
IDLBuiltinType . Types . short ) ,
IDLBuiltinType . Types . unsigned_short :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " UnsignedShort " ,
IDLBuiltinType . Types . unsigned_short ) ,
IDLBuiltinType . Types . long :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Long " ,
IDLBuiltinType . Types . long ) ,
IDLBuiltinType . Types . unsigned_long :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " UnsignedLong " ,
IDLBuiltinType . Types . unsigned_long ) ,
IDLBuiltinType . Types . long_long :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " LongLong " ,
IDLBuiltinType . Types . long_long ) ,
IDLBuiltinType . Types . unsigned_long_long :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " UnsignedLongLong " ,
IDLBuiltinType . Types . unsigned_long_long ) ,
IDLBuiltinType . Types . boolean :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Boolean " ,
IDLBuiltinType . Types . boolean ) ,
IDLBuiltinType . Types . float :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Float " ,
IDLBuiltinType . Types . float ) ,
2012-11-27 20:32:05 +00:00
IDLBuiltinType . Types . unrestricted_float :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " UnrestrictedFloat " ,
IDLBuiltinType . Types . unrestricted_float ) ,
2012-03-31 04:42:20 +00:00
IDLBuiltinType . Types . double :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Double " ,
IDLBuiltinType . Types . double ) ,
2012-11-27 20:32:05 +00:00
IDLBuiltinType . Types . unrestricted_double :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " UnrestrictedDouble " ,
IDLBuiltinType . Types . unrestricted_double ) ,
2012-03-31 04:42:20 +00:00
IDLBuiltinType . Types . any :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Any " ,
IDLBuiltinType . Types . any ) ,
IDLBuiltinType . Types . domstring :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " String " ,
IDLBuiltinType . Types . domstring ) ,
2013-06-13 05:15:35 +00:00
IDLBuiltinType . Types . bytestring :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " ByteString " ,
IDLBuiltinType . Types . bytestring ) ,
2014-11-20 11:58:00 +00:00
IDLBuiltinType . Types . usvstring :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " USVString " ,
IDLBuiltinType . Types . usvstring ) ,
2012-03-31 04:42:20 +00:00
IDLBuiltinType . Types . object :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Object " ,
IDLBuiltinType . Types . object ) ,
IDLBuiltinType . Types . date :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Date " ,
IDLBuiltinType . Types . date ) ,
IDLBuiltinType . Types . void :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Void " ,
IDLBuiltinType . Types . void ) ,
IDLBuiltinType . Types . ArrayBuffer :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " ArrayBuffer " ,
2012-05-25 04:41:33 +00:00
IDLBuiltinType . Types . ArrayBuffer ) ,
IDLBuiltinType . Types . ArrayBufferView :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " ArrayBufferView " ,
IDLBuiltinType . Types . ArrayBufferView ) ,
IDLBuiltinType . Types . Int8Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Int8Array " ,
IDLBuiltinType . Types . Int8Array ) ,
IDLBuiltinType . Types . Uint8Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Uint8Array " ,
IDLBuiltinType . Types . Uint8Array ) ,
IDLBuiltinType . Types . Uint8ClampedArray :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Uint8ClampedArray " ,
IDLBuiltinType . Types . Uint8ClampedArray ) ,
IDLBuiltinType . Types . Int16Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Int16Array " ,
IDLBuiltinType . Types . Int16Array ) ,
IDLBuiltinType . Types . Uint16Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Uint16Array " ,
IDLBuiltinType . Types . Uint16Array ) ,
IDLBuiltinType . Types . Int32Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Int32Array " ,
IDLBuiltinType . Types . Int32Array ) ,
IDLBuiltinType . Types . Uint32Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Uint32Array " ,
IDLBuiltinType . Types . Uint32Array ) ,
IDLBuiltinType . Types . Float32Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Float32Array " ,
IDLBuiltinType . Types . Float32Array ) ,
IDLBuiltinType . Types . Float64Array :
IDLBuiltinType ( BuiltinLocation ( " <builtin type> " ) , " Float64Array " ,
IDLBuiltinType . Types . Float64Array )
2012-03-31 04:42:20 +00:00
}
integerTypeSizes = {
IDLBuiltinType . Types . byte : ( - 128 , 127 ) ,
IDLBuiltinType . Types . octet : ( 0 , 255 ) ,
IDLBuiltinType . Types . short : ( - 32768 , 32767 ) ,
IDLBuiltinType . Types . unsigned_short : ( 0 , 65535 ) ,
IDLBuiltinType . Types . long : ( - 2147483648 , 2147483647 ) ,
IDLBuiltinType . Types . unsigned_long : ( 0 , 4294967295 ) ,
IDLBuiltinType . Types . long_long : ( - 9223372036854775808 ,
9223372036854775807 ) ,
IDLBuiltinType . Types . unsigned_long_long : ( 0 , 18446744073709551615 )
}
def matchIntegerValueToType ( value ) :
for type , extremes in integerTypeSizes . items ( ) :
( min , max ) = extremes
if value < = max and value > = min :
return BuiltinTypes [ type ]
return None
class IDLValue ( IDLObject ) :
def __init__ ( self , location , type , value ) :
IDLObject . __init__ ( self , location )
self . type = type
assert isinstance ( type , IDLType )
self . value = value
def coerceToType ( self , type , location ) :
if type == self . type :
return self # Nothing to do
2013-08-30 03:29:38 +00:00
# We first check for unions to ensure that even if the union is nullable
# we end up with the right flat member type, not the union's type.
if type . isUnion ( ) :
2013-10-28 04:33:15 +00:00
# We use the flat member types here, because if we have a nullable
# member type, or a nested union, we want the type the value
# actually coerces to, not the nullable or nested union type.
for subtype in type . unroll ( ) . flatMemberTypes :
2013-08-30 03:29:38 +00:00
try :
coercedValue = self . coerceToType ( subtype , location )
# Create a new IDLValue to make sure that we have the
# correct float/double type. This is necessary because we
# use the value's type when it is a default value of a
# union, and the union cares about the exact float type.
return IDLValue ( self . location , subtype , coercedValue . value )
except :
pass
2013-04-20 03:04:19 +00:00
# If the type allows null, rerun this matching on the inner type, except
# nullable enums. We handle those specially, because we want our
# default string values to stay strings even when assigned to a nullable
# enum.
2013-08-30 03:29:38 +00:00
elif type . nullable ( ) and not type . isEnum ( ) :
2012-03-31 04:42:20 +00:00
innerValue = self . coerceToType ( type . inner , location )
return IDLValue ( self . location , type , innerValue . value )
2013-08-30 03:29:38 +00:00
elif self . type . isInteger ( ) and type . isInteger ( ) :
2012-03-31 04:42:20 +00:00
# We're both integer types. See if we fit.
2012-04-12 22:14:10 +00:00
( min , max ) = integerTypeSizes [ type . _typeTag ]
2012-03-31 04:42:20 +00:00
if self . value < = max and self . value > = min :
# Promote
return IDLValue ( self . location , type , self . value )
else :
raise WebIDLError ( " Value %s is out of range for type %s . " %
2012-06-30 05:53:28 +00:00
( self . value , type ) , [ location ] )
2012-11-01 16:30:21 +00:00
elif self . type . isInteger ( ) and type . isFloat ( ) :
# Convert an integer literal into float
if - 2 * * 24 < = self . value < = 2 * * 24 :
floatType = BuiltinTypes [ IDLBuiltinType . Types . float ]
return IDLValue ( self . location , floatType , float ( self . value ) )
else :
raise WebIDLError ( " Converting value %s to %s will lose precision. " %
( self . value , type ) , [ location ] )
2012-07-31 04:22:23 +00:00
elif self . type . isString ( ) and type . isEnum ( ) :
# Just keep our string, but make sure it's a valid value for this enum
2013-04-20 03:04:19 +00:00
enum = type . unroll ( ) . inner
if self . value not in enum . values ( ) :
2012-07-31 04:22:23 +00:00
raise WebIDLError ( " ' %s ' is not a valid default value for enum %s "
2013-04-20 03:04:19 +00:00
% ( self . value , enum . identifier . name ) ,
[ location , enum . location ] )
2012-07-31 04:22:23 +00:00
return self
2013-04-18 16:58:01 +00:00
elif self . type . isFloat ( ) and type . isFloat ( ) :
if ( not type . isUnrestricted ( ) and
( self . value == float ( " inf " ) or self . value == float ( " -inf " ) or
math . isnan ( self . value ) ) ) :
raise WebIDLError ( " Trying to convert unrestricted value %s to non-unrestricted "
% self . value , [ location ] ) ;
return self
2014-11-20 11:58:00 +00:00
elif self . type . isString ( ) and type . isUSVString ( ) :
# Allow USVStrings to use default value just like
2014-08-01 20:23:48 +00:00
# DOMString. No coercion is required in this case as Codegen.py
2014-11-20 11:58:00 +00:00
# treats USVString just like DOMString, but with an
2014-08-01 20:23:48 +00:00
# extra normalization step.
assert self . type . isDOMString ( )
return self
2013-08-30 03:29:38 +00:00
raise WebIDLError ( " Cannot coerce type %s to type %s . " %
( self . type , type ) , [ location ] )
2012-03-31 04:42:20 +00:00
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( )
2012-03-31 04:42:20 +00:00
class IDLNullValue ( IDLObject ) :
def __init__ ( self , location ) :
IDLObject . __init__ ( self , location )
self . type = None
self . value = None
def coerceToType ( self , type , location ) :
2012-07-17 16:18:53 +00:00
if ( not isinstance ( type , IDLNullableType ) and
not ( type . isUnion ( ) and type . hasNullableType ) and
2013-09-26 04:05:00 +00:00
not ( type . isUnion ( ) and type . hasDictionaryType ) and
2012-07-31 04:22:22 +00:00
not type . isDictionary ( ) and
not type . isAny ( ) ) :
2012-03-31 04:42:20 +00:00
raise WebIDLError ( " Cannot coerce null value to type %s . " % type ,
2012-06-30 05:53:28 +00:00
[ location ] )
2012-03-31 04:42:20 +00:00
nullValue = IDLNullValue ( self . location )
2013-10-28 04:33:15 +00:00
if type . isUnion ( ) and not type . nullable ( ) and type . hasDictionaryType :
# We're actually a default value for the union's dictionary member.
# Use its type.
for t in type . flatMemberTypes :
if t . isDictionary ( ) :
nullValue . type = t
return nullValue
2012-03-31 04:42:20 +00:00
nullValue . type = type
return nullValue
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( )
2014-02-19 15:13:38 +00:00
2014-06-23 20:03:56 +00:00
class IDLEmptySequenceValue ( IDLObject ) :
def __init__ ( self , location ) :
IDLObject . __init__ ( self , location )
self . type = None
self . value = None
def coerceToType ( self , type , location ) :
2014-06-23 20:03:58 +00:00
if type . isUnion ( ) :
# We use the flat member types here, because if we have a nullable
# member type, or a nested union, we want the type the value
# actually coerces to, not the nullable or nested union type.
for subtype in type . unroll ( ) . flatMemberTypes :
try :
return self . coerceToType ( subtype , location )
except :
pass
if not type . isSequence ( ) :
2014-06-23 20:03:56 +00:00
raise WebIDLError ( " Cannot coerce empty sequence value to type %s . " % type ,
[ location ] )
emptySequenceValue = IDLEmptySequenceValue ( self . location )
emptySequenceValue . type = type
return emptySequenceValue
def _getDependentObjects ( self ) :
return set ( )
2014-02-19 15:13:38 +00:00
class IDLUndefinedValue ( IDLObject ) :
def __init__ ( self , location ) :
IDLObject . __init__ ( self , location )
self . type = None
self . value = None
def coerceToType ( self , type , location ) :
if not type . isAny ( ) :
raise WebIDLError ( " Cannot coerce undefined value to type %s . " % type ,
[ location ] )
undefinedValue = IDLUndefinedValue ( self . location )
undefinedValue . type = type
return undefinedValue
def _getDependentObjects ( self ) :
return set ( )
2012-03-31 04:42:20 +00:00
class IDLInterfaceMember ( IDLObjectWithIdentifier ) :
Tags = enum (
' Const ' ,
' Attr ' ,
' Method '
)
2012-10-19 07:34:28 +00:00
Special = enum (
' Static ' ,
' Stringifier '
)
2015-01-15 22:39:01 +00:00
AffectsValues = ( " Nothing " , " Everything " )
2015-01-15 22:39:01 +00:00
DependsOnValues = ( " Nothing " , " DOMState " , " DeviceState " , " Everything " )
2015-01-15 22:39:01 +00:00
2012-03-31 04:42:20 +00:00
def __init__ ( self , location , identifier , tag ) :
IDLObjectWithIdentifier . __init__ ( self , location , None , identifier )
self . tag = tag
2012-07-13 23:29:14 +00:00
self . _extendedAttrDict = { }
2014-08-05 02:20:34 +00:00
# _exposureGlobalNames are the global names listed in our [Exposed]
# extended attribute. exposureSet is the exposure set as defined in the
# Web IDL spec: it contains interface names.
self . _exposureGlobalNames = set ( )
self . exposureSet = set ( )
2012-03-31 04:42:20 +00:00
def isMethod ( self ) :
return self . tag == IDLInterfaceMember . Tags . Method
def isAttr ( self ) :
return self . tag == IDLInterfaceMember . Tags . Attr
def isConst ( self ) :
return self . tag == IDLInterfaceMember . Tags . Const
def addExtendedAttributes ( self , attrs ) :
for attr in attrs :
2012-09-12 16:24:58 +00:00
self . handleExtendedAttribute ( attr )
attrlist = attr . listValue ( )
self . _extendedAttrDict [ attr . identifier ( ) ] = attrlist if len ( attrlist ) else True
2012-03-31 04:42:20 +00:00
2012-09-12 16:24:58 +00:00
def handleExtendedAttribute ( self , attr ) :
2012-03-31 04:42:20 +00:00
pass
2012-04-10 16:40:12 +00:00
def getExtendedAttribute ( self , name ) :
2012-03-31 04:42:20 +00:00
return self . _extendedAttrDict . get ( name , None )
2014-08-05 02:20:34 +00:00
def finish ( self , scope ) :
for globalName in self . _exposureGlobalNames :
if globalName not in scope . globalNames :
raise WebIDLError ( " Unknown [Exposed] value %s " % globalName ,
[ self . location ] )
globalNameSetToExposureSet ( scope , self . _exposureGlobalNames ,
self . exposureSet )
2014-08-05 02:20:35 +00:00
self . _scope = scope
def validate ( self ) :
if ( self . getExtendedAttribute ( " Pref " ) and
self . exposureSet != set ( [ self . _scope . primaryGlobalName ] ) ) :
raise WebIDLError ( " [Pref] used on an interface member that is not "
" %s -only " % self . _scope . primaryGlobalName ,
[ self . location ] )
2014-08-05 02:20:34 +00:00
2014-08-25 19:07:44 +00:00
if ( self . getExtendedAttribute ( " CheckPermissions " ) and
self . exposureSet != set ( [ self . _scope . primaryGlobalName ] ) ) :
raise WebIDLError ( " [CheckPermissions] used on an interface member "
" that is not %s -only " %
self . _scope . primaryGlobalName ,
[ self . location ] )
2015-01-15 22:39:01 +00:00
if self . isAttr ( ) or self . isMethod ( ) :
if self . affects == " Everything " and self . dependsOn != " Everything " :
raise WebIDLError ( " Interface member is flagged as affecting "
" everything but not depending on everything. "
" That seems rather unlikely. " ,
[ self . location ] )
2015-01-15 22:39:01 +00:00
def _setDependsOn ( self , dependsOn ) :
if self . dependsOn != " Everything " :
2015-01-15 22:39:01 +00:00
raise WebIDLError ( " Trying to specify multiple different DependsOn, "
2015-01-15 22:39:01 +00:00
" Pure, or Constant extended attributes for "
" attribute " , [ self . location ] )
2015-01-15 22:39:01 +00:00
if dependsOn not in IDLInterfaceMember . DependsOnValues :
raise WebIDLError ( " Invalid [DependsOn= %s ] on attribute " % dependsOn ,
[ self . location ] )
2015-01-15 22:39:01 +00:00
self . dependsOn = dependsOn
def _setAffects ( self , affects ) :
if self . affects != " Everything " :
2015-01-15 22:39:01 +00:00
raise WebIDLError ( " Trying to specify multiple different Affects, "
2015-01-15 22:39:01 +00:00
" Pure, or Constant extended attributes for "
" attribute " , [ self . location ] )
2015-01-15 22:39:01 +00:00
if affects not in IDLInterfaceMember . AffectsValues :
raise WebIDLError ( " Invalid [Affects= %s ] on attribute " % dependsOn ,
[ self . location ] )
2015-01-15 22:39:01 +00:00
self . affects = affects
2012-03-31 04:42:20 +00:00
class IDLConst ( IDLInterfaceMember ) :
def __init__ ( self , location , identifier , type , value ) :
IDLInterfaceMember . __init__ ( self , location , identifier ,
IDLInterfaceMember . Tags . Const )
assert isinstance ( type , IDLType )
2012-06-12 14:22:05 +00:00
if type . isDictionary ( ) :
raise WebIDLError ( " A constant cannot be of a dictionary type " ,
2012-06-30 05:53:28 +00:00
[ self . location ] )
2012-03-31 04:42:20 +00:00
self . type = type
2012-09-06 14:23:51 +00:00
self . value = value
2012-03-31 04:42:20 +00:00
2013-01-10 19:54:13 +00:00
if identifier . name == " prototype " :
raise WebIDLError ( " The identifier of a constant must not be ' prototype ' " ,
[ location ] )
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
return " ' %s ' const ' %s ' " % ( self . type , self . identifier )
def finish ( self , scope ) :
2014-08-05 02:20:34 +00:00
IDLInterfaceMember . finish ( self , scope )
2012-09-06 14:23:51 +00:00
if not self . type . isComplete ( ) :
type = self . type . complete ( scope )
if not type . isPrimitive ( ) and not type . isString ( ) :
locations = [ self . type . location , type . location ]
try :
locations . append ( type . inner . location )
except :
pass
raise WebIDLError ( " Incorrect type for constant " , locations )
self . type = type
# The value might not match the type
coercedValue = self . value . coerceToType ( self . type , self . location )
assert coercedValue
self . value = coercedValue
2012-03-31 04:42:20 +00:00
2012-06-22 20:18:50 +00:00
def validate ( self ) :
2014-08-05 02:20:35 +00:00
IDLInterfaceMember . validate ( self )
2012-06-22 20:18:50 +00:00
2014-08-05 02:20:34 +00:00
def handleExtendedAttribute ( self , attr ) :
identifier = attr . identifier ( )
if identifier == " Exposed " :
convertExposedAttrToGlobalNameSet ( attr , self . _exposureGlobalNames )
elif ( identifier == " Pref " or
identifier == " ChromeOnly " or
identifier == " Func " or
identifier == " AvailableIn " or
identifier == " CheckPermissions " ) :
# Known attributes that we don't need to do anything with here
pass
else :
raise WebIDLError ( " Unknown extended attribute %s on constant " % identifier ,
[ attr . location ] )
IDLInterfaceMember . handleExtendedAttribute ( self , attr )
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( [ self . type , self . value ] )
2012-03-31 04:42:20 +00:00
class IDLAttribute ( IDLInterfaceMember ) :
2012-10-19 07:34:28 +00:00
def __init__ ( self , location , identifier , type , readonly , inherit = False ,
static = False , stringifier = False ) :
2012-03-31 04:42:20 +00:00
IDLInterfaceMember . __init__ ( self , location , identifier ,
IDLInterfaceMember . Tags . Attr )
assert isinstance ( type , IDLType )
self . type = type
self . readonly = readonly
self . inherit = inherit
2012-09-12 16:24:58 +00:00
self . static = static
self . lenientThis = False
2012-10-24 20:10:49 +00:00
self . _unforgeable = False
2012-10-19 07:34:28 +00:00
self . stringifier = stringifier
2013-09-10 02:10:45 +00:00
self . enforceRange = False
self . clamp = False
2013-12-04 13:02:17 +00:00
self . slotIndex = None
2015-01-15 22:39:01 +00:00
self . dependsOn = " Everything "
self . affects = " Everything "
2012-03-31 04:42:20 +00:00
2013-01-10 19:54:13 +00:00
if static and identifier . name == " prototype " :
raise WebIDLError ( " The identifier of a static attribute must not be ' prototype ' " ,
[ location ] )
2012-03-31 04:42:20 +00:00
if readonly and inherit :
raise WebIDLError ( " An attribute cannot be both ' readonly ' and ' inherit ' " ,
2012-06-30 05:53:28 +00:00
[ self . location ] )
2012-03-31 04:42:20 +00:00
2012-09-12 16:24:58 +00:00
def isStatic ( self ) :
return self . static
2012-03-31 04:42:20 +00:00
def __str__ ( self ) :
return " ' %s ' attribute ' %s ' " % ( self . type , self . identifier )
def finish ( self , scope ) :
2014-08-05 02:20:34 +00:00
IDLInterfaceMember . finish ( self , scope )
2012-03-31 04:42:20 +00:00
if not self . type . isComplete ( ) :
t = self . type . complete ( scope )
assert not isinstance ( t , IDLUnresolvedType )
2012-09-06 14:23:51 +00:00
assert not isinstance ( t , IDLTypedefType )
2012-03-31 04:42:20 +00:00
assert not isinstance ( t . name , IDLUnresolvedIdentifier )
self . type = t
2014-02-05 18:38:15 +00:00
if self . type . isDictionary ( ) and not self . getExtendedAttribute ( " Cached " ) :
2012-05-18 21:25:47 +00:00
raise WebIDLError ( " An attribute cannot be of a dictionary type " ,
2012-06-30 05:53:28 +00:00
[ self . location ] )
2013-12-04 13:02:18 +00:00
if self . type . isSequence ( ) and not self . getExtendedAttribute ( " Cached " ) :
raise WebIDLError ( " A non-cached attribute cannot be of a sequence "
" type " , [ self . location ] )
2014-05-23 21:32:38 +00:00
if self . type . isMozMap ( ) and not self . getExtendedAttribute ( " Cached " ) :
raise WebIDLError ( " A non-cached attribute cannot be of a MozMap "
" type " , [ self . location ] )
2012-05-18 21:25:47 +00:00
if self . type . isUnion ( ) :
2013-07-26 18:25:54 +00:00
for f in self . type . unroll ( ) . flatMemberTypes :
2012-05-18 21:25:47 +00:00
if f . isDictionary ( ) :
raise WebIDLError ( " An attribute cannot be of a union "
" type if one of its member types (or "
" one of its member types ' s member "
" types, and so on) is a dictionary "
2012-06-30 05:53:28 +00:00
" type " , [ self . location , f . location ] )
2012-05-18 21:25:47 +00:00
if f . isSequence ( ) :
raise WebIDLError ( " An attribute cannot be of a union "
" type if one of its member types (or "
" one of its member types ' s member "
" types, and so on) is a sequence "
2012-06-30 05:53:28 +00:00
" type " , [ self . location , f . location ] )
2014-05-23 21:32:38 +00:00
if f . isMozMap ( ) :
raise WebIDLError ( " An attribute cannot be of a union "
" type if one of its member types (or "
" one of its member types ' s member "
" types, and so on) is a MozMap "
" type " , [ self . location , f . location ] )
2012-08-13 12:20:49 +00:00
if not self . type . isInterface ( ) and self . getExtendedAttribute ( " PutForwards " ) :
raise WebIDLError ( " An attribute with [PutForwards] must have an "
" interface type as its type " , [ self . location ] )
2012-05-18 21:25:47 +00:00
2013-08-29 04:30:05 +00:00
if not self . type . isInterface ( ) and self . getExtendedAttribute ( " SameObject " ) :
raise WebIDLError ( " An attribute with [SameObject] must have an "
" interface type as its type " , [ self . location ] )
2012-06-22 20:18:50 +00:00
def validate ( self ) :
2014-08-05 02:20:35 +00:00
IDLInterfaceMember . validate ( self )
2013-12-04 13:02:17 +00:00
if ( ( self . getExtendedAttribute ( " Cached " ) or
self . getExtendedAttribute ( " StoreInSlot " ) ) and
2015-01-15 22:39:01 +00:00
not self . affects == " Nothing " ) :
2013-12-04 13:02:17 +00:00
raise WebIDLError ( " Cached attributes and attributes stored in "
2015-01-15 22:39:01 +00:00
" slots must be Constant or Pure or "
" Affects=Nothing, since the getter won ' t always "
" be called. " ,
2013-12-04 13:02:17 +00:00
[ self . location ] )
2014-02-05 18:38:15 +00:00
if self . getExtendedAttribute ( " Frozen " ) :
2014-05-23 21:32:38 +00:00
if ( not self . type . isSequence ( ) and not self . type . isDictionary ( ) and
not self . type . isMozMap ( ) ) :
raise WebIDLError ( " [Frozen] is only allowed on "
" sequence-valued, dictionary-valued, and "
" MozMap-valued attributes " ,
2014-02-05 18:38:15 +00:00
[ self . location ] )
2014-08-05 02:20:34 +00:00
if not self . type . unroll ( ) . isExposedInAllOf ( self . exposureSet ) :
raise WebIDLError ( " Attribute returns a type that is not exposed "
" everywhere where the attribute is exposed " ,
[ self . location ] )
2012-06-22 20:18:50 +00:00
2012-09-12 16:24:58 +00:00
def handleExtendedAttribute ( self , attr ) :
identifier = attr . identifier ( )
2014-01-13 20:08:56 +00:00
if identifier == " SetterThrows " and self . readonly :
2012-07-27 04:09:10 +00:00
raise WebIDLError ( " Readonly attributes must not be flagged as "
2012-11-05 19:40:33 +00:00
" [SetterThrows] " ,
2012-07-27 04:09:10 +00:00
[ self . location ] )
2013-01-29 22:53:53 +00:00
elif ( ( ( identifier == " Throws " or identifier == " GetterThrows " ) and
2013-12-02 14:50:34 +00:00
self . getExtendedAttribute ( " StoreInSlot " ) ) or
( identifier == " StoreInSlot " and
2013-01-29 22:53:53 +00:00
( self . getExtendedAttribute ( " Throws " ) or
self . getExtendedAttribute ( " GetterThrows " ) ) ) ) :
2014-08-21 21:31:43 +00:00
raise WebIDLError ( " Throwing things can ' t be [StoreInSlot] " ,
2013-11-26 01:59:34 +00:00
[ attr . location ] )
2012-09-12 16:24:58 +00:00
elif identifier == " LenientThis " :
if not attr . noArguments ( ) :
raise WebIDLError ( " [LenientThis] must take no arguments " ,
[ attr . location ] )
if self . isStatic ( ) :
raise WebIDLError ( " [LenientThis] is only allowed on non-static "
" attributes " , [ attr . location , self . location ] )
2013-12-09 15:34:03 +00:00
if self . getExtendedAttribute ( " CrossOriginReadable " ) :
raise WebIDLError ( " [LenientThis] is not allowed in combination "
" with [CrossOriginReadable] " ,
[ attr . location , self . location ] )
if self . getExtendedAttribute ( " CrossOriginWritable " ) :
raise WebIDLError ( " [LenientThis] is not allowed in combination "
" with [CrossOriginWritable] " ,
[ attr . location , self . location ] )
2012-09-12 16:24:58 +00:00
self . lenientThis = True
2012-10-24 20:10:49 +00:00
elif identifier == " Unforgeable " :
2013-01-03 03:03:25 +00:00
if self . isStatic ( ) :
raise WebIDLError ( " [Unforgeable] is only allowed on non-static "
" attributes " , [ attr . location , self . location ] )
2012-10-24 20:10:49 +00:00
self . _unforgeable = True
2013-08-29 04:30:05 +00:00
elif identifier == " SameObject " and not self . readonly :
raise WebIDLError ( " [SameObject] only allowed on readonly attributes " ,
[ attr . location , self . location ] )
2012-11-28 21:28:36 +00:00
elif identifier == " Constant " and not self . readonly :
raise WebIDLError ( " [Constant] only allowed on readonly attributes " ,
[ attr . location , self . location ] )
2012-08-13 12:20:49 +00:00
elif identifier == " PutForwards " :
if not self . readonly :
raise WebIDLError ( " [PutForwards] is only allowed on readonly "
" attributes " , [ attr . location , self . location ] )
if self . isStatic ( ) :
raise WebIDLError ( " [PutForwards] is only allowed on non-static "
" attributes " , [ attr . location , self . location ] )
if self . getExtendedAttribute ( " Replaceable " ) is not None :
raise WebIDLError ( " [PutForwards] and [Replaceable] can ' t both "
" appear on the same attribute " ,
[ attr . location , self . location ] )
if not attr . hasValue ( ) :
raise WebIDLError ( " [PutForwards] takes an identifier " ,
[ attr . location , self . location ] )
elif identifier == " Replaceable " :
2014-08-20 15:31:39 +00:00
if not attr . noArguments ( ) :
raise WebIDLError ( " [Replaceable] must take no arguments " ,
[ attr . location ] )
if not self . readonly :
raise WebIDLError ( " [Replaceable] is only allowed on readonly "
" attributes " , [ attr . location , self . location ] )
if self . isStatic ( ) :
raise WebIDLError ( " [Replaceable] is only allowed on non-static "
" attributes " , [ attr . location , self . location ] )
2012-08-13 12:20:49 +00:00
if self . getExtendedAttribute ( " PutForwards " ) is not None :
raise WebIDLError ( " [PutForwards] and [Replaceable] can ' t both "
" appear on the same attribute " ,
[ attr . location , self . location ] )
2012-11-27 20:32:05 +00:00
elif identifier == " LenientFloat " :
if self . readonly :
raise WebIDLError ( " [LenientFloat] used on a readonly attribute " ,
[ attr . location , self . location ] )
if not self . type . includesRestrictedFloat ( ) :
raise WebIDLError ( " [LenientFloat] used on an attribute with a "
" non-restricted-float type " ,
[ attr . location , self . location ] )
2013-09-10 02:10:45 +00:00
elif identifier == " EnforceRange " :
if self . readonly :
raise WebIDLError ( " [EnforceRange] used on a readonly attribute " ,
[ attr . location , self . location ] )
self . enforceRange = True
elif identifier == " Clamp " :
if self . readonly :
raise WebIDLError ( " [Clamp] used on a readonly attribute " ,
[ attr . location , self . location ] )
self . clamp = True
2013-12-04 13:02:17 +00:00
elif identifier == " StoreInSlot " :
if self . getExtendedAttribute ( " Cached " ) :
raise WebIDLError ( " [StoreInSlot] and [Cached] must not be "
" specified on the same attribute " ,
[ attr . location , self . location ] )
elif identifier == " Cached " :
if self . getExtendedAttribute ( " StoreInSlot " ) :
raise WebIDLError ( " [Cached] and [StoreInSlot] must not be "
" specified on the same attribute " ,
[ attr . location , self . location ] )
2013-12-09 15:34:03 +00:00
elif ( identifier == " CrossOriginReadable " or
identifier == " CrossOriginWritable " ) :
2014-07-11 23:32:14 +00:00
if not attr . noArguments ( ) and identifier == " CrossOriginReadable " :
2013-12-09 15:34:03 +00:00
raise WebIDLError ( " [ %s ] must take no arguments " % identifier ,
[ attr . location ] )
if self . isStatic ( ) :
raise WebIDLError ( " [ %s ] is only allowed on non-static "
" attributes " % identifier ,
[ attr . location , self . location ] )
if self . getExtendedAttribute ( " LenientThis " ) :
raise WebIDLError ( " [LenientThis] is not allowed in combination "
" with [ %s ] " % identifier ,
[ attr . location , self . location ] )
2014-08-05 02:20:34 +00:00
elif identifier == " Exposed " :
convertExposedAttrToGlobalNameSet ( attr , self . _exposureGlobalNames )
2015-01-15 22:39:01 +00:00
elif identifier == " Pure " :
if not attr . noArguments ( ) :
raise WebIDLError ( " [Pure] must take no arguments " ,
[ attr . location ] )
self . _setDependsOn ( " DOMState " )
self . _setAffects ( " Nothing " )
elif identifier == " Constant " or identifier == " SameObject " :
if not attr . noArguments ( ) :
raise WebIDLError ( " [ %s ] must take no arguments " % identifier ,
[ attr . location ] )
self . _setDependsOn ( " Nothing " )
self . _setAffects ( " Nothing " )
2015-01-15 22:39:01 +00:00
elif identifier == " Affects " :
if not attr . hasValue ( ) :
raise WebIDLError ( " [Affects] takes an identifier " ,
[ attr . location ] )
self . _setAffects ( attr . value ( ) )
elif identifier == " DependsOn " :
if not attr . hasValue ( ) :
raise WebIDLError ( " [DependsOn] takes an identifier " ,
[ attr . location ] )
2015-01-15 22:39:01 +00:00
if ( attr . value ( ) != " Everything " and attr . value ( ) != " DOMState " and
not self . readonly ) :
raise WebIDLError ( " [DependsOn= %s ] only allowed on "
" readonly attributes " % attr . value ( ) ,
2015-01-15 22:39:01 +00:00
[ attr . location , self . location ] )
self . _setDependsOn ( attr . value ( ) )
2013-04-10 17:49:06 +00:00
elif ( identifier == " Pref " or
identifier == " SetterThrows " or
identifier == " Throws " or
identifier == " GetterThrows " or
identifier == " ChromeOnly " or
identifier == " Func " or
2014-02-05 18:38:15 +00:00
identifier == " Frozen " or
2014-02-05 18:38:17 +00:00
identifier == " AvailableIn " or
2014-05-25 18:31:07 +00:00
identifier == " NewObject " or
2014-08-20 23:32:19 +00:00
identifier == " UnsafeInPrerendering " or
2014-09-20 02:58:26 +00:00
identifier == " CheckPermissions " or
identifier == " BinaryName " ) :
2013-04-10 17:49:06 +00:00
# Known attributes that we don't need to do anything with here
pass
else :
2013-04-30 20:30:25 +00:00
raise WebIDLError ( " Unknown extended attribute %s on attribute " % identifier ,
2013-04-10 17:49:06 +00:00
[ attr . location ] )
2012-09-12 16:24:58 +00:00
IDLInterfaceMember . handleExtendedAttribute ( self , attr )
2012-03-31 04:42:20 +00:00
def resolve ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
self . type . resolveType ( parentScope )
IDLObjectWithIdentifier . resolve ( self , parentScope )
2012-09-01 00:59:46 +00:00
def addExtendedAttributes ( self , attrs ) :
attrs = self . checkForStringHandlingExtendedAttributes ( attrs )
IDLInterfaceMember . addExtendedAttributes ( self , attrs )
2012-09-12 16:24:58 +00:00
def hasLenientThis ( self ) :
return self . lenientThis
2012-10-24 20:10:49 +00:00
def isUnforgeable ( self ) :
return self . _unforgeable
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( [ self . type ] )
2012-03-31 04:42:20 +00:00
class IDLArgument ( IDLObjectWithIdentifier ) :
2012-06-30 05:53:32 +00:00
def __init__ ( self , location , identifier , type , optional = False , defaultValue = None , variadic = False , dictionaryMember = False ) :
2012-03-31 04:42:20 +00:00
IDLObjectWithIdentifier . __init__ ( self , location , None , identifier )
assert isinstance ( type , IDLType )
self . type = type
self . optional = optional
self . defaultValue = defaultValue
self . variadic = variadic
2012-06-30 05:53:32 +00:00
self . dictionaryMember = dictionaryMember
2012-07-17 16:18:53 +00:00
self . _isComplete = False
2012-09-06 07:25:03 +00:00
self . enforceRange = False
self . clamp = False
2014-01-09 06:12:27 +00:00
self . _allowTreatNonCallableAsNull = False
2012-03-31 04:42:20 +00:00
assert not variadic or optional
2014-09-19 04:02:33 +00:00
assert not variadic or not defaultValue
2012-03-31 04:42:20 +00:00
def addExtendedAttributes ( self , attrs ) :
2012-09-01 00:59:46 +00:00
attrs = self . checkForStringHandlingExtendedAttributes (
attrs ,
isDictionaryMember = self . dictionaryMember ,
isOptional = self . optional )
2012-09-06 07:25:03 +00:00
for attribute in attrs :
2012-09-12 16:24:58 +00:00
identifier = attribute . identifier ( )
if identifier == " Clamp " :
if not attribute . noArguments ( ) :
raise WebIDLError ( " [Clamp] must take no arguments " ,
[ attribute . location ] )
2012-09-06 07:25:03 +00:00
if self . enforceRange :
raise WebIDLError ( " [EnforceRange] and [Clamp] are mutually exclusive " ,
[ self . location ] ) ;
self . clamp = True
2012-09-12 16:24:58 +00:00
elif identifier == " EnforceRange " :
if not attribute . noArguments ( ) :
raise WebIDLError ( " [EnforceRange] must take no arguments " ,
[ attribute . location ] )
2012-09-06 07:25:03 +00:00
if self . clamp :
raise WebIDLError ( " [EnforceRange] and [Clamp] are mutually exclusive " ,
[ self . location ] ) ;
self . enforceRange = True
2014-01-09 06:12:27 +00:00
elif identifier == " TreatNonCallableAsNull " :
self . _allowTreatNonCallableAsNull = True
2012-09-06 07:25:03 +00:00
else :
raise WebIDLError ( " Unhandled extended attribute on an argument " ,
2012-09-12 16:24:58 +00:00
[ attribute . location ] )
2012-03-31 04:42:20 +00:00
2012-07-17 16:18:53 +00:00
def isComplete ( self ) :
return self . _isComplete
def complete ( self , scope ) :
if self . _isComplete :
return
self . _isComplete = True
if not self . type . isComplete ( ) :
type = self . type . complete ( scope )
assert not isinstance ( type , IDLUnresolvedType )
2012-09-06 14:23:51 +00:00
assert not isinstance ( type , IDLTypedefType )
2012-07-17 16:18:53 +00:00
assert not isinstance ( type . name , IDLUnresolvedIdentifier )
self . type = type
2013-09-26 04:05:00 +00:00
if ( ( self . type . isDictionary ( ) or
self . type . isUnion ( ) and self . type . unroll ( ) . hasDictionaryType ) and
2014-09-19 04:02:33 +00:00
self . optional and not self . defaultValue and not self . variadic ) :
# Default optional non-variadic dictionaries to null,
# for simplicity, so the codegen doesn't have to special-case this.
2012-07-17 16:18:53 +00:00
self . defaultValue = IDLNullValue ( self . location )
2014-02-19 15:13:38 +00:00
elif self . type . isAny ( ) :
assert ( self . defaultValue is None or
isinstance ( self . defaultValue , IDLNullValue ) )
2014-04-04 03:32:11 +00:00
# optional 'any' values always have a default value
if self . optional and not self . defaultValue and not self . variadic :
2014-02-19 15:13:38 +00:00
# Set the default value to undefined, for simplicity, so the
# codegen doesn't have to special-case this.
self . defaultValue = IDLUndefinedValue ( self . location )
2012-07-17 16:18:53 +00:00
# Now do the coercing thing; this needs to happen after the
# above creation of a default value.
if self . defaultValue :
self . defaultValue = self . defaultValue . coerceToType ( self . type ,
self . location )
assert self . defaultValue
2014-01-09 06:12:27 +00:00
def allowTreatNonCallableAsNull ( self ) :
return self . _allowTreatNonCallableAsNull
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
deps = set ( [ self . type ] )
if self . defaultValue :
deps . add ( self . defaultValue )
return deps
2014-09-05 18:28:43 +00:00
def canHaveMissingValue ( self ) :
return self . optional and not self . defaultValue
2012-03-31 04:42:20 +00:00
class IDLCallbackType ( IDLType , IDLObjectWithScope ) :
def __init__ ( self , location , parentScope , identifier , returnType , arguments ) :
assert isinstance ( returnType , IDLType )
IDLType . __init__ ( self , location , identifier . name )
self . _returnType = returnType
# Clone the list
self . _arguments = list ( arguments )
IDLObjectWithScope . __init__ ( self , location , parentScope , identifier )
for ( returnType , arguments ) in self . signatures ( ) :
for argument in arguments :
argument . resolve ( self )
2012-10-10 19:53:02 +00:00
self . _treatNonCallableAsNull = False
2014-01-13 20:08:56 +00:00
self . _treatNonObjectAsNull = False
2012-10-10 19:53:02 +00:00
2012-03-31 04:42:20 +00:00
def isCallback ( self ) :
return True
def signatures ( self ) :
return [ ( self . _returnType , self . _arguments ) ]
def tag ( self ) :
return IDLType . Tags . callback
def finish ( self , scope ) :
if not self . _returnType . isComplete ( ) :
2012-11-09 15:43:58 +00:00
type = self . _returnType . complete ( scope )
2012-03-31 04:42:20 +00:00
assert not isinstance ( type , IDLUnresolvedType )
2012-09-06 14:23:51 +00:00
assert not isinstance ( type , IDLTypedefType )
2012-03-31 04:42:20 +00:00
assert not isinstance ( type . name , IDLUnresolvedIdentifier )
self . _returnType = type
for argument in self . _arguments :
if argument . type . isComplete ( ) :
continue
type = argument . type . complete ( scope )
assert not isinstance ( type , IDLUnresolvedType )
2012-09-06 14:23:51 +00:00
assert not isinstance ( type , IDLTypedefType )
2012-03-31 04:42:20 +00:00
assert not isinstance ( type . name , IDLUnresolvedIdentifier )
argument . type = type
2012-06-22 20:18:50 +00:00
def validate ( self ) :
pass
2012-03-31 04:42:20 +00:00
def isDistinguishableFrom ( self , other ) :
2012-07-27 04:09:10 +00:00
if other . isUnion ( ) :
# Just forward to the union; it'll deal
return other . isDistinguishableFrom ( self )
2012-03-31 04:42:20 +00:00
return ( other . isPrimitive ( ) or other . isString ( ) or other . isEnum ( ) or
2014-09-24 13:11:30 +00:00
other . isNonCallbackInterface ( ) or other . isDate ( ) or
other . isSequence ( ) )
2012-03-31 04:42:20 +00:00
2012-10-10 19:53:02 +00:00
def addExtendedAttributes ( self , attrs ) :
unhandledAttrs = [ ]
for attr in attrs :
if attr . identifier ( ) == " TreatNonCallableAsNull " :
self . _treatNonCallableAsNull = True
2014-01-13 20:08:56 +00:00
elif attr . identifier ( ) == " TreatNonObjectAsNull " :
self . _treatNonObjectAsNull = True
2012-10-10 19:53:02 +00:00
else :
unhandledAttrs . append ( attr )
2014-01-13 20:08:56 +00:00
if self . _treatNonCallableAsNull and self . _treatNonObjectAsNull :
raise WebIDLError ( " Cannot specify both [TreatNonCallableAsNull] "
" and [TreatNonObjectAsNull] " , [ self . location ] )
2012-10-10 19:53:02 +00:00
if len ( unhandledAttrs ) != 0 :
IDLType . addExtendedAttributes ( self , unhandledAttrs )
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
return set ( [ self . _returnType ] + self . _arguments )
2012-07-06 16:21:24 +00:00
class IDLMethodOverload :
"""
A class that represents a single overload of a WebIDL method . This is not
quite the same as an element of the " effective overload set " in the spec ,
because separate IDLMethodOverloads are not created based on arguments being
optional . Rather , when multiple methods have the same name , there is an
IDLMethodOverload for each one , all hanging off an IDLMethod representing
the full set of overloads .
"""
def __init__ ( self , returnType , arguments , location ) :
self . returnType = returnType
# Clone the list of arguments, just in case
self . arguments = list ( arguments )
self . location = location
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
deps = set ( self . arguments )
deps . add ( self . returnType )
return deps
2012-03-31 04:42:20 +00:00
class IDLMethod ( IDLInterfaceMember , IDLScope ) :
Special = enum (
' Getter ' ,
' Setter ' ,
' Creator ' ,
' Deleter ' ,
' LegacyCaller ' ,
2012-10-19 07:34:28 +00:00
base = IDLInterfaceMember . Special
2012-03-31 04:42:20 +00:00
)
TypeSuffixModifier = enum (
' None ' ,
' QMark ' ,
' Brackets '
)
NamedOrIndexed = enum (
' Neither ' ,
' Named ' ,
' Indexed '
)
def __init__ ( self , location , identifier , returnType , arguments ,
2012-04-12 22:14:10 +00:00
static = False , getter = False , setter = False , creator = False ,
deleter = False , specialType = NamedOrIndexed . Neither ,
2013-07-26 16:00:49 +00:00
legacycaller = False , stringifier = False , jsonifier = False ) :
2012-04-12 22:14:10 +00:00
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
2012-03-31 04:42:20 +00:00
IDLInterfaceMember . __init__ ( self , location , identifier ,
IDLInterfaceMember . Tags . Method )
self . _hasOverloads = False
assert isinstance ( returnType , IDLType )
2012-07-06 16:21:24 +00:00
# self._overloads is a list of IDLMethodOverloads
self . _overloads = [ IDLMethodOverload ( returnType , arguments , location ) ]
2012-03-31 04:42:20 +00:00
assert isinstance ( static , bool )
self . _static = static
assert isinstance ( getter , bool )
self . _getter = getter
assert isinstance ( setter , bool )
self . _setter = setter
assert isinstance ( creator , bool )
self . _creator = creator
assert isinstance ( deleter , bool )
self . _deleter = deleter
assert isinstance ( legacycaller , bool )
self . _legacycaller = legacycaller
assert isinstance ( stringifier , bool )
self . _stringifier = stringifier
2013-07-26 16:00:49 +00:00
assert isinstance ( jsonifier , bool )
self . _jsonifier = jsonifier
2012-03-31 04:42:20 +00:00
self . _specialType = specialType
2014-07-04 13:02:10 +00:00
self . _unforgeable = False
2015-01-15 22:39:01 +00:00
self . dependsOn = " Everything "
self . affects = " Everything "
2012-03-31 04:42:20 +00:00
2013-01-10 19:54:13 +00:00
if static and identifier . name == " prototype " :
raise WebIDLError ( " The identifier of a static operation must not be ' prototype ' " ,
[ location ] )
2012-03-31 04:42:20 +00:00
self . assertSignatureConstraints ( )
def __str__ ( self ) :
return " Method ' %s ' " % self . identifier
def assertSignatureConstraints ( self ) :
if self . _getter or self . _deleter :
2012-07-06 16:21:24 +00:00
assert len ( self . _overloads ) == 1
overload = self . _overloads [ 0 ]
arguments = overload . arguments
assert len ( arguments ) == 1
assert arguments [ 0 ] . type == BuiltinTypes [ IDLBuiltinType . Types . domstring ] or \
arguments [ 0 ] . type == BuiltinTypes [ IDLBuiltinType . Types . unsigned_long ]
assert not arguments [ 0 ] . optional and not arguments [ 0 ] . variadic
assert not self . _getter or not overload . returnType . isVoid ( )
2012-03-31 04:42:20 +00:00
if self . _setter or self . _creator :
2012-07-06 16:21:24 +00:00
assert len ( self . _overloads ) == 1
arguments = self . _overloads [ 0 ] . arguments
assert len ( arguments ) == 2
assert arguments [ 0 ] . type == BuiltinTypes [ IDLBuiltinType . Types . domstring ] or \
arguments [ 0 ] . type == BuiltinTypes [ IDLBuiltinType . Types . unsigned_long ]
assert not arguments [ 0 ] . optional and not arguments [ 0 ] . variadic
assert not arguments [ 1 ] . optional and not arguments [ 1 ] . variadic
2012-03-31 04:42:20 +00:00
if self . _stringifier :
2012-07-06 16:21:24 +00:00
assert len ( self . _overloads ) == 1
overload = self . _overloads [ 0 ]
assert len ( overload . arguments ) == 0
assert overload . returnType == BuiltinTypes [ IDLBuiltinType . Types . domstring ]
2012-03-31 04:42:20 +00:00
2013-07-26 16:00:49 +00:00
if self . _jsonifier :
assert len ( self . _overloads ) == 1
overload = self . _overloads [ 0 ]
assert len ( overload . arguments ) == 0
assert overload . returnType == BuiltinTypes [ IDLBuiltinType . Types . object ]
2012-03-31 04:42:20 +00:00
def isStatic ( self ) :
return self . _static
def isGetter ( self ) :
return self . _getter
def isSetter ( self ) :
return self . _setter
def isCreator ( self ) :
return self . _creator
def isDeleter ( self ) :
return self . _deleter
def isNamed ( self ) :
assert self . _specialType == IDLMethod . NamedOrIndexed . Named or \
self . _specialType == IDLMethod . NamedOrIndexed . Indexed
return self . _specialType == IDLMethod . NamedOrIndexed . Named
def isIndexed ( self ) :
assert self . _specialType == IDLMethod . NamedOrIndexed . Named or \
self . _specialType == IDLMethod . NamedOrIndexed . Indexed
return self . _specialType == IDLMethod . NamedOrIndexed . Indexed
def isLegacycaller ( self ) :
return self . _legacycaller
def isStringifier ( self ) :
return self . _stringifier
2013-07-26 16:00:49 +00:00
def isJsonifier ( self ) :
return self . _jsonifier
2012-03-31 04:42:20 +00:00
def hasOverloads ( self ) :
return self . _hasOverloads
2012-05-22 13:46:20 +00:00
def isIdentifierLess ( self ) :
2014-01-26 12:35:10 +00:00
return self . identifier . name [ : 2 ] == " __ " and self . identifier . name != " __noSuchMethod__ "
2012-05-22 13:46:20 +00:00
2012-03-31 04:42:20 +00:00
def resolve ( self , parentScope ) :
assert isinstance ( parentScope , IDLScope )
IDLObjectWithIdentifier . resolve ( self , parentScope )
IDLScope . __init__ ( self , self . location , parentScope , self . identifier )
for ( returnType , arguments ) in self . signatures ( ) :
for argument in arguments :
argument . resolve ( self )
def addOverload ( self , method ) :
2012-07-06 16:21:24 +00:00
assert len ( method . _overloads ) == 1
2012-03-31 04:42:20 +00:00
2012-07-13 23:29:14 +00:00
if self . _extendedAttrDict != method . _extendedAttrDict :
raise WebIDLError ( " Extended attributes differ on different "
" overloads of %s " % method . identifier ,
[ self . location , method . location ] )
2012-07-06 16:21:24 +00:00
self . _overloads . extend ( method . _overloads )
2012-03-31 04:42:20 +00:00
self . _hasOverloads = True
if self . isStatic ( ) != method . isStatic ( ) :
2012-07-13 23:29:14 +00:00
raise WebIDLError ( " Overloaded identifier %s appears with different values of the ' static ' attribute " % method . identifier ,
2012-06-30 05:53:28 +00:00
[ method . location ] )
2012-03-31 04:42:20 +00:00
if self . isLegacycaller ( ) != method . isLegacycaller ( ) :
2012-07-13 23:29:14 +00:00
raise WebIDLError ( " Overloaded identifier %s appears with different values of the ' legacycaller ' attribute " % method . identifier ,
2012-06-30 05:53:28 +00:00
[ method . location ] )
2012-03-31 04:42:20 +00:00
# Can't overload special things!
assert not self . isGetter ( )
assert not method . isGetter ( )
assert not self . isSetter ( )
assert not method . isSetter ( )
assert not self . isCreator ( )
assert not method . isCreator ( )
assert not self . isDeleter ( )
assert not method . isDeleter ( )
assert not self . isStringifier ( )
assert not method . isStringifier ( )
2013-07-26 16:00:49 +00:00
assert not self . isJsonifier ( )
assert not method . isJsonifier ( )
2012-03-31 04:42:20 +00:00
return self
def signatures ( self ) :
2012-07-06 16:21:24 +00:00
return [ ( overload . returnType , overload . arguments ) for overload in
self . _overloads ]
2012-03-31 04:42:20 +00:00
def finish ( self , scope ) :
2014-08-05 02:20:34 +00:00
IDLInterfaceMember . finish ( self , scope )
2014-03-21 16:18:24 +00:00
overloadWithPromiseReturnType = None
overloadWithoutPromiseReturnType = None
2012-07-06 16:21:24 +00:00
for overload in self . _overloads :
2012-07-17 16:18:53 +00:00
variadicArgument = None
2012-03-31 04:42:20 +00:00
2012-07-17 16:18:53 +00:00
arguments = overload . arguments
for ( idx , argument ) in enumerate ( arguments ) :
2013-10-11 16:28:23 +00:00
if not argument . isComplete ( ) :
argument . complete ( scope )
2012-07-17 16:18:53 +00:00
assert argument . type . isComplete ( )
2013-01-03 19:03:00 +00:00
if ( argument . type . isDictionary ( ) or
( argument . type . isUnion ( ) and
argument . type . unroll ( ) . hasDictionaryType ) ) :
# Dictionaries and unions containing dictionaries at the
# end of the list or followed by optional arguments must be
# optional.
2012-07-17 16:18:53 +00:00
if ( not argument . optional and
2013-10-11 16:28:23 +00:00
all ( arg . optional for arg in arguments [ idx + 1 : ] ) ) :
2013-01-03 19:03:00 +00:00
raise WebIDLError ( " Dictionary argument or union "
" argument containing a dictionary "
" not followed by a required argument "
" must be optional " ,
[ argument . location ] )
2012-07-17 16:18:53 +00:00
2012-11-30 23:30:05 +00:00
# An argument cannot be a Nullable Dictionary
if argument . type . nullable ( ) :
2013-01-03 19:03:00 +00:00
raise WebIDLError ( " An argument cannot be a nullable "
" dictionary or nullable union "
" containing a dictionary " ,
2012-11-30 23:30:05 +00:00
[ argument . location ] )
2012-07-17 16:18:53 +00:00
# Only the last argument can be variadic
if variadicArgument :
raise WebIDLError ( " Variadic argument is not last argument " ,
[ variadicArgument . location ] )
if argument . variadic :
variadicArgument = argument
2012-03-31 04:42:20 +00:00
2012-07-06 16:21:24 +00:00
returnType = overload . returnType
2014-03-21 16:18:24 +00:00
if not returnType . isComplete ( ) :
returnType = returnType . complete ( scope )
assert not isinstance ( returnType , IDLUnresolvedType )
assert not isinstance ( returnType , IDLTypedefType )
assert not isinstance ( returnType . name , IDLUnresolvedIdentifier )
overload . returnType = returnType
if returnType . isPromise ( ) :
overloadWithPromiseReturnType = overload
else :
overloadWithoutPromiseReturnType = overload
# Make sure either all our overloads return Promises or none do
if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType :
raise WebIDLError ( " We have overloads with both Promise and "
" non-Promise return types " ,
[ overloadWithPromiseReturnType . location ,
overloadWithoutPromiseReturnType . location ] )
if overloadWithPromiseReturnType and self . _legacycaller :
raise WebIDLError ( " May not have a Promise return type for a "
" legacycaller. " ,
[ overloadWithPromiseReturnType . location ] )
2012-07-06 16:21:24 +00:00
2012-06-22 20:18:50 +00:00
# Now compute various information that will be used by the
# WebIDL overload resolution algorithm.
self . maxArgCount = max ( len ( s [ 1 ] ) for s in self . signatures ( ) )
self . allowedArgCounts = [ i for i in range ( self . maxArgCount + 1 )
if len ( self . signaturesForArgCount ( i ) ) != 0 ]
def validate ( self ) :
2014-08-05 02:20:35 +00:00
IDLInterfaceMember . validate ( self )
2012-06-22 20:18:50 +00:00
# Make sure our overloads are properly distinguishable and don't have
# different argument types before the distinguishing args.
for argCount in self . allowedArgCounts :
2012-07-06 16:21:24 +00:00
possibleOverloads = self . overloadsForArgCount ( argCount )
if len ( possibleOverloads ) == 1 :
2012-06-22 20:18:50 +00:00
continue
distinguishingIndex = self . distinguishingIndexForArgCount ( argCount )
for idx in range ( distinguishingIndex ) :
2012-07-06 16:21:24 +00:00
firstSigType = possibleOverloads [ 0 ] . arguments [ idx ] . type
for overload in possibleOverloads [ 1 : ] :
if overload . arguments [ idx ] . type != firstSigType :
2012-06-22 20:18:50 +00:00
raise WebIDLError (
" Signatures for method ' %s ' with %d arguments have "
" different types of arguments at index %d , which "
" is before distinguishing index %d " %
( self . identifier . name , argCount , idx ,
distinguishingIndex ) ,
2012-07-06 16:21:24 +00:00
[ self . location , overload . location ] )
2014-08-05 02:20:34 +00:00
for overload in self . _overloads :
if not overload . returnType . unroll ( ) . isExposedInAllOf ( self . exposureSet ) :
raise WebIDLError ( " Overload returns a type that is not exposed "
" everywhere where the method is exposed " ,
[ overload . location ] )
2012-07-06 16:21:24 +00:00
def overloadsForArgCount ( self , argc ) :
return [ overload for overload in self . _overloads if
len ( overload . arguments ) == argc or
( len ( overload . arguments ) > argc and
2013-10-11 16:28:23 +00:00
all ( arg . optional for arg in overload . arguments [ argc : ] ) ) or
2012-12-11 22:50:56 +00:00
( len ( overload . arguments ) < argc and
len ( overload . arguments ) > 0 and
overload . arguments [ - 1 ] . variadic ) ]
2012-06-22 20:18:50 +00:00
def signaturesForArgCount ( self , argc ) :
2012-07-06 16:21:24 +00:00
return [ ( overload . returnType , overload . arguments ) for overload
in self . overloadsForArgCount ( argc ) ]
2012-06-22 20:18:50 +00:00
def locationsForArgCount ( self , argc ) :
2012-12-11 22:50:56 +00:00
return [ overload . location for overload in self . overloadsForArgCount ( argc ) ]
2012-06-22 20:18:50 +00:00
def distinguishingIndexForArgCount ( self , argc ) :
def isValidDistinguishingIndex ( idx , signatures ) :
for ( firstSigIndex , ( firstRetval , firstArgs ) ) in enumerate ( signatures [ : - 1 ] ) :
for ( secondRetval , secondArgs ) in signatures [ firstSigIndex + 1 : ] :
2012-12-11 22:50:56 +00:00
if idx < len ( firstArgs ) :
firstType = firstArgs [ idx ] . type
else :
assert ( firstArgs [ - 1 ] . variadic )
firstType = firstArgs [ - 1 ] . type
if idx < len ( secondArgs ) :
secondType = secondArgs [ idx ] . type
else :
assert ( secondArgs [ - 1 ] . variadic )
secondType = secondArgs [ - 1 ] . type
2012-06-22 20:18:50 +00:00
if not firstType . isDistinguishableFrom ( secondType ) :
return False
return True
signatures = self . signaturesForArgCount ( argc )
for idx in range ( argc ) :
if isValidDistinguishingIndex ( idx , signatures ) :
return idx
# No valid distinguishing index. Time to throw
locations = self . locationsForArgCount ( argc )
raise WebIDLError ( " Signatures with %d arguments for method ' %s ' are not "
" distinguishable " % ( argc , self . identifier . name ) ,
2012-06-30 05:53:28 +00:00
locations )
2012-06-22 20:18:50 +00:00
2012-09-12 16:24:58 +00:00
def handleExtendedAttribute ( self , attr ) :
identifier = attr . identifier ( )
2012-11-05 19:40:33 +00:00
if identifier == " GetterThrows " :
2012-07-27 04:09:10 +00:00
raise WebIDLError ( " Methods must not be flagged as "
2012-11-05 19:40:33 +00:00
" [GetterThrows] " ,
2012-09-12 16:24:58 +00:00
[ attr . location , self . location ] )
2012-11-05 19:40:33 +00:00
elif identifier == " SetterThrows " :
2012-07-27 04:09:10 +00:00
raise WebIDLError ( " Methods must not be flagged as "
2012-11-05 19:40:33 +00:00
" [SetterThrows] " ,
2012-09-12 16:24:58 +00:00
[ attr . location , self . location ] )
2012-10-24 20:10:49 +00:00
elif identifier == " Unforgeable " :
2014-07-04 13:02:10 +00:00
if self . isStatic ( ) :
raise WebIDLError ( " [Unforgeable] is only allowed on non-static "
" methods " , [ attr . location , self . location ] )
self . _unforgeable = True
2013-08-29 04:30:05 +00:00
elif identifier == " SameObject " :
raise WebIDLError ( " Methods must not be flagged as [SameObject] " ,
[ attr . location , self . location ] ) ;
2012-11-28 21:28:36 +00:00
elif identifier == " Constant " :
2013-01-29 22:53:53 +00:00
raise WebIDLError ( " Methods must not be flagged as [Constant] " ,
[ attr . location , self . location ] ) ;
2012-08-13 12:20:49 +00:00
elif identifier == " PutForwards " :
raise WebIDLError ( " Only attributes support [PutForwards] " ,
[ attr . location , self . location ] )
2012-11-27 20:32:05 +00:00
elif identifier == " LenientFloat " :
# This is called before we've done overload resolution
assert len ( self . signatures ( ) ) == 1
sig = self . signatures ( ) [ 0 ]
if not sig [ 0 ] . isVoid ( ) :
raise WebIDLError ( " [LenientFloat] used on a non-void method " ,
[ attr . location , self . location ] )
if not any ( arg . type . includesRestrictedFloat ( ) for arg in sig [ 1 ] ) :
raise WebIDLError ( " [LenientFloat] used on an operation with no "
" restricted float type arguments " ,
[ attr . location , self . location ] )
2014-08-05 02:20:34 +00:00
elif identifier == " Exposed " :
convertExposedAttrToGlobalNameSet ( attr , self . _exposureGlobalNames )
2015-01-15 22:39:01 +00:00
elif ( identifier == " CrossOriginCallable " or
2014-07-24 19:57:02 +00:00
identifier == " WebGLHandlesContextLoss " ) :
2014-07-11 23:32:14 +00:00
# Known no-argument attributes.
if not attr . noArguments ( ) :
raise WebIDLError ( " [ %s ] must take no arguments " % identifier ,
[ attr . location ] )
2015-01-15 22:39:01 +00:00
elif identifier == " Pure " :
if not attr . noArguments ( ) :
raise WebIDLError ( " [Pure] must take no arguments " ,
[ attr . location ] )
self . _setDependsOn ( " DOMState " )
self . _setAffects ( " Nothing " )
2015-01-15 22:39:01 +00:00
elif identifier == " Affects " :
if not attr . hasValue ( ) :
raise WebIDLError ( " [Affects] takes an identifier " ,
[ attr . location ] )
self . _setAffects ( attr . value ( ) )
elif identifier == " DependsOn " :
if not attr . hasValue ( ) :
raise WebIDLError ( " [DependsOn] takes an identifier " ,
[ attr . location ] )
self . _setDependsOn ( attr . value ( ) )
2013-04-10 17:49:06 +00:00
elif ( identifier == " Throws " or
2013-09-30 16:32:22 +00:00
identifier == " NewObject " or
2013-04-10 17:49:06 +00:00
identifier == " ChromeOnly " or
2014-08-20 23:32:19 +00:00
identifier == " UnsafeInPrerendering " or
2013-04-10 17:49:06 +00:00
identifier == " Pref " or
identifier == " Func " or
2014-02-05 18:38:17 +00:00
identifier == " AvailableIn " or
2014-09-20 02:58:26 +00:00
identifier == " CheckPermissions " or
identifier == " BinaryName " ) :
2013-04-10 17:49:06 +00:00
# Known attributes that we don't need to do anything with here
pass
else :
2013-04-30 20:30:25 +00:00
raise WebIDLError ( " Unknown extended attribute %s on method " % identifier ,
2013-04-10 17:49:06 +00:00
[ attr . location ] )
2012-09-12 16:24:58 +00:00
IDLInterfaceMember . handleExtendedAttribute ( self , attr )
2012-07-27 04:09:10 +00:00
2014-03-21 16:18:24 +00:00
def returnsPromise ( self ) :
return self . _overloads [ 0 ] . returnType . isPromise ( )
2014-07-04 13:02:10 +00:00
def isUnforgeable ( self ) :
return self . _unforgeable
2013-02-24 20:36:44 +00:00
def _getDependentObjects ( self ) :
deps = set ( )
for overload in self . _overloads :
2014-12-01 20:17:58 +00:00
deps . update ( overload . _getDependentObjects ( ) )
2013-02-24 20:36:44 +00:00
return deps
2012-06-11 22:21:35 +00:00
class IDLImplementsStatement ( IDLObject ) :
def __init__ ( self , location , implementor , implementee ) :
IDLObject . __init__ ( self , location )
self . implementor = implementor ;
self . implementee = implementee
2014-09-24 13:11:29 +00:00
self . _finished = False
2012-06-11 22:21:35 +00:00
def finish ( self , scope ) :
2014-09-24 13:11:29 +00:00
if self . _finished :
return
2012-06-12 14:22:05 +00:00
assert ( isinstance ( self . implementor , IDLIdentifierPlaceholder ) )
assert ( isinstance ( self . implementee , IDLIdentifierPlaceholder ) )
2012-06-11 22:21:35 +00:00
implementor = self . implementor . finish ( scope )
implementee = self . implementee . finish ( scope )
2012-06-22 20:18:51 +00:00
# NOTE: we depend on not setting self.implementor and
2012-06-22 20:21:44 +00:00
# self.implementee here to keep track of the original
2012-06-22 20:18:51 +00:00
# locations.
if not isinstance ( implementor , IDLInterface ) :
raise WebIDLError ( " Left-hand side of ' implements ' is not an "
" interface " ,
2012-06-30 05:53:28 +00:00
[ self . implementor . location ] )
2012-06-22 20:18:51 +00:00
if implementor . isCallback ( ) :
raise WebIDLError ( " Left-hand side of ' implements ' is a callback "
" interface " ,
2012-06-30 05:53:28 +00:00
[ self . implementor . location ] )
2012-06-22 20:18:51 +00:00
if not isinstance ( implementee , IDLInterface ) :
raise WebIDLError ( " Right-hand side of ' implements ' is not an "
" interface " ,
2012-06-30 05:53:28 +00:00
[ self . implementee . location ] )
2012-06-22 20:18:51 +00:00
if implementee . isCallback ( ) :
raise WebIDLError ( " Right-hand side of ' implements ' is a callback "
" interface " ,
2012-06-30 05:53:28 +00:00
[ self . implementee . location ] )
2012-06-11 22:21:35 +00:00
implementor . addImplementedInterface ( implementee )
2014-09-24 13:11:29 +00:00
self . implementor = implementor
self . implementee = implementee
2012-06-11 22:21:35 +00:00
2012-06-22 20:18:50 +00:00
def validate ( self ) :
pass
2012-06-11 22:21:35 +00:00
def addExtendedAttributes ( self , attrs ) :
assert len ( attrs ) == 0
2012-09-12 16:24:58 +00:00
class IDLExtendedAttribute ( IDLObject ) :
"""
A class to represent IDL extended attributes so we can give them locations
"""
def __init__ ( self , location , tuple ) :
IDLObject . __init__ ( self , location )
self . _tuple = tuple
def identifier ( self ) :
return self . _tuple [ 0 ]
def noArguments ( self ) :
return len ( self . _tuple ) == 1
def hasValue ( self ) :
2013-01-22 10:51:15 +00:00
return len ( self . _tuple ) > = 2 and isinstance ( self . _tuple [ 1 ] , str )
2012-09-12 16:24:58 +00:00
def value ( self ) :
assert ( self . hasValue ( ) )
return self . _tuple [ 1 ]
def hasArgs ( self ) :
return ( len ( self . _tuple ) == 2 and isinstance ( self . _tuple [ 1 ] , list ) or
len ( self . _tuple ) == 3 )
def args ( self ) :
assert ( self . hasArgs ( ) )
# Our args are our last element
return self . _tuple [ - 1 ]
def listValue ( self ) :
"""
Backdoor for storing random data in _extendedAttrDict
"""
return list ( self . _tuple ) [ 1 : ]
2012-03-31 04:42:20 +00:00
# Parser
class Tokenizer ( object ) :
tokens = [
" INTEGER " ,
2012-05-02 03:23:45 +00:00
" FLOATLITERAL " ,
2012-03-31 04:42:20 +00:00
" IDENTIFIER " ,
" STRING " ,
" WHITESPACE " ,
" OTHER "
]
2013-04-18 16:58:01 +00:00
def t_FLOATLITERAL ( self , t ) :
r ' (-?(([0-9]+ \ .[0-9]*|[0-9]* \ .[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN '
t . value = float ( t . value )
return t
2012-03-31 04:42:20 +00:00
def t_INTEGER ( self , t ) :
r ' -?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*) '
try :
2012-04-12 22:14:10 +00:00
# Can't use int(), because that doesn't handle octal properly.
2012-03-31 04:42:20 +00:00
t . value = parseInt ( t . value )
except :
raise WebIDLError ( " Invalid integer literal " ,
2012-06-30 05:53:28 +00:00
[ Location ( lexer = self . lexer ,
lineno = self . lexer . lineno ,
lexpos = self . lexer . lexpos ,
filename = self . _filename ) ] )
2012-03-31 04:42:20 +00:00
return t
def t_IDENTIFIER ( self , t ) :
2014-08-04 19:02:58 +00:00
r ' [A-Z_a-z][0-9A-Z_a-z-]* '
2012-03-31 04:42:20 +00:00
t . type = self . keywords . get ( t . value , ' IDENTIFIER ' )
return t
def t_STRING ( self , t ) :
r ' " [^ " ]* " '
t . value = t . value [ 1 : - 1 ]
return t
def t_WHITESPACE ( self , t ) :
r ' [ \ t \ n \ r ]+|[ \ t \ n \ r ]*((//[^ \ n]*|/ \ *.*? \ */)[ \ t \ n \ r ]*)+ '
pass
def t_ELLIPSIS ( self , t ) :
r ' \ . \ . \ . '
t . type = self . keywords . get ( t . value )
return t
def t_OTHER ( self , t ) :
r ' [^ \ t \ n \ r 0-9A-Z_a-z] '
t . type = self . keywords . get ( t . value , ' OTHER ' )
return t
keywords = {
" module " : " MODULE " ,
" interface " : " INTERFACE " ,
" partial " : " PARTIAL " ,
" dictionary " : " DICTIONARY " ,
" exception " : " EXCEPTION " ,
" enum " : " ENUM " ,
" callback " : " CALLBACK " ,
" typedef " : " TYPEDEF " ,
" implements " : " IMPLEMENTS " ,
" const " : " CONST " ,
" null " : " NULL " ,
" true " : " TRUE " ,
" false " : " FALSE " ,
2012-11-05 19:40:32 +00:00
" serializer " : " SERIALIZER " ,
2012-03-31 04:42:20 +00:00
" stringifier " : " STRINGIFIER " ,
2013-07-26 16:00:49 +00:00
" jsonifier " : " JSONIFIER " ,
2012-11-05 19:40:32 +00:00
" unrestricted " : " UNRESTRICTED " ,
2012-03-31 04:42:20 +00:00
" attribute " : " ATTRIBUTE " ,
" readonly " : " READONLY " ,
" inherit " : " INHERIT " ,
" static " : " STATIC " ,
" getter " : " GETTER " ,
" setter " : " SETTER " ,
" creator " : " CREATOR " ,
" deleter " : " DELETER " ,
" legacycaller " : " LEGACYCALLER " ,
" optional " : " OPTIONAL " ,
" ... " : " ELLIPSIS " ,
" :: " : " SCOPE " ,
" Date " : " DATE " ,
" DOMString " : " DOMSTRING " ,
2013-06-13 05:15:35 +00:00
" ByteString " : " BYTESTRING " ,
2014-11-20 11:58:00 +00:00
" USVString " : " USVSTRING " ,
2012-03-31 04:42:20 +00:00
" any " : " ANY " ,
" boolean " : " BOOLEAN " ,
" byte " : " BYTE " ,
" double " : " DOUBLE " ,
2012-05-02 03:23:45 +00:00
" float " : " FLOAT " ,
2012-03-31 04:42:20 +00:00
" long " : " LONG " ,
" object " : " OBJECT " ,
" octet " : " OCTET " ,
2014-08-01 03:50:30 +00:00
" Promise " : " PROMISE " ,
2014-09-05 18:28:42 +00:00
" required " : " REQUIRED " ,
2012-03-31 04:42:20 +00:00
" sequence " : " SEQUENCE " ,
2014-05-23 21:32:38 +00:00
" MozMap " : " MOZMAP " ,
2012-03-31 04:42:20 +00:00
" short " : " SHORT " ,
" unsigned " : " UNSIGNED " ,
" void " : " VOID " ,
" : " : " COLON " ,
" ; " : " SEMICOLON " ,
" { " : " LBRACE " ,
" } " : " RBRACE " ,
" ( " : " LPAREN " ,
" ) " : " RPAREN " ,
" [ " : " LBRACKET " ,
" ] " : " RBRACKET " ,
" ? " : " QUESTIONMARK " ,
" , " : " COMMA " ,
" = " : " EQUALS " ,
" < " : " LT " ,
" > " : " GT " ,
2012-05-18 21:25:47 +00:00
" ArrayBuffer " : " ARRAYBUFFER " ,
" or " : " OR "
2012-03-31 04:42:20 +00:00
}
tokens . extend ( keywords . values ( ) )
def t_error ( self , t ) :
raise WebIDLError ( " Unrecognized Input " ,
2012-06-30 05:53:28 +00:00
[ Location ( lexer = self . lexer ,
lineno = self . lexer . lineno ,
lexpos = self . lexer . lexpos ,
filename = self . filename ) ] )
2012-03-31 04:42:20 +00:00
2012-06-26 03:35:42 +00:00
def __init__ ( self , outputdir , lexer = None ) :
if lexer :
self . lexer = lexer
else :
self . lexer = lex . lex ( object = self ,
outputdir = outputdir ,
lextab = ' webidllex ' ,
reflags = re . DOTALL )
2012-03-31 04:42:20 +00:00
2014-08-05 02:20:32 +00:00
class SqueakyCleanLogger ( object ) :
errorWhitelist = [
# Web IDL defines the WHITESPACE token, but doesn't actually
# use it ... so far.
" Token ' WHITESPACE ' defined, but not used " ,
# And that means we have an unused token
" There is 1 unused token " ,
# Web IDL defines a OtherOrComma rule that's only used in
# ExtendedAttributeInner, which we don't use yet.
" Rule ' OtherOrComma ' defined, but not used " ,
# And an unused rule
" There is 1 unused rule " ,
# And the OtherOrComma grammar symbol is unreachable.
" Symbol ' OtherOrComma ' is unreachable " ,
# Which means the Other symbol is unreachable.
" Symbol ' Other ' is unreachable " ,
]
def __init__ ( self ) :
self . errors = [ ]
def debug ( self , msg , * args , * * kwargs ) :
pass
info = debug
def warning ( self , msg , * args , * * kwargs ) :
if msg == " %s : %d : Rule ' %s ' defined, but not used " :
# Munge things so we don't have to hardcode filenames and
# line numbers in our whitelist.
whitelistmsg = " Rule ' %s ' defined, but not used "
whitelistargs = args [ 2 : ]
else :
whitelistmsg = msg
whitelistargs = args
if ( whitelistmsg % whitelistargs ) not in SqueakyCleanLogger . errorWhitelist :
self . errors . append ( msg % args )
error = warning
def reportGrammarErrors ( self ) :
if self . errors :
raise WebIDLError ( " \n " . join ( self . errors ) , [ ] )
2012-03-31 04:42:20 +00:00
class Parser ( Tokenizer ) :
def getLocation ( self , p , i ) :
return Location ( self . lexer , p . lineno ( i ) , p . lexpos ( i ) , self . _filename )
def globalScope ( self ) :
return self . _globalScope
# The p_Foo functions here must match the WebIDL spec's grammar.
# It's acceptable to split things at '|' boundaries.
def p_Definitions ( self , p ) :
2014-05-05 19:24:00 +00:00
"""
2012-03-31 04:42:20 +00:00
Definitions : ExtendedAttributeList Definition Definitions
"""
if p [ 2 ] :
p [ 0 ] = [ p [ 2 ] ]
p [ 2 ] . addExtendedAttributes ( p [ 1 ] )
else :
assert not p [ 1 ]
p [ 0 ] = [ ]
p [ 0 ] . extend ( p [ 3 ] )
def p_DefinitionsEmpty ( self , p ) :
"""
Definitions :
"""
p [ 0 ] = [ ]
def p_Definition ( self , p ) :
"""
Definition : CallbackOrInterface
| PartialInterface
| Dictionary
| Exception
| Enum
| Typedef
| ImplementsStatement
"""
p [ 0 ] = p [ 1 ]
assert p [ 1 ] # We might not have implemented something ...
def p_CallbackOrInterfaceCallback ( self , p ) :
"""
CallbackOrInterface : CALLBACK CallbackRestOrInterface
"""
if p [ 2 ] . isInterface ( ) :
assert isinstance ( p [ 2 ] , IDLInterface )
p [ 2 ] . setCallback ( True )
p [ 0 ] = p [ 2 ]
def p_CallbackOrInterfaceInterface ( self , p ) :
"""
CallbackOrInterface : Interface
"""
p [ 0 ] = p [ 1 ]
def p_CallbackRestOrInterface ( self , p ) :
"""
CallbackRestOrInterface : CallbackRest
| Interface
"""
assert p [ 1 ]
p [ 0 ] = p [ 1 ]
def p_Interface ( self , p ) :
"""
Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
"""
location = self . getLocation ( p , 1 )
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 2 ) , p [ 2 ] )
members = p [ 5 ]
2013-01-10 15:49:07 +00:00
parent = p [ 3 ]
try :
2014-08-05 02:20:33 +00:00
existingObj = self . globalScope ( ) . _lookupIdentifier ( identifier )
if existingObj :
p [ 0 ] = existingObj
2013-01-10 15:49:07 +00:00
if not isinstance ( p [ 0 ] , IDLInterface ) :
2014-08-05 02:20:33 +00:00
raise WebIDLError ( " Interface has the same name as "
2013-01-10 15:49:07 +00:00
" non-interface object " ,
[ location , p [ 0 ] . location ] )
p [ 0 ] . setNonPartial ( location , parent , members )
return
except Exception , ex :
if isinstance ( ex , WebIDLError ) :
raise ex
pass
p [ 0 ] = IDLInterface ( location , self . globalScope ( ) , identifier , parent ,
2014-08-05 02:20:33 +00:00
members , isKnownNonPartial = True )
2012-03-31 04:42:20 +00:00
def p_InterfaceForwardDecl ( self , p ) :
"""
Interface : INTERFACE IDENTIFIER SEMICOLON
"""
location = self . getLocation ( p , 1 )
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 2 ) , p [ 2 ] )
try :
if self . globalScope ( ) . _lookupIdentifier ( identifier ) :
p [ 0 ] = self . globalScope ( ) . _lookupIdentifier ( identifier )
2013-05-09 17:08:29 +00:00
if not isinstance ( p [ 0 ] , IDLExternalInterface ) :
raise WebIDLError ( " Name collision between external "
" interface declaration for identifier "
" %s and %s " % ( identifier . name , p [ 0 ] ) ,
[ location , p [ 0 ] . location ] )
2012-03-31 04:42:20 +00:00
return
2013-05-09 17:08:29 +00:00
except Exception , ex :
if isinstance ( ex , WebIDLError ) :
raise ex
2012-03-31 04:42:20 +00:00
pass
p [ 0 ] = IDLExternalInterface ( location , self . globalScope ( ) , identifier )
def p_PartialInterface ( self , p ) :
"""
PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
"""
2013-01-10 15:49:07 +00:00
location = self . getLocation ( p , 2 )
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 3 ) , p [ 3 ] )
members = p [ 5 ]
2014-08-05 02:20:33 +00:00
nonPartialInterface = None
2013-01-10 15:49:07 +00:00
try :
2014-08-05 02:20:33 +00:00
nonPartialInterface = self . globalScope ( ) . _lookupIdentifier ( identifier )
if nonPartialInterface :
if not isinstance ( nonPartialInterface , IDLInterface ) :
2013-01-10 15:49:07 +00:00
raise WebIDLError ( " Partial interface has the same name as "
" non-interface object " ,
2014-08-05 02:20:33 +00:00
[ location , nonPartialInterface . location ] )
2013-01-10 15:49:07 +00:00
except Exception , ex :
if isinstance ( ex , WebIDLError ) :
raise ex
pass
2014-08-05 02:20:33 +00:00
if not nonPartialInterface :
nonPartialInterface = IDLInterface ( location , self . globalScope ( ) ,
identifier , None ,
[ ] , isKnownNonPartial = False )
partialInterface = IDLPartialInterface ( location , identifier , members ,
nonPartialInterface )
p [ 0 ] = partialInterface
2012-03-31 04:42:20 +00:00
def p_Inheritance ( self , p ) :
"""
Inheritance : COLON ScopedName
"""
2012-06-12 14:22:05 +00:00
p [ 0 ] = IDLIdentifierPlaceholder ( self . getLocation ( p , 2 ) , p [ 2 ] )
2012-03-31 04:42:20 +00:00
def p_InheritanceEmpty ( self , p ) :
"""
Inheritance :
"""
pass
def p_InterfaceMembers ( self , p ) :
"""
InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
"""
p [ 0 ] = [ p [ 2 ] ] if p [ 2 ] else [ ]
assert not p [ 1 ] or p [ 2 ]
p [ 2 ] . addExtendedAttributes ( p [ 1 ] )
p [ 0 ] . extend ( p [ 3 ] )
def p_InterfaceMembersEmpty ( self , p ) :
"""
InterfaceMembers :
"""
p [ 0 ] = [ ]
def p_InterfaceMember ( self , p ) :
"""
InterfaceMember : Const
| AttributeOrOperation
"""
p [ 0 ] = p [ 1 ]
def p_Dictionary ( self , p ) :
"""
Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
"""
2012-06-12 14:22:05 +00:00
location = self . getLocation ( p , 1 )
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 2 ) , p [ 2 ] )
members = p [ 5 ]
p [ 0 ] = IDLDictionary ( location , self . globalScope ( ) , identifier , p [ 3 ] , members )
2012-03-31 04:42:20 +00:00
def p_DictionaryMembers ( self , p ) :
"""
DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
|
"""
2012-06-12 14:22:05 +00:00
if len ( p ) == 1 :
# We're at the end of the list
p [ 0 ] = [ ]
return
# Add our extended attributes
p [ 2 ] . addExtendedAttributes ( p [ 1 ] )
p [ 0 ] = [ p [ 2 ] ]
p [ 0 ] . extend ( p [ 3 ] )
2012-03-31 04:42:20 +00:00
def p_DictionaryMember ( self , p ) :
"""
2014-09-05 18:28:42 +00:00
DictionaryMember : Required Type IDENTIFIER Default SEMICOLON
2012-03-31 04:42:20 +00:00
"""
2012-06-12 14:22:05 +00:00
# These quack a lot like optional arguments, so just treat them that way.
2014-09-05 18:28:42 +00:00
t = p [ 2 ]
2012-06-12 14:22:05 +00:00
assert isinstance ( t , IDLType )
2014-09-05 18:28:42 +00:00
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 3 ) , p [ 3 ] )
defaultValue = p [ 4 ]
optional = not p [ 1 ]
if not optional and defaultValue :
raise WebIDLError ( " Required dictionary members can ' t have a default value. " ,
[ self . getLocation ( p , 4 ) ] )
2012-06-12 14:22:05 +00:00
2014-09-05 18:28:42 +00:00
p [ 0 ] = IDLArgument ( self . getLocation ( p , 3 ) , identifier , t ,
optional = optional ,
2012-06-30 05:53:32 +00:00
defaultValue = defaultValue , variadic = False ,
dictionaryMember = True )
2012-03-31 04:42:20 +00:00
2014-06-23 20:03:56 +00:00
def p_Default ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2014-06-23 20:03:56 +00:00
Default : EQUALS DefaultValue
|
2012-03-31 04:42:20 +00:00
"""
if len ( p ) > 1 :
p [ 0 ] = p [ 2 ]
else :
p [ 0 ] = None
2014-06-23 20:03:56 +00:00
def p_DefaultValue ( self , p ) :
"""
DefaultValue : ConstValue
| LBRACKET RBRACKET
"""
if len ( p ) == 2 :
p [ 0 ] = p [ 1 ]
else :
assert len ( p ) == 3 # Must be []
p [ 0 ] = IDLEmptySequenceValue ( self . getLocation ( p , 1 ) )
2012-03-31 04:42:20 +00:00
def p_Exception ( self , p ) :
"""
Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON
"""
pass
def p_Enum ( self , p ) :
"""
Enum : ENUM IDENTIFIER LBRACE EnumValueList RBRACE SEMICOLON
"""
location = self . getLocation ( p , 1 )
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 2 ) , p [ 2 ] )
values = p [ 4 ]
assert values
p [ 0 ] = IDLEnum ( location , self . globalScope ( ) , identifier , values )
def p_EnumValueList ( self , p ) :
"""
2013-08-05 17:40:32 +00:00
EnumValueList : STRING EnumValueListComma
2012-03-31 04:42:20 +00:00
"""
p [ 0 ] = [ p [ 1 ] ]
p [ 0 ] . extend ( p [ 2 ] )
2013-08-05 17:40:32 +00:00
def p_EnumValueListComma ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2013-08-05 17:40:32 +00:00
EnumValueListComma : COMMA EnumValueListString
2012-03-31 04:42:20 +00:00
"""
2013-08-05 17:40:32 +00:00
p [ 0 ] = p [ 2 ]
def p_EnumValueListCommaEmpty ( self , p ) :
"""
EnumValueListComma :
"""
p [ 0 ] = [ ]
def p_EnumValueListString ( self , p ) :
"""
EnumValueListString : STRING EnumValueListComma
"""
p [ 0 ] = [ p [ 1 ] ]
p [ 0 ] . extend ( p [ 2 ] )
2012-03-31 04:42:20 +00:00
2013-08-05 17:40:32 +00:00
def p_EnumValueListStringEmpty ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2013-08-05 17:40:32 +00:00
EnumValueListString :
2012-03-31 04:42:20 +00:00
"""
p [ 0 ] = [ ]
def p_CallbackRest ( self , p ) :
"""
CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
"""
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 1 ) , p [ 1 ] )
p [ 0 ] = IDLCallbackType ( self . getLocation ( p , 1 ) , self . globalScope ( ) ,
identifier , p [ 3 ] , p [ 5 ] )
def p_ExceptionMembers ( self , p ) :
"""
ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
|
"""
pass
def p_Typedef ( self , p ) :
"""
Typedef : TYPEDEF Type IDENTIFIER SEMICOLON
"""
typedef = IDLTypedefType ( self . getLocation ( p , 1 ) , p [ 2 ] , p [ 3 ] )
typedef . resolve ( self . globalScope ( ) )
p [ 0 ] = typedef
def p_ImplementsStatement ( self , p ) :
"""
ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON
"""
2012-06-11 22:21:35 +00:00
assert ( p [ 2 ] == " implements " )
2012-06-12 14:22:05 +00:00
implementor = IDLIdentifierPlaceholder ( self . getLocation ( p , 1 ) , p [ 1 ] )
implementee = IDLIdentifierPlaceholder ( self . getLocation ( p , 3 ) , p [ 3 ] )
2012-06-11 22:21:35 +00:00
p [ 0 ] = IDLImplementsStatement ( self . getLocation ( p , 1 ) , implementor ,
implementee )
2012-03-31 04:42:20 +00:00
def p_Const ( self , p ) :
"""
Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON
"""
location = self . getLocation ( p , 1 )
type = p [ 2 ]
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 3 ) , p [ 3 ] )
value = p [ 5 ]
p [ 0 ] = IDLConst ( location , identifier , type , value )
def p_ConstValueBoolean ( self , p ) :
"""
ConstValue : BooleanLiteral
"""
location = self . getLocation ( p , 1 )
booleanType = BuiltinTypes [ IDLBuiltinType . Types . boolean ]
p [ 0 ] = IDLValue ( location , booleanType , p [ 1 ] )
def p_ConstValueInteger ( self , p ) :
"""
ConstValue : INTEGER
"""
location = self . getLocation ( p , 1 )
# We don't know ahead of time what type the integer literal is.
# Determine the smallest type it could possibly fit in and use that.
integerType = matchIntegerValueToType ( p [ 1 ] )
if integerType == None :
2012-06-30 05:53:28 +00:00
raise WebIDLError ( " Integer literal out of range " , [ location ] )
2012-03-31 04:42:20 +00:00
p [ 0 ] = IDLValue ( location , integerType , p [ 1 ] )
def p_ConstValueFloat ( self , p ) :
"""
2012-05-02 03:23:45 +00:00
ConstValue : FLOATLITERAL
2012-03-31 04:42:20 +00:00
"""
2013-04-18 16:58:01 +00:00
location = self . getLocation ( p , 1 )
p [ 0 ] = IDLValue ( location , BuiltinTypes [ IDLBuiltinType . Types . unrestricted_float ] , p [ 1 ] )
2012-03-31 04:42:20 +00:00
def p_ConstValueString ( self , p ) :
"""
ConstValue : STRING
"""
2012-07-31 04:22:23 +00:00
location = self . getLocation ( p , 1 )
stringType = BuiltinTypes [ IDLBuiltinType . Types . domstring ]
p [ 0 ] = IDLValue ( location , stringType , p [ 1 ] )
2012-03-31 04:42:20 +00:00
def p_ConstValueNull ( self , p ) :
"""
ConstValue : NULL
"""
p [ 0 ] = IDLNullValue ( self . getLocation ( p , 1 ) )
def p_BooleanLiteralTrue ( self , p ) :
"""
BooleanLiteral : TRUE
"""
p [ 0 ] = True
def p_BooleanLiteralFalse ( self , p ) :
"""
BooleanLiteral : FALSE
"""
p [ 0 ] = False
def p_AttributeOrOperation ( self , p ) :
"""
AttributeOrOperation : Attribute
| Operation
"""
p [ 0 ] = p [ 1 ]
2012-10-19 07:34:28 +00:00
def p_AttributeWithQualifier ( self , p ) :
"""
Attribute : Qualifier AttributeRest
"""
static = IDLInterfaceMember . Special . Static in p [ 1 ]
stringifier = IDLInterfaceMember . Special . Stringifier in p [ 1 ]
( location , identifier , type , readonly ) = p [ 2 ]
p [ 0 ] = IDLAttribute ( location , identifier , type , readonly , static = static ,
stringifier = stringifier )
2012-03-31 04:42:20 +00:00
def p_Attribute ( self , p ) :
"""
2012-10-19 07:34:28 +00:00
Attribute : Inherit AttributeRest
2012-03-31 04:42:20 +00:00
"""
2012-10-19 07:34:28 +00:00
( location , identifier , type , readonly ) = p [ 2 ]
p [ 0 ] = IDLAttribute ( location , identifier , type , readonly , inherit = p [ 1 ] )
def p_AttributeRest ( self , p ) :
"""
2014-09-05 18:28:42 +00:00
AttributeRest : ReadOnly ATTRIBUTE Type AttributeName SEMICOLON
2012-10-19 07:34:28 +00:00
"""
location = self . getLocation ( p , 2 )
readonly = p [ 1 ]
t = p [ 3 ]
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 4 ) , p [ 4 ] )
p [ 0 ] = ( location , identifier , t , readonly )
2012-03-31 04:42:20 +00:00
def p_ReadOnly ( self , p ) :
"""
ReadOnly : READONLY
"""
p [ 0 ] = True
def p_ReadOnlyEmpty ( self , p ) :
"""
ReadOnly :
"""
p [ 0 ] = False
def p_Inherit ( self , p ) :
"""
Inherit : INHERIT
"""
p [ 0 ] = True
def p_InheritEmpty ( self , p ) :
"""
Inherit :
"""
p [ 0 ] = False
def p_Operation ( self , p ) :
"""
Operation : Qualifiers OperationRest
"""
qualifiers = p [ 1 ]
# Disallow duplicates in the qualifier set
if not len ( set ( qualifiers ) ) == len ( qualifiers ) :
raise WebIDLError ( " Duplicate qualifiers are not allowed " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 1 ) ] )
2012-03-31 04:42:20 +00:00
2012-10-19 07:34:28 +00:00
static = IDLInterfaceMember . Special . Static in p [ 1 ]
2012-03-31 04:42:20 +00:00
# If static is there that's all that's allowed. This is disallowed
# by the parser, so we can assert here.
assert not static or len ( qualifiers ) == 1
2012-10-19 07:34:28 +00:00
stringifier = IDLInterfaceMember . Special . Stringifier in p [ 1 ]
# If stringifier is there that's all that's allowed. This is disallowed
# by the parser, so we can assert here.
assert not stringifier or len ( qualifiers ) == 1
2012-03-31 04:42:20 +00:00
getter = True if IDLMethod . Special . Getter in p [ 1 ] else False
setter = True if IDLMethod . Special . Setter in p [ 1 ] else False
creator = True if IDLMethod . Special . Creator in p [ 1 ] else False
deleter = True if IDLMethod . Special . Deleter in p [ 1 ] else False
legacycaller = True if IDLMethod . Special . LegacyCaller in p [ 1 ] else False
if getter or deleter :
if setter or creator :
raise WebIDLError ( " getter and deleter are incompatible with setter and creator " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 1 ) ] )
2012-03-31 04:42:20 +00:00
( returnType , identifier , arguments ) = p [ 2 ]
assert isinstance ( returnType , IDLType )
specialType = IDLMethod . NamedOrIndexed . Neither
if getter or deleter :
if len ( arguments ) != 1 :
raise WebIDLError ( " %s has wrong number of arguments " %
( " getter " if getter else " deleter " ) ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2012-03-31 04:42:20 +00:00
argType = arguments [ 0 ] . type
if argType == BuiltinTypes [ IDLBuiltinType . Types . domstring ] :
specialType = IDLMethod . NamedOrIndexed . Named
elif argType == BuiltinTypes [ IDLBuiltinType . Types . unsigned_long ] :
specialType = IDLMethod . NamedOrIndexed . Indexed
else :
raise WebIDLError ( " %s has wrong argument type (must be DOMString or UnsignedLong) " %
( " getter " if getter else " deleter " ) ,
2012-06-30 05:53:28 +00:00
[ arguments [ 0 ] . location ] )
2012-03-31 04:42:20 +00:00
if arguments [ 0 ] . optional or arguments [ 0 ] . variadic :
raise WebIDLError ( " %s cannot have %s argument " %
( " getter " if getter else " deleter " ,
" optional " if arguments [ 0 ] . optional else " variadic " ) ,
2012-06-30 05:53:28 +00:00
[ arguments [ 0 ] . location ] )
2012-05-22 10:02:21 +00:00
if getter :
2012-03-31 04:42:20 +00:00
if returnType . isVoid ( ) :
2012-05-22 10:02:21 +00:00
raise WebIDLError ( " getter cannot have void return type " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2012-03-31 04:42:20 +00:00
if setter or creator :
if len ( arguments ) != 2 :
raise WebIDLError ( " %s has wrong number of arguments " %
( " setter " if setter else " creator " ) ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2012-03-31 04:42:20 +00:00
argType = arguments [ 0 ] . type
if argType == BuiltinTypes [ IDLBuiltinType . Types . domstring ] :
specialType = IDLMethod . NamedOrIndexed . Named
elif argType == BuiltinTypes [ IDLBuiltinType . Types . unsigned_long ] :
specialType = IDLMethod . NamedOrIndexed . Indexed
else :
raise WebIDLError ( " %s has wrong argument type (must be DOMString or UnsignedLong) " %
( " setter " if setter else " creator " ) ,
2012-06-30 05:53:28 +00:00
[ arguments [ 0 ] . location ] )
2012-03-31 04:42:20 +00:00
if arguments [ 0 ] . optional or arguments [ 0 ] . variadic :
raise WebIDLError ( " %s cannot have %s argument " %
( " setter " if setter else " creator " ,
" optional " if arguments [ 0 ] . optional else " variadic " ) ,
2012-06-30 05:53:28 +00:00
[ arguments [ 0 ] . location ] )
2012-03-31 04:42:20 +00:00
if arguments [ 1 ] . optional or arguments [ 1 ] . variadic :
raise WebIDLError ( " %s cannot have %s argument " %
( " setter " if setter else " creator " ,
" optional " if arguments [ 1 ] . optional else " variadic " ) ,
2012-06-30 05:53:28 +00:00
[ arguments [ 1 ] . location ] )
2012-05-22 10:02:21 +00:00
if stringifier :
if len ( arguments ) != 0 :
raise WebIDLError ( " stringifier has wrong number of arguments " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2013-06-13 05:15:35 +00:00
if not returnType . isDOMString ( ) :
raise WebIDLError ( " stringifier must have DOMString return type " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2012-03-31 04:42:20 +00:00
# identifier might be None. This is only permitted for special methods.
if not identifier :
if not getter and not setter and not creator and \
2012-05-22 10:02:21 +00:00
not deleter and not legacycaller and not stringifier :
2012-03-31 04:42:20 +00:00
raise WebIDLError ( " Identifier required for non-special methods " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2012-03-31 04:42:20 +00:00
location = BuiltinLocation ( " <auto-generated-identifier> " )
2012-05-22 10:02:21 +00:00
identifier = IDLUnresolvedIdentifier ( location , " __ %s %s %s %s %s %s %s " %
2012-03-31 04:42:20 +00:00
( " named " if specialType == IDLMethod . NamedOrIndexed . Named else \
" indexed " if specialType == IDLMethod . NamedOrIndexed . Indexed else " " ,
" getter " if getter else " " ,
" setter " if setter else " " ,
" deleter " if deleter else " " ,
" creator " if creator else " " ,
2012-05-22 10:02:21 +00:00
" legacycaller " if legacycaller else " " ,
" stringifier " if stringifier else " " ) , allowDoubleUnderscore = True )
2012-03-31 04:42:20 +00:00
method = IDLMethod ( self . getLocation ( p , 2 ) , identifier , returnType , arguments ,
2012-04-12 22:14:10 +00:00
static = static , getter = getter , setter = setter , creator = creator ,
deleter = deleter , specialType = specialType ,
2012-05-22 10:02:21 +00:00
legacycaller = legacycaller , stringifier = stringifier )
2012-03-31 04:42:20 +00:00
p [ 0 ] = method
2012-11-05 19:40:32 +00:00
def p_Stringifier ( self , p ) :
"""
Operation : STRINGIFIER SEMICOLON
"""
identifier = IDLUnresolvedIdentifier ( BuiltinLocation ( " <auto-generated-identifier> " ) ,
" __stringifier " ,
allowDoubleUnderscore = True )
method = IDLMethod ( self . getLocation ( p , 1 ) ,
identifier ,
returnType = BuiltinTypes [ IDLBuiltinType . Types . domstring ] ,
arguments = [ ] ,
stringifier = True )
p [ 0 ] = method
2013-07-26 16:00:49 +00:00
def p_Jsonifier ( self , p ) :
"""
Operation : JSONIFIER SEMICOLON
"""
identifier = IDLUnresolvedIdentifier ( BuiltinLocation ( " <auto-generated-identifier> " ) ,
" __jsonifier " , allowDoubleUnderscore = True )
method = IDLMethod ( self . getLocation ( p , 1 ) ,
identifier ,
returnType = BuiltinTypes [ IDLBuiltinType . Types . object ] ,
arguments = [ ] ,
jsonifier = True )
p [ 0 ] = method
2012-10-19 07:34:28 +00:00
def p_QualifierStatic ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-10-19 07:34:28 +00:00
Qualifier : STATIC
2012-03-31 04:42:20 +00:00
"""
2012-10-19 07:34:28 +00:00
p [ 0 ] = [ IDLInterfaceMember . Special . Static ]
2012-03-31 04:42:20 +00:00
2012-10-19 07:34:28 +00:00
def p_QualifierStringifier ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-10-19 07:34:28 +00:00
Qualifier : STRINGIFIER
"""
p [ 0 ] = [ IDLInterfaceMember . Special . Stringifier ]
def p_Qualifiers ( self , p ) :
"""
Qualifiers : Qualifier
| Specials
2012-03-31 04:42:20 +00:00
"""
p [ 0 ] = p [ 1 ]
def p_Specials ( self , p ) :
"""
Specials : Special Specials
"""
p [ 0 ] = [ p [ 1 ] ]
p [ 0 ] . extend ( p [ 2 ] )
def p_SpecialsEmpty ( self , p ) :
"""
Specials :
"""
p [ 0 ] = [ ]
def p_SpecialGetter ( self , p ) :
"""
Special : GETTER
"""
p [ 0 ] = IDLMethod . Special . Getter
def p_SpecialSetter ( self , p ) :
"""
Special : SETTER
"""
p [ 0 ] = IDLMethod . Special . Setter
def p_SpecialCreator ( self , p ) :
"""
Special : CREATOR
"""
p [ 0 ] = IDLMethod . Special . Creator
def p_SpecialDeleter ( self , p ) :
"""
Special : DELETER
"""
p [ 0 ] = IDLMethod . Special . Deleter
def p_SpecialLegacyCaller ( self , p ) :
"""
Special : LEGACYCALLER
"""
p [ 0 ] = IDLMethod . Special . LegacyCaller
def p_OperationRest ( self , p ) :
"""
OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON
"""
p [ 0 ] = ( p [ 1 ] , p [ 2 ] , p [ 4 ] )
def p_OptionalIdentifier ( self , p ) :
"""
OptionalIdentifier : IDENTIFIER
"""
p [ 0 ] = IDLUnresolvedIdentifier ( self . getLocation ( p , 1 ) , p [ 1 ] )
def p_OptionalIdentifierEmpty ( self , p ) :
"""
OptionalIdentifier :
"""
pass
def p_ArgumentList ( self , p ) :
"""
ArgumentList : Argument Arguments
"""
p [ 0 ] = [ p [ 1 ] ] if p [ 1 ] else [ ]
p [ 0 ] . extend ( p [ 2 ] )
def p_ArgumentListEmpty ( self , p ) :
"""
ArgumentList :
"""
p [ 0 ] = [ ]
def p_Arguments ( self , p ) :
"""
Arguments : COMMA Argument Arguments
"""
p [ 0 ] = [ p [ 2 ] ] if p [ 2 ] else [ ]
p [ 0 ] . extend ( p [ 3 ] )
def p_ArgumentsEmpty ( self , p ) :
"""
Arguments :
"""
p [ 0 ] = [ ]
def p_Argument ( self , p ) :
"""
2014-06-23 20:03:56 +00:00
Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName Default
2012-03-31 04:42:20 +00:00
"""
t = p [ 3 ]
assert isinstance ( t , IDLType )
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 5 ) , p [ 5 ] )
optional = p [ 2 ]
variadic = p [ 4 ]
defaultValue = p [ 6 ]
if not optional and defaultValue :
raise WebIDLError ( " Mandatory arguments can ' t have a default value. " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 6 ) ] )
2012-03-31 04:42:20 +00:00
2014-04-04 03:32:11 +00:00
# We can't test t.isAny() here and give it a default value as needed,
# since at this point t is not a fully resolved type yet (e.g. it might
# be a typedef). We'll handle the 'any' case in IDLArgument.complete.
2014-02-19 15:13:38 +00:00
2012-03-31 04:42:20 +00:00
if variadic :
if optional :
raise WebIDLError ( " Variadic arguments should not be marked optional. " ,
2012-06-30 05:53:28 +00:00
[ self . getLocation ( p , 2 ) ] )
2012-03-31 04:42:20 +00:00
optional = variadic
p [ 0 ] = IDLArgument ( self . getLocation ( p , 5 ) , identifier , t , optional , defaultValue , variadic )
p [ 0 ] . addExtendedAttributes ( p [ 1 ] )
2012-11-05 19:40:32 +00:00
def p_ArgumentName ( self , p ) :
"""
ArgumentName : IDENTIFIER
| ATTRIBUTE
| CALLBACK
| CONST
| CREATOR
| DELETER
| DICTIONARY
| ENUM
| EXCEPTION
| GETTER
| IMPLEMENTS
| INHERIT
| INTERFACE
| LEGACYCALLER
| PARTIAL
2014-09-05 18:28:42 +00:00
| REQUIRED
2012-11-05 19:40:32 +00:00
| SERIALIZER
| SETTER
| STATIC
| STRINGIFIER
2013-07-26 16:00:49 +00:00
| JSONIFIER
2012-11-05 19:40:32 +00:00
| TYPEDEF
| UNRESTRICTED
"""
p [ 0 ] = p [ 1 ]
2014-09-05 18:28:42 +00:00
def p_AttributeName ( self , p ) :
"""
AttributeName : IDENTIFIER
| REQUIRED
"""
p [ 0 ] = p [ 1 ]
2012-03-31 04:42:20 +00:00
def p_Optional ( self , p ) :
"""
Optional : OPTIONAL
"""
p [ 0 ] = True
def p_OptionalEmpty ( self , p ) :
"""
Optional :
"""
p [ 0 ] = False
2014-09-05 18:28:42 +00:00
def p_Required ( self , p ) :
"""
Required : REQUIRED
"""
p [ 0 ] = True
def p_RequiredEmpty ( self , p ) :
"""
Required :
"""
p [ 0 ] = False
2012-03-31 04:42:20 +00:00
def p_Ellipsis ( self , p ) :
"""
Ellipsis : ELLIPSIS
"""
p [ 0 ] = True
def p_EllipsisEmpty ( self , p ) :
"""
Ellipsis :
"""
p [ 0 ] = False
def p_ExceptionMember ( self , p ) :
"""
ExceptionMember : Const
| ExceptionField
"""
pass
def p_ExceptionField ( self , p ) :
"""
2012-05-18 21:25:47 +00:00
ExceptionField : Type IDENTIFIER SEMICOLON
2012-03-31 04:42:20 +00:00
"""
pass
def p_ExtendedAttributeList ( self , p ) :
"""
ExtendedAttributeList : LBRACKET ExtendedAttribute ExtendedAttributes RBRACKET
"""
p [ 0 ] = [ p [ 2 ] ]
if p [ 3 ] :
p [ 0 ] . extend ( p [ 3 ] )
def p_ExtendedAttributeListEmpty ( self , p ) :
"""
ExtendedAttributeList :
"""
p [ 0 ] = [ ]
def p_ExtendedAttribute ( self , p ) :
"""
ExtendedAttribute : ExtendedAttributeNoArgs
| ExtendedAttributeArgList
| ExtendedAttributeIdent
| ExtendedAttributeNamedArgList
2014-08-05 02:20:33 +00:00
| ExtendedAttributeIdentList
2012-03-31 04:42:20 +00:00
"""
2012-09-12 16:24:58 +00:00
p [ 0 ] = IDLExtendedAttribute ( self . getLocation ( p , 1 ) , p [ 1 ] )
2012-03-31 04:42:20 +00:00
def p_ExtendedAttributeEmpty ( self , p ) :
"""
ExtendedAttribute :
"""
pass
def p_ExtendedAttributes ( self , p ) :
"""
ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes
"""
p [ 0 ] = [ p [ 2 ] ] if p [ 2 ] else [ ]
p [ 0 ] . extend ( p [ 3 ] )
def p_ExtendedAttributesEmpty ( self , p ) :
"""
ExtendedAttributes :
"""
p [ 0 ] = [ ]
def p_Other ( self , p ) :
"""
Other : INTEGER
2012-05-02 03:23:45 +00:00
| FLOATLITERAL
2012-03-31 04:42:20 +00:00
| IDENTIFIER
| STRING
| OTHER
| ELLIPSIS
| COLON
| SCOPE
| SEMICOLON
| LT
| EQUALS
| GT
| QUESTIONMARK
| DATE
| DOMSTRING
2013-06-13 05:15:35 +00:00
| BYTESTRING
2014-11-20 11:58:00 +00:00
| USVSTRING
2012-03-31 04:42:20 +00:00
| ANY
| ATTRIBUTE
| BOOLEAN
| BYTE
| LEGACYCALLER
| CONST
| CREATOR
| DELETER
| DOUBLE
| EXCEPTION
| FALSE
2012-05-02 03:23:45 +00:00
| FLOAT
2012-03-31 04:42:20 +00:00
| GETTER
| IMPLEMENTS
| INHERIT
| INTERFACE
| LONG
| MODULE
| NULL
| OBJECT
| OCTET
| OPTIONAL
| SEQUENCE
2014-05-23 21:32:38 +00:00
| MOZMAP
2012-03-31 04:42:20 +00:00
| SETTER
| SHORT
| STATIC
| STRINGIFIER
2013-07-26 16:00:49 +00:00
| JSONIFIER
2012-03-31 04:42:20 +00:00
| TRUE
| TYPEDEF
| UNSIGNED
| VOID
"""
pass
def p_OtherOrComma ( self , p ) :
"""
OtherOrComma : Other
| COMMA
"""
pass
2012-05-18 21:25:47 +00:00
def p_TypeSingleType ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
Type : SingleType
2012-03-31 04:42:20 +00:00
"""
p [ 0 ] = p [ 1 ]
2012-05-18 21:25:47 +00:00
def p_TypeUnionType ( self , p ) :
"""
Type : UnionType TypeSuffix
"""
p [ 0 ] = self . handleModifiers ( p [ 1 ] , p [ 2 ] )
def p_SingleTypeNonAnyType ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
SingleType : NonAnyType
2012-03-31 04:42:20 +00:00
"""
p [ 0 ] = p [ 1 ]
2012-05-18 21:25:47 +00:00
def p_SingleTypeAnyType ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
SingleType : ANY TypeSuffixStartingWithArray
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
p [ 0 ] = self . handleModifiers ( BuiltinTypes [ IDLBuiltinType . Types . any ] , p [ 2 ] )
def p_UnionType ( self , p ) :
"""
UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN
"""
types = [ p [ 2 ] , p [ 4 ] ]
types . extend ( p [ 5 ] )
p [ 0 ] = IDLUnionType ( self . getLocation ( p , 1 ) , types )
2012-03-31 04:42:20 +00:00
2012-05-18 21:25:47 +00:00
def p_UnionMemberTypeNonAnyType ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
UnionMemberType : NonAnyType
"""
p [ 0 ] = p [ 1 ]
def p_UnionMemberTypeArrayOfAny ( self , p ) :
"""
UnionMemberTypeArrayOfAny : ANY LBRACKET RBRACKET
"""
p [ 0 ] = IDLArrayType ( self . getLocation ( p , 2 ) ,
BuiltinTypes [ IDLBuiltinType . Types . any ] )
def p_UnionMemberType ( self , p ) :
"""
UnionMemberType : UnionType TypeSuffix
| UnionMemberTypeArrayOfAny TypeSuffix
"""
p [ 0 ] = self . handleModifiers ( p [ 1 ] , p [ 2 ] )
def p_UnionMemberTypes ( self , p ) :
"""
UnionMemberTypes : OR UnionMemberType UnionMemberTypes
"""
p [ 0 ] = [ p [ 2 ] ]
p [ 0 ] . extend ( p [ 3 ] )
def p_UnionMemberTypesEmpty ( self , p ) :
"""
2014-05-05 19:24:00 +00:00
UnionMemberTypes :
2012-05-18 21:25:47 +00:00
"""
p [ 0 ] = [ ]
def p_NonAnyType ( self , p ) :
"""
NonAnyType : PrimitiveOrStringType TypeSuffix
| ARRAYBUFFER TypeSuffix
| OBJECT TypeSuffix
2012-03-31 04:42:20 +00:00
"""
if p [ 1 ] == " object " :
type = BuiltinTypes [ IDLBuiltinType . Types . object ]
elif p [ 1 ] == " ArrayBuffer " :
type = BuiltinTypes [ IDLBuiltinType . Types . ArrayBuffer ]
else :
type = BuiltinTypes [ p [ 1 ] ]
2012-05-18 21:25:47 +00:00
p [ 0 ] = self . handleModifiers ( type , p [ 2 ] )
2012-03-31 04:42:20 +00:00
2012-05-18 21:25:47 +00:00
def p_NonAnyTypeSequenceType ( self , p ) :
"""
NonAnyType : SEQUENCE LT Type GT Null
"""
innerType = p [ 3 ]
type = IDLSequenceType ( self . getLocation ( p , 1 ) , innerType )
if p [ 5 ] :
type = IDLNullableType ( self . getLocation ( p , 5 ) , type )
2012-03-31 04:42:20 +00:00
p [ 0 ] = type
2014-08-01 03:50:30 +00:00
# Note: Promise<void> is allowed, so we want to parametrize on
# ReturnType, not Type. Also, we want this to end up picking up
# the Promise interface for now, hence the games with IDLUnresolvedType.
def p_NonAnyTypePromiseType ( self , p ) :
"""
NonAnyType : PROMISE LT ReturnType GT Null
"""
innerType = p [ 3 ]
promiseIdent = IDLUnresolvedIdentifier ( self . getLocation ( p , 1 ) , " Promise " )
type = IDLUnresolvedType ( self . getLocation ( p , 1 ) , promiseIdent , p [ 3 ] )
if p [ 5 ] :
type = IDLNullableType ( self . getLocation ( p , 5 ) , type )
p [ 0 ] = type
2014-05-23 21:32:38 +00:00
def p_NonAnyTypeMozMapType ( self , p ) :
"""
NonAnyType : MOZMAP LT Type GT Null
"""
innerType = p [ 3 ]
type = IDLMozMapType ( self . getLocation ( p , 1 ) , innerType )
if p [ 5 ] :
type = IDLNullableType ( self . getLocation ( p , 5 ) , type )
p [ 0 ] = type
2012-05-18 21:25:47 +00:00
def p_NonAnyTypeScopedName ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
NonAnyType : ScopedName TypeSuffix
2012-03-31 04:42:20 +00:00
"""
assert isinstance ( p [ 1 ] , IDLUnresolvedIdentifier )
2014-08-01 03:50:30 +00:00
if p [ 1 ] . name == " Promise " :
raise WebIDLError ( " Promise used without saying what it ' s "
" parametrized over " ,
[ self . getLocation ( p , 1 ) ] )
2012-03-31 04:42:20 +00:00
type = None
try :
if self . globalScope ( ) . _lookupIdentifier ( p [ 1 ] ) :
obj = self . globalScope ( ) . _lookupIdentifier ( p [ 1 ] )
if obj . isType ( ) :
type = obj
else :
type = IDLWrapperType ( self . getLocation ( p , 1 ) , p [ 1 ] )
2012-05-18 21:25:47 +00:00
p [ 0 ] = self . handleModifiers ( type , p [ 2 ] )
2012-03-31 04:42:20 +00:00
return
except :
pass
type = IDLUnresolvedType ( self . getLocation ( p , 1 ) , p [ 1 ] )
2012-05-18 21:25:47 +00:00
p [ 0 ] = self . handleModifiers ( type , p [ 2 ] )
2012-03-31 04:42:20 +00:00
2012-05-18 21:25:47 +00:00
def p_NonAnyTypeDate ( self , p ) :
2012-03-31 04:42:20 +00:00
"""
2012-05-18 21:25:47 +00:00
NonAnyType : DATE TypeSuffix
2012-03-31 04:42:20 +00:00
"""
2013-05-02 18:38:19 +00:00
p [ 0 ] = self . handleModifiers ( BuiltinTypes [ IDLBuiltinType . Types . date ] ,
p [ 2 ] )
2012-03-31 04:42:20 +00:00
def p_ConstType ( self , p ) :
"""
ConstType : PrimitiveOrStringType Null
"""
type = BuiltinTypes [ p [ 1 ] ]
if p [ 2 ] :
type = IDLNullableType ( self . getLocation ( p , 1 ) , type )
p [ 0 ] = type
2012-09-06 14:23:51 +00:00
def p_ConstTypeIdentifier ( self , p ) :
"""
ConstType : IDENTIFIER Null
"""
identifier = IDLUnresolvedIdentifier ( self . getLocation ( p , 1 ) , p [ 1 ] )
type = IDLUnresolvedType ( self . getLocation ( p , 1 ) , identifier )
if p [ 2 ] :
type = IDLNullableType ( self . getLocation ( p , 1 ) , type )
p [ 0 ] = type
2012-03-31 04:42:20 +00:00
def p_PrimitiveOrStringTypeUint ( self , p ) :
"""
PrimitiveOrStringType : UnsignedIntegerType
"""
p [ 0 ] = p [ 1 ]
def p_PrimitiveOrStringTypeBoolean ( self , p ) :
"""
PrimitiveOrStringType : BOOLEAN
"""
p [ 0 ] = IDLBuiltinType . Types . boolean
def p_PrimitiveOrStringTypeByte ( self , p ) :
"""
PrimitiveOrStringType : BYTE
"""
p [ 0 ] = IDLBuiltinType . Types . byte
def p_PrimitiveOrStringTypeOctet ( self , p ) :
"""
PrimitiveOrStringType : OCTET
"""
p [ 0 ] = IDLBuiltinType . Types . octet
def p_PrimitiveOrStringTypeFloat ( self , p ) :
"""
PrimitiveOrStringType : FLOAT
"""
p [ 0 ] = IDLBuiltinType . Types . float
2012-11-27 20:32:05 +00:00
def p_PrimitiveOrStringTypeUnrestictedFloat ( self , p ) :
"""
PrimitiveOrStringType : UNRESTRICTED FLOAT
"""
p [ 0 ] = IDLBuiltinType . Types . unrestricted_float
2012-03-31 04:42:20 +00:00
def p_PrimitiveOrStringTypeDouble ( self , p ) :
"""
PrimitiveOrStringType : DOUBLE
"""
p [ 0 ] = IDLBuiltinType . Types . double
2012-11-27 20:32:05 +00:00
def p_PrimitiveOrStringTypeUnrestictedDouble ( self , p ) :
"""
PrimitiveOrStringType : UNRESTRICTED DOUBLE
"""
p [ 0 ] = IDLBuiltinType . Types . unrestricted_double
2012-03-31 04:42:20 +00:00
def p_PrimitiveOrStringTypeDOMString ( self , p ) :
"""
PrimitiveOrStringType : DOMSTRING
"""
p [ 0 ] = IDLBuiltinType . Types . domstring
2013-06-13 05:15:35 +00:00
def p_PrimitiveOrStringTypeBytestring ( self , p ) :
"""
PrimitiveOrStringType : BYTESTRING
"""
p [ 0 ] = IDLBuiltinType . Types . bytestring
2014-11-20 11:58:00 +00:00
def p_PrimitiveOrStringTypeUSVString ( self , p ) :
2014-08-01 20:23:48 +00:00
"""
2014-11-20 11:58:00 +00:00
PrimitiveOrStringType : USVSTRING
2014-08-01 20:23:48 +00:00
"""
2014-11-20 11:58:00 +00:00
p [ 0 ] = IDLBuiltinType . Types . usvstring
2014-08-01 20:23:48 +00:00
2012-03-31 04:42:20 +00:00
def p_UnsignedIntegerTypeUnsigned ( self , p ) :
"""
UnsignedIntegerType : UNSIGNED IntegerType
"""
p [ 0 ] = p [ 2 ] + 1 # Adding one to a given signed integer type
# gets you the unsigned type.
def p_UnsignedIntegerType ( self , p ) :
"""
UnsignedIntegerType : IntegerType
"""
p [ 0 ] = p [ 1 ]
def p_IntegerTypeShort ( self , p ) :
"""
IntegerType : SHORT
"""
p [ 0 ] = IDLBuiltinType . Types . short
def p_IntegerTypeLong ( self , p ) :
"""
IntegerType : LONG OptionalLong
"""
if p [ 2 ] :
p [ 0 ] = IDLBuiltinType . Types . long_long
else :
p [ 0 ] = IDLBuiltinType . Types . long
def p_OptionalLong ( self , p ) :
"""
OptionalLong : LONG
"""
p [ 0 ] = True
def p_OptionalLongEmpty ( self , p ) :
"""
OptionalLong :
"""
p [ 0 ] = False
def p_TypeSuffixBrackets ( self , p ) :
"""
TypeSuffix : LBRACKET RBRACKET TypeSuffix
"""
p [ 0 ] = [ ( IDLMethod . TypeSuffixModifier . Brackets , self . getLocation ( p , 1 ) ) ]
p [ 0 ] . extend ( p [ 3 ] )
def p_TypeSuffixQMark ( self , p ) :
"""
TypeSuffix : QUESTIONMARK TypeSuffixStartingWithArray
"""
p [ 0 ] = [ ( IDLMethod . TypeSuffixModifier . QMark , self . getLocation ( p , 1 ) ) ]
p [ 0 ] . extend ( p [ 2 ] )
def p_TypeSuffixEmpty ( self , p ) :
"""
TypeSuffix :
"""
p [ 0 ] = [ ]
def p_TypeSuffixStartingWithArray ( self , p ) :
"""
TypeSuffixStartingWithArray : LBRACKET RBRACKET TypeSuffix
"""
p [ 0 ] = [ ( IDLMethod . TypeSuffixModifier . Brackets , self . getLocation ( p , 1 ) ) ]
p [ 0 ] . extend ( p [ 3 ] )
def p_TypeSuffixStartingWithArrayEmpty ( self , p ) :
"""
TypeSuffixStartingWithArray :
"""
p [ 0 ] = [ ]
def p_Null ( self , p ) :
"""
Null : QUESTIONMARK
|
"""
if len ( p ) > 1 :
p [ 0 ] = True
else :
p [ 0 ] = False
def p_ReturnTypeType ( self , p ) :
"""
ReturnType : Type
"""
p [ 0 ] = p [ 1 ]
def p_ReturnTypeVoid ( self , p ) :
"""
ReturnType : VOID
"""
p [ 0 ] = BuiltinTypes [ IDLBuiltinType . Types . void ]
def p_ScopedName ( self , p ) :
"""
ScopedName : AbsoluteScopedName
| RelativeScopedName
"""
p [ 0 ] = p [ 1 ]
def p_AbsoluteScopedName ( self , p ) :
"""
AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts
"""
assert False
pass
def p_RelativeScopedName ( self , p ) :
"""
RelativeScopedName : IDENTIFIER ScopedNameParts
"""
assert not p [ 2 ] # Not implemented!
p [ 0 ] = IDLUnresolvedIdentifier ( self . getLocation ( p , 1 ) , p [ 1 ] )
def p_ScopedNameParts ( self , p ) :
"""
ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts
"""
assert False
pass
def p_ScopedNamePartsEmpty ( self , p ) :
"""
ScopedNameParts :
"""
p [ 0 ] = None
def p_ExtendedAttributeNoArgs ( self , p ) :
"""
ExtendedAttributeNoArgs : IDENTIFIER
"""
p [ 0 ] = ( p [ 1 ] , )
def p_ExtendedAttributeArgList ( self , p ) :
"""
ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN
"""
p [ 0 ] = ( p [ 1 ] , p [ 3 ] )
def p_ExtendedAttributeIdent ( self , p ) :
"""
2012-05-09 18:49:56 +00:00
ExtendedAttributeIdent : IDENTIFIER EQUALS STRING
| IDENTIFIER EQUALS IDENTIFIER
2012-03-31 04:42:20 +00:00
"""
p [ 0 ] = ( p [ 1 ] , p [ 3 ] )
def p_ExtendedAttributeNamedArgList ( self , p ) :
"""
ExtendedAttributeNamedArgList : IDENTIFIER EQUALS IDENTIFIER LPAREN ArgumentList RPAREN
"""
p [ 0 ] = ( p [ 1 ] , p [ 3 ] , p [ 5 ] )
2014-08-05 02:20:33 +00:00
def p_ExtendedAttributeIdentList ( self , p ) :
"""
ExtendedAttributeIdentList : IDENTIFIER EQUALS LPAREN IdentifierList RPAREN
"""
p [ 0 ] = ( p [ 1 ] , p [ 4 ] )
def p_IdentifierList ( self , p ) :
"""
IdentifierList : IDENTIFIER Identifiers
"""
idents = list ( p [ 2 ] )
idents . insert ( 0 , p [ 1 ] )
p [ 0 ] = idents
def p_IdentifiersList ( self , p ) :
"""
Identifiers : COMMA IDENTIFIER Identifiers
"""
idents = list ( p [ 3 ] )
idents . insert ( 0 , p [ 2 ] )
p [ 0 ] = idents
def p_IdentifiersEmpty ( self , p ) :
"""
Identifiers :
"""
p [ 0 ] = [ ]
2012-03-31 04:42:20 +00:00
def p_error ( self , p ) :
if not p :
2013-10-18 14:17:00 +00:00
raise WebIDLError ( " Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both " ,
[ self . _filename ] )
2012-03-31 04:42:20 +00:00
else :
2012-06-30 05:53:28 +00:00
raise WebIDLError ( " invalid syntax " , [ Location ( self . lexer , p . lineno , p . lexpos , self . _filename ) ] )
2012-03-31 04:42:20 +00:00
2012-06-26 03:35:42 +00:00
def __init__ ( self , outputdir = ' ' , lexer = None ) :
Tokenizer . __init__ ( self , outputdir , lexer )
2014-08-05 02:20:32 +00:00
logger = SqueakyCleanLogger ( )
2012-03-31 04:42:20 +00:00
self . parser = yacc . yacc ( module = self ,
outputdir = outputdir ,
2012-06-26 03:35:42 +00:00
tabmodule = ' webidlyacc ' ,
2014-08-05 02:20:32 +00:00
errorlog = logger
2014-06-23 20:03:56 +00:00
# Pickling the grammar is a speedup in
# some cases (older Python?) but a
# significant slowdown in others.
# We're not pickling for now, until it
# becomes a speedup again.
# , picklefile='WebIDLGrammar.pkl'
)
2014-08-05 02:20:32 +00:00
logger . reportGrammarErrors ( )
2012-03-31 04:42:20 +00:00
self . _globalScope = IDLScope ( BuiltinLocation ( " <Global Scope> " ) , None , None )
2014-08-05 02:20:34 +00:00
# To make our test harness work, pretend like we have a primary global already. Note that we _don't_ set _globalScope.primaryGlobalAttr, so we'll still be able to detect multiple PrimaryGlobal extended attributes.
self . _globalScope . primaryGlobalName = " FakeTestPrimaryGlobal "
self . _globalScope . globalNames . add ( " FakeTestPrimaryGlobal " )
self . _globalScope . globalNameMapping [ " FakeTestPrimaryGlobal " ] . add ( " FakeTestPrimaryGlobal " )
2014-10-17 15:30:18 +00:00
# And we add the special-cased "System" global name, which
# doesn't have any corresponding interfaces.
self . _globalScope . globalNames . add ( " System " )
self . _globalScope . globalNameMapping [ " System " ] . add ( " BackstagePass " )
2012-05-25 04:41:33 +00:00
self . _installBuiltins ( self . _globalScope )
2012-03-31 04:42:20 +00:00
self . _productions = [ ]
self . _filename = " <builtin> "
self . lexer . input ( Parser . _builtins )
self . _filename = None
2012-06-05 01:30:03 +00:00
self . parser . parse ( lexer = self . lexer , tracking = True )
2012-03-31 04:42:20 +00:00
2012-05-25 04:41:33 +00:00
def _installBuiltins ( self , scope ) :
assert isinstance ( scope , IDLScope )
# xrange omits the last value.
for x in xrange ( IDLBuiltinType . Types . ArrayBuffer , IDLBuiltinType . Types . Float64Array + 1 ) :
builtin = BuiltinTypes [ x ]
name = builtin . name
typedef = IDLTypedefType ( BuiltinLocation ( " <builtin type> " ) , builtin , name )
typedef . resolve ( scope )
2012-05-18 21:25:47 +00:00
@ staticmethod
def handleModifiers ( type , modifiers ) :
for ( modifier , modifierLocation ) in modifiers :
assert modifier == IDLMethod . TypeSuffixModifier . QMark or \
modifier == IDLMethod . TypeSuffixModifier . Brackets
if modifier == IDLMethod . TypeSuffixModifier . QMark :
type = IDLNullableType ( modifierLocation , type )
elif modifier == IDLMethod . TypeSuffixModifier . Brackets :
type = IDLArrayType ( modifierLocation , type )
return type
2012-03-31 04:42:20 +00:00
def parse ( self , t , filename = None ) :
self . lexer . input ( t )
#for tok in iter(self.lexer.token, None):
# print tok
self . _filename = filename
2012-06-05 01:30:03 +00:00
self . _productions . extend ( self . parser . parse ( lexer = self . lexer , tracking = True ) )
2012-03-31 04:42:20 +00:00
self . _filename = None
def finish ( self ) :
2012-06-11 22:21:35 +00:00
# First, finish all the IDLImplementsStatements. In particular, we
# have to make sure we do those before we do the IDLInterfaces.
# XXX khuey hates this bit and wants to nuke it from orbit.
implementsStatements = [ p for p in self . _productions if
isinstance ( p , IDLImplementsStatement ) ]
otherStatements = [ p for p in self . _productions if
not isinstance ( p , IDLImplementsStatement ) ]
for production in implementsStatements :
production . finish ( self . globalScope ( ) )
for production in otherStatements :
2012-03-31 04:42:20 +00:00
production . finish ( self . globalScope ( ) )
2012-06-22 20:18:50 +00:00
# Do any post-finish validation we need to do
for production in self . _productions :
production . validate ( )
2012-04-12 22:14:10 +00:00
# De-duplicate self._productions, without modifying its order.
seen = set ( )
result = [ ]
for p in self . _productions :
if p not in seen :
seen . add ( p )
result . append ( p )
return result
2012-03-31 04:42:20 +00:00
def reset ( self ) :
2012-06-26 03:35:42 +00:00
return Parser ( lexer = self . lexer )
2012-03-31 04:42:20 +00:00
# Builtin IDL defined by WebIDL
_builtins = """
typedef unsigned long long DOMTimeStamp ;
2014-11-16 20:01:08 +00:00
typedef ( ArrayBufferView or ArrayBuffer ) BufferSource ;
2012-03-31 04:42:20 +00:00
"""
2012-08-24 18:51:45 +00:00
def main ( ) :
# Parse arguments.
from optparse import OptionParser
usageString = " usage: % prog [options] files "
o = OptionParser ( usage = usageString )
o . add_option ( " --cachedir " , dest = ' cachedir ' , default = None ,
help = " Directory in which to cache lex/parse tables. " )
o . add_option ( " --verbose-errors " , action = ' store_true ' , default = False ,
help = " When an error happens, display the Python traceback. " )
( options , args ) = o . parse_args ( )
if len ( args ) < 1 :
o . error ( usageString )
fileList = args
baseDir = os . getcwd ( )
# Parse the WebIDL.
parser = Parser ( options . cachedir )
try :
for filename in fileList :
fullPath = os . path . normpath ( os . path . join ( baseDir , filename ) )
f = open ( fullPath , ' rb ' )
lines = f . readlines ( )
f . close ( )
print fullPath
parser . parse ( ' ' . join ( lines ) , fullPath )
parser . finish ( )
2012-08-24 20:47:45 +00:00
except WebIDLError , e :
2012-08-24 18:51:45 +00:00
if options . verbose_errors :
traceback . print_exc ( )
else :
print e
if __name__ == ' __main__ ' :
main ( )