mirror of
https://github.com/servo/servo.git
synced 2025-08-02 12:10:29 +01:00
components/script/dom/bindings/codegen/parser/update.sh now downloads all
the latest *.py tests from https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/
This commit is contained in:
parent
003fdd4176
commit
d3528ffce4
30 changed files with 2910 additions and 70 deletions
|
@ -3238,7 +3238,7 @@ class CGMemberJITInfo(CGThing):
|
||||||
aliasSet = self.aliasSet()
|
aliasSet = self.aliasSet()
|
||||||
|
|
||||||
isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
|
isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
|
||||||
if self.member.slotIndex is not None:
|
if self.member.slotIndices is not None:
|
||||||
assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached")
|
assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached")
|
||||||
isLazilyCachedInSlot = not isAlwaysInSlot
|
isLazilyCachedInSlot = not isAlwaysInSlot
|
||||||
slotIndex = memberReservedSlot(self.member) # noqa:FIXME: memberReservedSlot is not defined
|
slotIndex = memberReservedSlot(self.member) # noqa:FIXME: memberReservedSlot is not defined
|
||||||
|
|
|
@ -508,6 +508,9 @@ class IDLExposureMixins():
|
||||||
def isExposedInAnyWorker(self):
|
def isExposedInAnyWorker(self):
|
||||||
return len(self.getWorkerExposureSet()) > 0
|
return len(self.getWorkerExposureSet()) > 0
|
||||||
|
|
||||||
|
def isExposedInWorkerDebugger(self):
|
||||||
|
return len(self.getWorkerDebuggerExposureSet()) > 0
|
||||||
|
|
||||||
def isExposedInSystemGlobals(self):
|
def isExposedInSystemGlobals(self):
|
||||||
return 'BackstagePass' in self.exposureSet
|
return 'BackstagePass' in self.exposureSet
|
||||||
|
|
||||||
|
@ -527,6 +530,10 @@ class IDLExposureMixins():
|
||||||
workerScopes = self._globalScope.globalNameMapping["Worker"]
|
workerScopes = self._globalScope.globalNameMapping["Worker"]
|
||||||
return workerScopes.intersection(self.exposureSet)
|
return workerScopes.intersection(self.exposureSet)
|
||||||
|
|
||||||
|
def getWorkerDebuggerExposureSet(self):
|
||||||
|
workerDebuggerScopes = self._globalScope.globalNameMapping["WorkerDebugger"]
|
||||||
|
return workerDebuggerScopes.intersection(self.exposureSet)
|
||||||
|
|
||||||
|
|
||||||
class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
|
class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||||
def __init__(self, location, parentScope, identifier):
|
def __init__(self, location, parentScope, identifier):
|
||||||
|
@ -978,7 +985,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
(member.getExtendedAttribute("StoreInSlot") or
|
(member.getExtendedAttribute("StoreInSlot") or
|
||||||
member.getExtendedAttribute("Cached"))) or
|
member.getExtendedAttribute("Cached"))) or
|
||||||
member.isMaplikeOrSetlike()):
|
member.isMaplikeOrSetlike()):
|
||||||
member.slotIndex = self.totalMembersInSlots
|
if member.slotIndices is None:
|
||||||
|
member.slotIndices = dict()
|
||||||
|
member.slotIndices[self.identifier.name] = self.totalMembersInSlots
|
||||||
self.totalMembersInSlots += 1
|
self.totalMembersInSlots += 1
|
||||||
if member.getExtendedAttribute("StoreInSlot"):
|
if member.getExtendedAttribute("StoreInSlot"):
|
||||||
self._ownMembersInSlots += 1
|
self._ownMembersInSlots += 1
|
||||||
|
@ -1102,7 +1111,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
# We don't support consequential unforgeable interfaces. Need to check
|
# We don't support consequential unforgeable interfaces. Need to check
|
||||||
# this here, becaue in finish() an interface might not know yet that
|
# this here, because in finish() an interface might not know yet that
|
||||||
# it's consequential.
|
# it's consequential.
|
||||||
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
|
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
|
||||||
raise WebIDLError(
|
raise WebIDLError(
|
||||||
|
@ -1121,6 +1130,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
self.identifier.name,
|
self.identifier.name,
|
||||||
locations)
|
locations)
|
||||||
|
|
||||||
|
indexedGetter = None
|
||||||
|
hasLengthAttribute = False
|
||||||
for member in self.members:
|
for member in self.members:
|
||||||
member.validate()
|
member.validate()
|
||||||
|
|
||||||
|
@ -1131,8 +1142,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
[self.location, member.location])
|
[self.location, member.location])
|
||||||
|
|
||||||
# Check that PutForwards refers to another attribute and that no
|
# Check that PutForwards refers to another attribute and that no
|
||||||
# cycles exist in forwarded assignments.
|
# cycles exist in forwarded assignments. Also check for a
|
||||||
|
# integer-typed "length" attribute.
|
||||||
if member.isAttr():
|
if member.isAttr():
|
||||||
|
if (member.identifier.name == "length" and
|
||||||
|
member.type.isInteger()):
|
||||||
|
hasLengthAttribute = True
|
||||||
|
|
||||||
iface = self
|
iface = self
|
||||||
attr = member
|
attr = member
|
||||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||||
|
@ -1170,8 +1186,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
putForwards = attr.getExtendedAttribute("PutForwards")
|
putForwards = attr.getExtendedAttribute("PutForwards")
|
||||||
|
|
||||||
# Check that the name of an [Alias] doesn't conflict with an
|
# Check that the name of an [Alias] doesn't conflict with an
|
||||||
# interface member.
|
# interface member and whether we support indexed properties.
|
||||||
if member.isMethod():
|
if member.isMethod():
|
||||||
|
if member.isGetter() and member.isIndexed():
|
||||||
|
indexedGetter = member
|
||||||
|
|
||||||
for alias in member.aliases:
|
for alias in member.aliases:
|
||||||
if self.isOnGlobalProtoChain():
|
if self.isOnGlobalProtoChain():
|
||||||
raise WebIDLError("[Alias] must not be used on a "
|
raise WebIDLError("[Alias] must not be used on a "
|
||||||
|
@ -1232,6 +1251,35 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||||
"exposed conditionally",
|
"exposed conditionally",
|
||||||
[self.location])
|
[self.location])
|
||||||
|
|
||||||
|
# Value iterators are only allowed on interfaces with indexed getters,
|
||||||
|
# and pair iterators are only allowed on interfaces without indexed
|
||||||
|
# getters.
|
||||||
|
if self.isIterable():
|
||||||
|
iterableDecl = self.maplikeOrSetlikeOrIterable
|
||||||
|
if iterableDecl.isValueIterator():
|
||||||
|
if not indexedGetter:
|
||||||
|
raise WebIDLError("Interface with value iterator does not "
|
||||||
|
"support indexed properties",
|
||||||
|
[self.location])
|
||||||
|
|
||||||
|
if iterableDecl.valueType != indexedGetter.signatures()[0][0]:
|
||||||
|
raise WebIDLError("Iterable type does not match indexed "
|
||||||
|
"getter type",
|
||||||
|
[iterableDecl.location,
|
||||||
|
indexedGetter.location])
|
||||||
|
|
||||||
|
if not hasLengthAttribute:
|
||||||
|
raise WebIDLError('Interface with value iterator does not '
|
||||||
|
'have an integer-typed "length" attribute',
|
||||||
|
[self.location])
|
||||||
|
else:
|
||||||
|
assert iterableDecl.isPairIterator()
|
||||||
|
if indexedGetter:
|
||||||
|
raise WebIDLError("Interface with pair iterator supports "
|
||||||
|
"indexed properties",
|
||||||
|
[self.location, iterableDecl.location,
|
||||||
|
indexedGetter.location])
|
||||||
|
|
||||||
def isInterface(self):
|
def isInterface(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -3432,7 +3480,10 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
|
|
||||||
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
||||||
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
||||||
assert isinstance(keyType, IDLType)
|
if keyType is not None:
|
||||||
|
assert isinstance(keyType, IDLType)
|
||||||
|
else:
|
||||||
|
assert valueType is not None
|
||||||
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
||||||
if valueType is not None:
|
if valueType is not None:
|
||||||
assert isinstance(valueType, IDLType)
|
assert isinstance(valueType, IDLType)
|
||||||
|
@ -3451,6 +3502,9 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
def isIterable(self):
|
def isIterable(self):
|
||||||
return self.maplikeOrSetlikeOrIterableType == "iterable"
|
return self.maplikeOrSetlikeOrIterableType == "iterable"
|
||||||
|
|
||||||
|
def hasKeyType(self):
|
||||||
|
return self.keyType is not None
|
||||||
|
|
||||||
def hasValueType(self):
|
def hasValueType(self):
|
||||||
return self.valueType is not None
|
return self.valueType is not None
|
||||||
|
|
||||||
|
@ -3475,7 +3529,8 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
[self.location, member.location])
|
[self.location, member.location])
|
||||||
|
|
||||||
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
|
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
|
||||||
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False):
|
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False,
|
||||||
|
isIteratorAlias=False):
|
||||||
"""
|
"""
|
||||||
Create an IDLMethod based on the parameters passed in.
|
Create an IDLMethod based on the parameters passed in.
|
||||||
|
|
||||||
|
@ -3535,16 +3590,20 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
if newObject:
|
if newObject:
|
||||||
method.addExtendedAttributes(
|
method.addExtendedAttributes(
|
||||||
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
||||||
|
if isIteratorAlias:
|
||||||
|
method.addExtendedAttributes(
|
||||||
|
[IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))])
|
||||||
members.append(method)
|
members.append(method)
|
||||||
|
|
||||||
def resolve(self, parentScope):
|
def resolve(self, parentScope):
|
||||||
self.keyType.resolveType(parentScope)
|
if self.keyType:
|
||||||
|
self.keyType.resolveType(parentScope)
|
||||||
if self.valueType:
|
if self.valueType:
|
||||||
self.valueType.resolveType(parentScope)
|
self.valueType.resolveType(parentScope)
|
||||||
|
|
||||||
def finish(self, scope):
|
def finish(self, scope):
|
||||||
IDLInterfaceMember.finish(self, scope)
|
IDLInterfaceMember.finish(self, scope)
|
||||||
if not self.keyType.isComplete():
|
if self.keyType and not self.keyType.isComplete():
|
||||||
t = self.keyType.complete(scope)
|
t = self.keyType.complete(scope)
|
||||||
|
|
||||||
assert not isinstance(t, IDLUnresolvedType)
|
assert not isinstance(t, IDLUnresolvedType)
|
||||||
|
@ -3566,9 +3625,23 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||||
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
|
deps = set()
|
||||||
|
if self.keyType:
|
||||||
|
deps.add(self.keyType)
|
||||||
if self.valueType:
|
if self.valueType:
|
||||||
return set([self.keyType, self.valueType])
|
deps.add(self.valueType)
|
||||||
return set([self.keyType])
|
return deps
|
||||||
|
|
||||||
|
def getForEachArguments(self):
|
||||||
|
return [IDLArgument(self.location,
|
||||||
|
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||||
|
"callback"),
|
||||||
|
BuiltinTypes[IDLBuiltinType.Types.object]),
|
||||||
|
IDLArgument(self.location,
|
||||||
|
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||||
|
"thisArg"),
|
||||||
|
BuiltinTypes[IDLBuiltinType.Types.any],
|
||||||
|
optional=True)]
|
||||||
|
|
||||||
# Iterable adds ES6 iterator style functions and traits
|
# Iterable adds ES6 iterator style functions and traits
|
||||||
# (keys/values/entries/@@iterator) to an interface.
|
# (keys/values/entries/@@iterator) to an interface.
|
||||||
|
@ -3589,9 +3662,15 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
we generate our functions as if they were part of the interface
|
we generate our functions as if they were part of the interface
|
||||||
specification during parsing.
|
specification during parsing.
|
||||||
"""
|
"""
|
||||||
|
# We only need to add entries/keys/values here if we're a pair iterator.
|
||||||
|
# Value iterators just copy these from %ArrayPrototype% instead.
|
||||||
|
if not self.isPairIterator():
|
||||||
|
return
|
||||||
|
|
||||||
# object entries()
|
# object entries()
|
||||||
self.addMethod("entries", members, False, self.iteratorType,
|
self.addMethod("entries", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
affectsNothing=True, newObject=True,
|
||||||
|
isIteratorAlias=True)
|
||||||
# object keys()
|
# object keys()
|
||||||
self.addMethod("keys", members, False, self.iteratorType,
|
self.addMethod("keys", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
affectsNothing=True, newObject=True)
|
||||||
|
@ -3599,6 +3678,17 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
self.addMethod("values", members, False, self.iteratorType,
|
self.addMethod("values", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
affectsNothing=True, newObject=True)
|
||||||
|
|
||||||
|
# void forEach(callback(valueType, keyType), optional any thisArg)
|
||||||
|
self.addMethod("forEach", members, False,
|
||||||
|
BuiltinTypes[IDLBuiltinType.Types.void],
|
||||||
|
self.getForEachArguments())
|
||||||
|
|
||||||
|
def isValueIterator(self):
|
||||||
|
return not self.isPairIterator()
|
||||||
|
|
||||||
|
def isPairIterator(self):
|
||||||
|
return self.hasKeyType()
|
||||||
|
|
||||||
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
|
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
|
||||||
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
|
|
||||||
|
@ -3607,7 +3697,7 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier, maplikeOrSetlikeType,
|
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier, maplikeOrSetlikeType,
|
||||||
keyType, valueType, IDLInterfaceMember.Tags.MaplikeOrSetlike)
|
keyType, valueType, IDLInterfaceMember.Tags.MaplikeOrSetlike)
|
||||||
self.readonly = readonly
|
self.readonly = readonly
|
||||||
self.slotIndex = None
|
self.slotIndices = None
|
||||||
|
|
||||||
# When generating JSAPI access code, we need to know the backing object
|
# When generating JSAPI access code, we need to know the backing object
|
||||||
# type prefix to create the correct function. Generate here for reuse.
|
# type prefix to create the correct function. Generate here for reuse.
|
||||||
|
@ -3635,26 +3725,17 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
|
|
||||||
# object entries()
|
# object entries()
|
||||||
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||||
affectsNothing=True)
|
affectsNothing=True, isIteratorAlias=self.isMaplike())
|
||||||
# object keys()
|
# object keys()
|
||||||
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||||
affectsNothing=True)
|
affectsNothing=True)
|
||||||
# object values()
|
# object values()
|
||||||
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||||
affectsNothing=True)
|
affectsNothing=True, isIteratorAlias=self.isSetlike())
|
||||||
|
|
||||||
# void forEach(callback(valueType, keyType), thisVal)
|
# void forEach(callback(valueType, keyType), thisVal)
|
||||||
foreachArguments = [IDLArgument(self.location,
|
|
||||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
|
||||||
"callback"),
|
|
||||||
BuiltinTypes[IDLBuiltinType.Types.object]),
|
|
||||||
IDLArgument(self.location,
|
|
||||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
|
||||||
"thisArg"),
|
|
||||||
BuiltinTypes[IDLBuiltinType.Types.any],
|
|
||||||
optional=True)]
|
|
||||||
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||||
foreachArguments)
|
self.getForEachArguments())
|
||||||
|
|
||||||
def getKeyArg():
|
def getKeyArg():
|
||||||
return IDLArgument(self.location,
|
return IDLArgument(self.location,
|
||||||
|
@ -3801,7 +3882,7 @@ class IDLAttribute(IDLInterfaceMember):
|
||||||
self.stringifier = stringifier
|
self.stringifier = stringifier
|
||||||
self.enforceRange = False
|
self.enforceRange = False
|
||||||
self.clamp = False
|
self.clamp = False
|
||||||
self.slotIndex = None
|
self.slotIndices = None
|
||||||
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
|
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
|
||||||
self.maplikeOrSetlike = maplikeOrSetlike
|
self.maplikeOrSetlike = maplikeOrSetlike
|
||||||
self.dependsOn = "Everything"
|
self.dependsOn = "Everything"
|
||||||
|
@ -5444,10 +5525,13 @@ class Parser(Tokenizer):
|
||||||
location = self.getLocation(p, 2)
|
location = self.getLocation(p, 2)
|
||||||
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
||||||
allowDoubleUnderscore=True)
|
allowDoubleUnderscore=True)
|
||||||
keyType = p[3]
|
|
||||||
valueType = None
|
|
||||||
if (len(p) > 6):
|
if (len(p) > 6):
|
||||||
|
keyType = p[3]
|
||||||
valueType = p[5]
|
valueType = p[5]
|
||||||
|
else:
|
||||||
|
keyType = None
|
||||||
|
valueType = p[3]
|
||||||
|
|
||||||
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
|
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
|
||||||
|
|
||||||
def p_Setlike(self, p):
|
def p_Setlike(self, p):
|
||||||
|
@ -6518,7 +6602,7 @@ class Parser(Tokenizer):
|
||||||
if isinstance(m, IDLIterable):
|
if isinstance(m, IDLIterable):
|
||||||
iterable = m
|
iterable = m
|
||||||
break
|
break
|
||||||
if iterable:
|
if iterable and iterable.isPairIterator():
|
||||||
def simpleExtendedAttr(str):
|
def simpleExtendedAttr(str):
|
||||||
return IDLExtendedAttribute(iface.location, (str, ))
|
return IDLExtendedAttribute(iface.location, (str, ))
|
||||||
nextMethod = IDLMethod(
|
nextMethod = IDLMethod(
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
short a;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo1 {
|
||||||
|
Foo[] b;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Array must not contain dictionary "
|
||||||
|
"as element type.")
|
|
@ -0,0 +1,72 @@
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
interface TestByteString {
|
||||||
|
attribute ByteString bs;
|
||||||
|
attribute DOMString ds;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish();
|
||||||
|
|
||||||
|
harness.ok(True, "TestByteString interface parsed without error.")
|
||||||
|
|
||||||
|
harness.check(len(results), 1, "Should be one production")
|
||||||
|
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||||
|
"Should be an IDLInterface")
|
||||||
|
iface = results[0]
|
||||||
|
harness.check(iface.identifier.QName(), "::TestByteString", "Interface has the right QName")
|
||||||
|
harness.check(iface.identifier.name, "TestByteString", "Interface has the right name")
|
||||||
|
harness.check(iface.parent, None, "Interface has no parent")
|
||||||
|
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 2, "Should be two productions")
|
||||||
|
|
||||||
|
attr = members[0]
|
||||||
|
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||||
|
harness.check(attr.identifier.QName(), "::TestByteString::bs", "Attr has correct QName")
|
||||||
|
harness.check(attr.identifier.name, "bs", "Attr has correct name")
|
||||||
|
harness.check(str(attr.type), "ByteString", "Attr type is the correct name")
|
||||||
|
harness.ok(attr.type.isByteString(), "Should be ByteString type")
|
||||||
|
harness.ok(attr.type.isString(), "Should be String collective type")
|
||||||
|
harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type")
|
||||||
|
|
||||||
|
# now check we haven't broken DOMStrings in the process.
|
||||||
|
attr = members[1]
|
||||||
|
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||||
|
harness.check(attr.identifier.QName(), "::TestByteString::ds", "Attr has correct QName")
|
||||||
|
harness.check(attr.identifier.name, "ds", "Attr has correct name")
|
||||||
|
harness.check(str(attr.type), "String", "Attr type is the correct name")
|
||||||
|
harness.ok(attr.type.isDOMString(), "Should be DOMString type")
|
||||||
|
harness.ok(attr.type.isString(), "Should be String collective type")
|
||||||
|
harness.ok(not attr.type.isByteString(), "Should be not be ByteString type")
|
||||||
|
|
||||||
|
# Cannot represent constant ByteString in IDL.
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface ConstByteString {
|
||||||
|
const ByteString foo = "hello"
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except WebIDL.WebIDLError:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should have thrown a WebIDL error")
|
||||||
|
|
||||||
|
# Cannot have optional ByteStrings with default values
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface OptionalByteString {
|
||||||
|
void passByteString(optional ByteString arg = "hello");
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results2 = parser.finish();
|
||||||
|
except WebIDL.WebIDLError:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown a WebIDL error")
|
||||||
|
|
|
@ -12,7 +12,7 @@ def WebIDLTest(parser, harness):
|
||||||
results = parser.finish()
|
results = parser.finish()
|
||||||
|
|
||||||
harness.ok(True, "TestCallback interface parsed without error.")
|
harness.ok(True, "TestCallback interface parsed without error.")
|
||||||
harness.check(len(results), 2, "Should be one production.")
|
harness.check(len(results), 2, "Should be two productions.")
|
||||||
iface = results[0]
|
iface = results[0]
|
||||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
"Should be an IDLInterface")
|
"Should be an IDLInterface")
|
||||||
|
|
|
@ -45,3 +45,50 @@ def WebIDLTest(parser, harness):
|
||||||
|
|
||||||
harness.ok(threw, "Should not allow callback parent of non-callback interface")
|
harness.ok(threw, "Should not allow callback parent of non-callback interface")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
callback interface TestCallbackInterface1 {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface2 {
|
||||||
|
void foo(DOMString arg);
|
||||||
|
void foo(TestCallbackInterface1 arg);
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface3 {
|
||||||
|
void foo(DOMString arg);
|
||||||
|
void foo(TestCallbackInterface1 arg);
|
||||||
|
static void bar();
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface4 {
|
||||||
|
void foo(DOMString arg);
|
||||||
|
void foo(TestCallbackInterface1 arg);
|
||||||
|
static void bar();
|
||||||
|
const long baz = 5;
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface5 {
|
||||||
|
static attribute boolean bool;
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface6 {
|
||||||
|
void foo(DOMString arg);
|
||||||
|
void foo(TestCallbackInterface1 arg);
|
||||||
|
void bar();
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface7 {
|
||||||
|
static attribute boolean bool;
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface8 {
|
||||||
|
attribute boolean bool;
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface9 : TestCallbackInterface1 {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
callback interface TestCallbackInterface10 : TestCallbackInterface1 {
|
||||||
|
void bar();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
for (i, iface) in enumerate(results):
|
||||||
|
harness.check(iface.isSingleOperationInterface(), i < 4,
|
||||||
|
"Interface %s should be a single operation interface" %
|
||||||
|
iface.identifier.name)
|
||||||
|
|
|
@ -1,5 +1,30 @@
|
||||||
import WebIDL
|
import WebIDL
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
("::TestConsts::zero", "zero", "Byte", 0),
|
||||||
|
("::TestConsts::b", "b", "Byte", -1),
|
||||||
|
("::TestConsts::o", "o", "Octet", 2),
|
||||||
|
("::TestConsts::s", "s", "Short", -3),
|
||||||
|
("::TestConsts::us", "us", "UnsignedShort", 4),
|
||||||
|
("::TestConsts::l", "l", "Long", -5),
|
||||||
|
("::TestConsts::ul", "ul", "UnsignedLong", 6),
|
||||||
|
("::TestConsts::ull", "ull", "UnsignedLongLong", 7),
|
||||||
|
("::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),
|
||||||
|
("::TestConsts::udb", "udb", "UnrestrictedDouble", 0.2),
|
||||||
|
("::TestConsts::fli", "fli", "Float", 2),
|
||||||
|
("::TestConsts::dbi", "dbi", "Double", 2),
|
||||||
|
("::TestConsts::ufli", "ufli", "UnrestrictedFloat", 2),
|
||||||
|
("::TestConsts::udbi", "udbi", "UnrestrictedDouble", 2),
|
||||||
|
]
|
||||||
|
|
||||||
def WebIDLTest(parser, harness):
|
def WebIDLTest(parser, harness):
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface TestConsts {
|
interface TestConsts {
|
||||||
|
@ -17,6 +42,14 @@ def WebIDLTest(parser, harness):
|
||||||
const boolean? n = null;
|
const boolean? n = null;
|
||||||
const boolean? nt = true;
|
const boolean? nt = true;
|
||||||
const boolean? nf = false;
|
const boolean? nf = false;
|
||||||
|
const float fl = 0.2;
|
||||||
|
const double db = 0.2;
|
||||||
|
const unrestricted float ufl = 0.2;
|
||||||
|
const unrestricted double udb = 0.2;
|
||||||
|
const float fli = 2;
|
||||||
|
const double dbi = 2;
|
||||||
|
const unrestricted float ufli = 2;
|
||||||
|
const unrestricted double udbi = 2;
|
||||||
};
|
};
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -29,11 +62,9 @@ def WebIDLTest(parser, harness):
|
||||||
"Should be an IDLInterface")
|
"Should be an IDLInterface")
|
||||||
harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName")
|
harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName")
|
||||||
harness.check(iface.identifier.name, "TestConsts", "Interface has the right name")
|
harness.check(iface.identifier.name, "TestConsts", "Interface has the right name")
|
||||||
harness.check(len(iface.members), 14, "Expect 14 members")
|
harness.check(len(iface.members), len(expected), "Expect %s members" % len(expected))
|
||||||
|
|
||||||
consts = iface.members
|
for (const, (QName, name, type, value)) in zip(iface.members, expected):
|
||||||
|
|
||||||
def checkConst(const, QName, name, type, value):
|
|
||||||
harness.ok(isinstance(const, WebIDL.IDLConst),
|
harness.ok(isinstance(const, WebIDL.IDLConst),
|
||||||
"Should be an IDLConst")
|
"Should be an IDLConst")
|
||||||
harness.ok(const.isConst(), "Const is a const")
|
harness.ok(const.isConst(), "Const is a const")
|
||||||
|
@ -47,18 +78,3 @@ def WebIDLTest(parser, harness):
|
||||||
"Const's value has the same type as the type")
|
"Const's value has the same type as the type")
|
||||||
harness.check(const.value.value, value, "Const value has the right value.")
|
harness.check(const.value.value, value, "Const value has the right value.")
|
||||||
|
|
||||||
checkConst(consts[0], "::TestConsts::zero", "zero", "Byte", 0)
|
|
||||||
checkConst(consts[1], "::TestConsts::b", "b", "Byte", -1)
|
|
||||||
checkConst(consts[2], "::TestConsts::o", "o", "Octet", 2)
|
|
||||||
checkConst(consts[3], "::TestConsts::s", "s", "Short", -3)
|
|
||||||
checkConst(consts[4], "::TestConsts::us", "us", "UnsignedShort", 4)
|
|
||||||
checkConst(consts[5], "::TestConsts::l", "l", "Long", -5)
|
|
||||||
checkConst(consts[6], "::TestConsts::ul", "ul", "UnsignedLong", 6)
|
|
||||||
checkConst(consts[7], "::TestConsts::ull", "ull", "UnsignedLongLong", 7)
|
|
||||||
checkConst(consts[8], "::TestConsts::ll", "ll", "LongLong", -8)
|
|
||||||
checkConst(consts[9], "::TestConsts::t", "t", "Boolean", True)
|
|
||||||
checkConst(consts[10], "::TestConsts::f", "f", "Boolean", False)
|
|
||||||
checkConst(consts[11], "::TestConsts::n", "n", "BooleanOrNull", None)
|
|
||||||
checkConst(consts[12], "::TestConsts::nt", "nt", "BooleanOrNull", True)
|
|
||||||
checkConst(consts[13], "::TestConsts::nf", "nf", "BooleanOrNull", False)
|
|
||||||
|
|
||||||
|
|
|
@ -26,3 +26,11 @@ def WebIDLTest(parser, harness):
|
||||||
threw = True
|
threw = True
|
||||||
|
|
||||||
harness.ok(threw, "Should have thrown.")
|
harness.ok(threw, "Should have thrown.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
|
||||||
|
parser.parse("""
|
||||||
|
[NoInterfaceObject, NamedConstructor=FooBar]
|
||||||
|
interface TestNamedConstructorNoInterfaceObject {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
interface WithDates {
|
||||||
|
attribute Date foo;
|
||||||
|
void bar(Date arg);
|
||||||
|
void baz(sequence<Date> arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.ok(results[0].members[0].type.isDate(), "Should have Date")
|
||||||
|
harness.ok(results[0].members[1].signatures()[0][1][0].type.isDate(),
|
||||||
|
"Should have Date argument")
|
||||||
|
harness.ok(not results[0].members[2].signatures()[0][1][0].type.isDate(),
|
||||||
|
"Should have non-Date argument")
|
|
@ -108,20 +108,6 @@ def WebIDLTest(parser, harness):
|
||||||
|
|
||||||
harness.ok(threw, "Should not allow [TreatNullAs] on dictionary members");
|
harness.ok(threw, "Should not allow [TreatNullAs] on dictionary members");
|
||||||
|
|
||||||
parser = parser.reset()
|
|
||||||
threw = False
|
|
||||||
try:
|
|
||||||
parser.parse("""
|
|
||||||
dictionary A {
|
|
||||||
[TreatUndefinedAs=EmptyString] DOMString foo;
|
|
||||||
};
|
|
||||||
""")
|
|
||||||
results = parser.finish()
|
|
||||||
except:
|
|
||||||
threw = True
|
|
||||||
|
|
||||||
harness.ok(threw, "Should not allow [TreatUndefinedAs] on dictionary members");
|
|
||||||
|
|
||||||
parser = parser.reset()
|
parser = parser.reset()
|
||||||
threw = False
|
threw = False
|
||||||
try:
|
try:
|
||||||
|
@ -138,6 +124,23 @@ def WebIDLTest(parser, harness):
|
||||||
|
|
||||||
harness.ok(threw, "Trailing dictionary arg must be optional")
|
harness.ok(threw, "Trailing dictionary arg must be optional")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
void doFoo((A or DOMString) arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Trailing union arg containing a dictionary must be optional")
|
||||||
|
|
||||||
parser = parser.reset()
|
parser = parser.reset()
|
||||||
threw = False
|
threw = False
|
||||||
try:
|
try:
|
||||||
|
@ -154,6 +157,41 @@ def WebIDLTest(parser, harness):
|
||||||
|
|
||||||
harness.ok(threw, "Dictionary arg followed by optional arg must be optional")
|
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(A arg1, optional long arg2, long arg3);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(not threw,
|
||||||
|
"Dictionary arg followed by non-optional arg doesn't have to be optional")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
void doFoo((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 "
|
||||||
|
"be optional")
|
||||||
|
|
||||||
parser = parser.reset()
|
parser = parser.reset()
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
dictionary A {
|
dictionary A {
|
||||||
|
@ -188,7 +226,7 @@ def WebIDLTest(parser, harness):
|
||||||
dictionary A {
|
dictionary A {
|
||||||
};
|
};
|
||||||
interface X {
|
interface X {
|
||||||
void doFoo((A or long)? arg1);
|
void doFoo(optional (A or long)? arg1);
|
||||||
};
|
};
|
||||||
""")
|
""")
|
||||||
results = parser.finish()
|
results = parser.finish()
|
||||||
|
@ -196,3 +234,322 @@ def WebIDLTest(parser, harness):
|
||||||
threw = True
|
threw = True
|
||||||
|
|
||||||
harness.ok(threw, "Dictionary arg must not be in a nullable union")
|
harness.ok(threw, "Dictionary arg must not be in a nullable union")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
void doFoo(optional (A or long?) arg1);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Dictionary must not be in a union with a nullable type")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
void doFoo(optional (long? or A) arg1);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"A nullable type must not be in a union with a dictionary")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
A? doFoo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.ok(True, "Dictionary return value can be nullable")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
void doFoo(optional A arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.ok(True, "Dictionary arg should actually parse")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
};
|
||||||
|
interface X {
|
||||||
|
void doFoo(optional (A or DOMString) arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.ok(True, "Union arg containing a dictionary should actually parse")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
Foo foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo3 : Foo {
|
||||||
|
short d;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo2 : Foo3 {
|
||||||
|
boolean c;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo1 : Foo2 {
|
||||||
|
long a;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo {
|
||||||
|
Foo1 b;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be a Dictionary that "
|
||||||
|
"inherits from its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
(Foo or DOMString)[]? b;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be a Nullable type "
|
||||||
|
"whose inner type includes its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
(DOMString or Foo) b;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be a Union type, one of "
|
||||||
|
"whose member types includes its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
sequence<sequence<sequence<Foo>>> c;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be a Sequence type "
|
||||||
|
"whose element type includes its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
(DOMString or Foo)[] d;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be an Array type "
|
||||||
|
"whose element type includes its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
Foo1 b;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo3 {
|
||||||
|
Foo d;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo2 : Foo3 {
|
||||||
|
short c;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Foo1 : Foo2 {
|
||||||
|
long a;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be a Dictionary, one of whose "
|
||||||
|
"members or inherited members has a type that includes "
|
||||||
|
"its Dictionary.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Bar {
|
||||||
|
Foo? d;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Member type must not be a nullable dictionary")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
unrestricted float urFloat = 0;
|
||||||
|
unrestricted float urFloat2 = 1.1;
|
||||||
|
unrestricted float urFloat3 = -1.1;
|
||||||
|
unrestricted float? urFloat4 = null;
|
||||||
|
unrestricted float infUrFloat = Infinity;
|
||||||
|
unrestricted float negativeInfUrFloat = -Infinity;
|
||||||
|
unrestricted float nanUrFloat = NaN;
|
||||||
|
|
||||||
|
unrestricted double urDouble = 0;
|
||||||
|
unrestricted double urDouble2 = 1.1;
|
||||||
|
unrestricted double urDouble3 = -1.1;
|
||||||
|
unrestricted double? urDouble4 = null;
|
||||||
|
unrestricted double infUrDouble = Infinity;
|
||||||
|
unrestricted double negativeInfUrDouble = -Infinity;
|
||||||
|
unrestricted double nanUrDouble = NaN;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.ok(True, "Parsing default values for unrestricted types succeeded.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
double f = Infinity;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Only unrestricted values can be initialized to Infinity")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
double f = -Infinity;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Only unrestricted values can be initialized to -Infinity")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
double f = NaN;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Only unrestricted values can be initialized to NaN")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
float f = Infinity;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Only unrestricted values can be initialized to Infinity")
|
||||||
|
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
float f = -Infinity;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Only unrestricted values can be initialized to -Infinity")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Foo {
|
||||||
|
float f = NaN;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Only unrestricted values can be initialized to NaN")
|
||||||
|
|
|
@ -148,3 +148,149 @@ def WebIDLTest(parser, harness):
|
||||||
threw = True
|
threw = True
|
||||||
|
|
||||||
harness.ok(threw, "Should throw when there is no distinguishing index")
|
harness.ok(threw, "Should throw when there is no distinguishing index")
|
||||||
|
|
||||||
|
# Now let's test our whole distinguishability table
|
||||||
|
argTypes = [ "long", "short", "long?", "short?", "boolean",
|
||||||
|
"boolean?", "DOMString", "ByteString", "Enum", "Enum2",
|
||||||
|
"Interface", "Interface?",
|
||||||
|
"AncestorInterface", "UnrelatedInterface",
|
||||||
|
"ImplementedInterface", "CallbackInterface",
|
||||||
|
"CallbackInterface?", "CallbackInterface2",
|
||||||
|
"object", "Callback", "Callback2", "optional Dict",
|
||||||
|
"optional Dict2", "sequence<long>", "sequence<short>",
|
||||||
|
"MozMap<object>", "MozMap<Dict>", "MozMap<long>",
|
||||||
|
"long[]", "short[]", "Date", "Date?", "any",
|
||||||
|
"Promise<any>", "Promise<any>?",
|
||||||
|
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
|
||||||
|
"Uint8Array", "Uint16Array" ]
|
||||||
|
# When we can parse Date and RegExp, we need to add them here.
|
||||||
|
|
||||||
|
# Try to categorize things a bit to keep list lengths down
|
||||||
|
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>?")]
|
||||||
|
numerics = [ "long", "short", "long?", "short?" ]
|
||||||
|
booleans = [ "boolean", "boolean?" ]
|
||||||
|
primitives = numerics + booleans
|
||||||
|
nonNumerics = allBut(argTypes, numerics)
|
||||||
|
nonBooleans = allBut(argTypes, booleans)
|
||||||
|
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString" ]
|
||||||
|
nonStrings = allBut(argTypes, strings)
|
||||||
|
nonObjects = primitives + strings
|
||||||
|
objects = allBut(argTypes, nonObjects )
|
||||||
|
bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
|
||||||
|
sharedBufferSourceTypes = ["SharedArrayBuffer"]
|
||||||
|
interfaces = [ "Interface", "Interface?", "AncestorInterface",
|
||||||
|
"UnrelatedInterface", "ImplementedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes
|
||||||
|
nullables = ["long?", "short?", "boolean?", "Interface?",
|
||||||
|
"CallbackInterface?", "optional Dict", "optional Dict2",
|
||||||
|
"Date?", "any", "Promise<any>?"]
|
||||||
|
dates = [ "Date", "Date?" ]
|
||||||
|
sequences = [ "sequence<long>", "sequence<short>" ]
|
||||||
|
arrays = [ "long[]", "short[]" ]
|
||||||
|
nonUserObjects = nonObjects + interfaces + dates + sequences
|
||||||
|
otherObjects = allBut(argTypes, nonUserObjects + ["object"])
|
||||||
|
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] +
|
||||||
|
otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes)
|
||||||
|
mozMaps = [ "MozMap<object>", "MozMap<Dict>", "MozMap<long>" ]
|
||||||
|
|
||||||
|
# Build a representation of the distinguishability table as a dict
|
||||||
|
# of dicts, holding True values where needed, holes elsewhere.
|
||||||
|
data = dict();
|
||||||
|
for type in argTypes:
|
||||||
|
data[type] = dict()
|
||||||
|
def setDistinguishable(type, types):
|
||||||
|
for other in types:
|
||||||
|
data[type][other] = True
|
||||||
|
|
||||||
|
setDistinguishable("long", nonNumerics)
|
||||||
|
setDistinguishable("short", nonNumerics)
|
||||||
|
setDistinguishable("long?", allBut(nonNumerics, nullables))
|
||||||
|
setDistinguishable("short?", allBut(nonNumerics, nullables))
|
||||||
|
setDistinguishable("boolean", nonBooleans)
|
||||||
|
setDistinguishable("boolean?", allBut(nonBooleans, nullables))
|
||||||
|
setDistinguishable("DOMString", nonStrings)
|
||||||
|
setDistinguishable("ByteString", nonStrings)
|
||||||
|
setDistinguishable("USVString", nonStrings)
|
||||||
|
setDistinguishable("Enum", nonStrings)
|
||||||
|
setDistinguishable("Enum2", nonStrings)
|
||||||
|
setDistinguishable("Interface", notRelatedInterfaces)
|
||||||
|
setDistinguishable("Interface?", allBut(notRelatedInterfaces, nullables))
|
||||||
|
setDistinguishable("AncestorInterface", notRelatedInterfaces)
|
||||||
|
setDistinguishable("UnrelatedInterface",
|
||||||
|
allBut(argTypes, ["object", "UnrelatedInterface"]))
|
||||||
|
setDistinguishable("ImplementedInterface", notRelatedInterfaces)
|
||||||
|
setDistinguishable("CallbackInterface", nonUserObjects)
|
||||||
|
setDistinguishable("CallbackInterface?", allBut(nonUserObjects, nullables))
|
||||||
|
setDistinguishable("CallbackInterface2", nonUserObjects)
|
||||||
|
setDistinguishable("object", nonObjects)
|
||||||
|
setDistinguishable("Callback", nonUserObjects)
|
||||||
|
setDistinguishable("Callback2", nonUserObjects)
|
||||||
|
setDistinguishable("optional Dict", allBut(nonUserObjects, nullables))
|
||||||
|
setDistinguishable("optional Dict2", allBut(nonUserObjects, nullables))
|
||||||
|
setDistinguishable("sequence<long>",
|
||||||
|
allBut(argTypes, sequences + arrays + ["object"]))
|
||||||
|
setDistinguishable("sequence<short>",
|
||||||
|
allBut(argTypes, sequences + arrays + ["object"]))
|
||||||
|
setDistinguishable("MozMap<object>", nonUserObjects)
|
||||||
|
setDistinguishable("MozMap<Dict>", nonUserObjects)
|
||||||
|
setDistinguishable("MozMap<long>", nonUserObjects)
|
||||||
|
setDistinguishable("long[]", allBut(nonUserObjects, sequences))
|
||||||
|
setDistinguishable("short[]", allBut(nonUserObjects, sequences))
|
||||||
|
setDistinguishable("Date", allBut(argTypes, dates + ["object"]))
|
||||||
|
setDistinguishable("Date?", allBut(argTypes, dates + nullables + ["object"]))
|
||||||
|
setDistinguishable("any", [])
|
||||||
|
setDistinguishable("Promise<any>", [])
|
||||||
|
setDistinguishable("Promise<any>?", [])
|
||||||
|
setDistinguishable("ArrayBuffer", allBut(argTypes, ["ArrayBuffer", "object"]))
|
||||||
|
setDistinguishable("ArrayBufferView", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"]))
|
||||||
|
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"]))
|
||||||
|
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"]))
|
||||||
|
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
|
||||||
|
|
||||||
|
def areDistinguishable(type1, type2):
|
||||||
|
return data[type1].get(type2, False)
|
||||||
|
|
||||||
|
def checkDistinguishability(parser, type1, type2):
|
||||||
|
idlTemplate = """
|
||||||
|
enum Enum { "a", "b" };
|
||||||
|
enum Enum2 { "c", "d" };
|
||||||
|
interface Interface : AncestorInterface {};
|
||||||
|
interface AncestorInterface {};
|
||||||
|
interface UnrelatedInterface {};
|
||||||
|
interface ImplementedInterface {};
|
||||||
|
Interface implements ImplementedInterface;
|
||||||
|
callback interface CallbackInterface {};
|
||||||
|
callback interface CallbackInterface2 {};
|
||||||
|
callback Callback = any();
|
||||||
|
callback Callback2 = long(short arg);
|
||||||
|
dictionary Dict {};
|
||||||
|
dictionary Dict2 {};
|
||||||
|
interface _Promise {};
|
||||||
|
interface TestInterface {%s
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
methodTemplate = """
|
||||||
|
void myMethod(%s arg);"""
|
||||||
|
methods = (methodTemplate % type1) + (methodTemplate % type2)
|
||||||
|
idl = idlTemplate % methods
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(idl)
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
if areDistinguishable(type1, type2):
|
||||||
|
harness.ok(not threw,
|
||||||
|
"Should not throw for '%s' and '%s' because they are distinguishable" % (type1, type2))
|
||||||
|
else:
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should throw for '%s' and '%s' because they are not distinguishable" % (type1, type2))
|
||||||
|
|
||||||
|
# Enumerate over everything in both orders, since order matters in
|
||||||
|
# terms of our implementation of distinguishability checks
|
||||||
|
for type1 in argTypes:
|
||||||
|
for type2 in argTypes:
|
||||||
|
checkDistinguishability(parser, type1, type2)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface X {
|
||||||
|
const sequence<long> foo = [];
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Constant cannot have [] as a default value")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
|
||||||
|
parser.parse("""
|
||||||
|
interface X {
|
||||||
|
void foo(optional sequence<long> arg = []);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish();
|
||||||
|
|
||||||
|
harness.ok(isinstance(
|
||||||
|
results[0].members[0].signatures()[0][1][0].defaultValue,
|
||||||
|
WebIDL.IDLEmptySequenceValue),
|
||||||
|
"Should have IDLEmptySequenceValue as default value of argument")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
|
||||||
|
parser.parse("""
|
||||||
|
dictionary X {
|
||||||
|
sequence<long> foo = [];
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish();
|
||||||
|
|
||||||
|
harness.ok(isinstance(results[0].members[0].defaultValue,
|
||||||
|
WebIDL.IDLEmptySequenceValue),
|
||||||
|
"Should have IDLEmptySequenceValue as default value of "
|
||||||
|
"dictionary member")
|
||||||
|
|
|
@ -79,3 +79,15 @@ def WebIDLTest(parser, harness):
|
||||||
threw = True
|
threw = True
|
||||||
|
|
||||||
harness.ok(threw, "Should not allow a bogus default value for an enum")
|
harness.ok(threw, "Should not allow a bogus default value for an enum")
|
||||||
|
|
||||||
|
# Now reset our parser
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
enum Enum {
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 1, "Should allow trailing comma in enum")
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
[PrimaryGlobal] interface Foo {};
|
||||||
|
[Global=(Bar1,Bar2)] interface Bar {};
|
||||||
|
[Global=Baz2] interface Baz {};
|
||||||
|
|
||||||
|
[Exposed=(Foo,Bar1)]
|
||||||
|
interface Iface {
|
||||||
|
void method1();
|
||||||
|
|
||||||
|
[Exposed=Bar1]
|
||||||
|
readonly attribute any attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
partial interface Iface {
|
||||||
|
void method2();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.check(len(results), 5, "Should know about five things");
|
||||||
|
iface = results[3]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 3, "Should have three members")
|
||||||
|
|
||||||
|
harness.ok(members[0].exposureSet == set(["Foo", "Bar"]),
|
||||||
|
"method1 should have the right exposure set")
|
||||||
|
harness.ok(members[0]._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||||
|
"method1 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(members[1].exposureSet == set(["Bar"]),
|
||||||
|
"attr should have the right exposure set")
|
||||||
|
harness.ok(members[1]._exposureGlobalNames == set(["Bar1"]),
|
||||||
|
"attr should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(members[2].exposureSet == set(["Foo"]),
|
||||||
|
"method2 should have the right exposure set")
|
||||||
|
harness.ok(members[2]._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"method2 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(iface.exposureSet == set(["Foo", "Bar"]),
|
||||||
|
"Iface should have the right exposure set")
|
||||||
|
harness.ok(iface._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||||
|
"Iface should have the right exposure global names")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
[PrimaryGlobal] interface Foo {};
|
||||||
|
[Global=(Bar1,Bar2)] interface Bar {};
|
||||||
|
[Global=Baz2] interface Baz {};
|
||||||
|
|
||||||
|
interface Iface2 {
|
||||||
|
void method3();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.check(len(results), 4, "Should know about four things");
|
||||||
|
iface = results[3]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 1, "Should have one member")
|
||||||
|
|
||||||
|
harness.ok(members[0].exposureSet == set(["Foo"]),
|
||||||
|
"method3 should have the right exposure set")
|
||||||
|
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"method3 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(iface.exposureSet == set(["Foo"]),
|
||||||
|
"Iface2 should have the right exposure set")
|
||||||
|
harness.ok(iface._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"Iface2 should have the right exposure global names")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
[PrimaryGlobal] interface Foo {};
|
||||||
|
[Global=(Bar1,Bar2)] interface Bar {};
|
||||||
|
[Global=Baz2] interface Baz {};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Iface3 {
|
||||||
|
void method4();
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=(Foo,Bar1)]
|
||||||
|
interface Mixin {
|
||||||
|
void method5();
|
||||||
|
};
|
||||||
|
|
||||||
|
Iface3 implements Mixin;
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 6, "Should know about six things");
|
||||||
|
iface = results[3]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 2, "Should have two members")
|
||||||
|
|
||||||
|
harness.ok(members[0].exposureSet == set(["Foo"]),
|
||||||
|
"method4 should have the right exposure set")
|
||||||
|
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]),
|
||||||
|
"method4 should have the right exposure global names")
|
||||||
|
|
||||||
|
harness.ok(members[1].exposureSet == set(["Foo", "Bar"]),
|
||||||
|
"method5 should have the right exposure set")
|
||||||
|
harness.ok(members[1]._exposureGlobalNames == set(["Foo", "Bar1"]),
|
||||||
|
"method5 should have the right exposure global names")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Bar {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on interface.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Bar {
|
||||||
|
[Exposed=Foo]
|
||||||
|
readonly attribute bool attr;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on attribute.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Bar {
|
||||||
|
[Exposed=Foo]
|
||||||
|
void operation();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on operation.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Bar {
|
||||||
|
[Exposed=Foo]
|
||||||
|
const long constant = 5;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on invalid Exposed value on constant.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global] interface Foo {};
|
||||||
|
[Global] interface Bar {};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Baz {
|
||||||
|
[Exposed=Bar]
|
||||||
|
void method();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on member exposed where its interface is not.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global] interface Foo {};
|
||||||
|
[Global] interface Bar {};
|
||||||
|
|
||||||
|
[Exposed=Foo]
|
||||||
|
interface Baz {
|
||||||
|
void method();
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Bar]
|
||||||
|
interface Mixin {};
|
||||||
|
|
||||||
|
Baz implements Mixin;
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown on LHS of implements being exposed where RHS is not.")
|
|
@ -0,0 +1,125 @@
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
typedef float myFloat;
|
||||||
|
typedef unrestricted float myUnrestrictedFloat;
|
||||||
|
interface FloatTypes {
|
||||||
|
attribute float f;
|
||||||
|
attribute unrestricted float uf;
|
||||||
|
attribute double d;
|
||||||
|
attribute unrestricted double ud;
|
||||||
|
[LenientFloat]
|
||||||
|
attribute float lf;
|
||||||
|
[LenientFloat]
|
||||||
|
attribute double ld;
|
||||||
|
|
||||||
|
void m1(float arg1, double arg2, float? arg3, double? arg4,
|
||||||
|
myFloat arg5, unrestricted float arg6,
|
||||||
|
unrestricted double arg7, unrestricted float? arg8,
|
||||||
|
unrestricted double? arg9, myUnrestrictedFloat arg10);
|
||||||
|
[LenientFloat]
|
||||||
|
void m2(float arg1, double arg2, float? arg3, double? arg4,
|
||||||
|
myFloat arg5, unrestricted float arg6,
|
||||||
|
unrestricted double arg7, unrestricted float? arg8,
|
||||||
|
unrestricted double? arg9, myUnrestrictedFloat arg10);
|
||||||
|
[LenientFloat]
|
||||||
|
void m3(float arg);
|
||||||
|
[LenientFloat]
|
||||||
|
void m4(double arg);
|
||||||
|
[LenientFloat]
|
||||||
|
void m5((float or FloatTypes) arg);
|
||||||
|
[LenientFloat]
|
||||||
|
void m6(sequence<float> arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.check(len(results), 3, "Should be two typedefs and one interface.")
|
||||||
|
iface = results[2]
|
||||||
|
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||||
|
"Should be an IDLInterface")
|
||||||
|
types = [a.type for a in iface.members if a.isAttr()]
|
||||||
|
harness.ok(types[0].isFloat(), "'float' is a float")
|
||||||
|
harness.ok(not types[0].isUnrestricted(), "'float' is not unrestricted")
|
||||||
|
harness.ok(types[1].isFloat(), "'unrestricted float' is a float")
|
||||||
|
harness.ok(types[1].isUnrestricted(), "'unrestricted float' is unrestricted")
|
||||||
|
harness.ok(types[2].isFloat(), "'double' is a float")
|
||||||
|
harness.ok(not types[2].isUnrestricted(), "'double' is not unrestricted")
|
||||||
|
harness.ok(types[3].isFloat(), "'unrestricted double' is a float")
|
||||||
|
harness.ok(types[3].isUnrestricted(), "'unrestricted double' is unrestricted")
|
||||||
|
|
||||||
|
method = iface.members[6]
|
||||||
|
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
|
||||||
|
argtypes = [a.type for a in method.signatures()[0][1]]
|
||||||
|
for (idx, type) in enumerate(argtypes):
|
||||||
|
harness.ok(type.isFloat(), "Type %d should be float" % idx)
|
||||||
|
harness.check(type.isUnrestricted(), idx >= 5,
|
||||||
|
"Type %d should %sbe unrestricted" % (
|
||||||
|
idx, "" if idx >= 4 else "not "))
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface FloatTypes {
|
||||||
|
[LenientFloat]
|
||||||
|
long m(float arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "[LenientFloat] only allowed on void methods")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface FloatTypes {
|
||||||
|
[LenientFloat]
|
||||||
|
void m(unrestricted float arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface FloatTypes {
|
||||||
|
[LenientFloat]
|
||||||
|
void m(sequence<unrestricted float> arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface FloatTypes {
|
||||||
|
[LenientFloat]
|
||||||
|
void m((unrestricted float or FloatTypes) arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface FloatTypes {
|
||||||
|
[LenientFloat]
|
||||||
|
readonly attribute float foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "[LenientFloat] only allowed on writable attributes")
|
|
@ -0,0 +1,122 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo : Bar {
|
||||||
|
getter any(DOMString name);
|
||||||
|
};
|
||||||
|
interface Bar {};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.ok(results[0].isOnGlobalProtoChain(),
|
||||||
|
"[Global] interface should be on global's proto chain")
|
||||||
|
harness.ok(results[1].isOnGlobalProtoChain(),
|
||||||
|
"[Global] interface should be on global's proto chain")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
getter any(DOMString name);
|
||||||
|
setter void(DOMString name, any arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"named setter")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
getter any(DOMString name);
|
||||||
|
creator void(DOMString name, any arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"named creator")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
getter any(DOMString name);
|
||||||
|
deleter void(DOMString name);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"named deleter")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global, OverrideBuiltins]
|
||||||
|
interface Foo {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"[OverrideBuiltins]")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo : Bar {
|
||||||
|
};
|
||||||
|
[OverrideBuiltins]
|
||||||
|
interface Bar {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with an "
|
||||||
|
"[OverrideBuiltins] ancestor")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
};
|
||||||
|
interface Bar : Foo {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"descendant")
|
|
@ -186,3 +186,220 @@ def WebIDLTest(parser, harness):
|
||||||
threw = True
|
threw = True
|
||||||
|
|
||||||
harness.ok(threw, "Should not allow inheriting from an interface that is only forward declared")
|
harness.ok(threw, "Should not allow inheriting from an interface that is only forward declared")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
[Constructor(long arg)]
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean x;
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
[Constructor]
|
||||||
|
partial interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
void foo(long arg);
|
||||||
|
};
|
||||||
|
""");
|
||||||
|
results = parser.finish();
|
||||||
|
harness.check(len(results), 2,
|
||||||
|
"Should have two results with partial interface")
|
||||||
|
iface = results[0]
|
||||||
|
harness.check(len(iface.members), 3,
|
||||||
|
"Should have three members with partial interface")
|
||||||
|
harness.check(iface.members[0].identifier.name, "x",
|
||||||
|
"First member should be x with partial interface")
|
||||||
|
harness.check(iface.members[1].identifier.name, "foo",
|
||||||
|
"Second member should be foo with partial interface")
|
||||||
|
harness.check(len(iface.members[1].signatures()), 2,
|
||||||
|
"Should have two foo signatures with partial interface")
|
||||||
|
harness.check(iface.members[2].identifier.name, "y",
|
||||||
|
"Third member should be y with partial interface")
|
||||||
|
harness.check(len(iface.ctor().signatures()), 2,
|
||||||
|
"Should have two constructors with partial interface")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
[Constructor]
|
||||||
|
partial interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
void foo(long arg);
|
||||||
|
};
|
||||||
|
[Constructor(long arg)]
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean x;
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
""");
|
||||||
|
results = parser.finish();
|
||||||
|
harness.check(len(results), 2,
|
||||||
|
"Should have two results with reversed partial interface")
|
||||||
|
iface = results[1]
|
||||||
|
harness.check(len(iface.members), 3,
|
||||||
|
"Should have three members with reversed partial interface")
|
||||||
|
harness.check(iface.members[0].identifier.name, "x",
|
||||||
|
"First member should be x with reversed partial interface")
|
||||||
|
harness.check(iface.members[1].identifier.name, "foo",
|
||||||
|
"Second member should be foo with reversed partial interface")
|
||||||
|
harness.check(len(iface.members[1].signatures()), 2,
|
||||||
|
"Should have two foo signatures with reversed partial interface")
|
||||||
|
harness.check(iface.members[2].identifier.name, "y",
|
||||||
|
"Third member should be y with reversed partial interface")
|
||||||
|
harness.check(len(iface.ctor().signatures()), 2,
|
||||||
|
"Should have two constructors with reversed partial interface")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean x;
|
||||||
|
};
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow two non-partial interfaces with the same name")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
partial interface A {
|
||||||
|
readonly attribute boolean x;
|
||||||
|
};
|
||||||
|
partial interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Must have a non-partial interface for a given name")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
boolean x;
|
||||||
|
};
|
||||||
|
partial interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow a name collision between partial interface "
|
||||||
|
"and other object")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
boolean x;
|
||||||
|
};
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow a name collision between interface "
|
||||||
|
"and other object")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
dictionary A {
|
||||||
|
boolean x;
|
||||||
|
};
|
||||||
|
interface A;
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow a name collision between external interface "
|
||||||
|
"and other object")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean x;
|
||||||
|
};
|
||||||
|
interface A;
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow a name collision between external interface "
|
||||||
|
"and interface")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
interface A;
|
||||||
|
interface A;
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
harness.ok(len(results) == 1 and
|
||||||
|
isinstance(results[0], WebIDL.IDLExternalInterface),
|
||||||
|
"Should allow name collisions between external interface "
|
||||||
|
"declarations")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[SomeRandomAnnotation]
|
||||||
|
interface A {
|
||||||
|
readonly attribute boolean y;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"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,594 @@
|
||||||
|
import WebIDL
|
||||||
|
import traceback
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
|
||||||
|
def shouldPass(prefix, iface, expectedMembers, numProductions=1):
|
||||||
|
p = parser.reset()
|
||||||
|
p.parse(iface)
|
||||||
|
results = p.finish()
|
||||||
|
harness.check(len(results), numProductions,
|
||||||
|
"%s - Should have production count %d" % (prefix, numProductions))
|
||||||
|
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||||
|
"%s - Should be an IDLInterface" % (prefix))
|
||||||
|
# Make a copy, since we plan to modify it
|
||||||
|
expectedMembers = list(expectedMembers)
|
||||||
|
for m in results[0].members:
|
||||||
|
name = m.identifier.name
|
||||||
|
if (name, type(m)) in expectedMembers:
|
||||||
|
harness.ok(True, "%s - %s - Should be a %s" % (prefix, name,
|
||||||
|
type(m)))
|
||||||
|
expectedMembers.remove((name, type(m)))
|
||||||
|
else:
|
||||||
|
harness.ok(False, "%s - %s - Unknown symbol of type %s" %
|
||||||
|
(prefix, name, type(m)))
|
||||||
|
# A bit of a hoop because we can't generate the error string if we pass
|
||||||
|
if len(expectedMembers) == 0:
|
||||||
|
harness.ok(True, "Found all the members")
|
||||||
|
else:
|
||||||
|
harness.ok(False,
|
||||||
|
"Expected member not found: %s of type %s" %
|
||||||
|
(expectedMembers[0][0], expectedMembers[0][1]))
|
||||||
|
return results
|
||||||
|
|
||||||
|
def shouldFail(prefix, iface):
|
||||||
|
try:
|
||||||
|
p = parser.reset()
|
||||||
|
p.parse(iface)
|
||||||
|
p.finish()
|
||||||
|
harness.ok(False,
|
||||||
|
prefix + " - Interface passed when should've failed")
|
||||||
|
except WebIDL.WebIDLError, e:
|
||||||
|
harness.ok(True,
|
||||||
|
prefix + " - Interface failed as expected")
|
||||||
|
except Exception, e:
|
||||||
|
harness.ok(False,
|
||||||
|
prefix + " - Interface failed but not as a WebIDLError exception: %s" % e)
|
||||||
|
|
||||||
|
iterableMembers = [(x, WebIDL.IDLMethod) for x in ["entries", "keys",
|
||||||
|
"values", "forEach"]]
|
||||||
|
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has"]] +
|
||||||
|
[("__setlike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||||
|
iterableMembers)
|
||||||
|
setROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||||
|
setRWMembers = ([(x, WebIDL.IDLMethod) for x in ["add",
|
||||||
|
"clear",
|
||||||
|
"delete"]] +
|
||||||
|
setROMembers)
|
||||||
|
setROChromeMembers = ([(x, WebIDL.IDLMethod) for x in ["__add",
|
||||||
|
"__clear",
|
||||||
|
"__delete"]] +
|
||||||
|
setROMembers)
|
||||||
|
setRWChromeMembers = ([(x, WebIDL.IDLMethod) for x in ["__add",
|
||||||
|
"__clear",
|
||||||
|
"__delete"]] +
|
||||||
|
setRWMembers)
|
||||||
|
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has"]] +
|
||||||
|
[("__maplike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||||
|
iterableMembers)
|
||||||
|
mapROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||||
|
mapRWMembers = ([(x, WebIDL.IDLMethod) for x in ["set",
|
||||||
|
"clear",
|
||||||
|
"delete"]] + mapROMembers)
|
||||||
|
mapRWChromeMembers = ([(x, WebIDL.IDLMethod) for x in ["__set",
|
||||||
|
"__clear",
|
||||||
|
"__delete"]] +
|
||||||
|
mapRWMembers)
|
||||||
|
|
||||||
|
# OK, now that we've used iterableMembers to set up the above, append
|
||||||
|
# __iterable to it for the iterable<> case.
|
||||||
|
iterableMembers.append(("__iterable", WebIDL.IDLIterable))
|
||||||
|
|
||||||
|
valueIterableMembers = [("__iterable", WebIDL.IDLIterable)]
|
||||||
|
valueIterableMembers.append(("__indexedgetter", WebIDL.IDLMethod))
|
||||||
|
valueIterableMembers.append(("length", WebIDL.IDLAttribute))
|
||||||
|
|
||||||
|
disallowedIterableNames = ["keys", "entries", "values"]
|
||||||
|
disallowedMemberNames = ["forEach", "has", "size"] + disallowedIterableNames
|
||||||
|
mapDisallowedMemberNames = ["get"] + disallowedMemberNames
|
||||||
|
disallowedNonMethodNames = ["clear", "delete"]
|
||||||
|
mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames
|
||||||
|
setDisallowedNonMethodNames = ["add"] + disallowedNonMethodNames
|
||||||
|
|
||||||
|
#
|
||||||
|
# Simple Usage Tests
|
||||||
|
#
|
||||||
|
|
||||||
|
shouldPass("Iterable (key only)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
iterable<long>;
|
||||||
|
readonly attribute unsigned long length;
|
||||||
|
getter long(unsigned long index);
|
||||||
|
};
|
||||||
|
""", valueIterableMembers)
|
||||||
|
|
||||||
|
shouldPass("Iterable (key and value)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
iterable<long, long>;
|
||||||
|
};
|
||||||
|
""", iterableMembers,
|
||||||
|
# numProductions == 2 because of the generated iterator iface,
|
||||||
|
numProductions=2)
|
||||||
|
|
||||||
|
shouldPass("Maplike (readwrite)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""", mapRWMembers)
|
||||||
|
|
||||||
|
shouldPass("Maplike (readwrite)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""", mapRWMembers)
|
||||||
|
|
||||||
|
shouldPass("Maplike (readonly)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
readonly maplike<long, long>;
|
||||||
|
};
|
||||||
|
""", mapROMembers)
|
||||||
|
|
||||||
|
shouldPass("Setlike (readwrite)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
""", setRWMembers)
|
||||||
|
|
||||||
|
shouldPass("Setlike (readonly)",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
readonly setlike<long>;
|
||||||
|
};
|
||||||
|
""", setROMembers)
|
||||||
|
|
||||||
|
shouldPass("Inheritance of maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
""", mapRWMembers, numProductions=2)
|
||||||
|
|
||||||
|
shouldPass("Implements with maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
};
|
||||||
|
Foo2 implements Foo1;
|
||||||
|
""", mapRWMembers, numProductions=3)
|
||||||
|
|
||||||
|
shouldPass("JS Implemented maplike interface",
|
||||||
|
"""
|
||||||
|
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
|
||||||
|
Constructor()]
|
||||||
|
interface Foo1 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
""", setRWChromeMembers)
|
||||||
|
|
||||||
|
shouldPass("JS Implemented maplike interface",
|
||||||
|
"""
|
||||||
|
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
|
||||||
|
Constructor()]
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""", mapRWChromeMembers)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Multiple maplike/setlike tests
|
||||||
|
#
|
||||||
|
|
||||||
|
shouldFail("Two maplike/setlikes on same interface",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
setlike<long>;
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Two iterable/setlikes on same interface",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
iterable<long>;
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Two iterables on same interface",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
iterable<long>;
|
||||||
|
iterable<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Two maplike/setlikes in partials",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
partial interface Foo1 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Conflicting maplike/setlikes across inheritance",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Conflicting maplike/iterable across inheritance",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
iterable<long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Conflicting maplike/setlikes across multistep inheritance",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Consequential interface with conflicting maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
Foo2 implements Foo1;
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Consequential interfaces with conflicting maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
setlike<long>;
|
||||||
|
};
|
||||||
|
interface Foo3 {
|
||||||
|
};
|
||||||
|
Foo3 implements Foo1;
|
||||||
|
Foo3 implements Foo2;
|
||||||
|
""")
|
||||||
|
|
||||||
|
#
|
||||||
|
# Member name collision tests
|
||||||
|
#
|
||||||
|
|
||||||
|
def testConflictingMembers(likeMember, conflictName, expectedMembers, methodPasses):
|
||||||
|
"""
|
||||||
|
Tests for maplike/setlike member generation against conflicting member
|
||||||
|
names. If methodPasses is True, this means we expect the interface to
|
||||||
|
pass in the case of method shadowing, and expectedMembers should be the
|
||||||
|
list of interface members to check against on the passing interface.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if methodPasses:
|
||||||
|
shouldPass("Conflicting method: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
%s;
|
||||||
|
[Throws]
|
||||||
|
void %s(long test1, double test2, double test3);
|
||||||
|
};
|
||||||
|
""" % (likeMember, conflictName), expectedMembers)
|
||||||
|
else:
|
||||||
|
shouldFail("Conflicting method: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
%s;
|
||||||
|
[Throws]
|
||||||
|
void %s(long test1, double test2, double test3);
|
||||||
|
};
|
||||||
|
""" % (likeMember, conflictName))
|
||||||
|
# Inherited conflicting methods should ALWAYS fail
|
||||||
|
shouldFail("Conflicting inherited method: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
void %s(long test1, double test2, double test3);
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
%s;
|
||||||
|
};
|
||||||
|
""" % (conflictName, likeMember))
|
||||||
|
shouldFail("Conflicting static method: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
%s;
|
||||||
|
static void %s(long test1, double test2, double test3);
|
||||||
|
};
|
||||||
|
""" % (likeMember, conflictName))
|
||||||
|
shouldFail("Conflicting attribute: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
%s
|
||||||
|
attribute double %s;
|
||||||
|
};
|
||||||
|
""" % (likeMember, conflictName))
|
||||||
|
shouldFail("Conflicting const: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
%s;
|
||||||
|
const double %s = 0;
|
||||||
|
};
|
||||||
|
""" % (likeMember, conflictName))
|
||||||
|
shouldFail("Conflicting static attribute: %s and %s" % (likeMember, conflictName),
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
%s;
|
||||||
|
static attribute long %s;
|
||||||
|
};
|
||||||
|
""" % (likeMember, conflictName))
|
||||||
|
|
||||||
|
for member in disallowedIterableNames:
|
||||||
|
testConflictingMembers("iterable<long, long>", member, iterableMembers, False)
|
||||||
|
for member in mapDisallowedMemberNames:
|
||||||
|
testConflictingMembers("maplike<long, long>", member, mapRWMembers, False)
|
||||||
|
for member in disallowedMemberNames:
|
||||||
|
testConflictingMembers("setlike<long>", member, setRWMembers, False)
|
||||||
|
for member in mapDisallowedNonMethodNames:
|
||||||
|
testConflictingMembers("maplike<long, long>", member, mapRWMembers, True)
|
||||||
|
for member in setDisallowedNonMethodNames:
|
||||||
|
testConflictingMembers("setlike<long>", member, setRWMembers, True)
|
||||||
|
|
||||||
|
shouldPass("Inheritance of maplike/setlike with child member collision",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
""", mapRWMembers, numProductions=2)
|
||||||
|
|
||||||
|
shouldPass("Inheritance of multi-level maplike/setlike with child member collision",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
""", mapRWMembers, numProductions=3)
|
||||||
|
|
||||||
|
shouldFail("Interface with consequential maplike/setlike interface member collision",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
Foo1 implements Foo2;
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Maplike interface with consequential interface member collision",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
Foo1 implements Foo2;
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldPass("Consequential Maplike interface with inherited interface member collision",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
};
|
||||||
|
Foo3 implements Foo1;
|
||||||
|
""", mapRWMembers, numProductions=4)
|
||||||
|
|
||||||
|
shouldPass("Inherited Maplike interface with consequential interface member collision",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo1 {
|
||||||
|
};
|
||||||
|
Foo3 implements Foo2;
|
||||||
|
""", mapRWMembers, numProductions=4)
|
||||||
|
|
||||||
|
shouldFail("Inheritance of name collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Inheritance of multi-level name collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
void entries();
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldPass("Inheritance of attribute collision with parent maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
attribute double size;
|
||||||
|
};
|
||||||
|
""", mapRWMembers, numProductions=2)
|
||||||
|
|
||||||
|
shouldPass("Inheritance of multi-level attribute collision with parent maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
attribute double size;
|
||||||
|
};
|
||||||
|
""", mapRWMembers, numProductions=3)
|
||||||
|
|
||||||
|
shouldFail("Inheritance of attribute collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
attribute double size;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Inheritance of multi-level attribute collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
attribute double size;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Inheritance of attribute/rw function collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
attribute double set;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Inheritance of const/rw function collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
const double set = 0;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldPass("Inheritance of rw function with same name in child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
""", mapRWMembers, numProductions=2)
|
||||||
|
|
||||||
|
shouldFail("Inheritance of unforgeable attribute collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
[Unforgeable]
|
||||||
|
attribute double size;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldFail("Inheritance of multi-level unforgeable attribute collision with child maplike/setlike",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
[Unforgeable]
|
||||||
|
attribute double size;
|
||||||
|
};
|
||||||
|
interface Foo2 : Foo1 {
|
||||||
|
};
|
||||||
|
interface Foo3 : Foo2 {
|
||||||
|
maplike<long, long>;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
shouldPass("Implemented interface with readonly allowable overrides",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
readonly setlike<long>;
|
||||||
|
readonly attribute boolean clear;
|
||||||
|
};
|
||||||
|
""", setROMembers + [("clear", WebIDL.IDLAttribute)])
|
||||||
|
|
||||||
|
shouldPass("JS Implemented read-only interface with readonly allowable overrides",
|
||||||
|
"""
|
||||||
|
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
|
||||||
|
Constructor()]
|
||||||
|
interface Foo1 {
|
||||||
|
readonly setlike<long>;
|
||||||
|
readonly attribute boolean clear;
|
||||||
|
};
|
||||||
|
""", setROChromeMembers + [("clear", WebIDL.IDLAttribute)])
|
||||||
|
|
||||||
|
shouldFail("JS Implemented read-write interface with non-readwrite allowable overrides",
|
||||||
|
"""
|
||||||
|
[JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
|
||||||
|
Constructor()]
|
||||||
|
interface Foo1 {
|
||||||
|
setlike<long>;
|
||||||
|
readonly attribute boolean clear;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
r = shouldPass("Check proper override of clear/delete/set",
|
||||||
|
"""
|
||||||
|
interface Foo1 {
|
||||||
|
maplike<long, long>;
|
||||||
|
long clear(long a, long b, double c, double d);
|
||||||
|
long set(long a, long b, double c, double d);
|
||||||
|
long delete(long a, long b, double c, double d);
|
||||||
|
};
|
||||||
|
""", mapRWMembers)
|
||||||
|
|
||||||
|
for m in r[0].members:
|
||||||
|
if m.identifier.name in ["clear", "set", "delete"]:
|
||||||
|
harness.ok(m.isMethod(), "%s should be a method" % m.identifier.name)
|
||||||
|
harness.check(m.maxArgCount, 4, "%s should have 4 arguments" % m.identifier.name)
|
||||||
|
harness.ok(not m.isMaplikeOrSetlikeOrIterableMethod(),
|
||||||
|
"%s should not be a maplike/setlike function" % m.identifier.name)
|
|
@ -123,23 +123,62 @@ def WebIDLTest(parser, harness):
|
||||||
try:
|
try:
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface A {
|
interface A {
|
||||||
[GetterInfallible] void foo();
|
void foo(optional float bar = 1);
|
||||||
};
|
};
|
||||||
""")
|
""")
|
||||||
results = parser.finish()
|
results = parser.finish()
|
||||||
except Exception, x:
|
except Exception, x:
|
||||||
threw = True
|
threw = True
|
||||||
harness.ok(threw, "Should not allow [GetterInfallible] on methods")
|
harness.ok(not threw, "Should allow integer to float type corecion")
|
||||||
|
|
||||||
parser = parser.reset()
|
parser = parser.reset()
|
||||||
threw = False
|
threw = False
|
||||||
try:
|
try:
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface A {
|
interface A {
|
||||||
[SetterInfallible] void foo();
|
[GetterThrows] void foo();
|
||||||
};
|
};
|
||||||
""")
|
""")
|
||||||
results = parser.finish()
|
results = parser.finish()
|
||||||
except Exception, x:
|
except Exception, x:
|
||||||
threw = True
|
threw = True
|
||||||
harness.ok(threw, "Should not allow [SetterInfallible] on methods")
|
harness.ok(threw, "Should not allow [GetterThrows] on methods")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface A {
|
||||||
|
[SetterThrows] void foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should not allow [SetterThrows] on methods")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface A {
|
||||||
|
[Throw] void foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should spell [Throws] correctly on methods")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface A {
|
||||||
|
void __noSuchMethod__();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception, x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw, "Should not allow __noSuchMethod__ methods")
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
dictionary Dict {};
|
||||||
|
interface MozMapArg {
|
||||||
|
void foo(MozMap<Dict> arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.check(len(results), 2, "Should know about two things");
|
||||||
|
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
|
||||||
|
"Should have an interface here");
|
||||||
|
members = results[1].members
|
||||||
|
harness.check(len(members), 1, "Should have one member")
|
||||||
|
harness.ok(members[0].isMethod(), "Should have method")
|
||||||
|
signature = members[0].signatures()[0]
|
||||||
|
args = signature[1]
|
||||||
|
harness.check(len(args), 1, "Should have one arg")
|
||||||
|
harness.ok(args[0].type.isMozMap(), "Should have a MozMap type here")
|
||||||
|
harness.ok(args[0].type.inner.isDictionary(),
|
||||||
|
"Should have a dictionary inner type")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface MozMapVoidArg {
|
||||||
|
void foo(MozMap<void> arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
|
@ -8,6 +8,11 @@ def WebIDLTest(parser, harness):
|
||||||
boolean abitharder(TestOverloads foo);
|
boolean abitharder(TestOverloads foo);
|
||||||
boolean abitharder(boolean foo);
|
boolean abitharder(boolean foo);
|
||||||
void abitharder(ArrayBuffer? foo);
|
void abitharder(ArrayBuffer? foo);
|
||||||
|
void withVariadics(long... numbers);
|
||||||
|
void withVariadics(TestOverloads iface);
|
||||||
|
void withVariadics(long num, TestOverloads iface);
|
||||||
|
void optionalTest();
|
||||||
|
void optionalTest(optional long num1, long num2);
|
||||||
};
|
};
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -20,7 +25,7 @@ def WebIDLTest(parser, harness):
|
||||||
"Should be an IDLInterface")
|
"Should be an IDLInterface")
|
||||||
harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
|
harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
|
||||||
harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
|
harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
|
||||||
harness.check(len(iface.members), 2, "Expect %s members" % 2)
|
harness.check(len(iface.members), 4, "Expect %s members" % 4)
|
||||||
|
|
||||||
member = iface.members[0]
|
member = iface.members[0]
|
||||||
harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
|
harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
|
||||||
|
@ -45,3 +50,11 @@ def WebIDLTest(parser, harness):
|
||||||
harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName")
|
harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName")
|
||||||
harness.check(argument.identifier.name, "arg1", "Argument has the right name")
|
harness.check(argument.identifier.name, "arg1", "Argument has the right name")
|
||||||
harness.check(str(argument.type), "Long", "Argument has the right type")
|
harness.check(str(argument.type), "Long", "Argument has the right type")
|
||||||
|
|
||||||
|
member = iface.members[3]
|
||||||
|
harness.check(len(member.overloadsForArgCount(0)), 1,
|
||||||
|
"Only one overload for no args")
|
||||||
|
harness.check(len(member.overloadsForArgCount(1)), 0,
|
||||||
|
"No overloads for one arg")
|
||||||
|
harness.check(len(member.overloadsForArgCount(2)), 1,
|
||||||
|
"Only one overload for two args")
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface _Promise {};
|
||||||
|
interface A {
|
||||||
|
legacycaller Promise<any> foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow Promise return values for legacycaller.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface _Promise {};
|
||||||
|
interface A {
|
||||||
|
Promise<any> foo();
|
||||||
|
long foo(long arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish();
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow overloads which have both Promise and "
|
||||||
|
"non-Promise return types.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface _Promise {};
|
||||||
|
interface A {
|
||||||
|
long foo(long arg);
|
||||||
|
Promise<any> foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish();
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should not allow overloads which have both Promise and "
|
||||||
|
"non-Promise return types.")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
interface _Promise {};
|
||||||
|
interface A {
|
||||||
|
Promise<any> foo();
|
||||||
|
Promise<any> foo(long arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish();
|
||||||
|
|
||||||
|
harness.ok(True,
|
||||||
|
"Should allow overloads which only have Promise and return "
|
||||||
|
"types.")
|
|
@ -0,0 +1,80 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface TestIface {
|
||||||
|
static attribute boolean prototype;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "The identifier of a static attribute must not be 'prototype'")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface TestIface {
|
||||||
|
static boolean prototype();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "The identifier of a static operation must not be 'prototype'")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface TestIface {
|
||||||
|
const boolean prototype = true;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "The identifier of a constant must not be 'prototype'")
|
||||||
|
|
||||||
|
# Make sure that we can parse non-static attributes with 'prototype' as identifier.
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
interface TestIface {
|
||||||
|
attribute boolean prototype;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
testIface = results[0];
|
||||||
|
harness.check(testIface.members[0].isStatic(), False, "Attribute should not be static")
|
||||||
|
harness.check(testIface.members[0].identifier.name, "prototype", "Attribute identifier should be 'prototype'")
|
||||||
|
|
||||||
|
# Make sure that we can parse non-static operations with 'prototype' as identifier.
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
interface TestIface {
|
||||||
|
boolean prototype();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
testIface = results[0];
|
||||||
|
harness.check(testIface.members[0].isStatic(), False, "Operation should not be static")
|
||||||
|
harness.check(testIface.members[0].identifier.name, "prototype", "Operation identifier should be 'prototype'")
|
||||||
|
|
||||||
|
# Make sure that we can parse dictionary members with 'prototype' as identifier.
|
||||||
|
parser = parser.reset()
|
||||||
|
parser.parse("""
|
||||||
|
dictionary TestDict {
|
||||||
|
boolean prototype;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
testDict = results[0];
|
||||||
|
harness.check(testDict.members[0].identifier.name, "prototype", "Dictionary member should be 'prototype'")
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface I {
|
||||||
|
[PutForwards=B] readonly attribute long A;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface I {
|
||||||
|
[PutForwards=B] readonly attribute J A;
|
||||||
|
};
|
||||||
|
interface J {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface I {
|
||||||
|
[PutForwards=B] attribute J A;
|
||||||
|
};
|
||||||
|
interface J {
|
||||||
|
attribute long B;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface I {
|
||||||
|
[PutForwards=B] static readonly attribute J A;
|
||||||
|
};
|
||||||
|
interface J {
|
||||||
|
attribute long B;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
callback interface I {
|
||||||
|
[PutForwards=B] readonly attribute J A;
|
||||||
|
};
|
||||||
|
interface J {
|
||||||
|
attribute long B;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface I {
|
||||||
|
[PutForwards=C] readonly attribute J A;
|
||||||
|
[PutForwards=C] readonly attribute J B;
|
||||||
|
};
|
||||||
|
interface J {
|
||||||
|
[PutForwards=D] readonly attribute K C;
|
||||||
|
};
|
||||||
|
interface K {
|
||||||
|
[PutForwards=A] readonly attribute I D;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown.")
|
|
@ -0,0 +1,58 @@
|
||||||
|
# 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
def should_throw(parser, harness, message, code):
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse(code)
|
||||||
|
parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown: %s" % message)
|
||||||
|
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
# The [Replaceable] extended attribute MUST take no arguments.
|
||||||
|
should_throw(parser, harness, "no arguments", """
|
||||||
|
interface I {
|
||||||
|
[Replaceable=X] readonly attribute long A;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
# An attribute with the [Replaceable] extended attribute MUST NOT also be
|
||||||
|
# declared with the [PutForwards] extended attribute.
|
||||||
|
should_throw(parser, harness, "PutForwards", """
|
||||||
|
interface I {
|
||||||
|
[PutForwards=B, Replaceable] readonly attribute J A;
|
||||||
|
};
|
||||||
|
interface J {
|
||||||
|
attribute long B;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
# The [Replaceable] extended attribute MUST NOT be used on an attribute
|
||||||
|
# that is not read only.
|
||||||
|
should_throw(parser, harness, "writable attribute", """
|
||||||
|
interface I {
|
||||||
|
[Replaceable] attribute long A;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
# The [Replaceable] extended attribute MUST NOT be used on a static
|
||||||
|
# attribute.
|
||||||
|
should_throw(parser, harness, "static attribute", """
|
||||||
|
interface I {
|
||||||
|
[Replaceable] static readonly attribute long A;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
# The [Replaceable] extended attribute MUST NOT be used on an attribute
|
||||||
|
# declared on a callback interface.
|
||||||
|
should_throw(parser, harness, "callback interface", """
|
||||||
|
callback interface I {
|
||||||
|
[Replaceable] readonly attribute long A;
|
||||||
|
};
|
||||||
|
""")
|
|
@ -0,0 +1,46 @@
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
interface TestStringifier {
|
||||||
|
stringifier;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.ok(isinstance(results[0].members[0], WebIDL.IDLMethod),
|
||||||
|
"Stringifer should be method")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface TestStringifier {
|
||||||
|
stringifier;
|
||||||
|
stringifier;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should not allow two 'stringifier;'")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface TestStringifier {
|
||||||
|
stringifier;
|
||||||
|
stringifier DOMString foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should not allow a 'stringifier;' and a 'stringifier()'")
|
||||||
|
|
|
@ -0,0 +1,253 @@
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 2,
|
||||||
|
"Should be able to inherit from an interface with "
|
||||||
|
"[Unforgeable] properties.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
const short foo = 10;
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 2,
|
||||||
|
"Should be able to inherit from an interface with "
|
||||||
|
"[Unforgeable] properties even if we have a constant with "
|
||||||
|
"the same name.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
static attribute short foo;
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 2,
|
||||||
|
"Should be able to inherit from an interface with "
|
||||||
|
"[Unforgeable] properties even if we have a static attribute "
|
||||||
|
"with the same name.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
static void foo();
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 2,
|
||||||
|
"Should be able to inherit from an interface with "
|
||||||
|
"[Unforgeable] properties even if we have a static operation "
|
||||||
|
"with the same name.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when shadowing unforgeable attribute on "
|
||||||
|
"parent with operation.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] void foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when shadowing unforgeable operation on "
|
||||||
|
"parent with operation.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
attribute short foo;
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when shadowing unforgeable attribute on "
|
||||||
|
"parent with attribute.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
attribute short foo;
|
||||||
|
};
|
||||||
|
interface Parent {
|
||||||
|
[Unforgeable] void foo();
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except Exception,x:
|
||||||
|
threw = True
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when shadowing unforgeable operation on "
|
||||||
|
"parent with attribute.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
};
|
||||||
|
interface Parent {};
|
||||||
|
interface Consequential {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
Parent implements Consequential;
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 4,
|
||||||
|
"Should be able to inherit from an interface with a "
|
||||||
|
"consequential interface with [Unforgeable] properties.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
interface Parent {};
|
||||||
|
interface Consequential {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
Parent implements Consequential;
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when shadowing unforgeable attribute "
|
||||||
|
"of parent's consequential interface.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
};
|
||||||
|
interface Parent : GrandParent {};
|
||||||
|
interface GrandParent {};
|
||||||
|
interface Consequential {
|
||||||
|
[Unforgeable] readonly attribute long foo;
|
||||||
|
};
|
||||||
|
GrandParent implements Consequential;
|
||||||
|
interface ChildConsequential {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
Child implements ChildConsequential;
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when our consequential interface shadows unforgeable attribute "
|
||||||
|
"of ancestor's consequential interface.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface Child : Parent {
|
||||||
|
};
|
||||||
|
interface Parent : GrandParent {};
|
||||||
|
interface GrandParent {};
|
||||||
|
interface Consequential {
|
||||||
|
[Unforgeable] void foo();
|
||||||
|
};
|
||||||
|
GrandParent implements Consequential;
|
||||||
|
interface ChildConsequential {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
Child implements ChildConsequential;
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown when our consequential interface shadows unforgeable operation "
|
||||||
|
"of ancestor's consequential interface.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
parser.parse("""
|
||||||
|
interface iface {
|
||||||
|
[Unforgeable] attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
harness.check(len(results), 1,
|
||||||
|
"Should allow writable [Unforgeable] attribute.")
|
||||||
|
|
||||||
|
parser = parser.reset();
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
interface iface {
|
||||||
|
[Unforgeable] static readonly attribute long foo;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw, "Should have thrown for static [Unforgeable] attribute.")
|
|
@ -62,6 +62,8 @@ def WebIDLTest(parser, harness):
|
||||||
"byte",
|
"byte",
|
||||||
"octet",
|
"octet",
|
||||||
"DOMString",
|
"DOMString",
|
||||||
|
"ByteString",
|
||||||
|
"USVString",
|
||||||
#"sequence<float>",
|
#"sequence<float>",
|
||||||
"object",
|
"object",
|
||||||
"ArrayBuffer",
|
"ArrayBuffer",
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
import WebIDL
|
||||||
|
|
||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
interface TestUSVString {
|
||||||
|
attribute USVString svs;
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish();
|
||||||
|
|
||||||
|
harness.check(len(results), 1, "Should be one production")
|
||||||
|
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||||
|
"Should be an IDLInterface")
|
||||||
|
iface = results[0]
|
||||||
|
harness.check(iface.identifier.QName(), "::TestUSVString",
|
||||||
|
"Interface has the right QName")
|
||||||
|
harness.check(iface.identifier.name, "TestUSVString",
|
||||||
|
"Interface has the right name")
|
||||||
|
harness.check(iface.parent, None, "Interface has no parent")
|
||||||
|
|
||||||
|
members = iface.members
|
||||||
|
harness.check(len(members), 1, "Should be one member")
|
||||||
|
|
||||||
|
attr = members[0]
|
||||||
|
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||||
|
harness.check(attr.identifier.QName(), "::TestUSVString::svs",
|
||||||
|
"Attr has correct QName")
|
||||||
|
harness.check(attr.identifier.name, "svs", "Attr has correct name")
|
||||||
|
harness.check(str(attr.type), "USVString",
|
||||||
|
"Attr type is the correct name")
|
||||||
|
harness.ok(attr.type.isUSVString(), "Should be USVString type")
|
||||||
|
harness.ok(attr.type.isString(), "Should be String collective type")
|
||||||
|
harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type")
|
|
@ -3,4 +3,8 @@ patch < abstract.patch
|
||||||
patch < debug.patch
|
patch < debug.patch
|
||||||
patch < legacy-unenumerable-named-properties.patch
|
patch < legacy-unenumerable-named-properties.patch
|
||||||
|
|
||||||
# TODO: update test files from https://dxr.mozilla.org/mozilla-central/source/dom/bindings/parser/tests
|
wget https://hg.mozilla.org/mozilla-central/archive/tip.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
|
||||||
|
rm tests.tar.gz WebIDL.py.orig
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue