Update WebIDL parser

This commit is contained in:
Anthony Ramine 2015-12-15 23:24:16 +01:00
parent 06947965b1
commit c1718a0b1f

View file

@ -540,6 +540,9 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def validate(self): def validate(self):
pass pass
def isIteratorInterface(self):
return False
def isExternal(self): def isExternal(self):
return True return True
@ -640,7 +643,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
self._callback = False self._callback = False
self._finished = False self._finished = False
self.members = [] self.members = []
self.maplikeOrSetlike = None self.maplikeOrSetlikeOrIterable = None
self._partialInterfaces = [] self._partialInterfaces = []
self._extendedAttrDict = {} self._extendedAttrDict = {}
# namedConstructors needs deterministic ordering because bindings code # namedConstructors needs deterministic ordering because bindings code
@ -664,6 +667,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
self.totalMembersInSlots = 0 self.totalMembersInSlots = 0
# Tracking of the number of own own members we have in slots # Tracking of the number of own own members we have in slots
self._ownMembersInSlots = 0 self._ownMembersInSlots = 0
# If this is an iterator interface, we need to know what iterable
# interface we're iterating for in order to get its nativeType.
self.iterableInterface = None
IDLObjectWithScope.__init__(self, location, parentScope, name) IDLObjectWithScope.__init__(self, location, parentScope, name)
IDLExposureMixins.__init__(self, location) IDLExposureMixins.__init__(self, location)
@ -682,6 +688,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
except: except:
return None return None
def isIterable(self):
return (self.maplikeOrSetlikeOrIterable and
self.maplikeOrSetlikeOrIterable.isIterable())
def isIteratorInterface(self):
return self.iterableInterface is not None
def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject): def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
assert isinstance(scope, IDLScope) assert isinstance(scope, IDLScope)
assert isinstance(originalObject, IDLInterfaceMember) assert isinstance(originalObject, IDLInterfaceMember)
@ -718,22 +731,22 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
# need to be treated like regular interface members, do this before # need to be treated like regular interface members, do this before
# things like exposure setting. # things like exposure setting.
for member in self.members: for member in self.members:
if member.isMaplikeOrSetlike(): if member.isMaplikeOrSetlikeOrIterable():
# Check that we only have one interface declaration (currently # Check that we only have one interface declaration (currently
# there can only be one maplike/setlike declaration per # there can only be one maplike/setlike declaration per
# interface) # interface)
if self.maplikeOrSetlike: if self.maplikeOrSetlikeOrIterable:
raise WebIDLError("%s declaration used on " raise WebIDLError("%s declaration used on "
"interface that already has %s " "interface that already has %s "
"declaration" % "declaration" %
(member.maplikeOrSetlikeType, (member.maplikeOrSetlikeOrIterableType,
self.maplikeOrSetlike.maplikeOrSetlikeType), self.maplikeOrSetlikeOrIterable.maplikeOrSetlikeOrIterableType),
[self.maplikeOrSetlike.location, [self.maplikeOrSetlikeOrIterable.location,
member.location]) member.location])
self.maplikeOrSetlike = member self.maplikeOrSetlikeOrIterable = member
# If we've got a maplike or setlike declaration, we'll be building all of # If we've got a maplike or setlike declaration, we'll be building all of
# our required methods in Codegen. Generate members now. # our required methods in Codegen. Generate members now.
self.maplikeOrSetlike.expand(self.members, self.isJSImplemented()) self.maplikeOrSetlikeOrIterable.expand(self.members, self.isJSImplemented())
# Now that we've merged in our partial interfaces, set the # Now that we've merged in our partial interfaces, set the
# _exposureGlobalNames on any members that don't have it set yet. Note # _exposureGlobalNames on any members that don't have it set yet. Note
@ -884,14 +897,14 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
# If we have a maplike or setlike, and the consequential interface # If we have a maplike or setlike, and the consequential interface
# also does, throw an error. # also does, throw an error.
if iface.maplikeOrSetlike and self.maplikeOrSetlike: if iface.maplikeOrSetlikeOrIterable and self.maplikeOrSetlikeOrIterable:
raise WebIDLError("Maplike/setlike interface %s cannot have " raise WebIDLError("Maplike/setlike/iterable interface %s cannot have "
"maplike/setlike interface %s as a " "maplike/setlike/iterable interface %s as a "
"consequential interface" % "consequential interface" %
(self.identifier.name, (self.identifier.name,
iface.identifier.name), iface.identifier.name),
[self.maplikeOrSetlike.location, [self.maplikeOrSetlikeOrIterable.location,
iface.maplikeOrSetlike.location]) iface.maplikeOrSetlikeOrIterable.location])
additionalMembers = iface.originalMembers additionalMembers = iface.originalMembers
for additionalMember in additionalMembers: for additionalMember in additionalMembers:
for member in self.members: for member in self.members:
@ -905,15 +918,15 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
for ancestor in self.getInheritedInterfaces(): for ancestor in self.getInheritedInterfaces():
ancestor.interfacesBasedOnSelf.add(self) ancestor.interfacesBasedOnSelf.add(self)
if (ancestor.maplikeOrSetlike is not None and if (ancestor.maplikeOrSetlikeOrIterable is not None and
self.maplikeOrSetlike is not None): self.maplikeOrSetlikeOrIterable is not None):
raise WebIDLError("Cannot have maplike/setlike on %s that " raise WebIDLError("Cannot have maplike/setlike on %s that "
"inherits %s, which is already " "inherits %s, which is already "
"maplike/setlike" % "maplike/setlike" %
(self.identifier.name, (self.identifier.name,
ancestor.identifier.name), ancestor.identifier.name),
[self.maplikeOrSetlike.location, [self.maplikeOrSetlikeOrIterable.location,
ancestor.maplikeOrSetlike.location]) ancestor.maplikeOrSetlikeOrIterable.location])
for ancestorConsequential in ancestor.getConsequentialInterfaces(): for ancestorConsequential in ancestor.getConsequentialInterfaces():
ancestorConsequential.interfacesBasedOnSelf.add(self) ancestorConsequential.interfacesBasedOnSelf.add(self)
@ -997,11 +1010,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
# At this point, we have all of our members. If the current interface # At this point, we have all of our members. If the current interface
# uses maplike/setlike, check for collisions anywhere in the current # uses maplike/setlike, check for collisions anywhere in the current
# interface or higher in the inheritance chain. # interface or higher in the inheritance chain.
if self.maplikeOrSetlike: if self.maplikeOrSetlikeOrIterable:
testInterface = self testInterface = self
isAncestor = False isAncestor = False
while testInterface: while testInterface:
self.maplikeOrSetlike.checkCollisions(testInterface.members, self.maplikeOrSetlikeOrIterable.checkCollisions(testInterface.members,
isAncestor) isAncestor)
isAncestor = True isAncestor = True
testInterface = testInterface.parent testInterface = testInterface.parent
@ -1411,7 +1424,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
identifier == "AvailableIn" or identifier == "AvailableIn" or
identifier == "Func" or identifier == "Func" or
identifier == "CheckAnyPermissions" or identifier == "CheckAnyPermissions" or
identifier == "CheckAllPermissions"): identifier == "CheckAllPermissions" or
identifier == "Deprecated"):
# Known extended attributes that take a string value # Known extended attributes that take a string value
if not attr.hasValue(): if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier, raise WebIDLError("[%s] must have a value" % identifier,
@ -1821,15 +1835,9 @@ class IDLType(IDLObject):
def isSharedArrayBuffer(self): def isSharedArrayBuffer(self):
return False return False
def isSharedArrayBufferView(self):
return False
def isTypedArray(self): def isTypedArray(self):
return False return False
def isSharedTypedArray(self):
return False
def isCallbackInterface(self): def isCallbackInterface(self):
return False return False
@ -1850,9 +1858,7 @@ class IDLType(IDLObject):
return self.isInterface() and (self.isArrayBuffer() or return self.isInterface() and (self.isArrayBuffer() or
self.isArrayBufferView() or self.isArrayBufferView() or
self.isSharedArrayBuffer() or self.isSharedArrayBuffer() or
self.isSharedArrayBufferView() or self.isTypedArray())
self.isTypedArray() or
self.isSharedTypedArray())
def isDictionary(self): def isDictionary(self):
return False return False
@ -2039,15 +2045,9 @@ class IDLNullableType(IDLType):
def isSharedArrayBuffer(self): def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer() return self.inner.isSharedArrayBuffer()
def isSharedArrayBufferView(self):
return self.inner.isSharedArrayBufferView()
def isTypedArray(self): def isTypedArray(self):
return self.inner.isTypedArray() return self.inner.isTypedArray()
def isSharedTypedArray(self):
return self.inner.isSharedTypedArray()
def isDictionary(self): def isDictionary(self):
return self.inner.isDictionary() return self.inner.isDictionary()
@ -2554,15 +2554,9 @@ class IDLTypedefType(IDLType):
def isSharedArrayBuffer(self): def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer() return self.inner.isSharedArrayBuffer()
def isSharedArrayBufferView(self):
return self.inner.isSharedArrayBufferView()
def isTypedArray(self): def isTypedArray(self):
return self.inner.isTypedArray() return self.inner.isTypedArray()
def isSharedTypedArray(self):
return self.inner.isSharedTypedArray()
def isInterface(self): def isInterface(self):
return self.inner.isInterface() return self.inner.isInterface()
@ -2832,7 +2826,6 @@ class IDLBuiltinType(IDLType):
'ArrayBuffer', 'ArrayBuffer',
'ArrayBufferView', 'ArrayBufferView',
'SharedArrayBuffer', 'SharedArrayBuffer',
'SharedArrayBufferView',
'Int8Array', 'Int8Array',
'Uint8Array', 'Uint8Array',
'Uint8ClampedArray', 'Uint8ClampedArray',
@ -2841,16 +2834,7 @@ class IDLBuiltinType(IDLType):
'Int32Array', 'Int32Array',
'Uint32Array', 'Uint32Array',
'Float32Array', 'Float32Array',
'Float64Array', 'Float64Array'
'SharedInt8Array',
'SharedUint8Array',
'SharedUint8ClampedArray',
'SharedInt16Array',
'SharedUint16Array',
'SharedInt32Array',
'SharedUint32Array',
'SharedFloat32Array',
'SharedFloat64Array'
) )
TagLookup = { TagLookup = {
@ -2877,7 +2861,6 @@ class IDLBuiltinType(IDLType):
Types.ArrayBuffer: IDLType.Tags.interface, Types.ArrayBuffer: IDLType.Tags.interface,
Types.ArrayBufferView: IDLType.Tags.interface, Types.ArrayBufferView: IDLType.Tags.interface,
Types.SharedArrayBuffer: IDLType.Tags.interface, Types.SharedArrayBuffer: IDLType.Tags.interface,
Types.SharedArrayBufferView: IDLType.Tags.interface,
Types.Int8Array: IDLType.Tags.interface, Types.Int8Array: IDLType.Tags.interface,
Types.Uint8Array: IDLType.Tags.interface, Types.Uint8Array: IDLType.Tags.interface,
Types.Uint8ClampedArray: IDLType.Tags.interface, Types.Uint8ClampedArray: IDLType.Tags.interface,
@ -2886,16 +2869,7 @@ class IDLBuiltinType(IDLType):
Types.Int32Array: IDLType.Tags.interface, Types.Int32Array: IDLType.Tags.interface,
Types.Uint32Array: IDLType.Tags.interface, Types.Uint32Array: IDLType.Tags.interface,
Types.Float32Array: IDLType.Tags.interface, Types.Float32Array: IDLType.Tags.interface,
Types.Float64Array: IDLType.Tags.interface, Types.Float64Array: IDLType.Tags.interface
Types.SharedInt8Array: IDLType.Tags.interface,
Types.SharedUint8Array: IDLType.Tags.interface,
Types.SharedUint8ClampedArray: IDLType.Tags.interface,
Types.SharedInt16Array: IDLType.Tags.interface,
Types.SharedUint16Array: IDLType.Tags.interface,
Types.SharedInt32Array: IDLType.Tags.interface,
Types.SharedUint32Array: IDLType.Tags.interface,
Types.SharedFloat32Array: IDLType.Tags.interface,
Types.SharedFloat64Array: IDLType.Tags.interface
} }
def __init__(self, location, name, type): def __init__(self, location, name, type):
@ -2938,17 +2912,10 @@ class IDLBuiltinType(IDLType):
def isSharedArrayBuffer(self): def isSharedArrayBuffer(self):
return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer
def isSharedArrayBufferView(self):
return self._typeTag == IDLBuiltinType.Types.SharedArrayBufferView
def isTypedArray(self): def isTypedArray(self):
return (self._typeTag >= IDLBuiltinType.Types.Int8Array and return (self._typeTag >= IDLBuiltinType.Types.Int8Array and
self._typeTag <= IDLBuiltinType.Types.Float64Array) self._typeTag <= IDLBuiltinType.Types.Float64Array)
def isSharedTypedArray(self):
return (self._typeTag >= IDLBuiltinType.Types.SharedInt8Array and
self._typeTag <= IDLBuiltinType.Types.SharedFloat64Array)
def isInterface(self): def isInterface(self):
# TypedArray things are interface types per the TypedArray spec, # TypedArray things are interface types per the TypedArray spec,
# but we handle them as builtins because SpiderMonkey implements # but we handle them as builtins because SpiderMonkey implements
@ -2956,9 +2923,7 @@ class IDLBuiltinType(IDLType):
return (self.isArrayBuffer() or return (self.isArrayBuffer() or
self.isArrayBufferView() or self.isArrayBufferView() or
self.isSharedArrayBuffer() or self.isSharedArrayBuffer() or
self.isSharedArrayBufferView() or self.isTypedArray())
self.isTypedArray() or
self.isSharedTypedArray())
def isNonCallbackInterface(self): def isNonCallbackInterface(self):
# All the interfaces we can be are non-callback # All the interfaces we can be are non-callback
@ -3036,15 +3001,11 @@ class IDLBuiltinType(IDLType):
# that's not an ArrayBufferView or typed array. # that's not an ArrayBufferView or typed array.
(self.isArrayBufferView() and not other.isArrayBufferView() and (self.isArrayBufferView() and not other.isArrayBufferView() and
not other.isTypedArray()) or not other.isTypedArray()) or
(self.isSharedArrayBufferView() and not other.isSharedArrayBufferView() and
not other.isSharedTypedArray()) or
# Typed arrays are distinguishable from everything # Typed arrays are distinguishable from everything
# except ArrayBufferView and the same type of typed # except ArrayBufferView and the same type of typed
# array # array
(self.isTypedArray() and not other.isArrayBufferView() and not (self.isTypedArray() and not other.isArrayBufferView() and not
(other.isTypedArray() and other.name == self.name)) or (other.isTypedArray() and other.name == self.name)))))
(self.isSharedTypedArray() and not other.isSharedArrayBufferView() and not
(other.isSharedTypedArray() and other.name == self.name)))))
def _getDependentObjects(self): def _getDependentObjects(self):
return set() return set()
@ -3119,9 +3080,6 @@ BuiltinTypes = {
IDLBuiltinType.Types.SharedArrayBuffer: IDLBuiltinType.Types.SharedArrayBuffer:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBuffer", IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBuffer",
IDLBuiltinType.Types.SharedArrayBuffer), IDLBuiltinType.Types.SharedArrayBuffer),
IDLBuiltinType.Types.SharedArrayBufferView:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBufferView",
IDLBuiltinType.Types.SharedArrayBufferView),
IDLBuiltinType.Types.Int8Array: IDLBuiltinType.Types.Int8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array", IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
IDLBuiltinType.Types.Int8Array), IDLBuiltinType.Types.Int8Array),
@ -3148,34 +3106,7 @@ BuiltinTypes = {
IDLBuiltinType.Types.Float32Array), IDLBuiltinType.Types.Float32Array),
IDLBuiltinType.Types.Float64Array: IDLBuiltinType.Types.Float64Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array", IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array",
IDLBuiltinType.Types.Float64Array), IDLBuiltinType.Types.Float64Array)
IDLBuiltinType.Types.SharedInt8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedInt8Array",
IDLBuiltinType.Types.SharedInt8Array),
IDLBuiltinType.Types.SharedUint8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint8Array",
IDLBuiltinType.Types.SharedUint8Array),
IDLBuiltinType.Types.SharedUint8ClampedArray:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint8ClampedArray",
IDLBuiltinType.Types.SharedUint8ClampedArray),
IDLBuiltinType.Types.SharedInt16Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedInt16Array",
IDLBuiltinType.Types.SharedInt16Array),
IDLBuiltinType.Types.SharedUint16Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint16Array",
IDLBuiltinType.Types.SharedUint16Array),
IDLBuiltinType.Types.SharedInt32Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedInt32Array",
IDLBuiltinType.Types.SharedInt32Array),
IDLBuiltinType.Types.SharedUint32Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedUint32Array",
IDLBuiltinType.Types.SharedUint32Array),
IDLBuiltinType.Types.SharedFloat32Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedFloat32Array",
IDLBuiltinType.Types.SharedFloat32Array),
IDLBuiltinType.Types.SharedFloat64Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedFloat64Array",
IDLBuiltinType.Types.SharedFloat64Array)
} }
@ -3266,7 +3197,7 @@ class IDLValue(IDLObject):
(self.value == float("inf") or self.value == float("-inf") or (self.value == float("inf") or self.value == float("-inf") or
math.isnan(self.value))): math.isnan(self.value))):
raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted" raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted"
% self.value, [location]); % self.value, [location])
return IDLValue(self.location, type, self.value) return IDLValue(self.location, type, self.value)
elif self.type.isString() and type.isUSVString(): elif self.type.isString() and type.isUSVString():
# Allow USVStrings to use default value just like # Allow USVStrings to use default value just like
@ -3366,7 +3297,8 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
'Const', 'Const',
'Attr', 'Attr',
'Method', 'Method',
'MaplikeOrSetlike' 'MaplikeOrSetlike',
'Iterable'
) )
Special = enum( Special = enum(
@ -3392,6 +3324,10 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
def isConst(self): def isConst(self):
return self.tag == IDLInterfaceMember.Tags.Const return self.tag == IDLInterfaceMember.Tags.Const
def isMaplikeOrSetlikeOrIterable(self):
return (self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike or
self.tag == IDLInterfaceMember.Tags.Iterable)
def isMaplikeOrSetlike(self): def isMaplikeOrSetlike(self):
return self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike return self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike
@ -3469,58 +3405,42 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
self.aliases.append(alias) self.aliases.append(alias)
# MaplikeOrSetlike adds a trait to an interface, like map or iteration class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
# functions. To handle them while still getting all of the generated binding
# code taken care of, we treat them as macros that are expanded into members
# based on parsed values.
class IDLMaplikeOrSetlike(IDLInterfaceMember):
MaplikeOrSetlikeTypes = enum(
'maplike',
'setlike'
)
def __init__(self, location, identifier, maplikeOrSetlikeType,
readonly, keyType, valueType):
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.MaplikeOrSetlike)
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
assert isinstance(keyType, IDLType) assert isinstance(keyType, IDLType)
assert ifaceType in ['maplike', 'setlike', 'iterable']
if valueType is not None:
assert isinstance(valueType, IDLType) assert isinstance(valueType, IDLType)
self.maplikeOrSetlikeType = maplikeOrSetlikeType
self.readonly = readonly
self.keyType = keyType self.keyType = keyType
self.valueType = valueType self.valueType = valueType
self.slotIndex = None self.maplikeOrSetlikeOrIterableType = ifaceType
self.disallowedMemberNames = [] self.disallowedMemberNames = []
self.disallowedNonMethodNames = [] self.disallowedNonMethodNames = []
# When generating JSAPI access code, we need to know the backing object
# type prefix to create the correct function. Generate here for reuse.
if self.isMaplike():
self.prefix = 'Map'
elif self.isSetlike():
self.prefix = 'Set'
def __str__(self):
return "declared '%s' with key '%s'" % (self.maplikeOrSetlikeType, self.keyType)
def isMaplike(self): def isMaplike(self):
return self.maplikeOrSetlikeType == "maplike" return self.maplikeOrSetlikeOrIterableType == "maplike"
def isSetlike(self): def isSetlike(self):
return self.maplikeOrSetlikeType == "setlike" return self.maplikeOrSetlikeOrIterableType == "setlike"
def isIterable(self):
return self.maplikeOrSetlikeOrIterableType == "iterable"
def hasValueType(self):
return self.valueType is not None
def checkCollisions(self, members, isAncestor): def checkCollisions(self, members, isAncestor):
for member in members: for member in members:
# Check that there are no disallowed members # Check that there are no disallowed members
if (member.identifier.name in self.disallowedMemberNames and if (member.identifier.name in self.disallowedMemberNames and
not ((member.isMethod() and member.isMaplikeOrSetlikeMethod()) or not ((member.isMethod() and member.isMaplikeOrSetlikeOrIterableMethod()) or
(member.isAttr() and member.isMaplikeOrSetlikeAttr()))): (member.isAttr() and member.isMaplikeOrSetlikeAttr()))):
raise WebIDLError("Member '%s' conflicts " raise WebIDLError("Member '%s' conflicts "
"with reserved %s name." % "with reserved %s name." %
(member.identifier.name, (member.identifier.name,
self.maplikeOrSetlikeType), self.maplikeOrSetlikeOrIterableType),
[self.location, member.location]) [self.location, member.location])
# Check that there are no disallowed non-method members # Check that there are no disallowed non-method members
if (isAncestor or (member.isAttr() or member.isConst()) and if (isAncestor or (member.isAttr() or member.isConst()) and
@ -3528,27 +3448,31 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
raise WebIDLError("Member '%s' conflicts " raise WebIDLError("Member '%s' conflicts "
"with reserved %s method." % "with reserved %s method." %
(member.identifier.name, (member.identifier.name,
self.maplikeOrSetlikeType), self.maplikeOrSetlikeOrIterableType),
[self.location, member.location]) [self.location, member.location])
def expand(self, members, isJSImplemented): def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False):
""" """
In order to take advantage of all of the method machinery in Codegen, Create an IDLMethod based on the parameters passed in.
we generate our functions as if they were part of the interface
specification during parsing. - members is the member list to add this function to, since this is
""" called during the member expansion portion of interface object
def addMethod(name, allowExistingOperations, returnType, args=[], building.
chromeOnly=False, isPure=False, affectsNothing=False):
""" - chromeOnly is only True for read-only js implemented classes, to
Create an IDLMethod based on the parameters passed in. chromeOnly is only implement underscore prefixed convenience functions which would
True for read-only js implemented classes, to implement underscore otherwise not be available, unlike the case of C++ bindings.
prefixed convenience functions would otherwise not be available,
unlike the case of C++ bindings. isPure is only True for - isPure is only True for idempotent functions, so it is not valid for
idempotent functions, so it is not valid for things like keys, things like keys, values, etc. that return a new object every time.
values, etc. that return a new object every time.
- affectsNothing means that nothing changes due to this method, which
affects JIT optimization behavior
- newObject means the method creates and returns a new object.
""" """
# Only add name to lists for collision checks if it's not chrome # Only add name to lists for collision checks if it's not chrome
# only. # only.
if chromeOnly: if chromeOnly:
@ -3558,7 +3482,6 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
self.disallowedMemberNames.append(name) self.disallowedMemberNames.append(name)
else: else:
self.disallowedNonMethodNames.append(name) self.disallowedNonMethodNames.append(name)
# If allowExistingOperations is True, and another operation exists # If allowExistingOperations is True, and another operation exists
# with the same name as the one we're trying to add, don't add the # with the same name as the one we're trying to add, don't add the
# maplike/setlike operation. However, if the operation is static, # maplike/setlike operation. However, if the operation is static,
@ -3568,11 +3491,9 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
for m in members: for m in members:
if m.identifier.name == name and m.isMethod() and not m.isStatic(): if m.identifier.name == name and m.isMethod() and not m.isStatic():
return return
method = IDLMethod(self.location, method = IDLMethod(self.location,
IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly), IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly),
returnType, args, maplikeOrSetlike=self) returnType, args, maplikeOrSetlikeOrIterable=self)
# We need to be able to throw from declaration methods # We need to be able to throw from declaration methods
method.addExtendedAttributes( method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("Throws",))]) [IDLExtendedAttribute(self.location, ("Throws",))])
@ -3588,107 +3509,14 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
method.addExtendedAttributes( method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("DependsOn", "Everything")), [IDLExtendedAttribute(self.location, ("DependsOn", "Everything")),
IDLExtendedAttribute(self.location, ("Affects", "Nothing"))]) IDLExtendedAttribute(self.location, ("Affects", "Nothing"))])
if newObject:
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("NewObject",))])
members.append(method) members.append(method)
# Both maplike and setlike have a size attribute
members.append(IDLAttribute(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"),
BuiltinTypes[IDLBuiltinType.Types.unsigned_long],
True,
maplikeOrSetlike=self))
self.reserved_ro_names = ["size"]
# object entries()
addMethod("entries", False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# object keys()
addMethod("keys", False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# object values()
addMethod("values", False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# void forEach(callback(valueType, keyType), thisVal)
foreachArguments = [IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"callback"),
BuiltinTypes[IDLBuiltinType.Types.object]),
IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"thisArg"),
BuiltinTypes[IDLBuiltinType.Types.any],
optional=True)]
addMethod("forEach", False, BuiltinTypes[IDLBuiltinType.Types.void],
foreachArguments)
def getKeyArg():
return IDLArgument(self.location,
IDLUnresolvedIdentifier(self.location, "key"),
self.keyType)
# boolean has(keyType key)
addMethod("has", False, BuiltinTypes[IDLBuiltinType.Types.boolean],
[getKeyArg()], isPure=True)
if not self.readonly:
# void clear()
addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void],
[])
# boolean delete(keyType key)
addMethod("delete", True,
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()])
# Always generate underscored functions (e.g. __add, __clear) for js
# implemented interfaces as convenience functions.
if isJSImplemented:
# void clear()
addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void],
[], chromeOnly=True)
# boolean delete(keyType key)
addMethod("delete", True,
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()],
chromeOnly=True)
if self.isSetlike():
if not self.readonly:
# Add returns the set object it just added to.
# object add(keyType key)
addMethod("add", True,
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()])
if isJSImplemented:
addMethod("add", True,
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()],
chromeOnly=True)
return
# If we get this far, we're a maplike declaration.
# valueType get(keyType key)
#
# Note that instead of the value type, we're using any here. The
# validity checks should happen as things are inserted into the map,
# and using any as the return type makes code generation much simpler.
#
# TODO: Bug 1155340 may change this to use specific type to provide
# more info to JIT.
addMethod("get", False, BuiltinTypes[IDLBuiltinType.Types.any],
[getKeyArg()], isPure=True)
def getValueArg():
return IDLArgument(self.location,
IDLUnresolvedIdentifier(self.location, "value"),
self.valueType)
if not self.readonly:
addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg(), getValueArg()])
if isJSImplemented:
addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg(), getValueArg()], chromeOnly=True)
def resolve(self, parentScope): def resolve(self, parentScope):
self.keyType.resolveType(parentScope) self.keyType.resolveType(parentScope)
if self.valueType:
self.valueType.resolveType(parentScope) self.valueType.resolveType(parentScope)
def finish(self, scope): def finish(self, scope):
@ -3700,7 +3528,7 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
assert not isinstance(t, IDLTypedefType) assert not isinstance(t, IDLTypedefType)
assert not isinstance(t.name, IDLUnresolvedIdentifier) assert not isinstance(t.name, IDLUnresolvedIdentifier)
self.keyType = t self.keyType = t
if not self.valueType.isComplete(): if self.valueType and not self.valueType.isComplete():
t = self.valueType.complete(scope) t = self.valueType.complete(scope)
assert not isinstance(t, IDLUnresolvedType) assert not isinstance(t, IDLUnresolvedType)
@ -3715,8 +3543,161 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
IDLInterfaceMember.handleExtendedAttribute(self, attr) IDLInterfaceMember.handleExtendedAttribute(self, attr)
def _getDependentObjects(self): def _getDependentObjects(self):
if self.valueType:
return set([self.keyType, self.valueType]) return set([self.keyType, self.valueType])
return set([self.keyType])
# Iterable adds ES6 iterator style functions and traits
# (keys/values/entries/@@iterator) to an interface.
class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
def __init__(self, location, identifier, keyType, valueType=None, scope=None):
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier,
"iterable", keyType, valueType,
IDLInterfaceMember.Tags.Iterable)
self.iteratorType = None
def __str__(self):
return "declared iterable with key '%s' and value '%s'" % (self.keyType, self.valueType)
def expand(self, members, isJSImplemented):
"""
In order to take advantage of all of the method machinery in Codegen,
we generate our functions as if they were part of the interface
specification during parsing.
"""
# object entries()
self.addMethod("entries", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
# object keys()
self.addMethod("keys", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
# object values()
self.addMethod("values", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
def __init__(self, location, identifier, maplikeOrSetlikeType,
readonly, keyType, valueType):
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier, maplikeOrSetlikeType,
keyType, valueType, IDLInterfaceMember.Tags.MaplikeOrSetlike)
self.readonly = readonly
self.slotIndex = None
# When generating JSAPI access code, we need to know the backing object
# type prefix to create the correct function. Generate here for reuse.
if self.isMaplike():
self.prefix = 'Map'
elif self.isSetlike():
self.prefix = 'Set'
def __str__(self):
return "declared '%s' with key '%s'" % (self.maplikeOrSetlikeOrIterableType, self.keyType)
def expand(self, members, isJSImplemented):
"""
In order to take advantage of all of the method machinery in Codegen,
we generate our functions as if they were part of the interface
specification during parsing.
"""
# Both maplike and setlike have a size attribute
members.append(IDLAttribute(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"),
BuiltinTypes[IDLBuiltinType.Types.unsigned_long],
True,
maplikeOrSetlike=self))
self.reserved_ro_names = ["size"]
# object entries()
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# object keys()
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# object values()
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# void forEach(callback(valueType, keyType), thisVal)
foreachArguments = [IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"callback"),
BuiltinTypes[IDLBuiltinType.Types.object]),
IDLArgument(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"thisArg"),
BuiltinTypes[IDLBuiltinType.Types.any],
optional=True)]
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
foreachArguments)
def getKeyArg():
return IDLArgument(self.location,
IDLUnresolvedIdentifier(self.location, "key"),
self.keyType)
# boolean has(keyType key)
self.addMethod("has", members, False, BuiltinTypes[IDLBuiltinType.Types.boolean],
[getKeyArg()], isPure=True)
if not self.readonly:
# void clear()
self.addMethod("clear", members, True, BuiltinTypes[IDLBuiltinType.Types.void],
[])
# boolean delete(keyType key)
self.addMethod("delete", members, True,
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()])
# Always generate underscored functions (e.g. __add, __clear) for js
# implemented interfaces as convenience functions.
if isJSImplemented:
# void clear()
self.addMethod("clear", members, True, BuiltinTypes[IDLBuiltinType.Types.void],
[], chromeOnly=True)
# boolean delete(keyType key)
self.addMethod("delete", members, True,
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()],
chromeOnly=True)
if self.isSetlike():
if not self.readonly:
# Add returns the set object it just added to.
# object add(keyType key)
self.addMethod("add", members, True,
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()])
if isJSImplemented:
self.addMethod("add", members, True,
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()],
chromeOnly=True)
return
# If we get this far, we're a maplike declaration.
# valueType get(keyType key)
#
# Note that instead of the value type, we're using any here. The
# validity checks should happen as things are inserted into the map,
# and using any as the return type makes code generation much simpler.
#
# TODO: Bug 1155340 may change this to use specific type to provide
# more info to JIT.
self.addMethod("get", members, False, BuiltinTypes[IDLBuiltinType.Types.any],
[getKeyArg()], isPure=True)
def getValueArg():
return IDLArgument(self.location,
IDLUnresolvedIdentifier(self.location, "value"),
self.valueType)
if not self.readonly:
self.addMethod("set", members, True, BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg(), getValueArg()])
if isJSImplemented:
self.addMethod("set", members, True, BuiltinTypes[IDLBuiltinType.Types.object],
[getKeyArg(), getValueArg()], chromeOnly=True)
class IDLConst(IDLInterfaceMember): class IDLConst(IDLInterfaceMember):
def __init__(self, location, identifier, type, value): def __init__(self, location, identifier, type, value):
@ -4026,6 +4007,11 @@ class IDLAttribute(IDLInterfaceMember):
"readonly attributes" % attr.value(), "readonly attributes" % attr.value(),
[attr.location, self.location]) [attr.location, self.location])
self._setDependsOn(attr.value()) self._setDependsOn(attr.value())
elif identifier == "UseCounter":
if self.stringifier:
raise WebIDLError("[UseCounter] must not be used on a "
"stringifier attribute",
[attr.location, self.location])
elif (identifier == "Pref" or elif (identifier == "Pref" or
identifier == "Deprecated" or identifier == "Deprecated" or
identifier == "SetterThrows" or identifier == "SetterThrows" or
@ -4313,7 +4299,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
static=False, getter=False, setter=False, creator=False, static=False, getter=False, setter=False, creator=False,
deleter=False, specialType=NamedOrIndexed.Neither, deleter=False, specialType=NamedOrIndexed.Neither,
legacycaller=False, stringifier=False, jsonifier=False, legacycaller=False, stringifier=False, jsonifier=False,
maplikeOrSetlike=None): maplikeOrSetlikeOrIterable=None):
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up. # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
IDLInterfaceMember.__init__(self, location, identifier, IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Method) IDLInterfaceMember.Tags.Method)
@ -4341,8 +4327,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self._stringifier = stringifier self._stringifier = stringifier
assert isinstance(jsonifier, bool) assert isinstance(jsonifier, bool)
self._jsonifier = jsonifier self._jsonifier = jsonifier
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike) assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
self.maplikeOrSetlike = maplikeOrSetlike self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
self._specialType = specialType self._specialType = specialType
self._unforgeable = False self._unforgeable = False
self.dependsOn = "Everything" self.dependsOn = "Everything"
@ -4424,12 +4410,21 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def isJsonifier(self): def isJsonifier(self):
return self._jsonifier return self._jsonifier
def isMaplikeOrSetlikeMethod(self): def isMaplikeOrSetlikeOrIterableMethod(self):
""" """
True if this method was generated as part of a True if this method was generated as part of a
maplike/setlike/etc interface (e.g. has/get methods) maplike/setlike/etc interface (e.g. has/get methods)
""" """
return self.maplikeOrSetlike is not None return self.maplikeOrSetlikeOrIterable is not None
def isSpecial(self):
return (self.isGetter() or
self.isSetter() or
self.isCreator() or
self.isDeleter() or
self.isLegacycaller() or
self.isStringifier() or
self.isJsonifier())
def hasOverloads(self): def hasOverloads(self):
return self._hasOverloads return self._hasOverloads
@ -4443,7 +4438,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
an non-identifier name, they actually DO have an identifier. an non-identifier name, they actually DO have an identifier.
""" """
return (self.identifier.name[:2] == "__" and return (self.identifier.name[:2] == "__" and
not self.isMaplikeOrSetlikeMethod()) not self.isMaplikeOrSetlikeOrIterableMethod())
def resolve(self, parentScope): def resolve(self, parentScope):
assert isinstance(parentScope, IDLScope) assert isinstance(parentScope, IDLScope)
@ -4712,6 +4707,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[Alias] takes an identifier or string", raise WebIDLError("[Alias] takes an identifier or string",
[attr.location]) [attr.location])
self._addAlias(attr.value()) self._addAlias(attr.value())
elif identifier == "UseCounter":
if self.isSpecial():
raise WebIDLError("[UseCounter] must not be used on a special "
"operation",
[attr.location, self.location])
elif (identifier == "Throws" or elif (identifier == "Throws" or
identifier == "NewObject" or identifier == "NewObject" or
identifier == "ChromeOnly" or identifier == "ChromeOnly" or
@ -4723,7 +4723,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "CheckAnyPermissions" or identifier == "CheckAnyPermissions" or
identifier == "CheckAllPermissions" or identifier == "CheckAllPermissions" or
identifier == "BinaryName" or identifier == "BinaryName" or
identifier == "MethodIdentityTestable" or
identifier == "StaticClassOverride"): identifier == "StaticClassOverride"):
# Known attributes that we don't need to do anything with here # Known attributes that we don't need to do anything with here
pass pass
@ -4946,7 +4945,8 @@ class Tokenizer(object):
"SharedArrayBuffer": "SHAREDARRAYBUFFER", "SharedArrayBuffer": "SHAREDARRAYBUFFER",
"or": "OR", "or": "OR",
"maplike": "MAPLIKE", "maplike": "MAPLIKE",
"setlike": "SETLIKE" "setlike": "SETLIKE",
"iterable": "ITERABLE"
} }
tokens.extend(keywords.values()) tokens.extend(keywords.values())
@ -5100,8 +5100,9 @@ class Parser(Tokenizer):
raise ex raise ex
pass pass
p[0] = IDLInterface(location, self.globalScope(), identifier, parent, iface = IDLInterface(location, self.globalScope(), identifier, parent,
members, isKnownNonPartial=True) members, isKnownNonPartial=True)
p[0] = iface
def p_InterfaceForwardDecl(self, p): def p_InterfaceForwardDecl(self, p):
""" """
@ -5187,7 +5188,7 @@ class Parser(Tokenizer):
def p_InterfaceMember(self, p): def p_InterfaceMember(self, p):
""" """
InterfaceMember : Const InterfaceMember : Const
| AttributeOrOperationOrMaplikeOrSetlike | AttributeOrOperationOrMaplikeOrSetlikeOrIterable
""" """
p[0] = p[1] p[0] = p[1]
@ -5402,15 +5403,30 @@ class Parser(Tokenizer):
""" """
p[0] = False p[0] = False
def p_AttributeOrOperationOrMaplikeOrSetlike(self, p): def p_AttributeOrOperationOrMaplikeOrSetlikeOrIterable(self, p):
""" """
AttributeOrOperationOrMaplikeOrSetlike : Attribute AttributeOrOperationOrMaplikeOrSetlikeOrIterable : Attribute
| Maplike | Maplike
| Setlike | Setlike
| Iterable
| Operation | Operation
""" """
p[0] = p[1] p[0] = p[1]
def p_Iterable(self, p):
"""
Iterable : ITERABLE LT Type GT SEMICOLON
| ITERABLE LT Type COMMA Type GT SEMICOLON
"""
location = self.getLocation(p, 2)
identifier = IDLUnresolvedIdentifier(location, "__iterable",
allowDoubleUnderscore=True)
keyType = p[3]
valueType = None
if (len(p) > 6):
valueType = p[5]
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
def p_Setlike(self, p): def p_Setlike(self, p):
""" """
Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON
@ -5783,6 +5799,7 @@ class Parser(Tokenizer):
| IMPLEMENTS | IMPLEMENTS
| INHERIT | INHERIT
| INTERFACE | INTERFACE
| ITERABLE
| LEGACYCALLER | LEGACYCALLER
| MAPLIKE | MAPLIKE
| PARTIAL | PARTIAL
@ -6432,7 +6449,7 @@ class Parser(Tokenizer):
assert isinstance(scope, IDLScope) assert isinstance(scope, IDLScope)
# xrange omits the last value. # xrange omits the last value.
for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.SharedFloat64Array + 1): for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
builtin = BuiltinTypes[x] builtin = BuiltinTypes[x]
name = builtin.name name = builtin.name
typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name) typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name)
@ -6461,7 +6478,49 @@ class Parser(Tokenizer):
self._filename = None self._filename = None
def finish(self): def finish(self):
# First, finish all the IDLImplementsStatements. In particular, we # If we have interfaces that are iterable, create their
# iterator interfaces and add them to the productions array.
interfaceStatements = [p for p in self._productions if
isinstance(p, IDLInterface)]
iterableIteratorIface = None
for iface in interfaceStatements:
iterable = None
# We haven't run finish() on the interface yet, so we don't know
# whether our interface is maplike/setlike/iterable or not. This
# means we have to loop through the members to see if we have an
# iterable member.
for m in iface.members:
if isinstance(m, IDLIterable):
iterable = m
break
if iterable:
def simpleExtendedAttr(str):
return IDLExtendedAttribute(iface.location, (str, ))
nextMethod = IDLMethod(
iface.location,
IDLUnresolvedIdentifier(iface.location, "next"),
BuiltinTypes[IDLBuiltinType.Types.object], [])
nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")])
itr_ident = IDLUnresolvedIdentifier(iface.location,
iface.identifier.name + "Iterator")
itr_iface = IDLInterface(iface.location, self.globalScope(),
itr_ident, None, [nextMethod],
isKnownNonPartial=True)
itr_iface.addExtendedAttributes([simpleExtendedAttr("NoInterfaceObject")])
# Make sure the exposure set for the iterator interface is the
# same as the exposure set for the iterable interface, because
# we're going to generate methods on the iterable that return
# instances of the iterator.
itr_iface._exposureGlobalNames = set(iface._exposureGlobalNames)
# Always append generated iterable interfaces after the
# interface they're a member of, otherwise nativeType generation
# won't work correctly.
itr_iface.iterableInterface = iface
self._productions.append(itr_iface)
iterable.iteratorType = IDLWrapperType(iface.location, itr_iface)
# Then, finish all the IDLImplementsStatements. In particular, we
# have to make sure we do those before we do the IDLInterfaces. # have to make sure we do those before we do the IDLInterfaces.
# XXX khuey hates this bit and wants to nuke it from orbit. # XXX khuey hates this bit and wants to nuke it from orbit.
implementsStatements = [p for p in self._productions if implementsStatements = [p for p in self._productions if
@ -6493,7 +6552,6 @@ class Parser(Tokenizer):
_builtins = """ _builtins = """
typedef unsigned long long DOMTimeStamp; typedef unsigned long long DOMTimeStamp;
typedef (ArrayBufferView or ArrayBuffer) BufferSource; typedef (ArrayBufferView or ArrayBuffer) BufferSource;
typedef (SharedArrayBufferView or SharedArrayBuffer) SharedBufferSource;
""" """