Auto merge of #25964 - servo:webidl, r=jdm

Update the WebIDL parser

It now supports Python 3.
This commit is contained in:
bors-servo 2020-03-17 12:55:26 -04:00 committed by GitHub
commit 9fb83d8143
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 535 additions and 204 deletions

View file

@ -427,17 +427,6 @@ class CGMethodCall(CGThing):
(s[1][distinguishingIndex].type.isSequence() or (s[1][distinguishingIndex].type.isSequence() or
s[1][distinguishingIndex].type.isObject())) s[1][distinguishingIndex].type.isObject()))
# Check for Date objects
# XXXbz Do we need to worry about security wrappers around the Date?
pickFirstSignature("%s.get().is_object() && "
"{ rooted!(in(*cx) let obj = %s.get().to_object()); "
"let mut is_date = false; "
"assert!(ObjectIsDate(*cx, obj.handle(), &mut is_date)); "
"is_date }" %
(distinguishingArg, distinguishingArg),
lambda s: (s[1][distinguishingIndex].type.isDate() or
s[1][distinguishingIndex].type.isObject()))
# Check for vanilla JS objects # Check for vanilla JS objects
# XXXbz Do we need to worry about security wrappers? # XXXbz Do we need to worry about security wrappers?
pickFirstSignature("%s.get().is_object() && !is_platform_object(%s.get().to_object(), *cx)" % pickFirstSignature("%s.get().is_object() && !is_platform_object(%s.get().to_object(), *cx)" %
@ -596,8 +585,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
# We should not have a defaultValue if we know we're an object # We should not have a defaultValue if we know we're an object
assert not isDefinitelyObject or defaultValue is None assert not isDefinitelyObject or defaultValue is None
isEnforceRange = type.enforceRange isEnforceRange = type.hasEnforceRange()
isClamp = type.clamp isClamp = type.hasClamp()
if type.treatNullAsEmpty: if type.treatNullAsEmpty:
treatNullAs = "EmptyString" treatNullAs = "EmptyString"
else: else:
@ -1665,6 +1654,8 @@ class MethodDefiner(PropertyDefiner):
(maplikeOrSetlikeOrIterable and (maplikeOrSetlikeOrIterable and
maplikeOrSetlikeOrIterable.isIterable() and maplikeOrSetlikeOrIterable.isIterable() and
maplikeOrSetlikeOrIterable.isValueIterator())): maplikeOrSetlikeOrIterable.isValueIterator())):
m = maplikeOrSetlikeOrIterable
# Add our keys/values/entries/forEach # Add our keys/values/entries/forEach
self.regular.append({ self.regular.append({
"name": "keys", "name": "keys",
@ -4162,8 +4153,6 @@ class CGMemberJITInfo(CGThing):
u.flatMemberTypes, "") u.flatMemberTypes, "")
if t.isDictionary(): if t.isDictionary():
return "JSVAL_TYPE_OBJECT" return "JSVAL_TYPE_OBJECT"
if t.isDate():
return "JSVAL_TYPE_OBJECT"
if not t.isPrimitive(): if not t.isPrimitive():
raise TypeError("No idea what type " + str(t) + " is.") raise TypeError("No idea what type " + str(t) + " is.")
tag = t.tag() tag = t.tag()
@ -4233,8 +4222,6 @@ class CGMemberJITInfo(CGThing):
u.flatMemberTypes, type) u.flatMemberTypes, type)
if t.isDictionary(): if t.isDictionary():
return "JSJitInfo_ArgType::Object as i32" return "JSJitInfo_ArgType::Object as i32"
if t.isDate():
return "JSJitInfo_ArgType::Object as i32"
if not t.isPrimitive(): if not t.isPrimitive():
raise TypeError("No idea what type " + str(t) + " is.") raise TypeError("No idea what type " + str(t) + " is.")
tag = t.tag() tag = t.tag()
@ -4540,13 +4527,6 @@ class CGUnionConversionStruct(CGThing):
else: else:
arrayObject = None arrayObject = None
dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
if len(dateObjectMemberTypes) > 0:
assert len(dateObjectMemberTypes) == 1
raise TypeError("Can't handle dates in unions.")
else:
dateObject = None
callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes) callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
if len(callbackMemberTypes) > 0: if len(callbackMemberTypes) > 0:
assert len(callbackMemberTypes) == 1 assert len(callbackMemberTypes) == 1
@ -4582,10 +4562,10 @@ class CGUnionConversionStruct(CGThing):
else: else:
mozMapObject = None mozMapObject = None
hasObjectTypes = object or interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject hasObjectTypes = object or interfaceObject or arrayObject or callbackObject or mozMapObject
if hasObjectTypes: if hasObjectTypes:
# "object" is not distinguishable from other types # "object" is not distinguishable from other types
assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject) assert not object or not (interfaceObject or arrayObject or callbackObject or mozMapObject)
templateBody = CGList([], "\n") templateBody = CGList([], "\n")
if object: if object:
templateBody.append(object) templateBody.append(object)
@ -6848,7 +6828,7 @@ def type_needs_tracing(t):
def is_typed_array(t): def is_typed_array(t):
assert isinstance(t, IDLObject), (t, type(t)) assert isinstance(t, IDLObject), (t, type(t))
return t.isTypedArray() or t.isArrayBuffer() or t.isArrayBufferView() or t.isSharedArrayBuffer() return t.isTypedArray() or t.isArrayBuffer() or t.isArrayBufferView()
def type_needs_auto_root(t): def type_needs_auto_root(t):

View file

@ -481,9 +481,6 @@ class IDLExposureMixins():
def isExposedInWindow(self): def isExposedInWindow(self):
return 'Window' in self.exposureSet return 'Window' in self.exposureSet
def isExposedOnMainThread(self):
return self.isExposedInWindow()
def isExposedInAnyWorker(self): def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0 return len(self.getWorkerExposureSet()) > 0
@ -2090,9 +2087,9 @@ class IDLType(IDLObject):
'domstring', 'domstring',
'bytestring', 'bytestring',
'usvstring', 'usvstring',
'utf8string',
'jsstring', 'jsstring',
'object', 'object',
'date',
'void', 'void',
# Funny stuff # Funny stuff
'interface', 'interface',
@ -2109,15 +2106,17 @@ class IDLType(IDLObject):
IDLObject.__init__(self, location) IDLObject.__init__(self, location)
self.name = name self.name = name
self.builtin = False self.builtin = False
self.clamp = False
self.treatNullAsEmpty = False self.treatNullAsEmpty = False
self.enforceRange = False self._clamp = False
self._enforceRange = False
self._allowShared = False
self._extendedAttrDict = {} self._extendedAttrDict = {}
def __eq__(self, other): def __eq__(self, other):
return (other and self.builtin == other.builtin and self.name == other.name and return (other and self.builtin == other.builtin and self.name == other.name and
self.clamp == other.clamp and self.enforceRange == other.enforceRange and self._clamp == other.hasClamp() and self._enforceRange == other.hasEnforceRange() and
self.treatNullAsEmpty == other.treatNullAsEmpty) self.treatNullAsEmpty == other.treatNullAsEmpty and
self._allowShared == other.hasAllowShared())
def __ne__(self, other): def __ne__(self, other):
return not self == other return not self == other
@ -2125,6 +2124,14 @@ class IDLType(IDLObject):
def __str__(self): def __str__(self):
return str(self.name) return str(self.name)
def prettyName(self):
"""
A name that looks like what this type is named in the IDL spec. By default
this is just our .name, but types that have more interesting spec
representations should override this.
"""
return str(self.name)
def isType(self): def isType(self):
return True return True
@ -2152,6 +2159,9 @@ class IDLType(IDLObject):
def isUSVString(self): def isUSVString(self):
return False return False
def isUTF8String(self):
return False
def isJSString(self): def isJSString(self):
return False return False
@ -2173,12 +2183,12 @@ class IDLType(IDLObject):
def isArrayBufferView(self): def isArrayBufferView(self):
return False return False
def isSharedArrayBuffer(self):
return False
def isTypedArray(self): def isTypedArray(self):
return False return False
def isBufferSource(self):
return self.isArrayBuffer() or self.isArrayBufferView() or self.isTypedArray()
def isCallbackInterface(self): def isCallbackInterface(self):
return False return False
@ -2195,10 +2205,7 @@ class IDLType(IDLObject):
def isSpiderMonkeyInterface(self): def isSpiderMonkeyInterface(self):
""" Returns a boolean indicating whether this type is an 'interface' """ Returns a boolean indicating whether this type is an 'interface'
type that is implemented in SpiderMonkey. """ type that is implemented in SpiderMonkey. """
return self.isInterface() and (self.isArrayBuffer() or return self.isInterface() and (self.isBufferSource() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isTypedArray() or
self.isReadableStream()) self.isReadableStream())
def isDictionary(self): def isDictionary(self):
@ -2210,9 +2217,6 @@ class IDLType(IDLObject):
def isAny(self): def isAny(self):
return self.tag() == IDLType.Tags.any return self.tag() == IDLType.Tags.any
def isDate(self):
return self.tag() == IDLType.Tags.date
def isObject(self): def isObject(self):
return self.tag() == IDLType.Tags.object return self.tag() == IDLType.Tags.object
@ -2235,6 +2239,15 @@ class IDLType(IDLObject):
def isJSONType(self): def isJSONType(self):
return False return False
def hasClamp(self):
return self._clamp
def hasEnforceRange(self):
return self._enforceRange
def hasAllowShared(self):
return self._allowShared
def tag(self): def tag(self):
assert False # Override me! assert False # Override me!
@ -2342,10 +2355,7 @@ class IDLNullableType(IDLParametrizedType):
assert not innerType.isVoid() assert not innerType.isVoid()
assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any] assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
name = innerType.name IDLParametrizedType.__init__(self, location, None, innerType)
if innerType.isComplete():
name += "OrNull"
IDLParametrizedType.__init__(self, location, name, innerType)
def __eq__(self, other): def __eq__(self, other):
return isinstance(other, IDLNullableType) and self.inner == other.inner return isinstance(other, IDLNullableType) and self.inner == other.inner
@ -2353,6 +2363,9 @@ class IDLNullableType(IDLParametrizedType):
def __str__(self): def __str__(self):
return self.inner.__str__() + "OrNull" return self.inner.__str__() + "OrNull"
def prettyName(self):
return self.inner.prettyName() + "?"
def nullable(self): def nullable(self):
return True return True
@ -2380,6 +2393,9 @@ class IDLNullableType(IDLParametrizedType):
def isUSVString(self): def isUSVString(self):
return self.inner.isUSVString() return self.inner.isUSVString()
def isUTF8String(self):
return self.inner.isUTF8String()
def isJSString(self): def isJSString(self):
return self.inner.isJSString() return self.inner.isJSString()
@ -2410,9 +2426,6 @@ class IDLNullableType(IDLParametrizedType):
def isArrayBufferView(self): def isArrayBufferView(self):
return self.inner.isArrayBufferView() return self.inner.isArrayBufferView()
def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer()
def isTypedArray(self): def isTypedArray(self):
return self.inner.isTypedArray() return self.inner.isTypedArray()
@ -2442,11 +2455,26 @@ class IDLNullableType(IDLParametrizedType):
def isJSONType(self): def isJSONType(self):
return self.inner.isJSONType() return self.inner.isJSONType()
def hasClamp(self):
return self.inner.hasClamp()
def hasEnforceRange(self):
return self.inner.hasEnforceRange()
def hasAllowShared(self):
return self.inner.hasAllowShared()
def isComplete(self):
return self.name is not None
def tag(self): def tag(self):
return self.inner.tag() return self.inner.tag()
def complete(self, scope): def complete(self, scope):
if not self.inner.isComplete():
self.inner = self.inner.complete(scope) self.inner = self.inner.complete(scope)
assert self.inner.isComplete()
if self.inner.nullable(): if self.inner.nullable():
raise WebIDLError("The inner type of a nullable type must not be " raise WebIDLError("The inner type of a nullable type must not be "
"a nullable type", "a nullable type",
@ -2456,6 +2484,10 @@ class IDLNullableType(IDLParametrizedType):
raise WebIDLError("The inner type of a nullable type must not " raise WebIDLError("The inner type of a nullable type must not "
"be a union type that itself has a nullable " "be a union type that itself has a nullable "
"type as a member type", [self.location]) "type as a member type", [self.location])
if self.inner.isDOMString():
if self.inner.treatNullAsEmpty:
raise WebIDLError("[TreatNullAs] not allowed on a nullable DOMString",
[self.location, self.inner.location])
self.name = self.inner.name + "OrNull" self.name = self.inner.name + "OrNull"
return self return self
@ -2469,6 +2501,13 @@ class IDLNullableType(IDLParametrizedType):
return False return False
return self.inner.isDistinguishableFrom(other) return self.inner.isDistinguishableFrom(other)
def withExtendedAttributes(self, attrs):
# See https://github.com/heycam/webidl/issues/827#issuecomment-565131350
# Allowing extended attributes to apply to a nullable type is an intermediate solution.
# A potential longer term solution is to introduce a null type and get rid of nullables.
# For example, we could do `([Clamp] long or null) foo` in the future.
return IDLNullableType(self.location, self.inner.withExtendedAttributes(attrs))
class IDLSequenceType(IDLParametrizedType): class IDLSequenceType(IDLParametrizedType):
def __init__(self, location, parameterType): def __init__(self, location, parameterType):
@ -2486,6 +2525,9 @@ class IDLSequenceType(IDLParametrizedType):
def __str__(self): def __str__(self):
return self.inner.__str__() + "Sequence" return self.inner.__str__() + "Sequence"
def prettyName(self):
return "sequence<%s>" % self.inner.prettyName()
def nullable(self): def nullable(self):
return False return False
@ -2504,6 +2546,9 @@ class IDLSequenceType(IDLParametrizedType):
def isUSVString(self): def isUSVString(self):
return False return False
def isUTF8String(self):
return False
def isJSString(self): def isJSString(self):
return False return False
@ -2540,8 +2585,7 @@ class IDLSequenceType(IDLParametrizedType):
# Just forward to the union; it'll deal # Just forward to the union; it'll deal
return other.isDistinguishableFrom(self) return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isInterface() or other.isInterface() or other.isDictionary() or
other.isDictionary() or
other.isCallback() or other.isRecord()) other.isCallback() or other.isRecord())
@ -2565,6 +2609,9 @@ class IDLRecordType(IDLParametrizedType):
def __str__(self): def __str__(self):
return self.keyType.__str__() + self.inner.__str__() + "Record" return self.keyType.__str__() + self.inner.__str__() + "Record"
def prettyName(self):
return "record<%s, %s>" % (self.keyType.prettyName(), self.inner.prettyName())
def isRecord(self): def isRecord(self):
return True return True
@ -2592,7 +2639,7 @@ class IDLRecordType(IDLParametrizedType):
# Just forward to the union; it'll deal # Just forward to the union; it'll deal
return other.isDistinguishableFrom(self) return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isNonCallbackInterface() or other.isSequence()) other.isNonCallbackInterface() or other.isSequence())
def isExposedInAllOf(self, exposureSet): def isExposedInAllOf(self, exposureSet):
return self.inner.unroll().isExposedInAllOf(exposureSet) return self.inner.unroll().isExposedInAllOf(exposureSet)
@ -2614,6 +2661,9 @@ class IDLUnionType(IDLType):
assert self.isComplete() assert self.isComplete()
return self.name.__hash__() return self.name.__hash__()
def prettyName(self):
return "(" + " or ".join(m.prettyName() for m in self.memberTypes) + ")"
def isVoid(self): def isVoid(self):
return False return False
@ -2645,6 +2695,9 @@ class IDLUnionType(IDLType):
return typeName(type._identifier.object()) return typeName(type._identifier.object())
if isinstance(type, IDLObjectWithIdentifier): if isinstance(type, IDLObjectWithIdentifier):
return typeName(type.identifier) return typeName(type.identifier)
if isinstance(type, IDLBuiltinType) and type.hasAllowShared():
assert type.isBufferSource()
return "MaybeShared" + type.name
return type.name return type.name
for (i, type) in enumerate(self.memberTypes): for (i, type) in enumerate(self.memberTypes):
@ -2768,6 +2821,9 @@ class IDLTypedefType(IDLType):
def isUSVString(self): def isUSVString(self):
return self.inner.isUSVString() return self.inner.isUSVString()
def isUTF8String(self):
return self.inner.isUTF8String()
def isJSString(self): def isJSString(self):
return self.inner.isJSString() return self.inner.isJSString()
@ -2795,9 +2851,6 @@ class IDLTypedefType(IDLType):
def isArrayBufferView(self): def isArrayBufferView(self):
return self.inner.isArrayBufferView() return self.inner.isArrayBufferView()
def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer()
def isTypedArray(self): def isTypedArray(self):
return self.inner.isTypedArray() return self.inner.isTypedArray()
@ -2901,6 +2954,9 @@ class IDLWrapperType(IDLType):
def isUSVString(self): def isUSVString(self):
return False return False
def isUTF8String(self):
return False
def isJSString(self): def isJSString(self):
return False return False
@ -2976,11 +3032,11 @@ class IDLWrapperType(IDLType):
if self.isEnum(): if self.isEnum():
return (other.isPrimitive() or other.isInterface() or other.isObject() or return (other.isPrimitive() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate()) other.isSequence() or other.isRecord())
if self.isDictionary() and other.nullable(): if self.isDictionary() and other.nullable():
return False return False
if (other.isPrimitive() or other.isString() or other.isEnum() or if (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isSequence()): other.isSequence()):
return True return True
if self.isDictionary(): if self.isDictionary():
return other.isNonCallbackInterface() return other.isNonCallbackInterface()
@ -3052,6 +3108,9 @@ class IDLPromiseType(IDLParametrizedType):
def __str__(self): def __str__(self):
return self.inner.__str__() + "Promise" return self.inner.__str__() + "Promise"
def prettyName(self):
return "Promise<%s>" % self.inner.prettyName()
def isPromise(self): def isPromise(self):
return True return True
@ -3104,14 +3163,13 @@ class IDLBuiltinType(IDLType):
'domstring', 'domstring',
'bytestring', 'bytestring',
'usvstring', 'usvstring',
'utf8string',
'jsstring', 'jsstring',
'object', 'object',
'date',
'void', 'void',
# Funny stuff # Funny stuff
'ArrayBuffer', 'ArrayBuffer',
'ArrayBufferView', 'ArrayBufferView',
'SharedArrayBuffer',
'Int8Array', 'Int8Array',
'Uint8Array', 'Uint8Array',
'Uint8ClampedArray', 'Uint8ClampedArray',
@ -3142,13 +3200,12 @@ class IDLBuiltinType(IDLType):
Types.domstring: IDLType.Tags.domstring, Types.domstring: IDLType.Tags.domstring,
Types.bytestring: IDLType.Tags.bytestring, Types.bytestring: IDLType.Tags.bytestring,
Types.usvstring: IDLType.Tags.usvstring, Types.usvstring: IDLType.Tags.usvstring,
Types.utf8string: IDLType.Tags.utf8string,
Types.jsstring: IDLType.Tags.jsstring, Types.jsstring: IDLType.Tags.jsstring,
Types.object: IDLType.Tags.object, Types.object: IDLType.Tags.object,
Types.date: IDLType.Tags.date,
Types.void: IDLType.Tags.void, Types.void: IDLType.Tags.void,
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.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,
@ -3161,11 +3218,48 @@ class IDLBuiltinType(IDLType):
Types.ReadableStream: IDLType.Tags.interface, Types.ReadableStream: IDLType.Tags.interface,
} }
PrettyNames = {
Types.byte: "byte",
Types.octet: "octet",
Types.short: "short",
Types.unsigned_short: "unsigned short",
Types.long: "long",
Types.unsigned_long: "unsigned long",
Types.long_long: "long long",
Types.unsigned_long_long: "unsigned long long",
Types.boolean: "boolean",
Types.unrestricted_float: "unrestricted float",
Types.float: "float",
Types.unrestricted_double: "unrestricted double",
Types.double: "double",
Types.any: "any",
Types.domstring: "DOMString",
Types.bytestring: "ByteString",
Types.usvstring: "USVString",
Types.utf8string: "USVString", # That's what it is in spec terms
Types.jsstring: "USVString", # Again, that's what it is in spec terms
Types.object: "object",
Types.void: "void",
Types.ArrayBuffer: "ArrayBuffer",
Types.ArrayBufferView: "ArrayBufferView",
Types.Int8Array: "Int8Array",
Types.Uint8Array: "Uint8Array",
Types.Uint8ClampedArray: "Uint8ClampedArray",
Types.Int16Array: "Int16Array",
Types.Uint16Array: "Uint16Array",
Types.Int32Array: "Int32Array",
Types.Uint32Array: "Uint32Array",
Types.Float32Array: "Float32Array",
Types.Float64Array: "Float64Array",
Types.ReadableStream: "ReadableStream",
}
def __init__(self, location, name, type, clamp=False, enforceRange=False, treatNullAsEmpty=False, def __init__(self, location, name, type, clamp=False, enforceRange=False, treatNullAsEmpty=False,
attrLocation=[]): allowShared=False, attrLocation=[]):
""" """
The mutually exclusive clamp/enforceRange/treatNullAsEmpty arguments are used to create instances The mutually exclusive clamp/enforceRange/treatNullAsEmpty/allowShared arguments are used
of this type with the appropriate attributes attached. Use .clamped(), .rangeEnforced(), and .treatNullAs(). to create instances of this type with the appropriate attributes attached. Use .clamped(),
.rangeEnforced(), .withTreatNullAs() and .withAllowShared().
attrLocation is an array of source locations of these attributes for error reporting. attrLocation is an array of source locations of these attributes for error reporting.
""" """
@ -3175,24 +3269,40 @@ class IDLBuiltinType(IDLType):
self._clamped = None self._clamped = None
self._rangeEnforced = None self._rangeEnforced = None
self._withTreatNullAs = None self._withTreatNullAs = None
if self.isNumeric(): self._withAllowShared = None;
if self.isInteger():
if clamp: if clamp:
self.clamp = True self._clamp = True
self.name = "Clamped" + self.name self.name = "Clamped" + self.name
self._extendedAttrDict["Clamp"] = True self._extendedAttrDict["Clamp"] = True
elif enforceRange: elif enforceRange:
self.enforceRange = True self._enforceRange = True
self.name = "RangeEnforced" + self.name self.name = "RangeEnforced" + self.name
self._extendedAttrDict["EnforceRange"] = True self._extendedAttrDict["EnforceRange"] = True
elif clamp or enforceRange: elif clamp or enforceRange:
raise WebIDLError("Non-numeric types cannot be [Clamp] or [EnforceRange]", attrLocation) raise WebIDLError("Non-integer types cannot be [Clamp] or [EnforceRange]", attrLocation)
if self.isDOMString(): if self.isDOMString() or self.isUTF8String():
if treatNullAsEmpty: if treatNullAsEmpty:
self.treatNullAsEmpty = True self.treatNullAsEmpty = True
self.name = "NullIsEmpty" + self.name self.name = "NullIsEmpty" + self.name
self._extendedAttrDict["TreatNullAs"] = ["EmptyString"] self._extendedAttrDict["TreatNullAs"] = ["EmptyString"]
elif treatNullAsEmpty: elif treatNullAsEmpty:
raise WebIDLError("Non-string types cannot be [TreatNullAs]", attrLocation) raise WebIDLError("Non-string types cannot be [TreatNullAs]", attrLocation)
if self.isBufferSource():
if allowShared:
self._allowShared = True
self._extendedAttrDict["AllowShared"] = True
elif allowShared:
raise WebIDLError("Types that are not buffer source types cannot be [AllowShared]", attrLocation)
def __str__(self):
if self._allowShared:
assert self.isBufferSource()
return "MaybeShared" + str(self.name)
return str(self.name)
def prettyName(self):
return IDLBuiltinType.PrettyNames[self._typeTag]
def clamped(self, attrLocation): def clamped(self, attrLocation):
if not self._clamped: if not self._clamped:
@ -3215,6 +3325,13 @@ class IDLBuiltinType(IDLType):
attrLocation=attrLocation) attrLocation=attrLocation)
return self._withTreatNullAs return self._withTreatNullAs
def withAllowShared(self, attrLocation):
if not self._withAllowShared:
self._withAllowShared = IDLBuiltinType(self.location, self.name,
self._typeTag, allowShared=True,
attrLocation=attrLocation)
return self._withAllowShared
def isPrimitive(self): def isPrimitive(self):
return self._typeTag <= IDLBuiltinType.Types.double return self._typeTag <= IDLBuiltinType.Types.double
@ -3228,6 +3345,7 @@ class IDLBuiltinType(IDLType):
return (self._typeTag == IDLBuiltinType.Types.domstring or return (self._typeTag == IDLBuiltinType.Types.domstring or
self._typeTag == IDLBuiltinType.Types.bytestring or self._typeTag == IDLBuiltinType.Types.bytestring or
self._typeTag == IDLBuiltinType.Types.usvstring or self._typeTag == IDLBuiltinType.Types.usvstring or
self._typeTag == IDLBuiltinType.Types.utf8string or
self._typeTag == IDLBuiltinType.Types.jsstring) self._typeTag == IDLBuiltinType.Types.jsstring)
def isByteString(self): def isByteString(self):
@ -3239,6 +3357,9 @@ class IDLBuiltinType(IDLType):
def isUSVString(self): def isUSVString(self):
return self._typeTag == IDLBuiltinType.Types.usvstring return self._typeTag == IDLBuiltinType.Types.usvstring
def isUTF8String(self):
return self._typeTag == IDLBuiltinType.Types.utf8string
def isJSString(self): def isJSString(self):
return self._typeTag == IDLBuiltinType.Types.jsstring return self._typeTag == IDLBuiltinType.Types.jsstring
@ -3251,9 +3372,6 @@ class IDLBuiltinType(IDLType):
def isArrayBufferView(self): def isArrayBufferView(self):
return self._typeTag == IDLBuiltinType.Types.ArrayBufferView return self._typeTag == IDLBuiltinType.Types.ArrayBufferView
def isSharedArrayBuffer(self):
return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer
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)
@ -3267,7 +3385,6 @@ class IDLBuiltinType(IDLType):
# all of it internally. # all of it internally.
return (self.isArrayBuffer() or return (self.isArrayBuffer() or
self.isArrayBufferView() or self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isTypedArray() or self.isTypedArray() or
self.isReadableStream()) self.isReadableStream())
@ -3305,27 +3422,22 @@ class IDLBuiltinType(IDLType):
return (other.isNumeric() or other.isString() or other.isEnum() or return (other.isNumeric() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate()) other.isSequence() or other.isRecord())
if self.isNumeric(): if self.isNumeric():
return (other.isBoolean() or other.isString() or other.isEnum() or return (other.isBoolean() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate()) other.isSequence() or other.isRecord())
if self.isString(): if self.isString():
return (other.isPrimitive() or other.isInterface() or return (other.isPrimitive() or other.isInterface() or
other.isObject() or other.isObject() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate()) other.isSequence() or other.isRecord())
if self.isAny(): if self.isAny():
# Can't tell "any" apart from anything # Can't tell "any" apart from anything
return False return False
if self.isObject(): if self.isObject():
return other.isPrimitive() or other.isString() or other.isEnum() 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
other.isRecord())
if self.isVoid(): if self.isVoid():
return not other.isVoid() return not other.isVoid()
# Not much else we could be! # Not much else we could be!
@ -3333,12 +3445,11 @@ class IDLBuiltinType(IDLType):
# Like interfaces, but we know we're not a callback # Like interfaces, but we know we're not a callback
return (other.isPrimitive() or other.isString() or other.isEnum() or return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isCallback() or other.isDictionary() or other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate() or other.isSequence() or other.isRecord() or
(other.isInterface() and ( (other.isInterface() and (
# ArrayBuffer is distinguishable from everything # ArrayBuffer is distinguishable from everything
# that's not an ArrayBuffer or a callback interface # that's not an ArrayBuffer or a callback interface
(self.isArrayBuffer() and not other.isArrayBuffer()) or (self.isArrayBuffer() and not other.isArrayBuffer()) or
(self.isSharedArrayBuffer() and not other.isSharedArrayBuffer()) or
(self.isReadableStream() and not other.isReadableStream()) or (self.isReadableStream() and not other.isReadableStream()) or
# ArrayBufferView is distinguishable from everything # ArrayBufferView is distinguishable from everything
# that's not an ArrayBufferView or typed array. # that's not an ArrayBufferView or typed array.
@ -3361,7 +3472,7 @@ class IDLBuiltinType(IDLType):
if not attribute.noArguments(): if not attribute.noArguments():
raise WebIDLError("[Clamp] must take no arguments", raise WebIDLError("[Clamp] must take no arguments",
[attribute.location]) [attribute.location])
if ret.enforceRange or self.enforceRange: if ret.hasEnforceRange() or self._enforceRange:
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
[self.location, attribute.location]) [self.location, attribute.location])
ret = self.clamped([self.location, attribute.location]) ret = self.clamped([self.location, attribute.location])
@ -3369,17 +3480,17 @@ class IDLBuiltinType(IDLType):
if not attribute.noArguments(): if not attribute.noArguments():
raise WebIDLError("[EnforceRange] must take no arguments", raise WebIDLError("[EnforceRange] must take no arguments",
[attribute.location]) [attribute.location])
if ret.clamp or self.clamp: if ret.hasClamp() or self._clamp:
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
[self.location, attribute.location]) [self.location, attribute.location])
ret = self.rangeEnforced([self.location, attribute.location]) ret = self.rangeEnforced([self.location, attribute.location])
elif identifier == "TreatNullAs": elif identifier == "TreatNullAs":
if not self.isDOMString(): if not (self.isDOMString() or self.isUTF8String()):
raise WebIDLError("[TreatNullAs] only allowed on DOMStrings", raise WebIDLError("[TreatNullAs] only allowed on DOMStrings and UTF8Strings",
[self.location, attribute.location]) [self.location, attribute.location])
assert not self.nullable() assert not self.nullable()
if not attribute.hasValue(): if not attribute.hasValue():
raise WebIDLError("[TreatNullAs] must take an identifier argument" raise WebIDLError("[TreatNullAs] must take an identifier argument",
[attribute.location]) [attribute.location])
value = attribute.value() value = attribute.value()
if value != 'EmptyString': if value != 'EmptyString':
@ -3387,6 +3498,15 @@ class IDLBuiltinType(IDLType):
"'EmptyString', not '%s'" % value, "'EmptyString', not '%s'" % value,
[attribute.location]) [attribute.location])
ret = self.withTreatNullAs([self.location, attribute.location]) ret = self.withTreatNullAs([self.location, attribute.location])
elif identifier == "AllowShared":
if not attribute.noArguments():
raise WebIDLError("[AllowShared] must take no arguments",
[attribute.location])
if not self.isBufferSource():
raise WebIDLError("[AllowShared] only allowed on buffer source types",
[self.location, attribute.location])
ret = self.withAllowShared([self.location, attribute.location])
else: else:
raise WebIDLError("Unhandled extended attribute on type", raise WebIDLError("Unhandled extended attribute on type",
[self.location, attribute.location]) [self.location, attribute.location])
@ -3444,15 +3564,15 @@ BuiltinTypes = {
IDLBuiltinType.Types.usvstring: IDLBuiltinType.Types.usvstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "USVString", IDLBuiltinType(BuiltinLocation("<builtin type>"), "USVString",
IDLBuiltinType.Types.usvstring), IDLBuiltinType.Types.usvstring),
IDLBuiltinType.Types.utf8string:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "UTF8String",
IDLBuiltinType.Types.utf8string),
IDLBuiltinType.Types.jsstring: IDLBuiltinType.Types.jsstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "JSString", IDLBuiltinType(BuiltinLocation("<builtin type>"), "JSString",
IDLBuiltinType.Types.jsstring), IDLBuiltinType.Types.jsstring),
IDLBuiltinType.Types.object: IDLBuiltinType.Types.object:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object", IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
IDLBuiltinType.Types.object), IDLBuiltinType.Types.object),
IDLBuiltinType.Types.date:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date",
IDLBuiltinType.Types.date),
IDLBuiltinType.Types.void: IDLBuiltinType.Types.void:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void", IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void",
IDLBuiltinType.Types.void), IDLBuiltinType.Types.void),
@ -3462,9 +3582,6 @@ BuiltinTypes = {
IDLBuiltinType.Types.ArrayBufferView: IDLBuiltinType.Types.ArrayBufferView:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView", IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView",
IDLBuiltinType.Types.ArrayBufferView), IDLBuiltinType.Types.ArrayBufferView),
IDLBuiltinType.Types.SharedArrayBuffer:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBuffer",
IDLBuiltinType.Types.SharedArrayBuffer),
IDLBuiltinType.Types.Int8Array: IDLBuiltinType.Types.Int8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array", IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
IDLBuiltinType.Types.Int8Array), IDLBuiltinType.Types.Int8Array),
@ -3613,8 +3730,9 @@ class IDLValue(IDLObject):
# TreatNullAsEmpty is a different type for resolution reasons, # TreatNullAsEmpty is a different type for resolution reasons,
# however once you have a value it doesn't matter # however once you have a value it doesn't matter
return self return self
elif self.type.isString() and (type.isByteString() or type.isJSString()): elif self.type.isString() and (type.isByteString() or type.isJSString() or type.isUTF8String()):
# Allow ByteStrings and JSStrings to use a default value like DOMString. # Allow ByteStrings, UTF8String, and JSStrings to use a default
# value like DOMString.
# No coercion is required as Codegen.py will handle the # No coercion is required as Codegen.py will handle the
# extra steps. We want to make sure that our string contains # extra steps. We want to make sure that our string contains
# only valid characters, so we check that here. # only valid characters, so we check that here.
@ -4307,8 +4425,9 @@ class IDLAttribute(IDLInterfaceMember):
assert not isinstance(t.name, IDLUnresolvedIdentifier) assert not isinstance(t.name, IDLUnresolvedIdentifier)
self.type = t self.type = t
if self.readonly and (self.type.clamp or self.type.enforceRange or self.type.treatNullAsEmpty): if self.readonly and (self.type.hasClamp() or self.type.hasEnforceRange() or
raise WebIDLError("A readonly attribute cannot be [Clamp] or [EnforceRange]", self.type.hasAllowShared() or self.type.treatNullAsEmpty):
raise WebIDLError("A readonly attribute cannot be [Clamp] or [EnforceRange] or [AllowShared]",
[self.location]) [self.location])
if self.type.isDictionary() and not self.getExtendedAttribute("Cached"): if self.type.isDictionary() and not self.getExtendedAttribute("Cached"):
raise WebIDLError("An attribute cannot be of a dictionary type", raise WebIDLError("An attribute cannot be of a dictionary type",
@ -4709,7 +4828,7 @@ class IDLArgument(IDLObjectWithIdentifier):
for attribute in attrs: for attribute in attrs:
identifier = attribute.identifier() identifier = attribute.identifier()
if self.allowTypeAttributes and (identifier == "EnforceRange" or identifier == "Clamp" or if self.allowTypeAttributes and (identifier == "EnforceRange" or identifier == "Clamp" or
identifier == "TreatNullAs"): identifier == "TreatNullAs" or identifier == "AllowShared"):
self.type = self.type.withExtendedAttributes([attribute]) self.type = self.type.withExtendedAttributes([attribute])
elif identifier == "TreatNonCallableAsNull": elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True self._allowTreatNonCallableAsNull = True
@ -4879,8 +4998,7 @@ class IDLCallbackType(IDLType):
# Just forward to the union; it'll deal # Just forward to the union; it'll deal
return other.isDistinguishableFrom(self) return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate() or other.isNonCallbackInterface() or other.isSequence())
other.isSequence())
def _getDependentObjects(self): def _getDependentObjects(self):
return self.callback._getDependentObjects() return self.callback._getDependentObjects()
@ -5475,7 +5593,9 @@ class IDLConstructor(IDLMethod):
identifier == "ChromeOnly" or identifier == "ChromeOnly" or
identifier == "NewObject" or identifier == "NewObject" or
identifier == "SecureContext" or identifier == "SecureContext" or
identifier == "Throws"): identifier == "Throws" or
identifier == "Func" or
identifier == "Pref"):
IDLMethod.handleExtendedAttribute(self, attr) IDLMethod.handleExtendedAttribute(self, attr)
elif identifier == "HTMLConstructor": elif identifier == "HTMLConstructor":
if not attr.noArguments(): if not attr.noArguments():
@ -5675,11 +5795,11 @@ class Tokenizer(object):
"optional": "OPTIONAL", "optional": "OPTIONAL",
"...": "ELLIPSIS", "...": "ELLIPSIS",
"::": "SCOPE", "::": "SCOPE",
"Date": "DATE",
"DOMString": "DOMSTRING", "DOMString": "DOMSTRING",
"ByteString": "BYTESTRING", "ByteString": "BYTESTRING",
"USVString": "USVSTRING", "USVString": "USVSTRING",
"JSString": "JSSTRING", "JSString": "JSSTRING",
"UTF8String": "UTF8STRING",
"any": "ANY", "any": "ANY",
"boolean": "BOOLEAN", "boolean": "BOOLEAN",
"byte": "BYTE", "byte": "BYTE",
@ -5709,7 +5829,6 @@ class Tokenizer(object):
"<": "LT", "<": "LT",
">": "GT", ">": "GT",
"ArrayBuffer": "ARRAYBUFFER", "ArrayBuffer": "ARRAYBUFFER",
"SharedArrayBuffer": "SHAREDARRAYBUFFER",
"or": "OR", "or": "OR",
"maplike": "MAPLIKE", "maplike": "MAPLIKE",
"setlike": "SETLIKE", "setlike": "SETLIKE",
@ -6939,10 +7058,10 @@ class Parser(Tokenizer):
| EQUALS | EQUALS
| GT | GT
| QUESTIONMARK | QUESTIONMARK
| DATE
| DOMSTRING | DOMSTRING
| BYTESTRING | BYTESTRING
| USVSTRING | USVSTRING
| UTF8STRING
| JSSTRING | JSSTRING
| PROMISE | PROMISE
| ANY | ANY
@ -7050,7 +7169,6 @@ class Parser(Tokenizer):
""" """
DistinguishableType : PrimitiveType Null DistinguishableType : PrimitiveType Null
| ARRAYBUFFER Null | ARRAYBUFFER Null
| SHAREDARRAYBUFFER Null
| READABLESTREAM Null | READABLESTREAM Null
| OBJECT Null | OBJECT Null
""" """
@ -7058,8 +7176,6 @@ class Parser(Tokenizer):
type = BuiltinTypes[IDLBuiltinType.Types.object] type = BuiltinTypes[IDLBuiltinType.Types.object]
elif p[1] == "ArrayBuffer": elif p[1] == "ArrayBuffer":
type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer] type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
elif p[1] == "SharedArrayBuffer":
type = BuiltinTypes[IDLBuiltinType.Types.SharedArrayBuffer]
elif p[1] == "ReadableStream": elif p[1] == "ReadableStream":
type = BuiltinTypes[IDLBuiltinType.Types.ReadableStream] type = BuiltinTypes[IDLBuiltinType.Types.ReadableStream]
else: else:
@ -7122,13 +7238,6 @@ class Parser(Tokenizer):
type = IDLUnresolvedType(self.getLocation(p, 1), p[1]) type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
p[0] = self.handleNullable(type, p[2]) p[0] = self.handleNullable(type, p[2])
def p_DistinguishableTypeDate(self, p):
"""
DistinguishableType : DATE Null
"""
p[0] = self.handleNullable(BuiltinTypes[IDLBuiltinType.Types.date],
p[2])
def p_ConstType(self, p): def p_ConstType(self, p):
""" """
ConstType : PrimitiveType ConstType : PrimitiveType
@ -7215,6 +7324,12 @@ class Parser(Tokenizer):
""" """
p[0] = IDLBuiltinType.Types.usvstring p[0] = IDLBuiltinType.Types.usvstring
def p_BuiltinStringTypeUTF8String(self, p):
"""
BuiltinStringType : UTF8STRING
"""
p[0] = IDLBuiltinType.Types.utf8string
def p_BuiltinStringTypeJSString(self, p): def p_BuiltinStringTypeJSString(self, p):
""" """
BuiltinStringType : JSSTRING BuiltinStringType : JSSTRING
@ -7354,7 +7469,13 @@ class Parser(Tokenizer):
IdentifierList : IDENTIFIER Identifiers IdentifierList : IDENTIFIER Identifiers
""" """
idents = list(p[2]) idents = list(p[2])
idents.insert(0, p[1]) # This is only used for identifier-list-valued extended attributes, and if
# we're going to restrict to IDENTIFIER here we should at least allow
# escaping with leading '_' as usual for identifiers.
ident = p[1]
if ident[0] == '_':
ident = ident[1:]
idents.insert(0, ident)
p[0] = idents p[0] = idents
def p_IdentifiersList(self, p): def p_IdentifiersList(self, p):
@ -7362,7 +7483,13 @@ class Parser(Tokenizer):
Identifiers : COMMA IDENTIFIER Identifiers Identifiers : COMMA IDENTIFIER Identifiers
""" """
idents = list(p[3]) idents = list(p[3])
idents.insert(0, p[2]) # This is only used for identifier-list-valued extended attributes, and if
# we're going to restrict to IDENTIFIER here we should at least allow
# escaping with leading '_' as usual for identifiers.
ident = p[2]
if ident[0] == '_':
ident = ident[1:]
idents.insert(0, ident)
p[0] = idents p[0] = idents
def p_IdentifiersEmpty(self, p): def p_IdentifiersEmpty(self, p):

View file

@ -0,0 +1,11 @@
--- WebIDL.py
+++ WebIDL.py
@@ -3490,7 +3490,7 @@ class IDLBuiltinType(IDLType):
[self.location, attribute.location])
assert not self.nullable()
if not attribute.hasValue():
- raise WebIDLError("[TreatNullAs] must take an identifier argument"
+ raise WebIDLError("[TreatNullAs] must take an identifier argument",
[attribute.location])
value = attribute.value()
if value != 'EmptyString':

View file

@ -25,6 +25,12 @@ def WebIDLTest(parser, harness):
void method2(optional [EnforceRange] long foo, optional [Clamp] long bar, void method2(optional [EnforceRange] long foo, optional [Clamp] long bar,
optional [TreatNullAs=EmptyString] DOMString baz); optional [TreatNullAs=EmptyString] DOMString baz);
}; };
interface C {
attribute [EnforceRange] long? foo;
attribute [Clamp] long? bar;
void method([EnforceRange] long? foo, [Clamp] long? bar);
void method2(optional [EnforceRange] long? foo, optional [Clamp] long? bar);
};
interface Setlike { interface Setlike {
setlike<[Clamp] long>; setlike<[Clamp] long>;
}; };
@ -41,29 +47,105 @@ def WebIDLTest(parser, harness):
harness.ok(not threw, "Should not have thrown on parsing normal") harness.ok(not threw, "Should not have thrown on parsing normal")
if not threw: if not threw:
harness.check(results[0].innerType.enforceRange, True, "Foo is [EnforceRange]") harness.check(results[0].innerType.hasEnforceRange(), True, "Foo is [EnforceRange]")
harness.check(results[1].innerType.clamp, True, "Bar is [Clamp]") harness.check(results[1].innerType.hasClamp(), True, "Bar is [Clamp]")
harness.check(results[2].innerType.treatNullAsEmpty, True, "Baz is [TreatNullAs=EmptyString]") harness.check(results[2].innerType.treatNullAsEmpty, True, "Baz is [TreatNullAs=EmptyString]")
A = results[3] A = results[3]
harness.check(A.members[0].type.enforceRange, True, "A.a is [EnforceRange]") harness.check(A.members[0].type.hasEnforceRange(), True, "A.a is [EnforceRange]")
harness.check(A.members[1].type.clamp, True, "A.b is [Clamp]") harness.check(A.members[1].type.hasClamp(), True, "A.b is [Clamp]")
harness.check(A.members[2].type.enforceRange, True, "A.c is [EnforceRange]") harness.check(A.members[2].type.hasEnforceRange(), True, "A.c is [EnforceRange]")
harness.check(A.members[3].type.enforceRange, True, "A.d is [EnforceRange]") harness.check(A.members[3].type.hasEnforceRange(), True, "A.d is [EnforceRange]")
B = results[4] B = results[4]
harness.check(B.members[0].type.enforceRange, True, "B.typedefFoo is [EnforceRange]") harness.check(B.members[0].type.hasEnforceRange(), True, "B.typedefFoo is [EnforceRange]")
harness.check(B.members[1].type.enforceRange, True, "B.foo is [EnforceRange]") harness.check(B.members[1].type.hasEnforceRange(), True, "B.foo is [EnforceRange]")
harness.check(B.members[2].type.clamp, True, "B.bar is [Clamp]") harness.check(B.members[2].type.hasClamp(), True, "B.bar is [Clamp]")
harness.check(B.members[3].type.treatNullAsEmpty, True, "B.baz is [TreatNullAs=EmptyString]") harness.check(B.members[3].type.treatNullAsEmpty, True, "B.baz is [TreatNullAs=EmptyString]")
method = B.members[4].signatures()[0][1] method = B.members[4].signatures()[0][1]
harness.check(method[0].type.enforceRange, True, "foo argument of method is [EnforceRange]") harness.check(method[0].type.hasEnforceRange(), True, "foo argument of method is [EnforceRange]")
harness.check(method[1].type.clamp, True, "bar argument of method is [Clamp]") harness.check(method[1].type.hasClamp(), True, "bar argument of method is [Clamp]")
harness.check(method[2].type.treatNullAsEmpty, True, "baz argument of method is [TreatNullAs=EmptyString]") harness.check(method[2].type.treatNullAsEmpty, True, "baz argument of method is [TreatNullAs=EmptyString]")
method2 = B.members[5].signatures()[0][1] method2 = B.members[5].signatures()[0][1]
harness.check(method[0].type.enforceRange, True, "foo argument of method2 is [EnforceRange]") harness.check(method[0].type.hasEnforceRange(), True, "foo argument of method2 is [EnforceRange]")
harness.check(method[1].type.clamp, True, "bar argument of method2 is [Clamp]") harness.check(method[1].type.hasClamp(), True, "bar argument of method2 is [Clamp]")
harness.check(method[2].type.treatNullAsEmpty, True, "baz argument of method2 is [TreatNullAs=EmptyString]") harness.check(method[2].type.treatNullAsEmpty, True, "baz argument of method2 is [TreatNullAs=EmptyString]")
C = results[5]
harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
harness.ok(C.members[0].type.hasEnforceRange(), "C.foo has [EnforceRange]")
harness.ok(C.members[1].type.nullable(), "C.bar is nullable")
harness.ok(C.members[1].type.hasClamp(), "C.bar has [Clamp]")
method = C.members[2].signatures()[0][1]
harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
harness.ok(method[0].type.hasEnforceRange(), "foo argument of method has [EnforceRange]")
harness.ok(method[1].type.nullable(), "bar argument of method is nullable")
harness.ok(method[1].type.hasClamp(), "bar argument of method has [Clamp]")
method2 = C.members[3].signatures()[0][1]
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
harness.ok(method2[0].type.hasEnforceRange(), "foo argument of method2 has [EnforceRange]")
harness.ok(method2[1].type.nullable(), "bar argument of method2 is nullable")
harness.ok(method2[1].type.hasClamp(), "bar argument of method2 has [Clamp]")
ATTRIBUTES = [("[Clamp]", "long"), ("[EnforceRange]", "long"), ("[TreatNullAs=EmptyString]", "DOMString")] # Test [AllowShared]
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [AllowShared] ArrayBufferView Foo;
dictionary A {
required [AllowShared] ArrayBufferView a;
[ChromeOnly, AllowShared] ArrayBufferView b;
Foo c;
};
interface B {
attribute Foo typedefFoo;
attribute [AllowShared] ArrayBufferView foo;
void method([AllowShared] ArrayBufferView foo);
void method2(optional [AllowShared] ArrayBufferView foo);
};
interface C {
attribute [AllowShared] ArrayBufferView? foo;
void method([AllowShared] ArrayBufferView? foo);
void method2(optional [AllowShared] ArrayBufferView? foo);
};
interface Setlike {
setlike<[AllowShared] ArrayBufferView>;
};
interface Maplike {
maplike<[Clamp] long, [AllowShared] ArrayBufferView>;
};
interface Iterable {
iterable<[Clamp] long, [AllowShared] ArrayBufferView>;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(not threw, "Should not have thrown on parsing normal")
if not threw:
harness.ok(results[0].innerType.hasAllowShared(), "Foo is [AllowShared]")
A = results[1]
harness.ok(A.members[0].type.hasAllowShared(), "A.a is [AllowShared]")
harness.ok(A.members[1].type.hasAllowShared(), "A.b is [AllowShared]")
harness.ok(A.members[2].type.hasAllowShared(), "A.c is [AllowShared]")
B = results[2]
harness.ok(B.members[0].type.hasAllowShared(), "B.typedefFoo is [AllowShared]")
harness.ok(B.members[1].type.hasAllowShared(), "B.foo is [AllowShared]")
method = B.members[2].signatures()[0][1]
harness.ok(method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]")
method2 = B.members[3].signatures()[0][1]
harness.ok(method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]")
C = results[3]
harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
harness.ok(C.members[0].type.hasAllowShared(), "C.foo is [AllowShared]")
method = C.members[1].signatures()[0][1]
harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
harness.ok(method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]")
method2 = C.members[2].signatures()[0][1]
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
harness.ok(method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]")
ATTRIBUTES = [("[Clamp]", "long"), ("[EnforceRange]", "long"),
("[TreatNullAs=EmptyString]", "DOMString"), ("[AllowShared]", "ArrayBufferView")]
TEMPLATES = [ TEMPLATES = [
("required dictionary members", """ ("required dictionary members", """
dictionary Foo { dictionary Foo {
@ -93,6 +175,53 @@ def WebIDLTest(parser, harness):
readonly attribute Bar baz; readonly attribute Bar baz;
}; };
typedef %s %s Bar; typedef %s %s Bar;
"""),
("method", """
interface Foo {
%s %s foo();
};
"""),
("interface","""
%s
interface Foo {
attribute %s foo;
};
"""),
("partial interface","""
interface Foo {
void foo();
};
%s
partial interface Foo {
attribute %s bar;
};
"""),
("interface mixin","""
%s
interface mixin Foo {
attribute %s foo;
};
"""),
("namespace","""
%s
namespace Foo {
attribute %s foo;
};
"""),
("partial namespace","""
namespace Foo {
void foo();
};
%s
partial namespace Foo {
attribute %s bar;
};
"""),
("dictionary","""
%s
dictionary Foo {
%s foo;
};
""") """)
]; ];
@ -167,30 +296,32 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs") harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
TYPES = ["DOMString", "unrestricted float", "float", "unrestricted double", "double"]
for type in TYPES:
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse("""
typedef [Clamp] DOMString Foo; typedef [Clamp] %s Foo;
""") """ % type)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [Clamp] on DOMString") harness.ok(threw, "Should not allow [Clamp] on %s" % type)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse("""
typedef [EnforceRange] DOMString Foo; typedef [EnforceRange] %s Foo;
""") """ % type)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [EnforceRange] on DOMString") harness.ok(threw, "Should not allow [EnforceRange] on %s" % type)
parser = parser.reset() parser = parser.reset()
@ -217,6 +348,40 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow [TreatNullAs] on JSString") harness.ok(threw, "Should not allow [TreatNullAs] on JSString")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [TreatNullAs=EmptyString] DOMString? Foo;
""")
parser.finish()
except:
threw = True
harness.ok(threw, "Should not allow [TreatNullAs] on nullable DOMString")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [AllowShared] DOMString Foo;
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "[AllowShared] only allowed on buffer source types")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [AllowShared=something] ArrayBufferView Foo;
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "[AllowShared] must take no arguments")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
@ -230,7 +395,7 @@ def WebIDLTest(parser, harness):
except: except:
threw = True threw = True
harness.ok(not threw, "Should allow type attributes on unresolved types") harness.ok(not threw, "Should allow type attributes on unresolved types")
harness.check(results[0].members[0].signatures()[0][1][0].type.clamp, True, harness.check(results[0].members[0].signatures()[0][1][0].type.hasClamp(), True,
"Unresolved types with type attributes should correctly resolve with attributes") "Unresolved types with type attributes should correctly resolve with attributes")
parser = parser.reset() parser = parser.reset()
@ -246,5 +411,5 @@ def WebIDLTest(parser, harness):
except: except:
threw = True threw = True
harness.ok(not threw, "Should allow type attributes on typedefs") harness.ok(not threw, "Should allow type attributes on typedefs")
harness.check(results[0].members[0].signatures()[0][1][0].type.clamp, True, harness.check(results[0].members[0].signatures()[0][1][0].type.hasClamp(), True,
"Unresolved types that resolve to typedefs with attributes should correctly resolve with attributes") "Unresolved types that resolve to typedefs with attributes should correctly resolve with attributes")

View file

@ -11,9 +11,9 @@ def WebIDLTest(parser, harness):
harness.check(argument.variadic, variadic, "Argument has the right variadic value") harness.check(argument.variadic, variadic, "Argument has the right variadic value")
def checkMethod(method, QName, name, signatures, def checkMethod(method, QName, name, signatures,
static=True, getter=False, setter=False, static=True, getter=False, setter=False, deleter=False,
deleter=False, legacycaller=False, stringifier=False, legacycaller=False, stringifier=False, chromeOnly=False,
chromeOnly=False, htmlConstructor=False): htmlConstructor=False, secureContext=False, pref=None, func=None):
harness.ok(isinstance(method, WebIDL.IDLMethod), harness.ok(isinstance(method, WebIDL.IDLMethod),
"Should be an IDLMethod") "Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method") harness.ok(method.isMethod(), "Method is a method")
@ -30,6 +30,9 @@ def WebIDLTest(parser, harness):
harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly") harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value") harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures") harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
harness.check(method.getExtendedAttribute("Pref"), pref, "Method has the correct pref value")
harness.check(method.getExtendedAttribute("Func"), func, "Method has the correct func value")
harness.check(method.getExtendedAttribute("SecureContext") is not None, secureContext, "Method has the correct SecureContext value")
sigpairs = zip(method.signatures(), signatures) sigpairs = zip(method.signatures(), signatures)
for (gotSignature, expectedSignature) in sigpairs: for (gotSignature, expectedSignature) in sigpairs:
@ -88,6 +91,21 @@ def WebIDLTest(parser, harness):
results = parser.finish() results = parser.finish()
checkResults(results) checkResults(results)
parser = parser.reset()
parser.parse("""
interface TestPrefConstructor {
[Pref="dom.webidl.test1"] constructor();
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestPrefConstructor::constructor",
"constructor", [("TestPrefConstructor (Wrapper)", [])],
pref=["dom.webidl.test1"])
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse("""
interface TestChromeOnlyConstructor { interface TestChromeOnlyConstructor {
@ -103,6 +121,53 @@ def WebIDLTest(parser, harness):
"constructor", [("TestChromeOnlyConstructor (Wrapper)", [])], "constructor", [("TestChromeOnlyConstructor (Wrapper)", [])],
chromeOnly=True) chromeOnly=True)
parser = parser.reset()
parser.parse("""
interface TestSCConstructor {
[SecureContext] constructor();
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestSCConstructor::constructor",
"constructor", [("TestSCConstructor (Wrapper)", [])],
secureContext=True)
parser = parser.reset()
parser.parse("""
interface TestFuncConstructor {
[Func="Document::IsWebAnimationsEnabled"] constructor();
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestFuncConstructor::constructor",
"constructor", [("TestFuncConstructor (Wrapper)", [])],
func=["Document::IsWebAnimationsEnabled"])
parser = parser.reset()
parser.parse("""
interface TestPrefChromeOnlySCFuncConstructor {
[ChromeOnly, Pref="dom.webidl.test1", SecureContext, Func="Document::IsWebAnimationsEnabled"]
constructor();
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestPrefChromeOnlySCFuncConstructor::constructor",
"constructor", [("TestPrefChromeOnlySCFuncConstructor (Wrapper)", [])],
func=["Document::IsWebAnimationsEnabled"], pref=["dom.webidl.test1"],
chromeOnly=True, secureContext=True)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse("""
interface TestHTMLConstructor { interface TestHTMLConstructor {

View file

@ -1,15 +0,0 @@
def WebIDLTest(parser, harness):
parser.parse("""
interface WithDates {
attribute Date foo;
void bar(Date arg);
void baz(sequence<Date> arg);
};
""")
results = parser.finish()
harness.ok(results[0].members[0].type.isDate(), "Should have Date")
harness.ok(results[0].members[1].signatures()[0][1][0].type.isDate(),
"Should have Date argument")
harness.ok(not results[0].members[2].signatures()[0][1][0].type.isDate(),
"Should have non-Date argument")

View file

@ -149,7 +149,7 @@ def WebIDLTest(parser, harness):
# Now let's test our whole distinguishability table # Now let's test our whole distinguishability table
argTypes = [ "long", "short", "long?", "short?", "boolean", argTypes = [ "long", "short", "long?", "short?", "boolean",
"boolean?", "DOMString", "ByteString", "Enum", "Enum2", "boolean?", "DOMString", "ByteString", "UTF8String", "Enum", "Enum2",
"Interface", "Interface?", "Interface", "Interface?",
"AncestorInterface", "UnrelatedInterface", "CallbackInterface", "AncestorInterface", "UnrelatedInterface", "CallbackInterface",
"CallbackInterface?", "CallbackInterface2", "CallbackInterface?", "CallbackInterface2",
@ -158,14 +158,12 @@ def WebIDLTest(parser, harness):
"record<DOMString, object>", "record<DOMString, object>",
"record<USVString, Dict>", "record<USVString, Dict>",
"record<ByteString, long>", "record<ByteString, long>",
"Date", "Date?", "any", "record<UTF8String, long>",
"Promise<any>", "Promise<any>?", "any", "Promise<any>", "Promise<any>?",
"USVString", "JSString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer", "USVString", "JSString", "ArrayBuffer", "ArrayBufferView",
"Uint8Array", "Uint16Array", "Uint8Array", "Uint16Array",
"(long or Callback)", "(long or Dict)", "(long or Callback)", "(long or Dict)",
] ]
# When we can parse Date, we need to add it here.
# XXXbz we can, and should really do that...
# Try to categorize things a bit to keep list lengths down # Try to categorize things a bit to keep list lengths down
def allBut(list1, list2): def allBut(list1, list2):
@ -177,26 +175,24 @@ def WebIDLTest(parser, harness):
primitives = numerics + booleans primitives = numerics + booleans
nonNumerics = allBut(argTypes, numerics + unions) nonNumerics = allBut(argTypes, numerics + unions)
nonBooleans = allBut(argTypes, booleans) nonBooleans = allBut(argTypes, booleans)
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString", "JSString" ] strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString", "JSString", "UTF8String" ]
nonStrings = allBut(argTypes, strings) nonStrings = allBut(argTypes, strings)
nonObjects = primitives + strings nonObjects = primitives + strings
objects = allBut(argTypes, nonObjects ) objects = allBut(argTypes, nonObjects )
bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"] bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
sharedBufferSourceTypes = ["SharedArrayBuffer"]
interfaces = [ "Interface", "Interface?", "AncestorInterface", interfaces = [ "Interface", "Interface?", "AncestorInterface",
"UnrelatedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes "UnrelatedInterface" ] + bufferSourceTypes
nullables = (["long?", "short?", "boolean?", "Interface?", nullables = (["long?", "short?", "boolean?", "Interface?",
"CallbackInterface?", "Dict", "Dict2", "CallbackInterface?", "Dict", "Dict2",
"Date?", "any", "Promise<any>?"] + "Date?", "any", "Promise<any>?"] +
allBut(unions, [ "(long or Callback)" ])) allBut(unions, [ "(long or Callback)" ]))
dates = [ "Date", "Date?" ]
sequences = [ "sequence<long>", "sequence<short>" ] sequences = [ "sequence<long>", "sequence<short>" ]
nonUserObjects = nonObjects + interfaces + dates + sequences nonUserObjects = nonObjects + interfaces + sequences
otherObjects = allBut(argTypes, nonUserObjects + ["object"]) otherObjects = allBut(argTypes, nonUserObjects + ["object"])
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] + notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] +
otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes) otherObjects + sequences + bufferSourceTypes)
records = [ "record<DOMString, object>", "record<USVString, Dict>", records = [ "record<DOMString, object>", "record<USVString, Dict>",
"record<ByteString, long>" ] # JSString not supported in records "record<ByteString, long>", "record<UTF8String, long>" ] # JSString not supported in records
# Build a representation of the distinguishability table as a dict # Build a representation of the distinguishability table as a dict
# of dicts, holding True values where needed, holes elsewhere. # of dicts, holding True values where needed, holes elsewhere.
@ -215,6 +211,7 @@ def WebIDLTest(parser, harness):
setDistinguishable("boolean?", allBut(nonBooleans, nullables)) setDistinguishable("boolean?", allBut(nonBooleans, nullables))
setDistinguishable("DOMString", nonStrings) setDistinguishable("DOMString", nonStrings)
setDistinguishable("ByteString", nonStrings) setDistinguishable("ByteString", nonStrings)
setDistinguishable("UTF8String", nonStrings)
setDistinguishable("USVString", nonStrings) setDistinguishable("USVString", nonStrings)
setDistinguishable("JSString", nonStrings) setDistinguishable("JSString", nonStrings)
setDistinguishable("Enum", nonStrings) setDistinguishable("Enum", nonStrings)
@ -240,8 +237,7 @@ def WebIDLTest(parser, harness):
setDistinguishable("record<USVString, Dict>", nonUserObjects) setDistinguishable("record<USVString, Dict>", nonUserObjects)
# JSString not supported in records # JSString not supported in records
setDistinguishable("record<ByteString, long>", nonUserObjects) setDistinguishable("record<ByteString, long>", nonUserObjects)
setDistinguishable("Date", allBut(argTypes, dates + ["object"])) setDistinguishable("record<UTF8String, long>", nonUserObjects)
setDistinguishable("Date?", allBut(argTypes, dates + nullables + ["object"]))
setDistinguishable("any", []) setDistinguishable("any", [])
setDistinguishable("Promise<any>", []) setDistinguishable("Promise<any>", [])
setDistinguishable("Promise<any>?", []) setDistinguishable("Promise<any>?", [])
@ -249,7 +245,6 @@ def WebIDLTest(parser, harness):
setDistinguishable("ArrayBufferView", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"])) setDistinguishable("ArrayBufferView", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"]))
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"])) setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"]))
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])) setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"]))
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
setDistinguishable("(long or Callback)", setDistinguishable("(long or Callback)",
allBut(nonUserObjects, numerics)) allBut(nonUserObjects, numerics))
setDistinguishable("(long or Dict)", setDistinguishable("(long or Dict)",

View file

@ -56,9 +56,9 @@ def WebIDLTest(parser, harness):
results = parser.finish() results = parser.finish()
# Pull out the first argument out of the arglist of the first (and # Pull out the first argument out of the arglist of the first (and
# only) signature. # only) signature.
harness.ok(results[0].members[0].signatures()[0][1][0].type.clamp, harness.ok(results[0].members[0].signatures()[0][1][0].type.hasClamp(),
"Should be clamped") "Should be clamped")
harness.ok(not results[0].members[1].signatures()[0][1][0].type.clamp, harness.ok(not results[0].members[1].signatures()[0][1][0].type.hasClamp(),
"Should not be clamped") "Should not be clamped")
parser = parser.reset() parser = parser.reset()
@ -86,9 +86,9 @@ def WebIDLTest(parser, harness):
results = parser.finish() results = parser.finish()
# Pull out the first argument out of the arglist of the first (and # Pull out the first argument out of the arglist of the first (and
# only) signature. # only) signature.
harness.ok(results[0].members[0].signatures()[0][1][0].type.enforceRange, harness.ok(results[0].members[0].signatures()[0][1][0].type.hasEnforceRange(),
"Should be enforceRange") "Should be enforceRange")
harness.ok(not results[0].members[1].signatures()[0][1][0].type.enforceRange, harness.ok(not results[0].members[1].signatures()[0][1][0].type.hasEnforceRange(),
"Should not be enforceRange") "Should not be enforceRange")
parser = parser.reset() parser = parser.reset()

View file

@ -80,7 +80,7 @@ def checkEquivalent(iface, harness):
for attr in dir(type1): for attr in dir(type1):
if attr.startswith('_') or \ if attr.startswith('_') or \
attr in ['nullable', 'builtin', 'filename', 'location', attr in ['nullable', 'builtin', 'filename', 'location',
'inner', 'QName', 'getDeps', 'name'] or \ 'inner', 'QName', 'getDeps', 'name', 'prettyName'] or \
(hasattr(type(type1), attr) and not callable(getattr(type1, attr))): (hasattr(type(type1), attr) and not callable(getattr(type1, attr))):
continue continue

View file

@ -85,7 +85,7 @@ def WebIDLTest(parser, harness):
JsonTypes = [ "byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", JsonTypes = [ "byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long",
"unsigned long long", "float", "unrestricted float", "double", "unrestricted double", "boolean", "unsigned long long", "float", "unrestricted float", "double", "unrestricted double", "boolean",
"DOMString", "ByteString", "USVString", "Enum", "InterfaceWithToJSON", "object" ] "DOMString", "ByteString", "UTF8String", "USVString", "Enum", "InterfaceWithToJSON", "object" ]
nonJsonTypes = [ "InterfaceWithoutToJSON", "any", "Int8Array", "Int16Array", "Int32Array","Uint8Array", nonJsonTypes = [ "InterfaceWithoutToJSON", "any", "Int8Array", "Int16Array", "Int32Array","Uint8Array",
"Uint16Array", "Uint32Array", "Uint8ClampedArray", "Float32Array", "Float64Array", "ArrayBuffer" ] "Uint16Array", "Uint32Array", "Uint8ClampedArray", "Float32Array", "Float64Array", "ArrayBuffer" ]
@ -132,6 +132,9 @@ def WebIDLTest(parser, harness):
doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, False, doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, False,
"record<ByteString, %s> should be a JSON type" % type) "record<ByteString, %s> should be a JSON type" % type)
doTest("interface Test { record<UTF8String, %s> toJSON(); };" % type, False,
"record<UTF8String, %s> should be a JSON type" % type)
doTest("interface Test { record<USVString, %s> toJSON(); };" % type, False, doTest("interface Test { record<USVString, %s> toJSON(); };" % type, False,
"record<USVString, %s> should be a JSON type" % type) "record<USVString, %s> should be a JSON type" % type)

View file

@ -5,8 +5,8 @@ patch < callback-location.patch
patch < union-typedef.patch patch < union-typedef.patch
patch < inline.patch patch < inline.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz wget https://hg.mozilla.org/mozilla-central/archive/tip.zip/dom/bindings/parser/tests/ -O tests.zip
rm -r tests rm -r tests
mkdir tests mkdir tests
tar xvpf tests.tar.gz -C tests --strip-components=5 unzip -d tests -j tests.zip
rm tests.tar.gz WebIDL.py.orig rm tests.zip WebIDL.py.orig