Sync WebIDL.py with gecko

This commit is contained in:
Kagami Sascha Rosylight 2019-07-11 13:16:10 +09:00
parent 5fdc7c0d2c
commit 56f31c85ef
35 changed files with 727 additions and 221 deletions

View file

@ -1,16 +1,18 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
""" A WebIDL parser. """
from __future__ import print_function
from ply import lex, yacc
import re
import os
import traceback
import math
import string
from collections import defaultdict
from collections import defaultdict, OrderedDict
from itertools import chain
# Machinery
@ -40,32 +42,22 @@ def parseInt(literal):
return value * sign
# Magic for creating enums
def M_add_class_attribs(attribs, start):
def foo(name, bases, dict_):
for v, k in enumerate(attribs):
dict_[k] = start + v
assert 'length' not in dict_
dict_['length'] = start + len(attribs)
return type(name, bases, dict_)
return foo
def enum(*names, **kw):
if len(kw) == 1:
base = kw['base'].__class__
start = base.length
else:
assert len(kw) == 0
base = object
start = 0
class Foo(base):
__metaclass__ = M_add_class_attribs(names, start)
class Foo(object):
attrs = OrderedDict()
def __init__(self, names):
for v, k in enumerate(names):
self.attrs[k] = v
def __getattr__(self, attr):
if attr in self.attrs:
return self.attrs[attr]
raise AttributeError
def __setattr__(self, name, value): # this makes it read-only
raise NotImplementedError
return Foo()
if "base" not in kw:
return Foo(names)
return Foo(chain(kw["base"].attrs.keys(), names))
class WebIDLError(Exception):
@ -482,9 +474,6 @@ class IDLExposureMixins():
def isExposedOnMainThread(self):
return self.isExposedInWindow()
def isExposedOffMainThread(self):
return len(self.exposureSet - {'Window', 'FakeTestPrimaryGlobal'}) > 0
def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0
@ -568,6 +557,9 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def isNavigatorProperty(self):
return False
def isSerializable(self):
return False
def _getDependentObjects(self):
return set()
@ -704,6 +696,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# outputs the constructs in the order that namedConstructors enumerates
# them.
self.namedConstructors = list()
self.legacyWindowAliases = []
self.implementedInterfaces = set()
self._consequential = False
self._isKnownNonPartial = False
@ -774,6 +767,16 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
IDLExposureMixins.finish(self, scope)
if len(self.legacyWindowAliases) > 0:
if not self.hasInterfaceObject():
raise WebIDLError("Interface %s unexpectedly has [LegacyWindowAlias] "
"and [NoInterfaceObject] together" % self.identifier.name,
[self.location])
if not self.isExposedInWindow():
raise WebIDLError("Interface %s has [LegacyWindowAlias] "
"but not exposed in Window" % self.identifier.name,
[self.location])
# Now go ahead and merge in our partial interfaces.
for partial in self._partialInterfaces:
partial.finish(scope)
@ -962,7 +965,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# self.members. Sort our consequential interfaces by name
# just so we have a consistent order.
for iface in sorted(self.getConsequentialInterfaces(),
cmp=cmp,
key=lambda x: x.identifier.name):
# Flag the interface as being someone's consequential interface
iface.setIsConsequentialInterfaceOf(self)
@ -1325,6 +1327,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
for bindingAlias in member.bindingAliases:
checkDuplicateNames(member, bindingAlias, "BindingAlias")
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object,
@ -1640,6 +1643,11 @@ class IDLInterface(IDLInterfaceOrNamespace):
raise WebIDLError(str(identifier) + " must take no arguments",
[attr.location])
if self.globalNames:
raise WebIDLError("[%s] must not be specified together with "
"[Global]" % identifier,
[self.location, attr.location])
args = attr.args() if attr.hasArgs() else []
retType = IDLWrapperType(self.location, self)
@ -1700,6 +1708,10 @@ class IDLInterface(IDLInterfaceOrNamespace):
"an interface with inherited interfaces",
[attr.location, self.location])
elif identifier == "Global":
if self.ctor() or self.namedConstructors:
raise WebIDLError("[Global] cannot be specified on an "
"interface with a constructor",
[attr.location, self.location]);
if attr.hasValue():
self.globalNames = [attr.value()]
elif attr.hasArgs():
@ -1723,6 +1735,18 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.parentScope.addIfaceGlobalNames(self.identifier.name,
[self.identifier.name])
self._isOnGlobalProtoChain = True
elif identifier == "LegacyWindowAlias":
if attr.hasValue():
self.legacyWindowAliases = [attr.value()]
elif attr.hasArgs():
self.legacyWindowAliases = attr.args()
else:
raise WebIDLError("[%s] must either take an identifier "
"or take an identifier list" % identifier,
[attr.location])
for alias in self.legacyWindowAliases:
unresolved = IDLUnresolvedIdentifier(attr.location, alias)
IDLObjectWithIdentifier(attr.location, self.parentScope, unresolved)
elif identifier == "SecureContext":
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
@ -1744,6 +1768,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
identifier == "Serializable" or
identifier == "Abstract" or
identifier == "Inline"):
# Known extended attributes that do not take values
@ -1770,6 +1795,19 @@ class IDLInterface(IDLInterfaceOrNamespace):
attrlist = attr.listValue()
self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
def validate(self):
IDLInterfaceOrNamespace.validate(self)
if self.parent and self.isSerializable() and not self.parent.isSerializable():
raise WebIDLError(
"Serializable interface inherits from non-serializable "
"interface. Per spec, that means the object should not be "
"serializable, so chances are someone made a mistake here "
"somewhere.",
[self.location, self.parent.location])
def isSerializable(self):
return self.getExtendedAttribute("Serializable")
class IDLNamespace(IDLInterfaceOrNamespace):
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
@ -1805,7 +1843,9 @@ class IDLNamespace(IDLInterfaceOrNamespace):
if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location])
elif identifier == "Pref" or identifier == "Func":
elif (identifier == "Pref" or
identifier == "HeaderFile" or
identifier == "Func"):
# Known extended attributes that take a string value
if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier,
@ -1818,6 +1858,9 @@ class IDLNamespace(IDLInterfaceOrNamespace):
attrlist = attr.listValue()
self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
def isSerializable(self):
return False
class IDLDictionary(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members):
@ -1877,7 +1920,7 @@ class IDLDictionary(IDLObjectWithScope):
assert member.type.isComplete()
# Members of a dictionary are sorted in lexicographic order
self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
self.members.sort(key=lambda x: x.identifier.name)
inheritedMembers = []
ancestor = self.parent
@ -2232,7 +2275,7 @@ class IDLUnresolvedType(IDLType):
assert obj
if obj.isType():
print obj
print(obj)
assert not obj.isType()
if obj.isTypedef():
assert self.name.name == obj.identifier.name
@ -3562,8 +3605,6 @@ class IDLNullValue(IDLObject):
def coerceToType(self, type, location):
if (not isinstance(type, IDLNullableType) and
not (type.isUnion() and type.hasNullableType) and
not (type.isUnion() and type.hasDictionaryType()) and
not type.isDictionary() and
not type.isAny()):
raise WebIDLError("Cannot coerce null value to type %s." % type,
[location])
@ -3612,6 +3653,35 @@ class IDLEmptySequenceValue(IDLObject):
return set()
class IDLDefaultDictionaryValue(IDLObject):
def __init__(self, location):
IDLObject.__init__(self, location)
self.type = None
self.value = None
def coerceToType(self, type, location):
if type.isUnion():
# We use the flat member types here, because if we have a nullable
# member type, or a nested union, we want the type the value
# actually coerces to, not the nullable or nested union type.
for subtype in type.unroll().flatMemberTypes:
try:
return self.coerceToType(subtype, location)
except:
pass
if not type.isDictionary():
raise WebIDLError("Cannot coerce default dictionary value to type %s." % type,
[location])
defaultDictionaryValue = IDLDefaultDictionaryValue(self.location)
defaultDictionaryValue.type = type
return defaultDictionaryValue
def _getDependentObjects(self):
return set()
class IDLUndefinedValue(IDLObject):
def __init__(self, location):
IDLObject.__init__(self, location)
@ -3689,7 +3759,7 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
def finish(self, scope):
# We better be exposed _somewhere_.
if (len(self._exposureGlobalNames) == 0):
print self.identifier.name
print(self.identifier.name)
assert len(self._exposureGlobalNames) != 0
IDLExposureMixins.finish(self, scope)
@ -4577,7 +4647,9 @@ class IDLArgument(IDLObjectWithIdentifier):
elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True
elif (self.dictionaryMember and
(identifier == "ChromeOnly" or identifier == "Func")):
(identifier == "ChromeOnly" or
identifier == "Func" or
identifier == "Pref")):
if not self.optional:
raise WebIDLError("[%s] must not be used on a required "
"dictionary member" % identifier,
@ -4609,14 +4681,7 @@ class IDLArgument(IDLObjectWithIdentifier):
assert not isinstance(type.name, IDLUnresolvedIdentifier)
self.type = type
if ((self.type.isDictionary() or
self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
self.optional and not self.defaultValue and not self.variadic and
not self.dictionaryMember):
# Default optional non-variadic dictionary arguments to null,
# for simplicity, so the codegen doesn't have to special-case this.
self.defaultValue = IDLNullValue(self.location)
elif self.type.isAny():
if self.type.isAny():
assert (self.defaultValue is None or
isinstance(self.defaultValue, IDLNullValue))
# optional 'any' values always have a default value
@ -4648,7 +4713,7 @@ class IDLArgument(IDLObjectWithIdentifier):
class IDLCallback(IDLObjectWithScope):
def __init__(self, location, parentScope, identifier, returnType, arguments):
def __init__(self, location, parentScope, identifier, returnType, arguments, isConstructor):
assert isinstance(returnType, IDLType)
self._returnType = returnType
@ -4663,10 +4728,15 @@ class IDLCallback(IDLObjectWithScope):
self._treatNonCallableAsNull = False
self._treatNonObjectAsNull = False
self._isRunScriptBoundary = False
self._isConstructor = isConstructor
def isCallback(self):
return True
def isConstructor(self):
return self._isConstructor
def signatures(self):
return [(self._returnType, self._arguments)]
@ -4699,7 +4769,16 @@ class IDLCallback(IDLObjectWithScope):
if attr.identifier() == "TreatNonCallableAsNull":
self._treatNonCallableAsNull = True
elif attr.identifier() == "TreatNonObjectAsNull":
if self._isConstructor:
raise WebIDLError("[TreatNonObjectAsNull] is not supported "
"on constructors", [self.location])
self._treatNonObjectAsNull = True
elif attr.identifier() == "MOZ_CAN_RUN_SCRIPT_BOUNDARY":
if self._isConstructor:
raise WebIDLError("[MOZ_CAN_RUN_SCRIPT_BOUNDARY] is not "
"permitted on constructors",
[self.location])
self._isRunScriptBoundary = True
else:
unhandledAttrs.append(attr)
if self._treatNonCallableAsNull and self._treatNonObjectAsNull:
@ -4711,6 +4790,9 @@ class IDLCallback(IDLObjectWithScope):
def _getDependentObjects(self):
return set([self._returnType] + self._arguments)
def isRunScriptBoundary(self):
return self._isRunScriptBoundary;
class IDLCallbackType(IDLType):
def __init__(self, location, callback):
@ -4757,6 +4839,9 @@ class IDLMethodOverload:
deps.add(self.returnType)
return deps
def includesRestrictedFloatArgument(self):
return any(arg.type.includesRestrictedFloat() for arg in self.arguments)
class IDLMethod(IDLInterfaceMember, IDLScope):
@ -4928,10 +5013,25 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def addOverload(self, method):
assert len(method._overloads) == 1
if self._extendedAttrDict != method ._extendedAttrDict:
raise WebIDLError("Extended attributes differ on different "
"overloads of %s" % method.identifier,
[self.location, method.location])
if self._extendedAttrDict != method._extendedAttrDict:
extendedAttrDiff = set(self._extendedAttrDict.keys()) ^ set(method._extendedAttrDict.keys())
if extendedAttrDiff == { "LenientFloat" }:
if "LenientFloat" not in self._extendedAttrDict:
for overload in self._overloads:
if overload.includesRestrictedFloatArgument():
raise WebIDLError("Restricted float behavior differs on different "
"overloads of %s" % method.identifier,
[overload.location, method.location])
self._extendedAttrDict["LenientFloat"] = method._extendedAttrDict["LenientFloat"]
elif method._overloads[0].includesRestrictedFloatArgument():
raise WebIDLError("Restricted float behavior differs on different "
"overloads of %s" % method.identifier,
[self.location, method.location])
else:
raise WebIDLError("Extended attributes differ on different "
"overloads of %s" % method.identifier,
[self.location, method.location])
self._overloads.extend(method._overloads)
@ -5039,6 +5139,15 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
"must be optional",
[argument.location])
if (not argument.defaultValue and
all(arg.optional for arg in arguments[idx+1:])):
raise WebIDLError("Dictionary argument without any "
"required fields or union argument "
"containing such dictionary not "
"followed by a required argument "
"must have a default value",
[argument.location])
# An argument cannot be a Nullable Dictionary
if argument.type.nullable():
raise WebIDLError("An argument cannot be a nullable "
@ -5162,12 +5271,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
[attr.location, self.location])
elif identifier == "LenientFloat":
# This is called before we've done overload resolution
assert len(self.signatures()) == 1
sig = self.signatures()[0]
if not sig[0].isVoid():
overloads = self._overloads
assert len(overloads) == 1
if not overloads[0].returnType.isVoid():
raise WebIDLError("[LenientFloat] used on a non-void method",
[attr.location, self.location])
if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
if not overloads[0].includesRestrictedFloatArgument():
raise WebIDLError("[LenientFloat] used on an operation with no "
"restricted float type arguments",
[attr.location, self.location])
@ -5238,7 +5347,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
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]);
[attr.location, self.location])
elif (identifier == "Throws" or
identifier == "CanOOM" or
identifier == "NewObject" or
@ -5251,7 +5360,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "NeedsSubjectPrincipal" or
identifier == "NeedsCallerType" or
identifier == "StaticClassOverride" or
identifier == "NonEnumerable"):
identifier == "NonEnumerable" or
identifier == "Unexposed"):
# Known attributes that we don't need to do anything with here
pass
else:
@ -5478,6 +5588,7 @@ class Tokenizer(object):
"iterable": "ITERABLE",
"namespace": "NAMESPACE",
"ReadableStream": "READABLESTREAM",
"constructor": "CONSTRUCTOR",
}
tokens.extend(keywords.values())
@ -5604,6 +5715,7 @@ class Parser(Tokenizer):
def p_CallbackRestOrInterface(self, p):
"""
CallbackRestOrInterface : CallbackRest
| CallbackConstructorRest
| Interface
"""
assert p[1]
@ -5637,7 +5749,7 @@ class Parser(Tokenizer):
[location, existingObj.location])
existingObj.setNonPartial(*nonPartialArgs)
return existingObj
except Exception, ex:
except Exception as ex:
if isinstance(ex, WebIDLError):
raise ex
pass
@ -5675,7 +5787,7 @@ class Parser(Tokenizer):
"%s and %s" % (identifier.name, p[0]),
[location, p[0].location])
return
except Exception, ex:
except Exception as ex:
if isinstance(ex, WebIDLError):
raise ex
pass
@ -5739,7 +5851,7 @@ class Parser(Tokenizer):
"non-%s object" %
(prettyname, prettyname),
[location, nonPartialObject.location])
except Exception, ex:
except Exception as ex:
if isinstance(ex, WebIDLError):
raise ex
pass
@ -5905,12 +6017,23 @@ class Parser(Tokenizer):
"""
DefaultValue : ConstValue
| LBRACKET RBRACKET
| LBRACE RBRACE
"""
if len(p) == 2:
p[0] = p[1]
else:
assert len(p) == 3 # Must be []
p[0] = IDLEmptySequenceValue(self.getLocation(p, 1))
assert len(p) == 3 # Must be [] or {}
if p[1] == "[":
p[0] = IDLEmptySequenceValue(self.getLocation(p, 1))
else:
assert p[1] == "{"
p[0] = IDLDefaultDictionaryValue(self.getLocation(p, 1))
def p_DefaultValueNull(self, p):
"""
DefaultValue : NULL
"""
p[0] = IDLNullValue(self.getLocation(p, 1))
def p_Exception(self, p):
"""
@ -5967,7 +6090,15 @@ class Parser(Tokenizer):
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
p[0] = IDLCallback(self.getLocation(p, 1), self.globalScope(),
identifier, p[3], p[5])
identifier, p[3], p[5], isConstructor=False)
def p_CallbackConstructorRest(self, p):
"""
CallbackConstructorRest : CONSTRUCTOR IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
p[0] = IDLCallback(self.getLocation(p, 2), self.globalScope(),
identifier, p[4], p[6], isConstructor=True)
def p_ExceptionMembers(self, p):
"""
@ -6041,12 +6172,6 @@ class Parser(Tokenizer):
stringType = BuiltinTypes[IDLBuiltinType.Types.domstring]
p[0] = IDLValue(location, stringType, p[1])
def p_ConstValueNull(self, p):
"""
ConstValue : NULL
"""
p[0] = IDLNullValue(self.getLocation(p, 1))
def p_BooleanLiteralTrue(self, p):
"""
BooleanLiteral : TRUE
@ -6442,6 +6567,7 @@ class Parser(Tokenizer):
| ATTRIBUTE
| CALLBACK
| CONST
| CONSTRUCTOR
| DELETER
| DICTIONARY
| ENUM
@ -6566,6 +6692,7 @@ class Parser(Tokenizer):
| BYTE
| LEGACYCALLER
| CONST
| CONSTRUCTOR
| DELETER
| DOUBLE
| EXCEPTION
@ -6619,9 +6746,9 @@ class Parser(Tokenizer):
"""
p[0] = p[2].withExtendedAttributes(p[1])
def p_SingleTypeNonAnyType(self, p):
def p_SingleTypeDistinguishableType(self, p):
"""
SingleType : NonAnyType
SingleType : DistinguishableType
"""
p[0] = p[1]
@ -6631,6 +6758,14 @@ class Parser(Tokenizer):
"""
p[0] = BuiltinTypes[IDLBuiltinType.Types.any]
# Note: Promise<void> is allowed, so we want to parametrize on ReturnType,
# not Type. Promise types can't be null, hence no "Null" in there.
def p_SingleTypePromiseType(self, p):
"""
SingleType : PROMISE LT ReturnType GT
"""
p[0] = IDLPromiseType(self.getLocation(p, 1), p[3])
def p_UnionType(self, p):
"""
UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN
@ -6639,9 +6774,9 @@ class Parser(Tokenizer):
types.extend(p[5])
p[0] = IDLUnionType(self.getLocation(p, 1), types)
def p_UnionMemberTypeNonAnyType(self, p):
def p_UnionMemberTypeDistinguishableType(self, p):
"""
UnionMemberType : ExtendedAttributeList NonAnyType
UnionMemberType : ExtendedAttributeList DistinguishableType
"""
p[0] = p[2].withExtendedAttributes(p[1])
@ -6664,13 +6799,13 @@ class Parser(Tokenizer):
"""
p[0] = []
def p_NonAnyType(self, p):
def p_DistinguishableType(self, p):
"""
NonAnyType : PrimitiveType Null
| ARRAYBUFFER Null
| SHAREDARRAYBUFFER Null
| READABLESTREAM Null
| OBJECT Null
DistinguishableType : PrimitiveType Null
| ARRAYBUFFER Null
| SHAREDARRAYBUFFER Null
| READABLESTREAM Null
| OBJECT Null
"""
if p[1] == "object":
type = BuiltinTypes[IDLBuiltinType.Types.object]
@ -6685,40 +6820,32 @@ class Parser(Tokenizer):
p[0] = self.handleNullable(type, p[2])
def p_NonAnyTypeStringType(self, p):
def p_DistinguishableTypeStringType(self, p):
"""
NonAnyType : StringType Null
DistinguishableType : StringType Null
"""
p[0] = self.handleNullable(p[1], p[2])
def p_NonAnyTypeSequenceType(self, p):
def p_DistinguishableTypeSequenceType(self, p):
"""
NonAnyType : SEQUENCE LT TypeWithExtendedAttributes GT Null
DistinguishableType : SEQUENCE LT TypeWithExtendedAttributes GT Null
"""
innerType = p[3]
type = IDLSequenceType(self.getLocation(p, 1), innerType)
p[0] = self.handleNullable(type, p[5])
# Note: Promise<void> is allowed, so we want to parametrize on ReturnType,
# not Type. Promise types can't be null, hence no "Null" in there.
def p_NonAnyTypePromiseType(self, p):
def p_DistinguishableTypeRecordType(self, p):
"""
NonAnyType : PROMISE LT ReturnType GT
"""
p[0] = IDLPromiseType(self.getLocation(p, 1), p[3])
def p_NonAnyTypeRecordType(self, p):
"""
NonAnyType : RECORD LT StringType COMMA TypeWithExtendedAttributes GT Null
DistinguishableType : RECORD LT StringType COMMA TypeWithExtendedAttributes GT Null
"""
keyType = p[3]
valueType = p[5]
type = IDLRecordType(self.getLocation(p, 1), keyType, valueType)
p[0] = self.handleNullable(type, p[7])
def p_NonAnyTypeScopedName(self, p):
def p_DistinguishableTypeScopedName(self, p):
"""
NonAnyType : ScopedName Null
DistinguishableType : ScopedName Null
"""
assert isinstance(p[1], IDLUnresolvedIdentifier)
@ -6748,28 +6875,26 @@ class Parser(Tokenizer):
type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
p[0] = self.handleNullable(type, p[2])
def p_NonAnyTypeDate(self, p):
def p_DistinguishableTypeDate(self, p):
"""
NonAnyType : DATE Null
DistinguishableType : DATE Null
"""
p[0] = self.handleNullable(BuiltinTypes[IDLBuiltinType.Types.date],
p[2])
def p_ConstType(self, p):
"""
ConstType : PrimitiveType Null
ConstType : PrimitiveType
"""
type = BuiltinTypes[p[1]]
p[0] = self.handleNullable(type, p[2])
p[0] = BuiltinTypes[p[1]]
def p_ConstTypeIdentifier(self, p):
"""
ConstType : IDENTIFIER Null
ConstType : IDENTIFIER
"""
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
p[0] = self.handleNullable(type, p[2])
p[0] = IDLUnresolvedType(self.getLocation(p, 1), identifier)
def p_PrimitiveTypeUint(self, p):
"""
@ -7040,8 +7165,8 @@ class Parser(Tokenizer):
def _installBuiltins(self, scope):
assert isinstance(scope, IDLScope)
# xrange omits the last value.
for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
# range omits the last value.
for x in range(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
builtin = BuiltinTypes[x]
name = builtin.name
typedef = IDLTypedef(BuiltinLocation("<builtin type>"), scope, builtin, name)
@ -7185,14 +7310,14 @@ def main():
f = open(fullPath, 'rb')
lines = f.readlines()
f.close()
print fullPath
print(fullPath)
parser.parse(''.join(lines), fullPath)
parser.finish()
except WebIDLError, e:
except WebIDLError as e:
if options.verbose_errors:
traceback.print_exc()
else:
print e
print(e)
if __name__ == '__main__':
main()

View file

@ -1,12 +1,12 @@
--- WebIDL.py
+++ WebIDL.py
@@ -1786,7 +1786,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "ProbablyShortLivingWrapper" or
@@ -1768,7 +1768,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
- identifier == "WantsEventListenerHooks"):
+ identifier == "WantsEventListenerHooks" or
identifier == "WantsEventListenerHooks" or
- identifier == "Serializable"):
+ identifier == "Serializable" or
+ identifier == "Abstract"):
# Known extended attributes that do not take values
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
raise WebIDLError("[%s] must take no arguments" % identifier,

View file

@ -1,7 +1,7 @@
--- WebIDL.py
+++ WebIDL.py
@@ -2275,7 +2275,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope)
@@ -2283,7 +2283,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope).withExtendedAttributes(self.extraTypeAttributes)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj)
@ -9,7 +9,7 @@
name = self.name.resolve(scope, None)
return IDLWrapperType(self.location, obj)
@@ -6688,7 +6688,7 @@ class Parser(Tokenizer):
@@ -6854,7 +6854,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():

View file

@ -1,6 +1,6 @@
--- WebIDL.py
+++ WebIDL.py
@@ -6959,7 +6959,8 @@ class Parser(Tokenizer):
@@ -7123,7 +7123,8 @@ class Parser(Tokenizer):
self.parser = yacc.yacc(module=self,
outputdir=outputdir,
tabmodule='webidlyacc',

View file

@ -1,9 +1,9 @@
--- WebIDL.py
+++ WebIDL.py
@@ -1787,7 +1787,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
@@ -1769,7 +1769,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
identifier == "Serializable" or
- identifier == "Abstract"):
+ identifier == "Abstract" or
+ identifier == "Inline"):

View file

@ -1,27 +0,0 @@
--- WebIDL.py
+++ WebIDL.py
@@ -1362,12 +1362,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
for bindingAlias in member.bindingAliases:
checkDuplicateNames(member, bindingAlias, "BindingAlias")
-
- if self.getExtendedAttribute("Pref") and self.isExposedOffMainThread():
- raise WebIDLError("[Pref] used on an interface that is not "
- "main-thread-only",
- [self.location])
-
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object,
@@ -3619,11 +3613,6 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
IDLExposureMixins.finish(self, scope)
def validate(self):
- if self.getExtendedAttribute("Pref") and self.isExposedOffMainThread():
- raise WebIDLError("[Pref] used on an interface member that is not "
- "main-thread-only",
- [self.location])
-
if self.isAttr() or self.isMethod():
if self.affects == "Everything" and self.dependsOn != "Everything":
raise WebIDLError("Interface member is flagged as affecting "

View file

@ -62,7 +62,7 @@ def run_tests(tests, verbose):
harness.start()
try:
_test.WebIDLTest.__call__(WebIDL.Parser(), harness)
except Exception, ex:
except Exception as ex:
print("TEST-UNEXPECTED-FAIL | Unhandled exception in test %s: %s" % (testpath, ex))
traceback.print_exc()
finally:

View file

@ -133,7 +133,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should not allow [SetterThrows] on readonly attributes")
@ -146,7 +146,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should spell [Throws] correctly")
@ -159,7 +159,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should not allow [SameObject] on attributes not of interface type")
@ -172,6 +172,6 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(not threw, "Should allow [SameObject] on attributes of interface type")

View file

@ -32,3 +32,6 @@ def WebIDLTest(parser, harness):
harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type")
harness.ok(isinstance(t, WebIDL.IDLNullableType), "Attr has the right type")
harness.ok(t.isCallback(), "Attr has the right type")
callback = results[1]
harness.ok(not callback.isConstructor(), "callback is not constructor")

View file

@ -0,0 +1,63 @@
import WebIDL
def WebIDLTest(parser, harness):
parser.parse("""
interface TestCallbackConstructor {
attribute CallbackConstructorType? constructorAttribute;
};
callback constructor CallbackConstructorType = TestCallbackConstructor (unsigned long arg);
""")
results = parser.finish()
harness.ok(True, "TestCallbackConstructor interface parsed without error.")
harness.check(len(results), 2, "Should be two productions.")
iface = results[0]
harness.ok(isinstance(iface, WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.check(iface.identifier.QName(), "::TestCallbackConstructor", "Interface has the right QName")
harness.check(iface.identifier.name, "TestCallbackConstructor", "Interface has the right name")
harness.check(len(iface.members), 1, "Expect %s members" % 1)
attr = iface.members[0]
harness.ok(isinstance(attr, WebIDL.IDLAttribute),
"Should be an IDLAttribute")
harness.ok(attr.isAttr(), "Should be an attribute")
harness.ok(not attr.isMethod(), "Attr is not an method")
harness.ok(not attr.isConst(), "Attr is not a const")
harness.check(attr.identifier.QName(), "::TestCallbackConstructor::constructorAttribute", "Attr has the right QName")
harness.check(attr.identifier.name, "constructorAttribute", "Attr has the right name")
t = attr.type
harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type")
harness.ok(isinstance(t, WebIDL.IDLNullableType), "Attr has the right type")
harness.ok(t.isCallback(), "Attr has the right type")
callback = results[1]
harness.ok(callback.isConstructor(), "Callback is constructor")
parser.reset()
threw = False
try:
parser.parse("""
[TreatNonObjectAsNull]
callback constructor CallbackConstructorType = object ();
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should throw on TreatNonObjectAsNull callback constructors")
parser.reset()
threw = False
try:
parser.parse("""
[MOZ_CAN_RUN_SCRIPT_BOUNDARY]
callback constructor CallbackConstructorType = object ();
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should not permit MOZ_CAN_RUN_SCRIPT_BOUNDARY callback constructors")

View file

@ -38,7 +38,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, e:
except Exception as e:
harness.ok(False, "Shouldn't have thrown for [CEReactions] used on writable attribute. %s" % e)
threw = True
@ -52,7 +52,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, e:
except Exception as e:
harness.ok(False, "Shouldn't have thrown for [CEReactions] used on regular operations. %s" % e)
threw = True

View file

@ -44,7 +44,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, exception:
except Exception as exception:
pass
harness.ok(exception, "Should have thrown.")
@ -70,7 +70,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, exception:
except Exception as exception:
pass
harness.ok(exception, "Should have thrown (2).")
@ -100,7 +100,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, exception:
except Exception as exception:
pass
harness.ok(exception, "Should have thrown (3).")

View file

@ -12,9 +12,6 @@ expected = [
("::TestConsts::ll", "ll", "LongLong", -8),
("::TestConsts::t", "t", "Boolean", True),
("::TestConsts::f", "f", "Boolean", False),
("::TestConsts::n", "n", "BooleanOrNull", None),
("::TestConsts::nt", "nt", "BooleanOrNull", True),
("::TestConsts::nf", "nf", "BooleanOrNull", False),
("::TestConsts::fl", "fl", "Float", 0.2),
("::TestConsts::db", "db", "Double", 0.2),
("::TestConsts::ufl", "ufl", "UnrestrictedFloat", 0.2),
@ -39,9 +36,6 @@ def WebIDLTest(parser, harness):
const long long ll = -010;
const boolean t = true;
const boolean f = false;
const boolean? n = null;
const boolean? nt = true;
const boolean? nf = false;
const float fl = 0.2;
const double db = 0.2;
const unrestricted float ufl = 0.2;
@ -78,3 +72,16 @@ def WebIDLTest(parser, harness):
"Const's value has the same type as the type")
harness.check(const.value.value, value, "Const value has the right value.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface TestConsts {
const boolean? zero = 0;
};
""")
parser.finish()
except:
threw = True
harness.ok(threw, "Nullable types are not allowed for consts.")

View file

@ -0,0 +1,87 @@
def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
[Constructor, Global]
interface TestConstructorGlobal {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global, Constructor]
interface TestConstructorGlobal {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global, NamedConstructor=FooBar]
interface TestNamedConstructorGlobal {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[NamedConstructor=FooBar, Global]
interface TestNamedConstructorGlobal {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global, HTMLConstructor]
interface TestHTMLConstructorGlobal {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor, Global]
interface TestHTMLConstructorGlobal {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")

View file

@ -13,6 +13,7 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""

View file

@ -167,6 +167,22 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Trailing dictionary arg must be optional")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
};
interface X {
void doFoo(optional A arg);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Trailing dictionary arg must have a default value")
parser = parser.reset()
threw = False
try:
@ -184,6 +200,23 @@ def WebIDLTest(parser, harness):
harness.ok(threw,
"Trailing union arg containing a dictionary must be optional")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
};
interface X {
void doFoo(optional (A or DOMString) arg);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Trailing union arg containing a dictionary must have a default value")
parser = parser.reset()
threw = False
try:
@ -200,6 +233,22 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Dictionary arg followed by optional arg must be optional")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
};
interface X {
void doFoo(optional A arg1, optional long arg2);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Dictionary arg followed by optional arg must have default value")
parser = parser.reset()
threw = False
try:
@ -235,6 +284,24 @@ def WebIDLTest(parser, harness):
"Union arg containing dictionary followed by optional arg must "
"be optional")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
};
interface X {
void doFoo(optional (A or DOMString) arg1, optional long arg2);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Union arg containing dictionary followed by optional arg must "
"have a default value")
parser = parser.reset()
parser.parse("""
dictionary A {
@ -326,7 +393,7 @@ def WebIDLTest(parser, harness):
dictionary A {
};
interface X {
void doFoo(optional A arg);
void doFoo(optional A arg = {});
};
""")
results = parser.finish()
@ -337,12 +404,23 @@ def WebIDLTest(parser, harness):
dictionary A {
};
interface X {
void doFoo(optional (A or DOMString) arg);
void doFoo(optional (A or DOMString) arg = {});
};
""")
results = parser.finish()
harness.ok(True, "Union arg containing a dictionary should actually parse")
parser = parser.reset()
parser.parse("""
dictionary A {
};
interface X {
void doFoo(optional (A or DOMString) arg = "abc");
};
""")
results = parser.finish()
harness.ok(True, "Union arg containing a dictionary with string default should actually parse")
parser = parser.reset()
threw = False
try:

View file

@ -3,13 +3,16 @@ def firstArgType(method):
def WebIDLTest(parser, harness):
parser.parse("""
// Give our dictionary a required member so we don't need to
// mess with optional and default values.
dictionary Dict {
required long member;
};
callback interface Foo {
};
interface Bar {
// Bit of a pain to get things that have dictionary types
void passDict(optional Dict arg);
void passDict(Dict arg);
void passFoo(Foo arg);
void passNullableUnion((object? or DOMString) arg);
void passNullable(Foo? arg);
@ -156,8 +159,8 @@ def WebIDLTest(parser, harness):
"AncestorInterface", "UnrelatedInterface",
"ImplementedInterface", "CallbackInterface",
"CallbackInterface?", "CallbackInterface2",
"object", "Callback", "Callback2", "optional Dict",
"optional Dict2", "sequence<long>", "sequence<short>",
"object", "Callback", "Callback2", "Dict",
"Dict2", "sequence<long>", "sequence<short>",
"record<DOMString, object>",
"record<USVString, Dict>",
"record<ByteString, long>",
@ -165,7 +168,7 @@ def WebIDLTest(parser, harness):
"Promise<any>", "Promise<any>?",
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"Uint8Array", "Uint16Array",
"(long or Callback)", "optional (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...
@ -174,7 +177,7 @@ def WebIDLTest(parser, harness):
def allBut(list1, list2):
return [a for a in list1 if a not in list2 and
(a != "any" and a != "Promise<any>" and a != "Promise<any>?")]
unions = [ "(long or Callback)", "optional (long or Dict)" ]
unions = [ "(long or Callback)", "(long or Dict)" ]
numerics = [ "long", "short", "long?", "short?" ]
booleans = [ "boolean", "boolean?" ]
primitives = numerics + booleans
@ -189,7 +192,7 @@ def WebIDLTest(parser, harness):
interfaces = [ "Interface", "Interface?", "AncestorInterface",
"UnrelatedInterface", "ImplementedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes
nullables = (["long?", "short?", "boolean?", "Interface?",
"CallbackInterface?", "optional Dict", "optional Dict2",
"CallbackInterface?", "Dict", "Dict2",
"Date?", "any", "Promise<any>?"] +
allBut(unions, [ "(long or Callback)" ]))
dates = [ "Date", "Date?" ]
@ -233,8 +236,8 @@ def WebIDLTest(parser, harness):
setDistinguishable("object", nonObjects)
setDistinguishable("Callback", nonUserObjects)
setDistinguishable("Callback2", nonUserObjects)
setDistinguishable("optional Dict", allBut(nonUserObjects, nullables))
setDistinguishable("optional Dict2", allBut(nonUserObjects, nullables))
setDistinguishable("Dict", allBut(nonUserObjects, nullables))
setDistinguishable("Dict2", allBut(nonUserObjects, nullables))
setDistinguishable("sequence<long>",
allBut(argTypes, sequences + ["object"]))
setDistinguishable("sequence<short>",
@ -254,7 +257,7 @@ def WebIDLTest(parser, harness):
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
setDistinguishable("(long or Callback)",
allBut(nonUserObjects, numerics))
setDistinguishable("optional (long or Dict)",
setDistinguishable("(long or Dict)",
allBut(nonUserObjects, numerics + nullables))
def areDistinguishable(type1, type2):
@ -273,8 +276,10 @@ def WebIDLTest(parser, harness):
callback interface CallbackInterface2 {};
callback Callback = any();
callback Callback2 = long(short arg);
dictionary Dict {};
dictionary Dict2 {};
// Give our dictionaries required members so we don't need to
// mess with optional and default values.
dictionary Dict { required long member; };
dictionary Dict2 { required long member; };
interface TestInterface {%s
};
"""

View file

@ -10,7 +10,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Constant cannot have [] as a default value")

View file

@ -8,7 +8,7 @@ def WebIDLTest(parser, harness):
try:
parser.parse(input)
results = parser.finish()
except WebIDL.WebIDLError, e:
except WebIDL.WebIDLError as e:
threw = True
lines = str(e).split('\n')

View file

@ -14,7 +14,7 @@ interface ?"""
try:
parser.parse(input)
results = parser.finish()
except WebIDL.WebIDLError, e:
except WebIDL.WebIDLError as e:
threw = True
lines = str(e).split('\n')

View file

@ -124,7 +124,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on invalid Exposed value on interface.")
@ -140,7 +140,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on invalid Exposed value on attribute.")
@ -156,7 +156,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on invalid Exposed value on operation.")
@ -172,7 +172,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on invalid Exposed value on constant.")
@ -192,7 +192,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on member exposed where its interface is not.")
@ -216,7 +216,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on LHS of implements being exposed where RHS is not.")

View file

@ -68,7 +68,7 @@ def WebIDLTest(parser, harness):
long m(float arg);
};
""")
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on void methods")
@ -81,7 +81,7 @@ def WebIDLTest(parser, harness):
void m(unrestricted float arg);
};
""")
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args")
@ -94,7 +94,7 @@ def WebIDLTest(parser, harness):
void m(sequence<unrestricted float> arg);
};
""")
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)")
@ -107,7 +107,7 @@ def WebIDLTest(parser, harness):
void m((unrestricted float or FloatTypes) arg);
};
""")
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)")
@ -120,6 +120,6 @@ def WebIDLTest(parser, harness):
readonly attribute float foo;
};
""")
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on writable attributes")

View file

@ -9,7 +9,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
harness.ok(False, "Should fail to parse")
except Exception, e:
except Exception as e:
harness.ok("Name collision" in e.message,
"Should have name collision for interface")
@ -21,7 +21,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
harness.ok(False, "Should fail to parse")
except Exception, e:
except Exception as e:
harness.ok("Name collision" in e.message,
"Should have name collision for dictionary")
@ -33,7 +33,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
harness.ok(False, "Should fail to parse")
except Exception, e:
except Exception as e:
harness.ok("Multiple unresolvable definitions" in e.message,
"Should have name collision for dictionary")

View file

@ -374,3 +374,89 @@ def WebIDLTest(parser, harness):
threw = True
harness.ok(threw,
"Should not allow unknown extended attributes on interfaces")
parser = parser.reset()
parser.parse("""
[Global] interface Window {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
[Exposed=Window, LegacyWindowAlias=(C, D)]
interface E {};
""");
results = parser.finish();
harness.check(results[1].legacyWindowAliases, ["A"],
"Should support a single identifier")
harness.check(results[2].legacyWindowAliases, ["C", "D"],
"Should support an identifier list")
parser = parser.reset()
threw = False
try:
parser.parse("""
[LegacyWindowAlias]
interface A {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] with no value")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Exposed=Worker, LegacyWindowAlias=B]
interface A {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] without Window exposure")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global] interface Window {};
interface A {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] to conflict with other identifiers")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global] interface Window {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
interface A {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] to conflict with other identifiers")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global] interface Window {};
[Exposed=Window, LegacyWindowAlias=A]
interface B {};
[Exposed=Window, LegacyWindowAlias=A]
interface C {};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should not allow [LegacyWindowAlias] to conflict with other identifiers")

View file

@ -37,10 +37,10 @@ def WebIDLTest(parser, harness):
p.finish()
harness.ok(False,
prefix + " - Interface passed when should've failed")
except WebIDL.WebIDLError, e:
except WebIDL.WebIDLError as e:
harness.ok(True,
prefix + " - Interface failed as expected")
except Exception, e:
except Exception as e:
harness.ok(False,
prefix + " - Interface failed but not as a WebIDLError exception: %s" % e)

View file

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code):
parser = parser.reset();

View file

@ -120,7 +120,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(not threw, "Should allow integer to float type corecion")
@ -133,7 +133,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should not allow [GetterThrows] on methods")
@ -146,7 +146,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should not allow [SetterThrows] on methods")
@ -159,7 +159,7 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should spell [Throws] correctly on methods")
@ -172,6 +172,85 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should not allow __noSuchMethod__ methods")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[Throws, LenientFloat]
void foo(float myFloat);
[Throws]
void foo();
};
""")
results = parser.finish()
except Exception as x:
threw = True
harness.ok(not threw, "Should allow LenientFloat to be only in a specific overload")
parser = parser.reset()
parser.parse("""
interface A {
[Throws]
void foo();
[Throws, LenientFloat]
void foo(float myFloat);
};
""")
results = parser.finish()
iface = results[0]
methods = iface.members
lenientFloat = methods[0].getExtendedAttribute("LenientFloat")
harness.ok(lenientFloat is not None, "LenientFloat in overloads must be added to the method")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[Throws, LenientFloat]
void foo(float myFloat);
[Throws]
void foo(float myFloat, float yourFloat);
};
""")
results = parser.finish()
except Exception as x:
threw = True
harness.ok(threw, "Should prevent overloads from getting different restricted float behavior")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[Throws]
void foo(float myFloat, float yourFloat);
[Throws, LenientFloat]
void foo(float myFloat);
};
""")
results = parser.finish()
except Exception as x:
threw = True
harness.ok(threw, "Should prevent overloads from getting different restricted float behavior (2)")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[Throws, LenientFloat]
void foo(float myFloat);
[Throws, LenientFloat]
void foo(short myShort);
};
""")
results = parser.finish()
except Exception as x:
threw = True
harness.ok(threw, "Should prevent overloads from getting redundant [LenientFloat]")

View file

@ -70,7 +70,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -85,7 +85,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -104,7 +104,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -123,7 +123,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -142,7 +142,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -161,7 +161,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -180,7 +180,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -199,7 +199,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -218,6 +218,6 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")

View file

@ -33,7 +33,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown because record can't have void as value type.")
@ -47,7 +47,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw,
"Should have thrown on dictionary containing itself via record.")

View file

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code):
parser = parser.reset();

View file

@ -4,15 +4,15 @@ def WebIDLTest(parser, harness):
typedef long? mynullablelong;
interface Foo {
const mylong X = 5;
const mynullablelong Y = 7;
const mynullablelong Z = null;
void foo(mylong arg);
void foo(optional mynullablelong arg = 7);
void bar(optional mynullablelong arg = null);
void baz(mylong arg);
};
""")
results = parser.finish()
harness.check(results[2].members[1].type.name, "LongOrNull",
harness.check(results[2].members[1].signatures()[0][1][0].type.name, "LongOrNull",
"Should expand typedefs")
parser = parser.reset()

View file

@ -24,7 +24,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -39,7 +39,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")
@ -59,6 +59,6 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception, x:
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown.")

View file

@ -111,7 +111,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw,
"Should have thrown when shadowing unforgeable attribute on "
@ -130,7 +130,7 @@ def WebIDLTest(parser, harness):
""")
results = parser.finish()
except Exception,x:
except Exception as x:
threw = True
harness.ok(threw,
"Should have thrown when shadowing unforgeable operation on "

View file

@ -17,7 +17,7 @@ def combinations(iterable, r):
n = len(pool)
if r > n:
return
indices = range(r)
indices = list(range(r))
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):

View file

@ -1,7 +1,6 @@
wget https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/bindings/parser/WebIDL.py -O WebIDL.py
patch < abstract.patch
patch < debug.patch
patch < pref-main-thread.patch
patch < callback-location.patch
patch < union-typedef.patch
patch < inline.patch