mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Update WebIDL parser
This commit is contained in:
parent
06947965b1
commit
c1718a0b1f
1 changed files with 376 additions and 318 deletions
|
@ -540,6 +540,9 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
|
|||
def validate(self):
|
||||
pass
|
||||
|
||||
def isIteratorInterface(self):
|
||||
return False
|
||||
|
||||
def isExternal(self):
|
||||
return True
|
||||
|
||||
|
@ -640,7 +643,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
self._callback = False
|
||||
self._finished = False
|
||||
self.members = []
|
||||
self.maplikeOrSetlike = None
|
||||
self.maplikeOrSetlikeOrIterable = None
|
||||
self._partialInterfaces = []
|
||||
self._extendedAttrDict = {}
|
||||
# namedConstructors needs deterministic ordering because bindings code
|
||||
|
@ -664,6 +667,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
self.totalMembersInSlots = 0
|
||||
# Tracking of the number of own own members we have in slots
|
||||
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)
|
||||
IDLExposureMixins.__init__(self, location)
|
||||
|
@ -682,6 +688,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
except:
|
||||
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):
|
||||
assert isinstance(scope, IDLScope)
|
||||
assert isinstance(originalObject, IDLInterfaceMember)
|
||||
|
@ -718,22 +731,22 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
# need to be treated like regular interface members, do this before
|
||||
# things like exposure setting.
|
||||
for member in self.members:
|
||||
if member.isMaplikeOrSetlike():
|
||||
if member.isMaplikeOrSetlikeOrIterable():
|
||||
# Check that we only have one interface declaration (currently
|
||||
# there can only be one maplike/setlike declaration per
|
||||
# interface)
|
||||
if self.maplikeOrSetlike:
|
||||
if self.maplikeOrSetlikeOrIterable:
|
||||
raise WebIDLError("%s declaration used on "
|
||||
"interface that already has %s "
|
||||
"declaration" %
|
||||
(member.maplikeOrSetlikeType,
|
||||
self.maplikeOrSetlike.maplikeOrSetlikeType),
|
||||
[self.maplikeOrSetlike.location,
|
||||
(member.maplikeOrSetlikeOrIterableType,
|
||||
self.maplikeOrSetlikeOrIterable.maplikeOrSetlikeOrIterableType),
|
||||
[self.maplikeOrSetlikeOrIterable.location,
|
||||
member.location])
|
||||
self.maplikeOrSetlike = member
|
||||
self.maplikeOrSetlikeOrIterable = member
|
||||
# If we've got a maplike or setlike declaration, we'll be building all of
|
||||
# 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
|
||||
# _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
|
||||
# also does, throw an error.
|
||||
if iface.maplikeOrSetlike and self.maplikeOrSetlike:
|
||||
raise WebIDLError("Maplike/setlike interface %s cannot have "
|
||||
"maplike/setlike interface %s as a "
|
||||
if iface.maplikeOrSetlikeOrIterable and self.maplikeOrSetlikeOrIterable:
|
||||
raise WebIDLError("Maplike/setlike/iterable interface %s cannot have "
|
||||
"maplike/setlike/iterable interface %s as a "
|
||||
"consequential interface" %
|
||||
(self.identifier.name,
|
||||
iface.identifier.name),
|
||||
[self.maplikeOrSetlike.location,
|
||||
iface.maplikeOrSetlike.location])
|
||||
[self.maplikeOrSetlikeOrIterable.location,
|
||||
iface.maplikeOrSetlikeOrIterable.location])
|
||||
additionalMembers = iface.originalMembers
|
||||
for additionalMember in additionalMembers:
|
||||
for member in self.members:
|
||||
|
@ -905,15 +918,15 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
|
||||
for ancestor in self.getInheritedInterfaces():
|
||||
ancestor.interfacesBasedOnSelf.add(self)
|
||||
if (ancestor.maplikeOrSetlike is not None and
|
||||
self.maplikeOrSetlike is not None):
|
||||
if (ancestor.maplikeOrSetlikeOrIterable is not None and
|
||||
self.maplikeOrSetlikeOrIterable is not None):
|
||||
raise WebIDLError("Cannot have maplike/setlike on %s that "
|
||||
"inherits %s, which is already "
|
||||
"maplike/setlike" %
|
||||
(self.identifier.name,
|
||||
ancestor.identifier.name),
|
||||
[self.maplikeOrSetlike.location,
|
||||
ancestor.maplikeOrSetlike.location])
|
||||
[self.maplikeOrSetlikeOrIterable.location,
|
||||
ancestor.maplikeOrSetlikeOrIterable.location])
|
||||
for ancestorConsequential in ancestor.getConsequentialInterfaces():
|
||||
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
|
||||
# uses maplike/setlike, check for collisions anywhere in the current
|
||||
# interface or higher in the inheritance chain.
|
||||
if self.maplikeOrSetlike:
|
||||
if self.maplikeOrSetlikeOrIterable:
|
||||
testInterface = self
|
||||
isAncestor = False
|
||||
while testInterface:
|
||||
self.maplikeOrSetlike.checkCollisions(testInterface.members,
|
||||
self.maplikeOrSetlikeOrIterable.checkCollisions(testInterface.members,
|
||||
isAncestor)
|
||||
isAncestor = True
|
||||
testInterface = testInterface.parent
|
||||
|
@ -1411,7 +1424,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
identifier == "AvailableIn" or
|
||||
identifier == "Func" or
|
||||
identifier == "CheckAnyPermissions" or
|
||||
identifier == "CheckAllPermissions"):
|
||||
identifier == "CheckAllPermissions" or
|
||||
identifier == "Deprecated"):
|
||||
# Known extended attributes that take a string value
|
||||
if not attr.hasValue():
|
||||
raise WebIDLError("[%s] must have a value" % identifier,
|
||||
|
@ -1821,15 +1835,9 @@ class IDLType(IDLObject):
|
|||
def isSharedArrayBuffer(self):
|
||||
return False
|
||||
|
||||
def isSharedArrayBufferView(self):
|
||||
return False
|
||||
|
||||
def isTypedArray(self):
|
||||
return False
|
||||
|
||||
def isSharedTypedArray(self):
|
||||
return False
|
||||
|
||||
def isCallbackInterface(self):
|
||||
return False
|
||||
|
||||
|
@ -1850,9 +1858,7 @@ class IDLType(IDLObject):
|
|||
return self.isInterface() and (self.isArrayBuffer() or
|
||||
self.isArrayBufferView() or
|
||||
self.isSharedArrayBuffer() or
|
||||
self.isSharedArrayBufferView() or
|
||||
self.isTypedArray() or
|
||||
self.isSharedTypedArray())
|
||||
self.isTypedArray())
|
||||
|
||||
def isDictionary(self):
|
||||
return False
|
||||
|
@ -2039,15 +2045,9 @@ class IDLNullableType(IDLType):
|
|||
def isSharedArrayBuffer(self):
|
||||
return self.inner.isSharedArrayBuffer()
|
||||
|
||||
def isSharedArrayBufferView(self):
|
||||
return self.inner.isSharedArrayBufferView()
|
||||
|
||||
def isTypedArray(self):
|
||||
return self.inner.isTypedArray()
|
||||
|
||||
def isSharedTypedArray(self):
|
||||
return self.inner.isSharedTypedArray()
|
||||
|
||||
def isDictionary(self):
|
||||
return self.inner.isDictionary()
|
||||
|
||||
|
@ -2554,15 +2554,9 @@ class IDLTypedefType(IDLType):
|
|||
def isSharedArrayBuffer(self):
|
||||
return self.inner.isSharedArrayBuffer()
|
||||
|
||||
def isSharedArrayBufferView(self):
|
||||
return self.inner.isSharedArrayBufferView()
|
||||
|
||||
def isTypedArray(self):
|
||||
return self.inner.isTypedArray()
|
||||
|
||||
def isSharedTypedArray(self):
|
||||
return self.inner.isSharedTypedArray()
|
||||
|
||||
def isInterface(self):
|
||||
return self.inner.isInterface()
|
||||
|
||||
|
@ -2832,7 +2826,6 @@ class IDLBuiltinType(IDLType):
|
|||
'ArrayBuffer',
|
||||
'ArrayBufferView',
|
||||
'SharedArrayBuffer',
|
||||
'SharedArrayBufferView',
|
||||
'Int8Array',
|
||||
'Uint8Array',
|
||||
'Uint8ClampedArray',
|
||||
|
@ -2841,16 +2834,7 @@ class IDLBuiltinType(IDLType):
|
|||
'Int32Array',
|
||||
'Uint32Array',
|
||||
'Float32Array',
|
||||
'Float64Array',
|
||||
'SharedInt8Array',
|
||||
'SharedUint8Array',
|
||||
'SharedUint8ClampedArray',
|
||||
'SharedInt16Array',
|
||||
'SharedUint16Array',
|
||||
'SharedInt32Array',
|
||||
'SharedUint32Array',
|
||||
'SharedFloat32Array',
|
||||
'SharedFloat64Array'
|
||||
'Float64Array'
|
||||
)
|
||||
|
||||
TagLookup = {
|
||||
|
@ -2877,7 +2861,6 @@ class IDLBuiltinType(IDLType):
|
|||
Types.ArrayBuffer: IDLType.Tags.interface,
|
||||
Types.ArrayBufferView: IDLType.Tags.interface,
|
||||
Types.SharedArrayBuffer: IDLType.Tags.interface,
|
||||
Types.SharedArrayBufferView: IDLType.Tags.interface,
|
||||
Types.Int8Array: IDLType.Tags.interface,
|
||||
Types.Uint8Array: IDLType.Tags.interface,
|
||||
Types.Uint8ClampedArray: IDLType.Tags.interface,
|
||||
|
@ -2886,16 +2869,7 @@ class IDLBuiltinType(IDLType):
|
|||
Types.Int32Array: IDLType.Tags.interface,
|
||||
Types.Uint32Array: IDLType.Tags.interface,
|
||||
Types.Float32Array: 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
|
||||
Types.Float64Array: IDLType.Tags.interface
|
||||
}
|
||||
|
||||
def __init__(self, location, name, type):
|
||||
|
@ -2938,17 +2912,10 @@ class IDLBuiltinType(IDLType):
|
|||
def isSharedArrayBuffer(self):
|
||||
return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer
|
||||
|
||||
def isSharedArrayBufferView(self):
|
||||
return self._typeTag == IDLBuiltinType.Types.SharedArrayBufferView
|
||||
|
||||
def isTypedArray(self):
|
||||
return (self._typeTag >= IDLBuiltinType.Types.Int8Array and
|
||||
self._typeTag <= IDLBuiltinType.Types.Float64Array)
|
||||
|
||||
def isSharedTypedArray(self):
|
||||
return (self._typeTag >= IDLBuiltinType.Types.SharedInt8Array and
|
||||
self._typeTag <= IDLBuiltinType.Types.SharedFloat64Array)
|
||||
|
||||
def isInterface(self):
|
||||
# TypedArray things are interface types per the TypedArray spec,
|
||||
# but we handle them as builtins because SpiderMonkey implements
|
||||
|
@ -2956,9 +2923,7 @@ class IDLBuiltinType(IDLType):
|
|||
return (self.isArrayBuffer() or
|
||||
self.isArrayBufferView() or
|
||||
self.isSharedArrayBuffer() or
|
||||
self.isSharedArrayBufferView() or
|
||||
self.isTypedArray() or
|
||||
self.isSharedTypedArray())
|
||||
self.isTypedArray())
|
||||
|
||||
def isNonCallbackInterface(self):
|
||||
# All the interfaces we can be are non-callback
|
||||
|
@ -3036,15 +3001,11 @@ class IDLBuiltinType(IDLType):
|
|||
# that's not an ArrayBufferView or typed array.
|
||||
(self.isArrayBufferView() and not other.isArrayBufferView() and
|
||||
not other.isTypedArray()) or
|
||||
(self.isSharedArrayBufferView() and not other.isSharedArrayBufferView() and
|
||||
not other.isSharedTypedArray()) 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)) or
|
||||
(self.isSharedTypedArray() and not other.isSharedArrayBufferView() and not
|
||||
(other.isSharedTypedArray() and other.name == self.name)))))
|
||||
(other.isTypedArray() and other.name == self.name)))))
|
||||
|
||||
def _getDependentObjects(self):
|
||||
return set()
|
||||
|
@ -3119,9 +3080,6 @@ BuiltinTypes = {
|
|||
IDLBuiltinType.Types.SharedArrayBuffer:
|
||||
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBuffer",
|
||||
IDLBuiltinType.Types.SharedArrayBuffer),
|
||||
IDLBuiltinType.Types.SharedArrayBufferView:
|
||||
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBufferView",
|
||||
IDLBuiltinType.Types.SharedArrayBufferView),
|
||||
IDLBuiltinType.Types.Int8Array:
|
||||
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
|
||||
IDLBuiltinType.Types.Int8Array),
|
||||
|
@ -3148,34 +3106,7 @@ BuiltinTypes = {
|
|||
IDLBuiltinType.Types.Float32Array),
|
||||
IDLBuiltinType.Types.Float64Array:
|
||||
IDLBuiltinType(BuiltinLocation("<builtin type>"), "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)
|
||||
IDLBuiltinType.Types.Float64Array)
|
||||
}
|
||||
|
||||
|
||||
|
@ -3266,7 +3197,7 @@ class IDLValue(IDLObject):
|
|||
(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]);
|
||||
% self.value, [location])
|
||||
return IDLValue(self.location, type, self.value)
|
||||
elif self.type.isString() and type.isUSVString():
|
||||
# Allow USVStrings to use default value just like
|
||||
|
@ -3366,7 +3297,8 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
|||
'Const',
|
||||
'Attr',
|
||||
'Method',
|
||||
'MaplikeOrSetlike'
|
||||
'MaplikeOrSetlike',
|
||||
'Iterable'
|
||||
)
|
||||
|
||||
Special = enum(
|
||||
|
@ -3392,6 +3324,10 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
|||
def isConst(self):
|
||||
return self.tag == IDLInterfaceMember.Tags.Const
|
||||
|
||||
def isMaplikeOrSetlikeOrIterable(self):
|
||||
return (self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike or
|
||||
self.tag == IDLInterfaceMember.Tags.Iterable)
|
||||
|
||||
def isMaplikeOrSetlike(self):
|
||||
return self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike
|
||||
|
||||
|
@ -3469,58 +3405,42 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
|||
self.aliases.append(alias)
|
||||
|
||||
|
||||
# MaplikeOrSetlike adds a trait to an interface, like map or iteration
|
||||
# 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)
|
||||
class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
|
||||
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
||||
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
||||
assert isinstance(keyType, IDLType)
|
||||
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
||||
if valueType is not None:
|
||||
assert isinstance(valueType, IDLType)
|
||||
self.maplikeOrSetlikeType = maplikeOrSetlikeType
|
||||
self.readonly = readonly
|
||||
self.keyType = keyType
|
||||
self.valueType = valueType
|
||||
self.slotIndex = None
|
||||
self.maplikeOrSetlikeOrIterableType = ifaceType
|
||||
self.disallowedMemberNames = []
|
||||
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):
|
||||
return self.maplikeOrSetlikeType == "maplike"
|
||||
return self.maplikeOrSetlikeOrIterableType == "maplike"
|
||||
|
||||
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):
|
||||
for member in members:
|
||||
# Check that there are no disallowed members
|
||||
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()))):
|
||||
raise WebIDLError("Member '%s' conflicts "
|
||||
"with reserved %s name." %
|
||||
(member.identifier.name,
|
||||
self.maplikeOrSetlikeType),
|
||||
self.maplikeOrSetlikeOrIterableType),
|
||||
[self.location, member.location])
|
||||
# Check that there are no disallowed non-method members
|
||||
if (isAncestor or (member.isAttr() or member.isConst()) and
|
||||
|
@ -3528,27 +3448,31 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
|||
raise WebIDLError("Member '%s' conflicts "
|
||||
"with reserved %s method." %
|
||||
(member.identifier.name,
|
||||
self.maplikeOrSetlikeType),
|
||||
self.maplikeOrSetlikeOrIterableType),
|
||||
[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,
|
||||
we generate our functions as if they were part of the interface
|
||||
specification during parsing.
|
||||
"""
|
||||
def addMethod(name, allowExistingOperations, returnType, args=[],
|
||||
chromeOnly=False, isPure=False, affectsNothing=False):
|
||||
"""
|
||||
Create an IDLMethod based on the parameters passed in. chromeOnly is only
|
||||
True for read-only js implemented classes, to implement underscore
|
||||
prefixed convenience functions would otherwise not be available,
|
||||
unlike the case of C++ bindings. isPure is only True for
|
||||
idempotent functions, so it is not valid for things like keys,
|
||||
values, etc. that return a new object every time.
|
||||
Create an IDLMethod based on the parameters passed in.
|
||||
|
||||
- members is the member list to add this function to, since this is
|
||||
called during the member expansion portion of interface object
|
||||
building.
|
||||
|
||||
- chromeOnly is only True for read-only js implemented classes, to
|
||||
implement underscore prefixed convenience functions which would
|
||||
otherwise not be available, unlike the case of C++ bindings.
|
||||
|
||||
- isPure is only True for idempotent functions, so it is not valid for
|
||||
things like keys, 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.
|
||||
if chromeOnly:
|
||||
|
@ -3558,7 +3482,6 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
|||
self.disallowedMemberNames.append(name)
|
||||
else:
|
||||
self.disallowedNonMethodNames.append(name)
|
||||
|
||||
# If allowExistingOperations is True, and another operation exists
|
||||
# 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,
|
||||
|
@ -3568,11 +3491,9 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
|||
for m in members:
|
||||
if m.identifier.name == name and m.isMethod() and not m.isStatic():
|
||||
return
|
||||
|
||||
method = IDLMethod(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly),
|
||||
returnType, args, maplikeOrSetlike=self)
|
||||
|
||||
returnType, args, maplikeOrSetlikeOrIterable=self)
|
||||
# We need to be able to throw from declaration methods
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("Throws",))])
|
||||
|
@ -3588,107 +3509,14 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
|||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("DependsOn", "Everything")),
|
||||
IDLExtendedAttribute(self.location, ("Affects", "Nothing"))])
|
||||
if newObject:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
||||
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):
|
||||
self.keyType.resolveType(parentScope)
|
||||
if self.valueType:
|
||||
self.valueType.resolveType(parentScope)
|
||||
|
||||
def finish(self, scope):
|
||||
|
@ -3700,7 +3528,7 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
|||
assert not isinstance(t, IDLTypedefType)
|
||||
assert not isinstance(t.name, IDLUnresolvedIdentifier)
|
||||
self.keyType = t
|
||||
if not self.valueType.isComplete():
|
||||
if self.valueType and not self.valueType.isComplete():
|
||||
t = self.valueType.complete(scope)
|
||||
|
||||
assert not isinstance(t, IDLUnresolvedType)
|
||||
|
@ -3715,8 +3543,161 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
|||
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
||||
|
||||
def _getDependentObjects(self):
|
||||
if 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):
|
||||
def __init__(self, location, identifier, type, value):
|
||||
|
@ -4026,6 +4007,11 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
"readonly attributes" % attr.value(),
|
||||
[attr.location, self.location])
|
||||
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
|
||||
identifier == "Deprecated" or
|
||||
identifier == "SetterThrows" or
|
||||
|
@ -4313,7 +4299,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
static=False, getter=False, setter=False, creator=False,
|
||||
deleter=False, specialType=NamedOrIndexed.Neither,
|
||||
legacycaller=False, stringifier=False, jsonifier=False,
|
||||
maplikeOrSetlike=None):
|
||||
maplikeOrSetlikeOrIterable=None):
|
||||
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
IDLInterfaceMember.Tags.Method)
|
||||
|
@ -4341,8 +4327,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
self._stringifier = stringifier
|
||||
assert isinstance(jsonifier, bool)
|
||||
self._jsonifier = jsonifier
|
||||
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
|
||||
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
|
||||
self._specialType = specialType
|
||||
self._unforgeable = False
|
||||
self.dependsOn = "Everything"
|
||||
|
@ -4424,12 +4410,21 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
def isJsonifier(self):
|
||||
return self._jsonifier
|
||||
|
||||
def isMaplikeOrSetlikeMethod(self):
|
||||
def isMaplikeOrSetlikeOrIterableMethod(self):
|
||||
"""
|
||||
True if this method was generated as part of a
|
||||
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):
|
||||
return self._hasOverloads
|
||||
|
@ -4443,7 +4438,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
an non-identifier name, they actually DO have an identifier.
|
||||
"""
|
||||
return (self.identifier.name[:2] == "__" and
|
||||
not self.isMaplikeOrSetlikeMethod())
|
||||
not self.isMaplikeOrSetlikeOrIterableMethod())
|
||||
|
||||
def resolve(self, parentScope):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
|
@ -4712,6 +4707,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
raise WebIDLError("[Alias] takes an identifier or string",
|
||||
[attr.location])
|
||||
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
|
||||
identifier == "NewObject" or
|
||||
identifier == "ChromeOnly" or
|
||||
|
@ -4723,7 +4723,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
identifier == "CheckAnyPermissions" or
|
||||
identifier == "CheckAllPermissions" or
|
||||
identifier == "BinaryName" or
|
||||
identifier == "MethodIdentityTestable" or
|
||||
identifier == "StaticClassOverride"):
|
||||
# Known attributes that we don't need to do anything with here
|
||||
pass
|
||||
|
@ -4946,7 +4945,8 @@ class Tokenizer(object):
|
|||
"SharedArrayBuffer": "SHAREDARRAYBUFFER",
|
||||
"or": "OR",
|
||||
"maplike": "MAPLIKE",
|
||||
"setlike": "SETLIKE"
|
||||
"setlike": "SETLIKE",
|
||||
"iterable": "ITERABLE"
|
||||
}
|
||||
|
||||
tokens.extend(keywords.values())
|
||||
|
@ -5100,8 +5100,9 @@ class Parser(Tokenizer):
|
|||
raise ex
|
||||
pass
|
||||
|
||||
p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
|
||||
iface = IDLInterface(location, self.globalScope(), identifier, parent,
|
||||
members, isKnownNonPartial=True)
|
||||
p[0] = iface
|
||||
|
||||
def p_InterfaceForwardDecl(self, p):
|
||||
"""
|
||||
|
@ -5187,7 +5188,7 @@ class Parser(Tokenizer):
|
|||
def p_InterfaceMember(self, p):
|
||||
"""
|
||||
InterfaceMember : Const
|
||||
| AttributeOrOperationOrMaplikeOrSetlike
|
||||
| AttributeOrOperationOrMaplikeOrSetlikeOrIterable
|
||||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
@ -5402,15 +5403,30 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
p[0] = False
|
||||
|
||||
def p_AttributeOrOperationOrMaplikeOrSetlike(self, p):
|
||||
def p_AttributeOrOperationOrMaplikeOrSetlikeOrIterable(self, p):
|
||||
"""
|
||||
AttributeOrOperationOrMaplikeOrSetlike : Attribute
|
||||
AttributeOrOperationOrMaplikeOrSetlikeOrIterable : Attribute
|
||||
| Maplike
|
||||
| Setlike
|
||||
| Iterable
|
||||
| Operation
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON
|
||||
|
@ -5783,6 +5799,7 @@ class Parser(Tokenizer):
|
|||
| IMPLEMENTS
|
||||
| INHERIT
|
||||
| INTERFACE
|
||||
| ITERABLE
|
||||
| LEGACYCALLER
|
||||
| MAPLIKE
|
||||
| PARTIAL
|
||||
|
@ -6432,7 +6449,7 @@ class Parser(Tokenizer):
|
|||
assert isinstance(scope, IDLScope)
|
||||
|
||||
# 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]
|
||||
name = builtin.name
|
||||
typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name)
|
||||
|
@ -6461,7 +6478,49 @@ class Parser(Tokenizer):
|
|||
self._filename = None
|
||||
|
||||
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.
|
||||
# XXX khuey hates this bit and wants to nuke it from orbit.
|
||||
implementsStatements = [p for p in self._productions if
|
||||
|
@ -6493,7 +6552,6 @@ class Parser(Tokenizer):
|
|||
_builtins = """
|
||||
typedef unsigned long long DOMTimeStamp;
|
||||
typedef (ArrayBufferView or ArrayBuffer) BufferSource;
|
||||
typedef (SharedArrayBufferView or SharedArrayBuffer) SharedBufferSource;
|
||||
"""
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue