mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
Update the WebIDL parser
This commit is contained in:
parent
70a0174b0a
commit
2b574bbdf8
6 changed files with 284 additions and 108 deletions
|
@ -684,7 +684,7 @@ def globalNameSetToExposureSet(globalScope, nameSet, exposureSet):
|
||||||
|
|
||||||
class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||||
def __init__(self, location, parentScope, name, parent, members,
|
def __init__(self, location, parentScope, name, parent, members,
|
||||||
isKnownNonPartial):
|
isKnownNonPartial, toStringTag):
|
||||||
assert isinstance(parentScope, IDLScope)
|
assert isinstance(parentScope, IDLScope)
|
||||||
assert isinstance(name, IDLUnresolvedIdentifier)
|
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||||
assert isKnownNonPartial or not parent
|
assert isKnownNonPartial or not parent
|
||||||
|
@ -722,6 +722,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||||
# interface we're iterating for in order to get its nativeType.
|
# interface we're iterating for in order to get its nativeType.
|
||||||
self.iterableInterface = None
|
self.iterableInterface = None
|
||||||
|
|
||||||
|
self.toStringTag = toStringTag
|
||||||
|
|
||||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||||
IDLExposureMixins.__init__(self, location)
|
IDLExposureMixins.__init__(self, location)
|
||||||
|
|
||||||
|
@ -1017,10 +1019,9 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||||
[self.location])
|
[self.location])
|
||||||
|
|
||||||
for m in self.members:
|
for m in self.members:
|
||||||
if ((m.isMethod() and m.isJsonifier()) or
|
if m.identifier.name == "toJSON":
|
||||||
m.identifier.name == "toJSON"):
|
|
||||||
raise WebIDLError("Unforgeable interface %s has a "
|
raise WebIDLError("Unforgeable interface %s has a "
|
||||||
"jsonifier so we won't be able to add "
|
"toJSON so we won't be able to add "
|
||||||
"one ourselves" % self.identifier.name,
|
"one ourselves" % self.identifier.name,
|
||||||
[self.location, m.location])
|
[self.location, m.location])
|
||||||
|
|
||||||
|
@ -1044,6 +1045,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||||
(member.getExtendedAttribute("StoreInSlot") or
|
(member.getExtendedAttribute("StoreInSlot") or
|
||||||
member.getExtendedAttribute("Cached"))) or
|
member.getExtendedAttribute("Cached"))) or
|
||||||
member.isMaplikeOrSetlike()):
|
member.isMaplikeOrSetlike()):
|
||||||
|
if self.isJSImplemented() and not member.isMaplikeOrSetlike():
|
||||||
|
raise WebIDLError("Interface %s is JS-implemented and we "
|
||||||
|
"don't support [Cached] or [StoreInSlot] "
|
||||||
|
"on JS-implemented interfaces" %
|
||||||
|
self.identifier.name,
|
||||||
|
[self.location, member.location])
|
||||||
if member.slotIndices is None:
|
if member.slotIndices is None:
|
||||||
member.slotIndices = dict()
|
member.slotIndices = dict()
|
||||||
member.slotIndices[self.identifier.name] = self.totalMembersInSlots
|
member.slotIndices[self.identifier.name] = self.totalMembersInSlots
|
||||||
|
@ -1115,15 +1122,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||||
memberType = "deleters"
|
memberType = "deleters"
|
||||||
elif member.isStringifier():
|
elif member.isStringifier():
|
||||||
memberType = "stringifiers"
|
memberType = "stringifiers"
|
||||||
elif member.isJsonifier():
|
|
||||||
memberType = "jsonifiers"
|
|
||||||
elif member.isLegacycaller():
|
elif member.isLegacycaller():
|
||||||
memberType = "legacycallers"
|
memberType = "legacycallers"
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (memberType != "stringifiers" and memberType != "legacycallers" and
|
if (memberType != "stringifiers" and memberType != "legacycallers"):
|
||||||
memberType != "jsonifiers"):
|
|
||||||
if member.isNamed():
|
if member.isNamed():
|
||||||
memberType = "named " + memberType
|
memberType = "named " + memberType
|
||||||
else:
|
else:
|
||||||
|
@ -1573,9 +1577,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||||
|
|
||||||
class IDLInterface(IDLInterfaceOrNamespace):
|
class IDLInterface(IDLInterfaceOrNamespace):
|
||||||
def __init__(self, location, parentScope, name, parent, members,
|
def __init__(self, location, parentScope, name, parent, members,
|
||||||
isKnownNonPartial):
|
isKnownNonPartial, classNameOverride=None,
|
||||||
|
toStringTag=None):
|
||||||
IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
|
IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
|
||||||
parent, members, isKnownNonPartial)
|
parent, members, isKnownNonPartial,
|
||||||
|
toStringTag)
|
||||||
|
self.classNameOverride = classNameOverride
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Interface '%s'" % self.identifier.name
|
return "Interface '%s'" % self.identifier.name
|
||||||
|
@ -1583,6 +1590,11 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||||
def isInterface(self):
|
def isInterface(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def getClassName(self):
|
||||||
|
if self.classNameOverride:
|
||||||
|
return self.classNameOverride
|
||||||
|
return self.identifier.name
|
||||||
|
|
||||||
def addExtendedAttributes(self, attrs):
|
def addExtendedAttributes(self, attrs):
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
identifier = attr.identifier()
|
identifier = attr.identifier()
|
||||||
|
@ -1677,14 +1689,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||||
elif newMethod not in self.namedConstructors:
|
elif newMethod not in self.namedConstructors:
|
||||||
raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
|
raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
|
||||||
[method.location, newMethod.location])
|
[method.location, newMethod.location])
|
||||||
elif (identifier == "ArrayClass"):
|
|
||||||
if not attr.noArguments():
|
|
||||||
raise WebIDLError("[ArrayClass] must take no arguments",
|
|
||||||
[attr.location])
|
|
||||||
if self.parent:
|
|
||||||
raise WebIDLError("[ArrayClass] must not be specified on "
|
|
||||||
"an interface with inherited interfaces",
|
|
||||||
[attr.location, self.location])
|
|
||||||
elif (identifier == "ExceptionClass"):
|
elif (identifier == "ExceptionClass"):
|
||||||
if not attr.noArguments():
|
if not attr.noArguments():
|
||||||
raise WebIDLError("[ExceptionClass] must take no arguments",
|
raise WebIDLError("[ExceptionClass] must take no arguments",
|
||||||
|
@ -1738,6 +1742,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||||
identifier == "ProbablyShortLivingWrapper" or
|
identifier == "ProbablyShortLivingWrapper" or
|
||||||
identifier == "LegacyUnenumerableNamedProperties" or
|
identifier == "LegacyUnenumerableNamedProperties" or
|
||||||
identifier == "RunConstructorInCallerCompartment" or
|
identifier == "RunConstructorInCallerCompartment" or
|
||||||
|
identifier == "WantsEventListenerHooks" or
|
||||||
identifier == "NonOrdinaryGetPrototypeOf" or
|
identifier == "NonOrdinaryGetPrototypeOf" or
|
||||||
identifier == "Abstract" or
|
identifier == "Abstract" or
|
||||||
identifier == "Inline"):
|
identifier == "Inline"):
|
||||||
|
@ -1769,7 +1774,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||||
class IDLNamespace(IDLInterfaceOrNamespace):
|
class IDLNamespace(IDLInterfaceOrNamespace):
|
||||||
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
|
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
|
||||||
IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
|
IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
|
||||||
None, members, isKnownNonPartial)
|
None, members, isKnownNonPartial,
|
||||||
|
toStringTag=None)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Namespace '%s'" % self.identifier.name
|
return "Namespace '%s'" % self.identifier.name
|
||||||
|
@ -2152,7 +2158,7 @@ class IDLType(IDLObject):
|
||||||
# Should only call this on float types
|
# Should only call this on float types
|
||||||
assert self.isFloat()
|
assert self.isFloat()
|
||||||
|
|
||||||
def isSerializable(self):
|
def isJSONType(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def tag(self):
|
def tag(self):
|
||||||
|
@ -2350,8 +2356,8 @@ class IDLNullableType(IDLParametrizedType):
|
||||||
def isUnion(self):
|
def isUnion(self):
|
||||||
return self.inner.isUnion()
|
return self.inner.isUnion()
|
||||||
|
|
||||||
def isSerializable(self):
|
def isJSONType(self):
|
||||||
return self.inner.isSerializable()
|
return self.inner.isJSONType()
|
||||||
|
|
||||||
def tag(self):
|
def tag(self):
|
||||||
return self.inner.tag()
|
return self.inner.tag()
|
||||||
|
@ -2430,8 +2436,8 @@ class IDLSequenceType(IDLParametrizedType):
|
||||||
def isEnum(self):
|
def isEnum(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isSerializable(self):
|
def isJSONType(self):
|
||||||
return self.inner.isSerializable()
|
return self.inner.isJSONType()
|
||||||
|
|
||||||
def tag(self):
|
def tag(self):
|
||||||
return IDLType.Tags.sequence
|
return IDLType.Tags.sequence
|
||||||
|
@ -2476,6 +2482,9 @@ class IDLRecordType(IDLParametrizedType):
|
||||||
def isRecord(self):
|
def isRecord(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def isJSONType(self):
|
||||||
|
return self.inner.isJSONType()
|
||||||
|
|
||||||
def tag(self):
|
def tag(self):
|
||||||
return IDLType.Tags.record
|
return IDLType.Tags.record
|
||||||
|
|
||||||
|
@ -2525,8 +2534,8 @@ class IDLUnionType(IDLType):
|
||||||
def isUnion(self):
|
def isUnion(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isSerializable(self):
|
def isJSONType(self):
|
||||||
return all(m.isSerializable() for m in self.memberTypes)
|
return all(m.isJSONType() for m in self.memberTypes)
|
||||||
|
|
||||||
def includesRestrictedFloat(self):
|
def includesRestrictedFloat(self):
|
||||||
return any(t.includesRestrictedFloat() for t in self.memberTypes)
|
return any(t.includesRestrictedFloat() for t in self.memberTypes)
|
||||||
|
@ -2676,6 +2685,9 @@ class IDLTypedefType(IDLType):
|
||||||
def isVoid(self):
|
def isVoid(self):
|
||||||
return self.inner.isVoid()
|
return self.inner.isVoid()
|
||||||
|
|
||||||
|
def isJSONType(self):
|
||||||
|
return self.inner.isJSONType()
|
||||||
|
|
||||||
def isSequence(self):
|
def isSequence(self):
|
||||||
return self.inner.isSequence()
|
return self.inner.isSequence()
|
||||||
|
|
||||||
|
@ -2817,15 +2829,25 @@ class IDLWrapperType(IDLType):
|
||||||
def isEnum(self):
|
def isEnum(self):
|
||||||
return isinstance(self.inner, IDLEnum)
|
return isinstance(self.inner, IDLEnum)
|
||||||
|
|
||||||
def isSerializable(self):
|
def isJSONType(self):
|
||||||
if self.isInterface():
|
if self.isInterface():
|
||||||
if self.inner.isExternal():
|
if self.inner.isExternal():
|
||||||
return False
|
return False
|
||||||
return any(m.isMethod() and m.isJsonifier() for m in self.inner.members)
|
iface = self.inner
|
||||||
|
while iface:
|
||||||
|
if any(m.isMethod() and m.isToJSON() for m in iface.members):
|
||||||
|
return True
|
||||||
|
iface = iface.parent
|
||||||
|
return False
|
||||||
elif self.isEnum():
|
elif self.isEnum():
|
||||||
return True
|
return True
|
||||||
elif self.isDictionary():
|
elif self.isDictionary():
|
||||||
return all(m.type.isSerializable() for m in self.inner.members)
|
dictionary = self.inner
|
||||||
|
while dictionary:
|
||||||
|
if not all(m.type.isJSONType() for m in dictionary.members):
|
||||||
|
return False
|
||||||
|
dictionary = dictionary.parent
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
|
raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
|
||||||
"is serializable" % type(self.inner), [self.location])
|
"is serializable" % type(self.inner), [self.location])
|
||||||
|
@ -3111,8 +3133,8 @@ class IDLBuiltinType(IDLType):
|
||||||
return (self._typeTag == IDLBuiltinType.Types.unrestricted_float or
|
return (self._typeTag == IDLBuiltinType.Types.unrestricted_float or
|
||||||
self._typeTag == IDLBuiltinType.Types.unrestricted_double)
|
self._typeTag == IDLBuiltinType.Types.unrestricted_double)
|
||||||
|
|
||||||
def isSerializable(self):
|
def isJSONType(self):
|
||||||
return self.isPrimitive() or self.isString() or self.isDate()
|
return self.isPrimitive() or self.isString() or self.isObject()
|
||||||
|
|
||||||
def includesRestrictedFloat(self):
|
def includesRestrictedFloat(self):
|
||||||
return self.isFloat() and not self.isUnrestricted()
|
return self.isFloat() and not self.isUnrestricted()
|
||||||
|
@ -4665,7 +4687,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
def __init__(self, location, identifier, returnType, arguments,
|
def __init__(self, location, identifier, returnType, arguments,
|
||||||
static=False, getter=False, setter=False,
|
static=False, getter=False, setter=False,
|
||||||
deleter=False, specialType=NamedOrIndexed.Neither,
|
deleter=False, specialType=NamedOrIndexed.Neither,
|
||||||
legacycaller=False, stringifier=False, jsonifier=False,
|
legacycaller=False, stringifier=False,
|
||||||
maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
|
maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
|
||||||
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
|
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
|
||||||
IDLInterfaceMember.__init__(self, location, identifier,
|
IDLInterfaceMember.__init__(self, location, identifier,
|
||||||
|
@ -4690,8 +4712,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
self._legacycaller = legacycaller
|
self._legacycaller = legacycaller
|
||||||
assert isinstance(stringifier, bool)
|
assert isinstance(stringifier, bool)
|
||||||
self._stringifier = stringifier
|
self._stringifier = stringifier
|
||||||
assert isinstance(jsonifier, bool)
|
|
||||||
self._jsonifier = jsonifier
|
|
||||||
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
|
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
|
||||||
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
|
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
|
||||||
assert isinstance(htmlConstructor, bool)
|
assert isinstance(htmlConstructor, bool)
|
||||||
|
@ -4739,12 +4759,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
assert len(overload.arguments) == 0
|
assert len(overload.arguments) == 0
|
||||||
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
|
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
|
||||||
|
|
||||||
if self._jsonifier:
|
|
||||||
assert len(self._overloads) == 1
|
|
||||||
overload = self._overloads[0]
|
|
||||||
assert len(overload.arguments) == 0
|
|
||||||
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
|
|
||||||
|
|
||||||
def isStatic(self):
|
def isStatic(self):
|
||||||
return self._static
|
return self._static
|
||||||
|
|
||||||
|
@ -4776,8 +4790,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
def isStringifier(self):
|
def isStringifier(self):
|
||||||
return self._stringifier
|
return self._stringifier
|
||||||
|
|
||||||
def isJsonifier(self):
|
def isToJSON(self):
|
||||||
return self._jsonifier
|
return self.identifier.name == "toJSON"
|
||||||
|
|
||||||
|
def isDefaultToJSON(self):
|
||||||
|
return self.isToJSON() and self.getExtendedAttribute("Default")
|
||||||
|
|
||||||
def isMaplikeOrSetlikeOrIterableMethod(self):
|
def isMaplikeOrSetlikeOrIterableMethod(self):
|
||||||
"""
|
"""
|
||||||
|
@ -4791,8 +4808,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
self.isSetter() or
|
self.isSetter() or
|
||||||
self.isDeleter() or
|
self.isDeleter() or
|
||||||
self.isLegacycaller() or
|
self.isLegacycaller() or
|
||||||
self.isStringifier() or
|
self.isStringifier())
|
||||||
self.isJsonifier())
|
|
||||||
|
|
||||||
def isHTMLConstructor(self):
|
def isHTMLConstructor(self):
|
||||||
return self._htmlConstructor
|
return self._htmlConstructor
|
||||||
|
@ -4848,8 +4864,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
assert not method.isDeleter()
|
assert not method.isDeleter()
|
||||||
assert not self.isStringifier()
|
assert not self.isStringifier()
|
||||||
assert not method.isStringifier()
|
assert not method.isStringifier()
|
||||||
assert not self.isJsonifier()
|
|
||||||
assert not method.isJsonifier()
|
|
||||||
assert not self.isHTMLConstructor()
|
assert not self.isHTMLConstructor()
|
||||||
assert not method.isHTMLConstructor()
|
assert not method.isHTMLConstructor()
|
||||||
|
|
||||||
|
@ -4972,6 +4986,19 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
" methods on JS-implemented classes only.",
|
" methods on JS-implemented classes only.",
|
||||||
[self.location])
|
[self.location])
|
||||||
|
|
||||||
|
# Ensure that toJSON methods satisfy the spec constraints on them.
|
||||||
|
if self.identifier.name == "toJSON":
|
||||||
|
if len(self.signatures()) != 1:
|
||||||
|
raise WebIDLError("toJSON method has multiple overloads",
|
||||||
|
[self._overloads[0].location,
|
||||||
|
self._overloads[1].location])
|
||||||
|
if len(self.signatures()[0][1]) != 0:
|
||||||
|
raise WebIDLError("toJSON method has arguments",
|
||||||
|
[self.location])
|
||||||
|
if not self.signatures()[0][0].isJSONType():
|
||||||
|
raise WebIDLError("toJSON method has non-JSON return type",
|
||||||
|
[self.location])
|
||||||
|
|
||||||
def overloadsForArgCount(self, argc):
|
def overloadsForArgCount(self, argc):
|
||||||
return [overload for overload in self._overloads if
|
return [overload for overload in self._overloads if
|
||||||
len(overload.arguments) == argc or
|
len(overload.arguments) == argc or
|
||||||
|
@ -5105,6 +5132,19 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
raise WebIDLError("[CEReactions] is only allowed on operation, "
|
raise WebIDLError("[CEReactions] is only allowed on operation, "
|
||||||
"attribute, setter, and deleter",
|
"attribute, setter, and deleter",
|
||||||
[attr.location, self.location])
|
[attr.location, self.location])
|
||||||
|
elif identifier == "Default":
|
||||||
|
if not attr.noArguments():
|
||||||
|
raise WebIDLError("[Default] must take no arguments",
|
||||||
|
[attr.location])
|
||||||
|
|
||||||
|
if not self.isToJSON():
|
||||||
|
raise WebIDLError("[Default] is only allowed on toJSON operations",
|
||||||
|
[attr.location, self.location])
|
||||||
|
|
||||||
|
if self.signatures()[0][0] != BuiltinTypes[IDLBuiltinType.Types.object]:
|
||||||
|
raise WebIDLError("The return type of the default toJSON "
|
||||||
|
"operation must be 'object'",
|
||||||
|
[attr.location, self.location]);
|
||||||
elif (identifier == "Throws" or
|
elif (identifier == "Throws" or
|
||||||
identifier == "CanOOM" or
|
identifier == "CanOOM" or
|
||||||
identifier == "NewObject" or
|
identifier == "NewObject" or
|
||||||
|
@ -5292,7 +5332,6 @@ class Tokenizer(object):
|
||||||
"false": "FALSE",
|
"false": "FALSE",
|
||||||
"serializer": "SERIALIZER",
|
"serializer": "SERIALIZER",
|
||||||
"stringifier": "STRINGIFIER",
|
"stringifier": "STRINGIFIER",
|
||||||
"jsonifier": "JSONIFIER",
|
|
||||||
"unrestricted": "UNRESTRICTED",
|
"unrestricted": "UNRESTRICTED",
|
||||||
"attribute": "ATTRIBUTE",
|
"attribute": "ATTRIBUTE",
|
||||||
"readonly": "READONLY",
|
"readonly": "READONLY",
|
||||||
|
@ -6123,19 +6162,6 @@ class Parser(Tokenizer):
|
||||||
stringifier=True)
|
stringifier=True)
|
||||||
p[0] = method
|
p[0] = method
|
||||||
|
|
||||||
def p_Jsonifier(self, p):
|
|
||||||
"""
|
|
||||||
Operation : JSONIFIER SEMICOLON
|
|
||||||
"""
|
|
||||||
identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
|
||||||
"__jsonifier", allowDoubleUnderscore=True)
|
|
||||||
method = IDLMethod(self.getLocation(p, 1),
|
|
||||||
identifier,
|
|
||||||
returnType=BuiltinTypes[IDLBuiltinType.Types.object],
|
|
||||||
arguments=[],
|
|
||||||
jsonifier=True)
|
|
||||||
p[0] = method
|
|
||||||
|
|
||||||
def p_QualifierStatic(self, p):
|
def p_QualifierStatic(self, p):
|
||||||
"""
|
"""
|
||||||
Qualifier : STATIC
|
Qualifier : STATIC
|
||||||
|
@ -6289,7 +6315,6 @@ class Parser(Tokenizer):
|
||||||
| SETTER
|
| SETTER
|
||||||
| STATIC
|
| STATIC
|
||||||
| STRINGIFIER
|
| STRINGIFIER
|
||||||
| JSONIFIER
|
|
||||||
| TYPEDEF
|
| TYPEDEF
|
||||||
| UNRESTRICTED
|
| UNRESTRICTED
|
||||||
| NAMESPACE
|
| NAMESPACE
|
||||||
|
@ -6441,7 +6466,6 @@ class Parser(Tokenizer):
|
||||||
| SHORT
|
| SHORT
|
||||||
| STATIC
|
| STATIC
|
||||||
| STRINGIFIER
|
| STRINGIFIER
|
||||||
| JSONIFIER
|
|
||||||
| TRUE
|
| TRUE
|
||||||
| TYPEDEF
|
| TYPEDEF
|
||||||
| UNSIGNED
|
| UNSIGNED
|
||||||
|
@ -6958,9 +6982,12 @@ class Parser(Tokenizer):
|
||||||
nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")])
|
nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")])
|
||||||
itr_ident = IDLUnresolvedIdentifier(iface.location,
|
itr_ident = IDLUnresolvedIdentifier(iface.location,
|
||||||
iface.identifier.name + "Iterator")
|
iface.identifier.name + "Iterator")
|
||||||
|
toStringTag = iface.identifier.name + " Iterator"
|
||||||
itr_iface = IDLInterface(iface.location, self.globalScope(),
|
itr_iface = IDLInterface(iface.location, self.globalScope(),
|
||||||
itr_ident, None, [nextMethod],
|
itr_ident, None, [nextMethod],
|
||||||
isKnownNonPartial=True)
|
isKnownNonPartial=True,
|
||||||
|
classNameOverride=toStringTag,
|
||||||
|
toStringTag=toStringTag)
|
||||||
itr_iface.addExtendedAttributes([simpleExtendedAttr("NoInterfaceObject")])
|
itr_iface.addExtendedAttributes([simpleExtendedAttr("NoInterfaceObject")])
|
||||||
# Make sure the exposure set for the iterator interface is the
|
# Make sure the exposure set for the iterator interface is the
|
||||||
# same as the exposure set for the iterable interface, because
|
# same as the exposure set for the iterable interface, because
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
--- WebIDL.py
|
--- WebIDL.py
|
||||||
+++ WebIDL.py
|
+++ WebIDL.py
|
||||||
@@ -1744,7 +1744,8 @@
|
@@ -1744,7 +1744,8 @@
|
||||||
identifier == "ProbablyShortLivingWrapper" or
|
|
||||||
identifier == "LegacyUnenumerableNamedProperties" or
|
identifier == "LegacyUnenumerableNamedProperties" or
|
||||||
identifier == "RunConstructorInCallerCompartment" or
|
identifier == "RunConstructorInCallerCompartment" or
|
||||||
|
identifier == "WantsEventListenerHooks" or
|
||||||
- identifier == "NonOrdinaryGetPrototypeOf"):
|
- identifier == "NonOrdinaryGetPrototypeOf"):
|
||||||
+ identifier == "NonOrdinaryGetPrototypeOf" or
|
+ identifier == "NonOrdinaryGetPrototypeOf" or
|
||||||
+ identifier == "Abstract"):
|
+ identifier == "Abstract"):
|
||||||
|
|
|
@ -131,17 +131,3 @@ def WebIDLTest(parser, harness):
|
||||||
harness.ok(threw,
|
harness.ok(threw,
|
||||||
"Should have thrown for [CEReactions] used on a stringifier")
|
"Should have thrown for [CEReactions] used on a stringifier")
|
||||||
|
|
||||||
parser = parser.reset()
|
|
||||||
threw = False
|
|
||||||
try:
|
|
||||||
parser.parse("""
|
|
||||||
interface Foo {
|
|
||||||
[CEReactions] jsonifier;
|
|
||||||
};
|
|
||||||
""")
|
|
||||||
|
|
||||||
results = parser.finish()
|
|
||||||
except:
|
|
||||||
threw = True
|
|
||||||
|
|
||||||
harness.ok(threw, "Should have thrown for [CEReactions] used on a jsonifier")
|
|
||||||
|
|
|
@ -374,32 +374,3 @@ def WebIDLTest(parser, harness):
|
||||||
threw = True
|
threw = True
|
||||||
harness.ok(threw,
|
harness.ok(threw,
|
||||||
"Should not allow unknown extended attributes on interfaces")
|
"Should not allow unknown extended attributes on interfaces")
|
||||||
|
|
||||||
parser = parser.reset()
|
|
||||||
threw = False
|
|
||||||
try:
|
|
||||||
parser.parse("""
|
|
||||||
interface B {};
|
|
||||||
[ArrayClass]
|
|
||||||
interface A : B {
|
|
||||||
};
|
|
||||||
""")
|
|
||||||
results = parser.finish()
|
|
||||||
except:
|
|
||||||
threw = True
|
|
||||||
harness.ok(threw,
|
|
||||||
"Should not allow [ArrayClass] on interfaces with parents")
|
|
||||||
|
|
||||||
parser = parser.reset()
|
|
||||||
threw = False
|
|
||||||
try:
|
|
||||||
parser.parse("""
|
|
||||||
[ArrayClass]
|
|
||||||
interface A {
|
|
||||||
};
|
|
||||||
""")
|
|
||||||
results = parser.finish()
|
|
||||||
except:
|
|
||||||
threw = True
|
|
||||||
harness.ok(not threw,
|
|
||||||
"Should allow [ArrayClass] on interfaces without parents")
|
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(
|
||||||
|
"""
|
||||||
|
interface Test {
|
||||||
|
object toJSON();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(not threw, "Should allow a toJSON method.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(
|
||||||
|
"""
|
||||||
|
interface Test {
|
||||||
|
object toJSON(object arg);
|
||||||
|
object toJSON(long arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should not allow overloads of a toJSON method.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(
|
||||||
|
"""
|
||||||
|
interface Test {
|
||||||
|
object toJSON(object arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should not allow a toJSON method with arguments.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(
|
||||||
|
"""
|
||||||
|
interface Test {
|
||||||
|
long toJSON();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(not threw, "Should allow a toJSON method with 'long' as return type.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(
|
||||||
|
"""
|
||||||
|
interface Test {
|
||||||
|
[Default] object toJSON();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(not threw, "Should allow a default toJSON method with 'object' as return type.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(
|
||||||
|
"""
|
||||||
|
interface Test {
|
||||||
|
[Default] long toJSON();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should not allow a default toJSON method with non-'object' as return type.")
|
||||||
|
|
||||||
|
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" ]
|
||||||
|
|
||||||
|
nonJsonTypes = [ "InterfaceWithoutToJSON", "any", "Int8Array", "Int16Array", "Int32Array","Uint8Array",
|
||||||
|
"Uint16Array", "Uint32Array", "Uint8ClampedArray", "Float32Array", "Float64Array", "ArrayBuffer" ]
|
||||||
|
|
||||||
|
def doTest(testIDL, shouldThrow, description):
|
||||||
|
p = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
p.parse(testIDL +
|
||||||
|
"""
|
||||||
|
enum Enum { "a", "b", "c" };
|
||||||
|
interface InterfaceWithToJSON { long toJSON(); };
|
||||||
|
interface InterfaceWithoutToJSON {};
|
||||||
|
""");
|
||||||
|
p.finish();
|
||||||
|
except Exception as x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(x.message == "toJSON method has non-JSON return type", x)
|
||||||
|
harness.check(threw, shouldThrow, description)
|
||||||
|
|
||||||
|
|
||||||
|
for type in JsonTypes:
|
||||||
|
doTest("interface Test { %s toJSON(); };" % type, False,
|
||||||
|
"%s should be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("interface Test { sequence<%s> toJSON(); };" % type, False,
|
||||||
|
"sequence<%s> should be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("dictionary Foo { %s foo; }; "
|
||||||
|
"interface Test { Foo toJSON(); }; " % type, False,
|
||||||
|
"dictionary containing only JSON type (%s) should be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
|
||||||
|
"interface Test { Bar toJSON(); }; " % type, False,
|
||||||
|
"dictionary whose ancestors only contain JSON types should be a JSON type")
|
||||||
|
|
||||||
|
doTest("dictionary Foo { any foo; }; dictionary Bar : Foo { %s bar; };"
|
||||||
|
"interface Test { Bar toJSON(); };" % type, True,
|
||||||
|
"dictionary whose ancestors contain non-JSON types should not be a JSON type")
|
||||||
|
|
||||||
|
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,
|
||||||
|
"record<ByteString, %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)
|
||||||
|
|
||||||
|
otherUnionType = "Foo" if type != "object" else "long"
|
||||||
|
doTest("interface Foo { object toJSON(); };"
|
||||||
|
"interface Test { (%s or %s) toJSON(); };" % (otherUnionType, type), False,
|
||||||
|
"union containing only JSON types (%s or %s) should be a JSON type" %(otherUnionType, type))
|
||||||
|
|
||||||
|
doTest("interface test { %s? toJSON(); };" % type, False,
|
||||||
|
"Nullable type (%s) should be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("interface Foo : InterfaceWithoutToJSON { %s toJSON(); };"
|
||||||
|
"interface Test { Foo toJSON(); };" % type, False,
|
||||||
|
"interface with toJSON should be a JSON type")
|
||||||
|
|
||||||
|
doTest("interface Foo : InterfaceWithToJSON { };"
|
||||||
|
"interface Test { Foo toJSON(); };", False,
|
||||||
|
"inherited interface with toJSON should be a JSON type")
|
||||||
|
|
||||||
|
for type in nonJsonTypes:
|
||||||
|
doTest("interface Test { %s toJSON(); };" % type, True,
|
||||||
|
"%s should not be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("interface Test { sequence<%s> toJSON(); };" % type, True,
|
||||||
|
"sequence<%s> should not be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("dictionary Foo { %s foo; }; "
|
||||||
|
"interface Test { Foo toJSON(); }; " % type, True,
|
||||||
|
"Dictionary containing a non-JSON type (%s) should not be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
|
||||||
|
"interface Test { Bar toJSON(); }; " % type, True,
|
||||||
|
"dictionary whose ancestors only contain non-JSON types should not be a JSON type")
|
||||||
|
|
||||||
|
doTest("interface Test { record<DOMString, %s> toJSON(); };" % type, True,
|
||||||
|
"record<DOMString, %s> should not be a JSON type" % type)
|
||||||
|
|
||||||
|
doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, True,
|
||||||
|
"record<ByteString, %s> should not be a JSON type" % type)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
doTest("dictionary Foo { long foo; any bar; };"
|
||||||
|
"interface Test { Foo toJSON(); };", True,
|
||||||
|
"dictionary containing a non-JSON type should not be a JSON type")
|
||||||
|
|
||||||
|
doTest("interface Foo : InterfaceWithoutToJSON { }; "
|
||||||
|
"interface Test { Foo toJSON(); };", True,
|
||||||
|
"interface without toJSON should not be a JSON type")
|
Loading…
Add table
Add a link
Reference in a new issue