Migrate to new constructor operation syntax

This commit is contained in:
Kagami Sascha Rosylight 2019-10-02 21:45:01 +09:00
parent 9706cd497d
commit 9ce82ea1ae
103 changed files with 659 additions and 413 deletions

View file

@ -554,9 +554,6 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def hasProbablyShortLivingWrapper(self):
return False
def isNavigatorProperty(self):
return False
def isSerializable(self):
return False
@ -611,7 +608,7 @@ class IDLPartialInterfaceOrNamespace(IDLObject):
for attr in attrs:
identifier = attr.identifier()
if identifier in ["Constructor", "NamedConstructor"]:
if identifier == "NamedConstructor":
self.propagatedExtendedAttrs.append(attr)
elif identifier == "SecureContext":
self._haveSecureContextExtendedAttribute = True
@ -737,7 +734,7 @@ class IDLInterfaceOrInterfaceMixinOrNamespace(IDLObjectWithScope, IDLExposureMix
self.location = location
# Put the new members at the beginning
self.members = members + self.members
def addPartial(self, partial):
assert self.identifier.name == partial.identifier.name
self._partials.append(partial)
@ -790,7 +787,7 @@ class IDLInterfaceMixin(IDLInterfaceOrInterfaceMixinOrNamespace):
def __str__(self):
return "Interface mixin '%s'" % self.identifier.name
def finish(self, scope):
if self._finished:
return
@ -969,7 +966,11 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
(self.identifier.name,
self.parent.identifier.name),
[self.location])
assert not parent or isinstance(parent, IDLInterface)
if parent and not isinstance(parent, IDLInterface):
raise WebIDLError("%s inherits from %s which is not an interface " %
(self.identifier.name,
self.parent.identifier.name),
[self.location, parent.location])
self.parent = parent
@ -1076,11 +1077,34 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
ctor = self.ctor()
if ctor is not None:
assert len(ctor._exposureGlobalNames) == 0
if not self.hasInterfaceObject():
raise WebIDLError(
"Can't have both a constructor and [NoInterfaceObject]",
[self.location, ctor.location])
if self.globalNames:
raise WebIDLError(
"Can't have both a constructor and [Global]",
[self.location, ctor.location])
assert(len(ctor._exposureGlobalNames) == 0 or
ctor._exposureGlobalNames == self._exposureGlobalNames)
ctor._exposureGlobalNames.update(self._exposureGlobalNames)
ctor.finish(scope)
if ctor in self.members:
# constructor operation.
self.members.remove(ctor)
else:
# extended attribute. This can only happen with
# [HTMLConstructor] and this is the only way we can get into this
# code with len(ctor._exposureGlobalNames) !=
# self._exposureGlobalNames.
ctor.finish(scope)
for ctor in self.namedConstructors:
if self.globalNames:
raise WebIDLError(
"Can't have both a named constructor and [Global]",
[self.location, self.namedConstructors.location])
assert len(ctor._exposureGlobalNames) == 0
ctor._exposureGlobalNames.update(self._exposureGlobalNames)
ctor.finish(scope)
@ -1462,12 +1486,11 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
# interface object.
# And SecureContext makes sense for interfaces with no interface object,
# since it is also propagated to interface members.
if (self.isExposedConditionally(exclusions=["SecureContext"]) and
not self.hasInterfaceObject() and
not self.isNavigatorProperty()):
not self.hasInterfaceObject()):
raise WebIDLError("Interface with no interface object is "
"exposed conditionally",
[self.location])
@ -1640,39 +1663,6 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
current = current.parent
return False
def isNavigatorProperty(self):
naviProp = self.getExtendedAttribute("NavigatorProperty")
if not naviProp:
return False
assert len(naviProp) == 1
assert isinstance(naviProp, list)
assert len(naviProp[0]) != 0
return True
def getNavigatorProperty(self):
naviProp = self.getExtendedAttribute("NavigatorProperty")
if not naviProp:
return None
assert len(naviProp) == 1
assert isinstance(naviProp, list)
assert len(naviProp[0]) != 0
conditionExtendedAttributes = self._extendedAttrDict.viewkeys() & IDLInterfaceOrNamespace.conditionExtendedAttributes
attr = IDLAttribute(self.location,
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), naviProp[0]),
IDLUnresolvedType(self.location, IDLUnresolvedIdentifier(self.location, self.identifier.name)),
True,
extendedAttrDict={ a: self._extendedAttrDict[a] for a in conditionExtendedAttributes },
navigatorObjectGetter=True)
attr._exposureGlobalNames = self._exposureGlobalNames
# We're abusing Constant a little bit here, because we need Cached. The
# getter will create a new object every time, but we're never going to
# clear the cached value.
extendedAttrs = [ IDLExtendedAttribute(self.location, ("Throws", )),
IDLExtendedAttribute(self.location, ("Cached", )),
IDLExtendedAttribute(self.location, ("Constant", )) ]
attr.addExtendedAttributes(extendedAttrs)
return attr
def hasChildInterfaces(self):
return self._hasChildInterfaces
@ -1731,67 +1721,39 @@ class IDLInterface(IDLInterfaceOrNamespace):
raise WebIDLError("[NoInterfaceObject] must take no arguments",
[attr.location])
if self.ctor():
raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
[self.location])
self._noInterfaceObject = True
elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
if identifier == "Constructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
elif identifier == "NamedConstructor" or identifier == "HTMLConstructor":
if identifier == "NamedConstructor" and not attr.hasValue():
raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
[attr.location])
if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
if identifier == "HTMLConstructor":
if not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
if not attr.noArguments():
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)
if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
if identifier == "HTMLConstructor":
name = "constructor"
allowForbidden = True
else:
name = attr.value()
allowForbidden = False
methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
allowForbidden=allowForbidden)
method = IDLConstructor(
attr.location, args, name,
htmlConstructor=(identifier == "HTMLConstructor"))
method.reallyInit(self)
method = IDLMethod(self.location, methodIdentifier, retType,
args, static=True,
htmlConstructor=(identifier == "HTMLConstructor"))
# Constructors are always NewObject and are always
# assumed to be able to throw (since there's no way to
# indicate otherwise) and never have any other
# extended attributes.
# Are always assumed to be able to throw (since there's no way to
# indicate otherwise).
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("NewObject",)),
IDLExtendedAttribute(self.location, ("Throws",))])
if identifier == "ChromeConstructor":
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("ChromeOnly",))])
[IDLExtendedAttribute(self.location, ("Throws",))])
if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
if identifier == "HTMLConstructor":
method.resolve(self)
else:
# We need to detect conflicts for NamedConstructors across
@ -1823,10 +1785,6 @@ 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():
@ -1896,7 +1854,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
elif (identifier == "Pref" or
identifier == "JSImplementation" or
identifier == "HeaderFile" or
identifier == "NavigatorProperty" or
identifier == "Func" or
identifier == "Deprecated"):
# Known extended attributes that take a string value
@ -1923,6 +1880,17 @@ class IDLInterface(IDLInterfaceOrNamespace):
def isSerializable(self):
return self.getExtendedAttribute("Serializable")
def setNonPartial(self, location, parent, members):
# Before we do anything else, finish initializing any constructors that
# might be in "members", so we don't have partially-initialized objects
# hanging around. We couldn't do it before now because we needed to have
# to have the IDLInterface on hand to properly set the return type.
for member in members:
if isinstance(member, IDLConstructor):
member.reallyInit(self)
IDLInterfaceOrNamespace.setNonPartial(self, location, parent, members)
class IDLNamespace(IDLInterfaceOrNamespace):
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
@ -2193,6 +2161,7 @@ class IDLType(IDLObject):
'domstring',
'bytestring',
'usvstring',
'jsstring',
'object',
'date',
'void',
@ -2254,6 +2223,9 @@ class IDLType(IDLObject):
def isUSVString(self):
return False
def isJSString(self):
return False
def isVoid(self):
return self.name == "Void"
@ -2479,6 +2451,9 @@ class IDLNullableType(IDLParametrizedType):
def isUSVString(self):
return self.inner.isUSVString()
def isJSString(self):
return self.inner.isJSString()
def isFloat(self):
return self.inner.isFloat()
@ -2600,6 +2575,9 @@ class IDLSequenceType(IDLParametrizedType):
def isUSVString(self):
return False
def isJSString(self):
return False
def isVoid(self):
return False
@ -2861,6 +2839,9 @@ class IDLTypedefType(IDLType):
def isUSVString(self):
return self.inner.isUSVString()
def isJSString(self):
return self.inner.isJSString()
def isVoid(self):
return self.inner.isVoid()
@ -2991,6 +2972,9 @@ class IDLWrapperType(IDLType):
def isUSVString(self):
return False
def isJSString(self):
return False
def isVoid(self):
return False
@ -3190,6 +3174,7 @@ class IDLBuiltinType(IDLType):
'domstring',
'bytestring',
'usvstring',
'jsstring',
'object',
'date',
'void',
@ -3227,6 +3212,7 @@ class IDLBuiltinType(IDLType):
Types.domstring: IDLType.Tags.domstring,
Types.bytestring: IDLType.Tags.bytestring,
Types.usvstring: IDLType.Tags.usvstring,
Types.jsstring: IDLType.Tags.jsstring,
Types.object: IDLType.Tags.object,
Types.date: IDLType.Tags.date,
Types.void: IDLType.Tags.void,
@ -3311,7 +3297,8 @@ class IDLBuiltinType(IDLType):
def isString(self):
return (self._typeTag == IDLBuiltinType.Types.domstring or
self._typeTag == IDLBuiltinType.Types.bytestring or
self._typeTag == IDLBuiltinType.Types.usvstring)
self._typeTag == IDLBuiltinType.Types.usvstring or
self._typeTag == IDLBuiltinType.Types.jsstring)
def isByteString(self):
return self._typeTag == IDLBuiltinType.Types.bytestring
@ -3322,6 +3309,9 @@ class IDLBuiltinType(IDLType):
def isUSVString(self):
return self._typeTag == IDLBuiltinType.Types.usvstring
def isJSString(self):
return self._typeTag == IDLBuiltinType.Types.jsstring
def isInteger(self):
return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long
@ -3524,6 +3514,9 @@ BuiltinTypes = {
IDLBuiltinType.Types.usvstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "USVString",
IDLBuiltinType.Types.usvstring),
IDLBuiltinType.Types.jsstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "JSString",
IDLBuiltinType.Types.jsstring),
IDLBuiltinType.Types.object:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
IDLBuiltinType.Types.object),
@ -3690,8 +3683,8 @@ 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():
# Allow ByteStrings to use a default value like DOMString.
elif self.type.isString() and (type.isByteString() or type.isJSString()):
# Allow ByteStrings 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.
@ -4340,7 +4333,7 @@ class IDLConst(IDLInterfaceMember):
class IDLAttribute(IDLInterfaceMember):
def __init__(self, location, identifier, type, readonly, inherit=False,
static=False, stringifier=False, maplikeOrSetlike=None,
extendedAttrDict=None, navigatorObjectGetter=False):
extendedAttrDict=None):
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Attr,
extendedAttrDict=extendedAttrDict)
@ -4358,7 +4351,6 @@ class IDLAttribute(IDLInterfaceMember):
self.maplikeOrSetlike = maplikeOrSetlike
self.dependsOn = "Everything"
self.affects = "Everything"
self.navigatorObjectGetter = navigatorObjectGetter
self.bindingAliases = []
if static and identifier.name == "prototype":
@ -5239,7 +5231,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert argument.type.isComplete()
if ((argument.type.isDictionary() and
argument.type.inner.canBeEmpty())or
argument.type.unroll().inner.canBeEmpty()) or
(argument.type.isUnion() and
argument.type.unroll().hasPossiblyEmptyDictionaryType())):
# Optional dictionaries and unions containing optional
@ -5263,12 +5255,16 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
"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 "
"dictionary or nullable union "
"containing a dictionary",
[argument.location])
# An argument cannot be a nullable dictionary or a
# nullable union containing a dictionary.
if (argument.type.nullable() and
(argument.type.isDictionary() or
(argument.type.isUnion() and
argument.type.unroll().hasDictionaryType()))):
raise WebIDLError("An argument cannot be a nullable "
"dictionary or nullable union "
"containing a dictionary",
[argument.location])
# Only the last argument can be variadic
if variadicArgument:
@ -5497,6 +5493,52 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
return deps
class IDLConstructor(IDLMethod):
def __init__(self, location, args, name, htmlConstructor=False):
# We can't actually init our IDLMethod yet, because we do not know the
# return type yet. Just save the info we have for now and we will init
# it later.
self._initLocation = location
self._initArgs = args
self._initName = name
self._htmlConstructor = htmlConstructor
self._inited = False
self._initExtendedAttrs = []
def addExtendedAttributes(self, attrs):
if self._inited:
return IDLMethod.addExtendedAttributes(self, attrs)
self._initExtendedAttrs.extend(attrs)
def handleExtendedAttribute(self, attr):
identifier = attr.identifier()
if (identifier == "BinaryName" or
identifier == "ChromeOnly" or
identifier == "NewObject" or
identifier == "SecureContext" or
identifier == "Throws"):
IDLMethod.handleExtendedAttribute(self, attr)
else:
raise WebIDLError("Unknown extended attribute %s on method" % identifier,
[attr.location])
def reallyInit(self, parentInterface):
name = self._initName
location = self._initLocation
identifier = IDLUnresolvedIdentifier(location, name, allowForbidden=True)
retType = IDLWrapperType(parentInterface.location, parentInterface)
IDLMethod.__init__(self, location, identifier, retType, self._initArgs,
static=True, htmlConstructor=self._htmlConstructor)
self._inited = True;
# Propagate through whatever extended attributes we already had
self.addExtendedAttributes(self._initExtendedAttrs)
self._initExtendedAttrs = []
# Constructors are always NewObject. Whether they throw or not is
# indicated by [Throws] annotations in the usual way.
self.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("NewObject",))])
class IDLImplementsStatement(IDLObject):
def __init__(self, location, implementor, implementee):
IDLObject.__init__(self, location)
@ -5712,6 +5754,7 @@ class Tokenizer(object):
"DOMString": "DOMSTRING",
"ByteString": "BYTESTRING",
"USVString": "USVSTRING",
"JSString": "JSSTRING",
"any": "ANY",
"boolean": "BOOLEAN",
"byte": "BYTE",
@ -6076,7 +6119,7 @@ class Parser(Tokenizer):
def p_PartialInterfaceRest(self, p):
"""
PartialInterfaceRest : IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
PartialInterfaceRest : IDENTIFIER LBRACE PartialInterfaceMembers RBRACE SEMICOLON
"""
location = self.getLocation(p, 1)
identifier = IDLUnresolvedIdentifier(location, p[1])
@ -6157,12 +6200,42 @@ class Parser(Tokenizer):
def p_InterfaceMember(self, p):
"""
InterfaceMember : Const
| AttributeOrOperationOrMaplikeOrSetlikeOrIterable
InterfaceMember : PartialInterfaceMember
| Constructor
"""
p[0] = p[1]
def p_Constructor(self, p):
"""
Constructor : CONSTRUCTOR LPAREN ArgumentList RPAREN SEMICOLON
"""
p[0] = IDLConstructor(self.getLocation(p, 1), p[3], "constructor")
def p_PartialInterfaceMembers(self, p):
"""
PartialInterfaceMembers : ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers
"""
p[0] = [p[2]]
assert not p[1] or p[2]
p[2].addExtendedAttributes(p[1])
p[0].extend(p[3])
def p_PartialInterfaceMembersEmpty(self, p):
"""
PartialInterfaceMembers :
"""
p[0] = []
def p_PartialInterfaceMember(self, p):
"""
PartialInterfaceMember : Const
| AttributeOrOperationOrMaplikeOrSetlikeOrIterable
"""
p[0] = p[1]
def p_MixinMembersEmpty(self, p):
"""
MixinMembers :
@ -6778,7 +6851,9 @@ class Parser(Tokenizer):
"""
t = p[2]
assert isinstance(t, IDLType)
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
# Arg names can be reserved identifiers
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3],
allowForbidden=True)
defaultValue = p[4]
@ -6795,7 +6870,9 @@ class Parser(Tokenizer):
"""
t = p[1]
assert isinstance(t, IDLType)
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
# Arg names can be reserved identifiers
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3],
allowForbidden=True)
variadic = p[2]
@ -6934,6 +7011,7 @@ class Parser(Tokenizer):
| DOMSTRING
| BYTESTRING
| USVSTRING
| JSSTRING
| ANY
| ATTRIBUTE
| BOOLEAN
@ -7216,6 +7294,12 @@ class Parser(Tokenizer):
"""
p[0] = IDLBuiltinType.Types.usvstring
def p_BuiltinStringTypeJSString(self, p):
"""
BuiltinStringType : JSSTRING
"""
p[0] = IDLBuiltinType.Types.jsstring
def p_UnsignedIntegerTypeUnsigned(self, p):
"""
UnsignedIntegerType : UNSIGNED IntegerType
@ -7443,23 +7527,9 @@ class Parser(Tokenizer):
for p in self._productions:
if isinstance(p, IDLInterface):
interfaceStatements.append(p)
if p.identifier.name == "Navigator":
navigatorInterface = p
iterableIteratorIface = None
for iface in interfaceStatements:
navigatorProperty = iface.getNavigatorProperty()
if navigatorProperty:
# We're generating a partial interface to add a readonly
# property to the Navigator interface for every interface
# annotated with NavigatorProperty.
partialInterface = IDLPartialInterfaceOrNamespace(
iface.location,
IDLUnresolvedIdentifier(iface.location, "Navigator"),
[ navigatorProperty ],
navigatorInterface)
self._productions.append(partialInterface)
iterable = None
# We haven't run finish() on the interface yet, so we don't know
# whether our interface is maplike/setlike/iterable or not. This

View file

@ -0,0 +1,17 @@
def WebIDLTest(parser, harness):
parser.parse("""
interface Foo {
void foo(object constructor);
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should have an interface");
iface = results[0];
harness.check(len(iface.members), 1, "Should have an operation");
operation = iface.members[0];
harness.check(len(operation.signatures()), 1, "Should have one signature");
(retval, args) = operation.signatures()[0];
harness.check(len(args), 1, "Should have an argument");
harness.check(args[0].identifier.name, "constructor",
"Should have an identifier named 'constructor'");

View file

@ -205,6 +205,18 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow [TreatNullAs] on long")
parser = parser.reset()
threw = False
try:
parser.parse("""
typedef [TreatNullAs=EmptyString] JSString Foo;
""")
parser.finish()
except:
threw = True
harness.ok(threw, "Should not allow [TreatNullAs] on JSString")
parser = parser.reset()
threw = False
try:

View file

@ -43,45 +43,55 @@ def WebIDLTest(parser, harness):
(QName, name, type, optional, variadic) = expectedArgs[i]
checkArgument(gotArgs[i], QName, name, type, optional, variadic)
def checkResults(results):
harness.check(len(results), 3, "Should be three productions")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.ok(isinstance(results[2], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor",
"constructor", [("TestConstructorNoArgs (Wrapper)", [])])
harness.check(len(results[0].members), 0,
"TestConstructorNoArgs should not have members")
checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor",
"constructor",
[("TestConstructorWithArgs (Wrapper)",
[("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])])
harness.check(len(results[1].members), 0,
"TestConstructorWithArgs should not have members")
checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor",
"constructor",
[("TestConstructorOverloads (Wrapper)",
[("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]),
("TestConstructorOverloads (Wrapper)",
[("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])])
harness.check(len(results[2].members), 0,
"TestConstructorOverloads should not have members")
parser.parse("""
[Constructor]
interface TestConstructorNoArgs {
constructor();
};
[Constructor(DOMString name)]
interface TestConstructorWithArgs {
constructor(DOMString name);
};
[Constructor(object foo), Constructor(boolean bar)]
interface TestConstructorOverloads {
constructor(object foo);
constructor(boolean bar);
};
""")
results = parser.finish()
harness.check(len(results), 3, "Should be three productions")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.ok(isinstance(results[2], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor",
"constructor", [("TestConstructorNoArgs (Wrapper)", [])])
checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor",
"constructor",
[("TestConstructorWithArgs (Wrapper)",
[("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])])
checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor",
"constructor",
[("TestConstructorOverloads (Wrapper)",
[("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]),
("TestConstructorOverloads (Wrapper)",
[("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])])
checkResults(results)
parser = parser.reset()
parser.parse("""
[ChromeConstructor()]
interface TestChromeConstructor {
interface TestChromeOnlyConstructor {
[ChromeOnly] constructor();
};
""")
results = parser.finish()
@ -89,8 +99,8 @@ def WebIDLTest(parser, harness):
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestChromeConstructor::constructor",
"constructor", [("TestChromeConstructor (Wrapper)", [])],
checkMethod(results[0].ctor(), "::TestChromeOnlyConstructor::constructor",
"constructor", [("TestChromeOnlyConstructor (Wrapper)", [])],
chromeOnly=True)
parser = parser.reset()
@ -112,16 +122,16 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
[Constructor(),
ChromeConstructor(DOMString a)]
interface TestChromeConstructor {
interface TestChromeOnlyConstructor {
constructor()
[ChromeOnly] constructor(DOMString a);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")
harness.ok(threw, "Can't have both a constructor and a ChromeOnly constructor")
# Test HTMLConstructor with argument
parser = parser.reset()
@ -153,120 +163,197 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
# Test HTMLConstructor and Constructor
# Test HTMLConstructor and constructor operation
parser = parser.reset()
threw = False
try:
parser.parse("""
[Constructor,
HTMLConstructor]
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
constructor();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a Constructor and a HTMLConstructor")
harness.ok(threw, "Can't have both a constructor and a HTMLConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
Constructor]
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
[Throws]
constructor();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
harness.ok(threw,
"Can't have both a throwing constructor and a HTMLConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
Constructor(DOMString a)]
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
constructor(DOMString a);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
harness.ok(threw,
"Can't have both a HTMLConstructor and a constructor operation")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Constructor(DOMString a),
HTMLConstructor]
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
};
""")
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
# Test HTMLConstructor and ChromeConstructor
parser = parser.reset()
threw = False
try:
parser.parse("""
[ChromeConstructor,
HTMLConstructor]
interface TestHTMLConstructorAndChromeConstructor {
[Throws]
constructor(DOMString a);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
harness.ok(threw,
"Can't have both a HTMLConstructor and a throwing constructor "
"operation")
# Test HTMLConstructor and [ChromeOnly] constructor operation
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
ChromeConstructor]
interface TestHTMLConstructorAndChromeConstructor {
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
[ChromeOnly]
constructor();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
harness.ok(threw,
"Can't have both a ChromeOnly constructor and a HTMLConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[ChromeConstructor(DOMString a),
HTMLConstructor]
interface TestHTMLConstructorAndChromeConstructor {
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
[Throws, ChromeOnly]
constructor();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Can't have both a throwing chromeonly constructor and a "
"HTMLConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
ChromeConstructor(DOMString a)]
interface TestHTMLConstructorAndChromeConstructor {
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
[ChromeOnly]
constructor(DOMString a);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
harness.ok(threw,
"Can't have both a HTMLConstructor and a chromeonly constructor "
"operation")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
[Throws, ChromeOnly]
constructor(DOMString a);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Can't have both a HTMLConstructor and a throwing chromeonly "
"constructor operation")
parser = parser.reset()
threw = False
try:
parser.parse("""
[NoInterfaceObject]
interface InterfaceWithoutInterfaceObject {
constructor();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Can't have a constructor operation on a [NoInterfaceObject] "
"interface")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface InterfaceWithPartial {
};
partial interface InterfaceWithPartial {
constructor();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Can't have a constructor operation on a partial interface")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface InterfaceWithMixin {
};
interface mixin Mixin {
constructor();
};
InterfaceWithMixin includes Mixin
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Can't have a constructor operation on a mixin")

View file

@ -2,23 +2,9 @@ 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]
[Global]
interface TestConstructorGlobal {
constructor();
};
""")

View file

@ -2,23 +2,9 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
[Constructor, NoInterfaceObject]
interface TestConstructorNoInterfaceObject {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[NoInterfaceObject, Constructor]
[NoInterfaceObject]
interface TestConstructorNoInterfaceObject {
constructor();
};
""")

View file

@ -320,14 +320,36 @@ def WebIDLTest(parser, harness):
dictionary A {
};
interface X {
void doFoo(optional A? arg1);
void doFoo(optional A? arg1 = {});
};
""")
results = parser.finish()
except:
threw = True
except Exception as x:
threw = x
harness.ok(threw, "Dictionary arg must not be nullable")
harness.ok(threw, "Optional dictionary arg must not be nullable")
harness.ok("nullable" in str(threw),
"Must have the expected exception for optional nullable dictionary arg")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
required long x;
};
interface X {
void doFoo(A? arg1);
};
""")
results = parser.finish()
except Exception as x:
threw = x
harness.ok(threw, "Required dictionary arg must not be nullable")
harness.ok("nullable" in str(threw),
"Must have the expected exception for required nullable "
"dictionary arg")
parser = parser.reset()
threw = False
@ -336,14 +358,54 @@ def WebIDLTest(parser, harness):
dictionary A {
};
interface X {
void doFoo(optional (A or long)? arg1);
void doFoo(optional (A or long)? arg1 = {});
};
""")
results = parser.finish()
except Exception as x:
threw = x
harness.ok(threw, "Dictionary arg must not be in an optional nullable union")
harness.ok("nullable" in str(threw),
"Must have the expected exception for optional nullable union "
"arg containing dictionary")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
required long x;
};
interface X {
void doFoo((A or long)? arg1);
};
""")
results = parser.finish()
except Exception as x:
threw = x
harness.ok(threw, "Dictionary arg must not be in a required nullable union")
harness.ok("nullable" in str(threw),
"Must have the expected exception for required nullable union "
"arg containing dictionary")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary A {
};
interface X {
void doFoo(sequence<A?> arg1);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Dictionary arg must not be in a nullable union")
harness.ok(not threw,
"Nullable union should be allowed in a sequence argument")
parser = parser.reset()
threw = False

View file

@ -166,7 +166,7 @@ def WebIDLTest(parser, harness):
"record<ByteString, long>",
"Date", "Date?", "any",
"Promise<any>", "Promise<any>?",
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"USVString", "JSString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"Uint8Array", "Uint16Array",
"(long or Callback)", "(long or Dict)",
]
@ -183,7 +183,7 @@ def WebIDLTest(parser, harness):
primitives = numerics + booleans
nonNumerics = allBut(argTypes, numerics + unions)
nonBooleans = allBut(argTypes, booleans)
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString" ]
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString", "JSString" ]
nonStrings = allBut(argTypes, strings)
nonObjects = primitives + strings
objects = allBut(argTypes, nonObjects )
@ -202,7 +202,7 @@ def WebIDLTest(parser, harness):
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] +
otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes)
records = [ "record<DOMString, object>", "record<USVString, Dict>",
"record<ByteString, long>" ]
"record<ByteString, 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.
@ -222,6 +222,7 @@ def WebIDLTest(parser, harness):
setDistinguishable("DOMString", nonStrings)
setDistinguishable("ByteString", nonStrings)
setDistinguishable("USVString", nonStrings)
setDistinguishable("JSString", nonStrings)
setDistinguishable("Enum", nonStrings)
setDistinguishable("Enum2", nonStrings)
setDistinguishable("Interface", notRelatedInterfaces)
@ -244,6 +245,7 @@ def WebIDLTest(parser, harness):
allBut(argTypes, sequences + ["object"]))
setDistinguishable("record<DOMString, object>", nonUserObjects)
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"]))

View file

@ -189,12 +189,12 @@ def WebIDLTest(parser, harness):
parser = parser.reset()
parser.parse("""
[Constructor(long arg)]
interface A {
constructor();
constructor(long arg);
readonly attribute boolean x;
void foo();
};
[Constructor]
partial interface A {
readonly attribute boolean y;
void foo(long arg);
@ -219,13 +219,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset()
parser.parse("""
[Constructor]
partial interface A {
readonly attribute boolean y;
void foo(long arg);
};
[Constructor(long arg)]
interface A {
constructor();
constructor(long arg);
readonly attribute boolean x;
void foo();
};

View file

@ -264,18 +264,18 @@ def WebIDLTest(parser, harness):
shouldPass("JS Implemented maplike interface",
"""
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
Constructor()]
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
interface Foo1 {
constructor();
setlike<long>;
};
""", setRWChromeMembers)
shouldPass("JS Implemented maplike interface",
"""
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
Constructor()]
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
interface Foo1 {
constructor();
maplike<long, long>;
};
""", mapRWChromeMembers)
@ -655,9 +655,9 @@ def WebIDLTest(parser, harness):
shouldPass("JS Implemented read-only interface with readonly allowable overrides",
"""
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
Constructor()]
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
interface Foo1 {
constructor();
readonly setlike<long>;
readonly attribute boolean clear;
};
@ -665,9 +665,9 @@ def WebIDLTest(parser, harness):
shouldFail("JS Implemented read-write interface with non-readwrite allowable overrides",
"""
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
Constructor()]
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
interface Foo1 {
constructor();
setlike<long>;
readonly attribute boolean clear;
};

View file

@ -1,11 +1,11 @@
wget https://hg.mozilla.org/mozilla-central/raw-file/tip/dom/bindings/parser/WebIDL.py -O WebIDL.py
wget https://hg.mozilla.org/mozilla-central/raw-file/e447e3d69684cf04a95a35b9708174a6538eb042/dom/bindings/parser/WebIDL.py -O WebIDL.py
patch < abstract.patch
patch < debug.patch
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/e447e3d69684cf04a95a35b9708174a6538eb042.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests
mkdir tests
tar xvpf tests.tar.gz -C tests --strip-components=5