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.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
# XXXbz Do we need to worry about security wrappers?
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
assert not isDefinitelyObject or defaultValue is None
isEnforceRange = type.enforceRange
isClamp = type.clamp
isEnforceRange = type.hasEnforceRange()
isClamp = type.hasClamp()
if type.treatNullAsEmpty:
treatNullAs = "EmptyString"
else:
@ -1665,6 +1654,8 @@ class MethodDefiner(PropertyDefiner):
(maplikeOrSetlikeOrIterable and
maplikeOrSetlikeOrIterable.isIterable() and
maplikeOrSetlikeOrIterable.isValueIterator())):
m = maplikeOrSetlikeOrIterable
# Add our keys/values/entries/forEach
self.regular.append({
"name": "keys",
@ -4162,8 +4153,6 @@ class CGMemberJITInfo(CGThing):
u.flatMemberTypes, "")
if t.isDictionary():
return "JSVAL_TYPE_OBJECT"
if t.isDate():
return "JSVAL_TYPE_OBJECT"
if not t.isPrimitive():
raise TypeError("No idea what type " + str(t) + " is.")
tag = t.tag()
@ -4233,8 +4222,6 @@ class CGMemberJITInfo(CGThing):
u.flatMemberTypes, type)
if t.isDictionary():
return "JSJitInfo_ArgType::Object as i32"
if t.isDate():
return "JSJitInfo_ArgType::Object as i32"
if not t.isPrimitive():
raise TypeError("No idea what type " + str(t) + " is.")
tag = t.tag()
@ -4540,13 +4527,6 @@ class CGUnionConversionStruct(CGThing):
else:
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)
if len(callbackMemberTypes) > 0:
assert len(callbackMemberTypes) == 1
@ -4582,10 +4562,10 @@ class CGUnionConversionStruct(CGThing):
else:
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:
# "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")
if object:
templateBody.append(object)
@ -6848,7 +6828,7 @@ def type_needs_tracing(t):
def is_typed_array(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):

View file

@ -481,9 +481,6 @@ class IDLExposureMixins():
def isExposedInWindow(self):
return 'Window' in self.exposureSet
def isExposedOnMainThread(self):
return self.isExposedInWindow()
def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0
@ -2090,9 +2087,9 @@ class IDLType(IDLObject):
'domstring',
'bytestring',
'usvstring',
'utf8string',
'jsstring',
'object',
'date',
'void',
# Funny stuff
'interface',
@ -2109,15 +2106,17 @@ class IDLType(IDLObject):
IDLObject.__init__(self, location)
self.name = name
self.builtin = False
self.clamp = False
self.treatNullAsEmpty = False
self.enforceRange = False
self._clamp = False
self._enforceRange = False
self._allowShared = False
self._extendedAttrDict = {}
def __eq__(self, other):
return (other and self.builtin == other.builtin and self.name == other.name and
self.clamp == other.clamp and self.enforceRange == other.enforceRange and
self.treatNullAsEmpty == other.treatNullAsEmpty)
self._clamp == other.hasClamp() and self._enforceRange == other.hasEnforceRange() and
self.treatNullAsEmpty == other.treatNullAsEmpty and
self._allowShared == other.hasAllowShared())
def __ne__(self, other):
return not self == other
@ -2125,6 +2124,14 @@ class IDLType(IDLObject):
def __str__(self):
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):
return True
@ -2152,6 +2159,9 @@ class IDLType(IDLObject):
def isUSVString(self):
return False
def isUTF8String(self):
return False
def isJSString(self):
return False
@ -2173,12 +2183,12 @@ class IDLType(IDLObject):
def isArrayBufferView(self):
return False
def isSharedArrayBuffer(self):
return False
def isTypedArray(self):
return False
def isBufferSource(self):
return self.isArrayBuffer() or self.isArrayBufferView() or self.isTypedArray()
def isCallbackInterface(self):
return False
@ -2195,10 +2205,7 @@ class IDLType(IDLObject):
def isSpiderMonkeyInterface(self):
""" Returns a boolean indicating whether this type is an 'interface'
type that is implemented in SpiderMonkey. """
return self.isInterface() and (self.isArrayBuffer() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isTypedArray() or
return self.isInterface() and (self.isBufferSource() or
self.isReadableStream())
def isDictionary(self):
@ -2210,9 +2217,6 @@ class IDLType(IDLObject):
def isAny(self):
return self.tag() == IDLType.Tags.any
def isDate(self):
return self.tag() == IDLType.Tags.date
def isObject(self):
return self.tag() == IDLType.Tags.object
@ -2235,6 +2239,15 @@ class IDLType(IDLObject):
def isJSONType(self):
return False
def hasClamp(self):
return self._clamp
def hasEnforceRange(self):
return self._enforceRange
def hasAllowShared(self):
return self._allowShared
def tag(self):
assert False # Override me!
@ -2342,10 +2355,7 @@ class IDLNullableType(IDLParametrizedType):
assert not innerType.isVoid()
assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
name = innerType.name
if innerType.isComplete():
name += "OrNull"
IDLParametrizedType.__init__(self, location, name, innerType)
IDLParametrizedType.__init__(self, location, None, innerType)
def __eq__(self, other):
return isinstance(other, IDLNullableType) and self.inner == other.inner
@ -2353,6 +2363,9 @@ class IDLNullableType(IDLParametrizedType):
def __str__(self):
return self.inner.__str__() + "OrNull"
def prettyName(self):
return self.inner.prettyName() + "?"
def nullable(self):
return True
@ -2380,6 +2393,9 @@ class IDLNullableType(IDLParametrizedType):
def isUSVString(self):
return self.inner.isUSVString()
def isUTF8String(self):
return self.inner.isUTF8String()
def isJSString(self):
return self.inner.isJSString()
@ -2410,9 +2426,6 @@ class IDLNullableType(IDLParametrizedType):
def isArrayBufferView(self):
return self.inner.isArrayBufferView()
def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer()
def isTypedArray(self):
return self.inner.isTypedArray()
@ -2442,11 +2455,26 @@ class IDLNullableType(IDLParametrizedType):
def isJSONType(self):
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):
return self.inner.tag()
def complete(self, scope):
self.inner = self.inner.complete(scope)
if not self.inner.isComplete():
self.inner = self.inner.complete(scope)
assert self.inner.isComplete()
if self.inner.nullable():
raise WebIDLError("The inner type of a nullable type must not be "
"a nullable type",
@ -2456,6 +2484,10 @@ class IDLNullableType(IDLParametrizedType):
raise WebIDLError("The inner type of a nullable type must not "
"be a union type that itself has a nullable "
"type as a member type", [self.location])
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"
return self
@ -2469,6 +2501,13 @@ class IDLNullableType(IDLParametrizedType):
return False
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):
def __init__(self, location, parameterType):
@ -2486,6 +2525,9 @@ class IDLSequenceType(IDLParametrizedType):
def __str__(self):
return self.inner.__str__() + "Sequence"
def prettyName(self):
return "sequence<%s>" % self.inner.prettyName()
def nullable(self):
return False
@ -2504,6 +2546,9 @@ class IDLSequenceType(IDLParametrizedType):
def isUSVString(self):
return False
def isUTF8String(self):
return False
def isJSString(self):
return False
@ -2540,8 +2585,7 @@ class IDLSequenceType(IDLParametrizedType):
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isInterface() or
other.isDictionary() or
other.isInterface() or other.isDictionary() or
other.isCallback() or other.isRecord())
@ -2565,6 +2609,9 @@ class IDLRecordType(IDLParametrizedType):
def __str__(self):
return self.keyType.__str__() + self.inner.__str__() + "Record"
def prettyName(self):
return "record<%s, %s>" % (self.keyType.prettyName(), self.inner.prettyName())
def isRecord(self):
return True
@ -2592,7 +2639,7 @@ class IDLRecordType(IDLParametrizedType):
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
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):
return self.inner.unroll().isExposedInAllOf(exposureSet)
@ -2614,6 +2661,9 @@ class IDLUnionType(IDLType):
assert self.isComplete()
return self.name.__hash__()
def prettyName(self):
return "(" + " or ".join(m.prettyName() for m in self.memberTypes) + ")"
def isVoid(self):
return False
@ -2645,6 +2695,9 @@ class IDLUnionType(IDLType):
return typeName(type._identifier.object())
if isinstance(type, IDLObjectWithIdentifier):
return typeName(type.identifier)
if isinstance(type, IDLBuiltinType) and type.hasAllowShared():
assert type.isBufferSource()
return "MaybeShared" + type.name
return type.name
for (i, type) in enumerate(self.memberTypes):
@ -2768,6 +2821,9 @@ class IDLTypedefType(IDLType):
def isUSVString(self):
return self.inner.isUSVString()
def isUTF8String(self):
return self.inner.isUTF8String()
def isJSString(self):
return self.inner.isJSString()
@ -2795,9 +2851,6 @@ class IDLTypedefType(IDLType):
def isArrayBufferView(self):
return self.inner.isArrayBufferView()
def isSharedArrayBuffer(self):
return self.inner.isSharedArrayBuffer()
def isTypedArray(self):
return self.inner.isTypedArray()
@ -2901,6 +2954,9 @@ class IDLWrapperType(IDLType):
def isUSVString(self):
return False
def isUTF8String(self):
return False
def isJSString(self):
return False
@ -2976,11 +3032,11 @@ class IDLWrapperType(IDLType):
if self.isEnum():
return (other.isPrimitive() or other.isInterface() or other.isObject() 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():
return False
if (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isSequence()):
other.isSequence()):
return True
if self.isDictionary():
return other.isNonCallbackInterface()
@ -3052,6 +3108,9 @@ class IDLPromiseType(IDLParametrizedType):
def __str__(self):
return self.inner.__str__() + "Promise"
def prettyName(self):
return "Promise<%s>" % self.inner.prettyName()
def isPromise(self):
return True
@ -3104,14 +3163,13 @@ class IDLBuiltinType(IDLType):
'domstring',
'bytestring',
'usvstring',
'utf8string',
'jsstring',
'object',
'date',
'void',
# Funny stuff
'ArrayBuffer',
'ArrayBufferView',
'SharedArrayBuffer',
'Int8Array',
'Uint8Array',
'Uint8ClampedArray',
@ -3142,13 +3200,12 @@ class IDLBuiltinType(IDLType):
Types.domstring: IDLType.Tags.domstring,
Types.bytestring: IDLType.Tags.bytestring,
Types.usvstring: IDLType.Tags.usvstring,
Types.utf8string: IDLType.Tags.utf8string,
Types.jsstring: IDLType.Tags.jsstring,
Types.object: IDLType.Tags.object,
Types.date: IDLType.Tags.date,
Types.void: IDLType.Tags.void,
Types.ArrayBuffer: IDLType.Tags.interface,
Types.ArrayBufferView: IDLType.Tags.interface,
Types.SharedArrayBuffer: IDLType.Tags.interface,
Types.Int8Array: IDLType.Tags.interface,
Types.Uint8Array: IDLType.Tags.interface,
Types.Uint8ClampedArray: IDLType.Tags.interface,
@ -3161,11 +3218,48 @@ class IDLBuiltinType(IDLType):
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,
attrLocation=[]):
allowShared=False, attrLocation=[]):
"""
The mutually exclusive clamp/enforceRange/treatNullAsEmpty arguments are used to create instances
of this type with the appropriate attributes attached. Use .clamped(), .rangeEnforced(), and .treatNullAs().
The mutually exclusive clamp/enforceRange/treatNullAsEmpty/allowShared arguments are used
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.
"""
@ -3175,24 +3269,40 @@ class IDLBuiltinType(IDLType):
self._clamped = None
self._rangeEnforced = None
self._withTreatNullAs = None
if self.isNumeric():
self._withAllowShared = None;
if self.isInteger():
if clamp:
self.clamp = True
self._clamp = True
self.name = "Clamped" + self.name
self._extendedAttrDict["Clamp"] = True
elif enforceRange:
self.enforceRange = True
self._enforceRange = True
self.name = "RangeEnforced" + self.name
self._extendedAttrDict["EnforceRange"] = True
elif clamp or enforceRange:
raise WebIDLError("Non-numeric types cannot be [Clamp] or [EnforceRange]", attrLocation)
if self.isDOMString():
raise WebIDLError("Non-integer types cannot be [Clamp] or [EnforceRange]", attrLocation)
if self.isDOMString() or self.isUTF8String():
if treatNullAsEmpty:
self.treatNullAsEmpty = True
self.name = "NullIsEmpty" + self.name
self._extendedAttrDict["TreatNullAs"] = ["EmptyString"]
elif treatNullAsEmpty:
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):
if not self._clamped:
@ -3215,6 +3325,13 @@ class IDLBuiltinType(IDLType):
attrLocation=attrLocation)
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):
return self._typeTag <= IDLBuiltinType.Types.double
@ -3228,6 +3345,7 @@ class IDLBuiltinType(IDLType):
return (self._typeTag == IDLBuiltinType.Types.domstring or
self._typeTag == IDLBuiltinType.Types.bytestring or
self._typeTag == IDLBuiltinType.Types.usvstring or
self._typeTag == IDLBuiltinType.Types.utf8string or
self._typeTag == IDLBuiltinType.Types.jsstring)
def isByteString(self):
@ -3239,6 +3357,9 @@ class IDLBuiltinType(IDLType):
def isUSVString(self):
return self._typeTag == IDLBuiltinType.Types.usvstring
def isUTF8String(self):
return self._typeTag == IDLBuiltinType.Types.utf8string
def isJSString(self):
return self._typeTag == IDLBuiltinType.Types.jsstring
@ -3251,9 +3372,6 @@ class IDLBuiltinType(IDLType):
def isArrayBufferView(self):
return self._typeTag == IDLBuiltinType.Types.ArrayBufferView
def isSharedArrayBuffer(self):
return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer
def isTypedArray(self):
return (self._typeTag >= IDLBuiltinType.Types.Int8Array and
self._typeTag <= IDLBuiltinType.Types.Float64Array)
@ -3267,7 +3385,6 @@ class IDLBuiltinType(IDLType):
# all of it internally.
return (self.isArrayBuffer() or
self.isArrayBufferView() or
self.isSharedArrayBuffer() or
self.isTypedArray() or
self.isReadableStream())
@ -3305,27 +3422,22 @@ class IDLBuiltinType(IDLType):
return (other.isNumeric() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate())
other.isSequence() or other.isRecord())
if self.isNumeric():
return (other.isBoolean() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate())
other.isSequence() or other.isRecord())
if self.isString():
return (other.isPrimitive() or other.isInterface() or
other.isObject() or
other.isCallback() or other.isDictionary() or
other.isSequence() or other.isRecord() or other.isDate())
other.isSequence() or other.isRecord())
if self.isAny():
# Can't tell "any" apart from anything
return False
if self.isObject():
return other.isPrimitive() or other.isString() or other.isEnum()
if self.isDate():
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isInterface() or other.isCallback() or
other.isDictionary() or other.isSequence() or
other.isRecord())
if self.isVoid():
return not other.isVoid()
# Not much else we could be!
@ -3333,12 +3445,11 @@ class IDLBuiltinType(IDLType):
# Like interfaces, but we know we're not a callback
return (other.isPrimitive() or other.isString() or other.isEnum() 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 (
# ArrayBuffer is distinguishable from everything
# that's not an ArrayBuffer or a callback interface
(self.isArrayBuffer() and not other.isArrayBuffer()) or
(self.isSharedArrayBuffer() and not other.isSharedArrayBuffer()) or
(self.isReadableStream() and not other.isReadableStream()) or
# ArrayBufferView is distinguishable from everything
# that's not an ArrayBufferView or typed array.
@ -3361,7 +3472,7 @@ class IDLBuiltinType(IDLType):
if not attribute.noArguments():
raise WebIDLError("[Clamp] must take no arguments",
[attribute.location])
if ret.enforceRange or self.enforceRange:
if ret.hasEnforceRange() or self._enforceRange:
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
[self.location, attribute.location])
ret = self.clamped([self.location, attribute.location])
@ -3369,17 +3480,17 @@ class IDLBuiltinType(IDLType):
if not attribute.noArguments():
raise WebIDLError("[EnforceRange] must take no arguments",
[attribute.location])
if ret.clamp or self.clamp:
if ret.hasClamp() or self._clamp:
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
[self.location, attribute.location])
ret = self.rangeEnforced([self.location, attribute.location])
elif identifier == "TreatNullAs":
if not self.isDOMString():
raise WebIDLError("[TreatNullAs] only allowed on DOMStrings",
if not (self.isDOMString() or self.isUTF8String()):
raise WebIDLError("[TreatNullAs] only allowed on DOMStrings and UTF8Strings",
[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':
@ -3387,6 +3498,15 @@ class IDLBuiltinType(IDLType):
"'EmptyString', not '%s'" % value,
[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:
raise WebIDLError("Unhandled extended attribute on type",
[self.location, attribute.location])
@ -3444,15 +3564,15 @@ BuiltinTypes = {
IDLBuiltinType.Types.usvstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "USVString",
IDLBuiltinType.Types.usvstring),
IDLBuiltinType.Types.utf8string:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "UTF8String",
IDLBuiltinType.Types.utf8string),
IDLBuiltinType.Types.jsstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "JSString",
IDLBuiltinType.Types.jsstring),
IDLBuiltinType.Types.object:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
IDLBuiltinType.Types.object),
IDLBuiltinType.Types.date:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date",
IDLBuiltinType.Types.date),
IDLBuiltinType.Types.void:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void",
IDLBuiltinType.Types.void),
@ -3462,9 +3582,6 @@ BuiltinTypes = {
IDLBuiltinType.Types.ArrayBufferView:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView",
IDLBuiltinType.Types.ArrayBufferView),
IDLBuiltinType.Types.SharedArrayBuffer:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "SharedArrayBuffer",
IDLBuiltinType.Types.SharedArrayBuffer),
IDLBuiltinType.Types.Int8Array:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
IDLBuiltinType.Types.Int8Array),
@ -3613,8 +3730,9 @@ class IDLValue(IDLObject):
# TreatNullAsEmpty is a different type for resolution reasons,
# however once you have a value it doesn't matter
return self
elif self.type.isString() and (type.isByteString() or type.isJSString()):
# Allow ByteStrings and JSStrings to use a default value like DOMString.
elif self.type.isString() and (type.isByteString() or type.isJSString() or type.isUTF8String()):
# Allow ByteStrings, UTF8String, and JSStrings to use a default
# value like DOMString.
# No coercion is required as Codegen.py will handle the
# extra steps. We want to make sure that our string contains
# only valid characters, so we check that here.
@ -4307,8 +4425,9 @@ class IDLAttribute(IDLInterfaceMember):
assert not isinstance(t.name, IDLUnresolvedIdentifier)
self.type = t
if self.readonly and (self.type.clamp or self.type.enforceRange or self.type.treatNullAsEmpty):
raise WebIDLError("A readonly attribute cannot be [Clamp] or [EnforceRange]",
if self.readonly and (self.type.hasClamp() or self.type.hasEnforceRange() or
self.type.hasAllowShared() or self.type.treatNullAsEmpty):
raise WebIDLError("A readonly attribute cannot be [Clamp] or [EnforceRange] or [AllowShared]",
[self.location])
if self.type.isDictionary() and not self.getExtendedAttribute("Cached"):
raise WebIDLError("An attribute cannot be of a dictionary type",
@ -4709,7 +4828,7 @@ class IDLArgument(IDLObjectWithIdentifier):
for attribute in attrs:
identifier = attribute.identifier()
if self.allowTypeAttributes and (identifier == "EnforceRange" or identifier == "Clamp" or
identifier == "TreatNullAs"):
identifier == "TreatNullAs" or identifier == "AllowShared"):
self.type = self.type.withExtendedAttributes([attribute])
elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True
@ -4879,8 +4998,7 @@ class IDLCallbackType(IDLType):
# Just forward to the union; it'll deal
return other.isDistinguishableFrom(self)
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate() or
other.isSequence())
other.isNonCallbackInterface() or other.isSequence())
def _getDependentObjects(self):
return self.callback._getDependentObjects()
@ -5475,7 +5593,9 @@ class IDLConstructor(IDLMethod):
identifier == "ChromeOnly" or
identifier == "NewObject" or
identifier == "SecureContext" or
identifier == "Throws"):
identifier == "Throws" or
identifier == "Func" or
identifier == "Pref"):
IDLMethod.handleExtendedAttribute(self, attr)
elif identifier == "HTMLConstructor":
if not attr.noArguments():
@ -5675,11 +5795,11 @@ class Tokenizer(object):
"optional": "OPTIONAL",
"...": "ELLIPSIS",
"::": "SCOPE",
"Date": "DATE",
"DOMString": "DOMSTRING",
"ByteString": "BYTESTRING",
"USVString": "USVSTRING",
"JSString": "JSSTRING",
"UTF8String": "UTF8STRING",
"any": "ANY",
"boolean": "BOOLEAN",
"byte": "BYTE",
@ -5709,7 +5829,6 @@ class Tokenizer(object):
"<": "LT",
">": "GT",
"ArrayBuffer": "ARRAYBUFFER",
"SharedArrayBuffer": "SHAREDARRAYBUFFER",
"or": "OR",
"maplike": "MAPLIKE",
"setlike": "SETLIKE",
@ -6939,10 +7058,10 @@ class Parser(Tokenizer):
| EQUALS
| GT
| QUESTIONMARK
| DATE
| DOMSTRING
| BYTESTRING
| USVSTRING
| UTF8STRING
| JSSTRING
| PROMISE
| ANY
@ -7050,7 +7169,6 @@ class Parser(Tokenizer):
"""
DistinguishableType : PrimitiveType Null
| ARRAYBUFFER Null
| SHAREDARRAYBUFFER Null
| READABLESTREAM Null
| OBJECT Null
"""
@ -7058,8 +7176,6 @@ class Parser(Tokenizer):
type = BuiltinTypes[IDLBuiltinType.Types.object]
elif p[1] == "ArrayBuffer":
type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
elif p[1] == "SharedArrayBuffer":
type = BuiltinTypes[IDLBuiltinType.Types.SharedArrayBuffer]
elif p[1] == "ReadableStream":
type = BuiltinTypes[IDLBuiltinType.Types.ReadableStream]
else:
@ -7122,13 +7238,6 @@ class Parser(Tokenizer):
type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
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):
"""
ConstType : PrimitiveType
@ -7215,6 +7324,12 @@ class Parser(Tokenizer):
"""
p[0] = IDLBuiltinType.Types.usvstring
def p_BuiltinStringTypeUTF8String(self, p):
"""
BuiltinStringType : UTF8STRING
"""
p[0] = IDLBuiltinType.Types.utf8string
def p_BuiltinStringTypeJSString(self, p):
"""
BuiltinStringType : JSSTRING
@ -7354,7 +7469,13 @@ class Parser(Tokenizer):
IdentifierList : IDENTIFIER Identifiers
"""
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
def p_IdentifiersList(self, p):
@ -7362,7 +7483,13 @@ class Parser(Tokenizer):
Identifiers : COMMA IDENTIFIER Identifiers
"""
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
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,
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 {
setlike<[Clamp] long>;
};
@ -41,29 +47,105 @@ def WebIDLTest(parser, harness):
harness.ok(not threw, "Should not have thrown on parsing normal")
if not threw:
harness.check(results[0].innerType.enforceRange, True, "Foo is [EnforceRange]")
harness.check(results[1].innerType.clamp, True, "Bar is [Clamp]")
harness.check(results[0].innerType.hasEnforceRange(), True, "Foo is [EnforceRange]")
harness.check(results[1].innerType.hasClamp(), True, "Bar is [Clamp]")
harness.check(results[2].innerType.treatNullAsEmpty, True, "Baz is [TreatNullAs=EmptyString]")
A = results[3]
harness.check(A.members[0].type.enforceRange, True, "A.a is [EnforceRange]")
harness.check(A.members[1].type.clamp, True, "A.b is [Clamp]")
harness.check(A.members[2].type.enforceRange, True, "A.c is [EnforceRange]")
harness.check(A.members[3].type.enforceRange, True, "A.d is [EnforceRange]")
harness.check(A.members[0].type.hasEnforceRange(), True, "A.a is [EnforceRange]")
harness.check(A.members[1].type.hasClamp(), True, "A.b is [Clamp]")
harness.check(A.members[2].type.hasEnforceRange(), True, "A.c is [EnforceRange]")
harness.check(A.members[3].type.hasEnforceRange(), True, "A.d is [EnforceRange]")
B = results[4]
harness.check(B.members[0].type.enforceRange, True, "B.typedefFoo is [EnforceRange]")
harness.check(B.members[1].type.enforceRange, True, "B.foo is [EnforceRange]")
harness.check(B.members[2].type.clamp, True, "B.bar is [Clamp]")
harness.check(B.members[0].type.hasEnforceRange(), True, "B.typedefFoo is [EnforceRange]")
harness.check(B.members[1].type.hasEnforceRange(), True, "B.foo is [EnforceRange]")
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]")
method = B.members[4].signatures()[0][1]
harness.check(method[0].type.enforceRange, True, "foo argument of method is [EnforceRange]")
harness.check(method[1].type.clamp, True, "bar argument of method is [Clamp]")
harness.check(method[0].type.hasEnforceRange(), True, "foo argument of method is [EnforceRange]")
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]")
method2 = B.members[5].signatures()[0][1]
harness.check(method[0].type.enforceRange, True, "foo argument of method2 is [EnforceRange]")
harness.check(method[1].type.clamp, True, "bar argument of method2 is [Clamp]")
harness.check(method[0].type.hasEnforceRange(), True, "foo argument of method2 is [EnforceRange]")
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]")
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 = [
("required dictionary members", """
dictionary Foo {
@ -93,7 +175,54 @@ def WebIDLTest(parser, harness):
readonly attribute Bar baz;
};
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;
};
""")
];
for (name, template) in TEMPLATES:
@ -167,30 +296,32 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [Clamp] DOMString Foo;
""")
parser.finish()
except:
threw = True
TYPES = ["DOMString", "unrestricted float", "float", "unrestricted double", "double"]
harness.ok(threw, "Should not allow [Clamp] on DOMString")
for type in TYPES:
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [Clamp] %s Foo;
""" % type)
parser.finish()
except:
threw = True
harness.ok(threw, "Should not allow [Clamp] on %s" % type)
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [EnforceRange] DOMString Foo;
""")
parser.finish()
except:
threw = True
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [EnforceRange] %s Foo;
""" % type)
parser.finish()
except:
threw = True
harness.ok(threw, "Should not allow [EnforceRange] on DOMString")
harness.ok(threw, "Should not allow [EnforceRange] on %s" % type)
parser = parser.reset()
@ -217,6 +348,40 @@ def WebIDLTest(parser, harness):
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()
threw = False
try:
@ -230,7 +395,7 @@ def WebIDLTest(parser, harness):
except:
threw = True
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")
parser = parser.reset()
@ -246,5 +411,5 @@ def WebIDLTest(parser, harness):
except:
threw = True
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")

View file

@ -11,9 +11,9 @@ def WebIDLTest(parser, harness):
harness.check(argument.variadic, variadic, "Argument has the right variadic value")
def checkMethod(method, QName, name, signatures,
static=True, getter=False, setter=False,
deleter=False, legacycaller=False, stringifier=False,
chromeOnly=False, htmlConstructor=False):
static=True, getter=False, setter=False, deleter=False,
legacycaller=False, stringifier=False, chromeOnly=False,
htmlConstructor=False, secureContext=False, pref=None, func=None):
harness.ok(isinstance(method, WebIDL.IDLMethod),
"Should be an IDLMethod")
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.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
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)
for (gotSignature, expectedSignature) in sigpairs:
@ -88,6 +91,21 @@ def WebIDLTest(parser, harness):
results = parser.finish()
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.parse("""
interface TestChromeOnlyConstructor {
@ -103,6 +121,53 @@ def WebIDLTest(parser, harness):
"constructor", [("TestChromeOnlyConstructor (Wrapper)", [])],
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.parse("""
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
argTypes = [ "long", "short", "long?", "short?", "boolean",
"boolean?", "DOMString", "ByteString", "Enum", "Enum2",
"boolean?", "DOMString", "ByteString", "UTF8String", "Enum", "Enum2",
"Interface", "Interface?",
"AncestorInterface", "UnrelatedInterface", "CallbackInterface",
"CallbackInterface?", "CallbackInterface2",
@ -158,14 +158,12 @@ def WebIDLTest(parser, harness):
"record<DOMString, object>",
"record<USVString, Dict>",
"record<ByteString, long>",
"Date", "Date?", "any",
"Promise<any>", "Promise<any>?",
"USVString", "JSString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"record<UTF8String, long>",
"any", "Promise<any>", "Promise<any>?",
"USVString", "JSString", "ArrayBuffer", "ArrayBufferView",
"Uint8Array", "Uint16Array",
"(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
def allBut(list1, list2):
@ -177,26 +175,24 @@ def WebIDLTest(parser, harness):
primitives = numerics + booleans
nonNumerics = allBut(argTypes, numerics + unions)
nonBooleans = allBut(argTypes, booleans)
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString", "JSString" ]
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString", "JSString", "UTF8String" ]
nonStrings = allBut(argTypes, strings)
nonObjects = primitives + strings
objects = allBut(argTypes, nonObjects )
bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
sharedBufferSourceTypes = ["SharedArrayBuffer"]
interfaces = [ "Interface", "Interface?", "AncestorInterface",
"UnrelatedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes
"UnrelatedInterface" ] + bufferSourceTypes
nullables = (["long?", "short?", "boolean?", "Interface?",
"CallbackInterface?", "Dict", "Dict2",
"Date?", "any", "Promise<any>?"] +
allBut(unions, [ "(long or Callback)" ]))
dates = [ "Date", "Date?" ]
sequences = [ "sequence<long>", "sequence<short>" ]
nonUserObjects = nonObjects + interfaces + dates + sequences
nonUserObjects = nonObjects + interfaces + sequences
otherObjects = allBut(argTypes, nonUserObjects + ["object"])
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] +
otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes)
otherObjects + sequences + bufferSourceTypes)
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
# of dicts, holding True values where needed, holes elsewhere.
@ -215,6 +211,7 @@ def WebIDLTest(parser, harness):
setDistinguishable("boolean?", allBut(nonBooleans, nullables))
setDistinguishable("DOMString", nonStrings)
setDistinguishable("ByteString", nonStrings)
setDistinguishable("UTF8String", nonStrings)
setDistinguishable("USVString", nonStrings)
setDistinguishable("JSString", nonStrings)
setDistinguishable("Enum", nonStrings)
@ -240,8 +237,7 @@ def WebIDLTest(parser, harness):
setDistinguishable("record<USVString, Dict>", nonUserObjects)
# JSString not supported in records
setDistinguishable("record<ByteString, long>", nonUserObjects)
setDistinguishable("Date", allBut(argTypes, dates + ["object"]))
setDistinguishable("Date?", allBut(argTypes, dates + nullables + ["object"]))
setDistinguishable("record<UTF8String, long>", nonUserObjects)
setDistinguishable("any", [])
setDistinguishable("Promise<any>", [])
setDistinguishable("Promise<any>?", [])
@ -249,7 +245,6 @@ def WebIDLTest(parser, harness):
setDistinguishable("ArrayBufferView", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"]))
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"]))
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"]))
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
setDistinguishable("(long or Callback)",
allBut(nonUserObjects, numerics))
setDistinguishable("(long or Dict)",

View file

@ -56,9 +56,9 @@ def WebIDLTest(parser, harness):
results = parser.finish()
# Pull out the first argument out of the arglist of the first (and
# 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")
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")
parser = parser.reset()
@ -86,9 +86,9 @@ def WebIDLTest(parser, harness):
results = parser.finish()
# Pull out the first argument out of the arglist of the first (and
# 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")
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")
parser = parser.reset()

View file

@ -80,7 +80,7 @@ def checkEquivalent(iface, harness):
for attr in dir(type1):
if attr.startswith('_') or \
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))):
continue

View file

@ -85,7 +85,7 @@ def WebIDLTest(parser, harness):
JsonTypes = [ "byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long",
"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",
"Uint16Array", "Uint32Array", "Uint8ClampedArray", "Float32Array", "Float64Array", "ArrayBuffer" ]
@ -129,9 +129,12 @@ def WebIDLTest(parser, harness):
doTest("interface Test { record<DOMString, %s> toJSON(); };" % type, False,
"record<DOMString, %s> should be a JSON type" % type)
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)
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,
"record<USVString, %s> should be a JSON type" % type)
@ -174,12 +177,12 @@ def WebIDLTest(parser, harness):
doTest("interface Test { record<USVString, %s> toJSON(); };" % type, True,
"record<USVString, %s> should not be a JSON type" % type)
if type != "any":
doTest("interface Foo { object toJSON(); }; "
"interface Test { (Foo or %s) toJSON(); };" % type, True,
"union containing a non-JSON type (%s) should not be a JSON type" % type)
doTest("interface test { %s? toJSON(); };" % type, True,
"Nullable type (%s) should not be a JSON type" % type)

View file

@ -5,8 +5,8 @@ patch < callback-location.patch
patch < union-typedef.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
mkdir tests
tar xvpf tests.tar.gz -C tests --strip-components=5
rm tests.tar.gz WebIDL.py.orig
unzip -d tests -j tests.zip
rm tests.zip WebIDL.py.orig