Auto merge of #29384 - sagudev:idl, r=jdm

Update WebIDL.py

Update WebIDL.py to latest version from mozilla-central.
There were two major changes:
- [Rename legacy extended attributes in webidls](55dac83d9a) [bug 1631581](https://bugzilla.mozilla.org/show_bug.cgi?id=1631581)
- [removal of ReadableStream from WebIDL](https://phabricator.services.mozilla.com/D143074), which was solved with porting reverted removal patch (2801cc82b0)

WebIDL.Parser now has `use_builtin_readable_streams` field by default set to `true` (to use SM readable stream implementation), which could help with #29088.

My try build: https://github.com/sagudev/servo/actions/runs/4216638911

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2023-03-22 02:23:01 +01:00 committed by GitHub
commit d5b910ee86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
196 changed files with 18982 additions and 5097 deletions

View file

@ -31,7 +31,7 @@ from WebIDL import (
from Configuration import ( from Configuration import (
MakeNativeName, MakeNativeName,
MemberIsUnforgeable, MemberIsLegacyUnforgeable,
getModuleFromObject, getModuleFromObject,
getTypesFromCallback, getTypesFromCallback,
getTypesFromDescriptor, getTypesFromDescriptor,
@ -587,7 +587,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
isEnforceRange = type.hasEnforceRange() isEnforceRange = type.hasEnforceRange()
isClamp = type.hasClamp() isClamp = type.hasClamp()
if type.treatNullAsEmpty: if type.legacyNullToEmptyString:
treatNullAs = "EmptyString" treatNullAs = "EmptyString"
else: else:
treatNullAs = "Default" treatNullAs = "Default"
@ -1702,7 +1702,7 @@ class MethodDefiner(PropertyDefiner):
m.isMethod() and m.isStatic() == static m.isMethod() and m.isStatic() == static
and (bool(m.getExtendedAttribute("CrossOriginCallable")) or not crossorigin) and (bool(m.getExtendedAttribute("CrossOriginCallable")) or not crossorigin)
and not m.isIdentifierLess() and not m.isIdentifierLess()
and (MemberIsUnforgeable(m, descriptor) == unforgeable or crossorigin)] and (MemberIsLegacyUnforgeable(m, descriptor) == unforgeable or crossorigin)]
else: else:
methods = [] methods = []
self.regular = [{"name": m.identifier.name, self.regular = [{"name": m.identifier.name,
@ -1787,8 +1787,8 @@ class MethodDefiner(PropertyDefiner):
descriptor) descriptor)
}) })
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable")) isLegacyUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("LegacyUnforgeable"))
if not static and unforgeable == isUnforgeableInterface and not crossorigin: if not static and unforgeable == isLegacyUnforgeableInterface and not crossorigin:
stringifier = descriptor.operations['Stringifier'] stringifier = descriptor.operations['Stringifier']
if stringifier: if stringifier:
self.regular.append({ self.regular.append({
@ -1890,7 +1890,7 @@ class AttrDefiner(PropertyDefiner):
} }
for m in descriptor.interface.members if for m in descriptor.interface.members if
m.isAttr() and m.isStatic() == static m.isAttr() and m.isStatic() == static
and (MemberIsUnforgeable(m, descriptor) == unforgeable or crossorigin) and (MemberIsLegacyUnforgeable(m, descriptor) == unforgeable or crossorigin)
and (not crossorigin and (not crossorigin
or m.getExtendedAttribute("CrossOriginReadable") or m.getExtendedAttribute("CrossOriginReadable")
or m.getExtendedAttribute("CrossOriginWritable")) or m.getExtendedAttribute("CrossOriginWritable"))
@ -1923,7 +1923,7 @@ class AttrDefiner(PropertyDefiner):
accessor = 'get_' + self.descriptor.internalNameFor(attr.identifier.name) accessor = 'get_' + self.descriptor.internalNameFor(attr.identifier.name)
jitinfo = "0 as *const JSJitInfo" jitinfo = "0 as *const JSJitInfo"
else: else:
if attr.hasLenientThis(): if attr.hasLegacyLenientThis():
accessor = "generic_lenient_getter" accessor = "generic_lenient_getter"
else: else:
accessor = "generic_getter" accessor = "generic_getter"
@ -1946,7 +1946,7 @@ class AttrDefiner(PropertyDefiner):
accessor = 'set_' + self.descriptor.internalNameFor(attr.identifier.name) accessor = 'set_' + self.descriptor.internalNameFor(attr.identifier.name)
jitinfo = "0 as *const JSJitInfo" jitinfo = "0 as *const JSJitInfo"
else: else:
if attr.hasLenientThis(): if attr.hasLegacyLenientThis():
accessor = "generic_lenient_setter" accessor = "generic_lenient_setter"
else: else:
accessor = "generic_setter" accessor = "generic_setter"
@ -2187,7 +2187,7 @@ class CGImports(CGWrapper):
if d.interface.isIteratorInterface(): if d.interface.isIteratorInterface():
types += [d.interface.iterableInterface] types += [d.interface.iterableInterface]
members = d.interface.members + d.interface.namedConstructors members = d.interface.members + d.interface.legacyFactoryFunctions
constructor = d.interface.ctor() constructor = d.interface.ctor()
if constructor: if constructor:
members += [constructor] members += [constructor]
@ -2436,7 +2436,7 @@ class CGPrototypeJSClass(CGThing):
def define(self): def define(self):
name = str_to_const_array(self.descriptor.interface.identifier.name + "Prototype") name = str_to_const_array(self.descriptor.interface.identifier.name + "Prototype")
slotCount = 0 slotCount = 0
if self.descriptor.hasUnforgeableMembers: if self.descriptor.hasLegacyUnforgeableMembers:
slotCount += 1 slotCount += 1
return """\ return """\
static PrototypeClass: JSClass = JSClass { static PrototypeClass: JSClass = JSClass {
@ -2814,7 +2814,7 @@ class CGConstructorEnabled(CGAbstractMethod):
return CGList((CGGeneric(cond) for cond in conditions), " &&\n") return CGList((CGGeneric(cond) for cond in conditions), " &&\n")
def InitUnforgeablePropertiesOnHolder(descriptor, properties): def InitLegacyUnforgeablePropertiesOnHolder(descriptor, properties):
""" """
Define the unforgeable properties on the unforgeable holder for Define the unforgeable properties on the unforgeable holder for
the interface represented by descriptor. the interface represented by descriptor.
@ -2823,12 +2823,12 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties):
""" """
unforgeables = [] unforgeables = []
defineUnforgeableAttrs = "define_guarded_properties(cx, unforgeable_holder.handle(), %s, global);" defineLegacyUnforgeableAttrs = "define_guarded_properties(cx, unforgeable_holder.handle(), %s, global);"
defineUnforgeableMethods = "define_guarded_methods(cx, unforgeable_holder.handle(), %s, global);" defineLegacyUnforgeableMethods = "define_guarded_methods(cx, unforgeable_holder.handle(), %s, global);"
unforgeableMembers = [ unforgeableMembers = [
(defineUnforgeableAttrs, properties.unforgeable_attrs), (defineLegacyUnforgeableAttrs, properties.unforgeable_attrs),
(defineUnforgeableMethods, properties.unforgeable_methods), (defineLegacyUnforgeableMethods, properties.unforgeable_methods),
] ]
for template, array in unforgeableMembers: for template, array in unforgeableMembers:
if array.length() > 0: if array.length() > 0:
@ -2836,12 +2836,12 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties):
return CGList(unforgeables, "\n") return CGList(unforgeables, "\n")
def CopyUnforgeablePropertiesToInstance(descriptor): def CopyLegacyUnforgeablePropertiesToInstance(descriptor):
""" """
Copy the unforgeable properties from the unforgeable holder for Copy the unforgeable properties from the unforgeable holder for
this interface to the instance object we have. this interface to the instance object we have.
""" """
if not descriptor.hasUnforgeableMembers: if not descriptor.hasLegacyUnforgeableMembers:
return "" return ""
copyCode = "" copyCode = ""
@ -2890,7 +2890,7 @@ class CGWrapMethod(CGAbstractMethod):
pub=True, unsafe=True) pub=True, unsafe=True)
def definition_body(self): def definition_body(self):
unforgeable = CopyUnforgeablePropertiesToInstance(self.descriptor) unforgeable = CopyLegacyUnforgeablePropertiesToInstance(self.descriptor)
if self.descriptor.proxy: if self.descriptor.proxy:
if self.descriptor.isMaybeCrossOriginObject(): if self.descriptor.isMaybeCrossOriginObject():
proto = "ptr::null_mut()" proto = "ptr::null_mut()"
@ -2958,10 +2958,10 @@ assert!(!proto.is_null());
%(createObject)s %(createObject)s
let root = raw.reflect_with(obj.get()); let root = raw.reflect_with(obj.get());
%(copyUnforgeable)s %(copyLegacyUnforgeable)s
DomRoot::from_ref(&*root)\ DomRoot::from_ref(&*root)\
""" % {'copyUnforgeable': unforgeable, 'createObject': create}) """ % {'copyLegacyUnforgeable': unforgeable, 'createObject': create})
class CGWrapGlobalMethod(CGAbstractMethod): class CGWrapGlobalMethod(CGAbstractMethod):
@ -2981,7 +2981,7 @@ class CGWrapGlobalMethod(CGAbstractMethod):
def definition_body(self): def definition_body(self):
values = { values = {
"concreteType": self.descriptor.concreteType, "concreteType": self.descriptor.concreteType,
"unforgeable": CopyUnforgeablePropertiesToInstance(self.descriptor) "unforgeable": CopyLegacyUnforgeablePropertiesToInstance(self.descriptor)
} }
pairs = [ pairs = [
@ -3121,10 +3121,10 @@ class PropertyArrays():
self.static_attrs = AttrDefiner(descriptor, "StaticAttributes", self.static_attrs = AttrDefiner(descriptor, "StaticAttributes",
static=True, unforgeable=False) static=True, unforgeable=False)
self.methods = MethodDefiner(descriptor, "Methods", static=False, unforgeable=False) self.methods = MethodDefiner(descriptor, "Methods", static=False, unforgeable=False)
self.unforgeable_methods = MethodDefiner(descriptor, "UnforgeableMethods", self.unforgeable_methods = MethodDefiner(descriptor, "LegacyUnforgeableMethods",
static=False, unforgeable=True) static=False, unforgeable=True)
self.attrs = AttrDefiner(descriptor, "Attributes", static=False, unforgeable=False) self.attrs = AttrDefiner(descriptor, "Attributes", static=False, unforgeable=False)
self.unforgeable_attrs = AttrDefiner(descriptor, "UnforgeableAttributes", self.unforgeable_attrs = AttrDefiner(descriptor, "LegacyUnforgeableAttributes",
static=False, unforgeable=True) static=False, unforgeable=True)
self.consts = ConstDefiner(descriptor, "Constants") self.consts = ConstDefiner(descriptor, "Constants")
pass pass
@ -3426,7 +3426,7 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
] + [defineAliasesFor(m) for m in sorted(aliasedMembers)]) ] + [defineAliasesFor(m) for m in sorted(aliasedMembers)])
code.append(defineAliases) code.append(defineAliases)
constructors = self.descriptor.interface.namedConstructors constructors = self.descriptor.interface.legacyFactoryFunctions
if constructors: if constructors:
decl = "let named_constructors: [(ConstructorClassHook, &'static [u8], u32); %d]" % len(constructors) decl = "let named_constructors: [(ConstructorClassHook, &'static [u8], u32); %d]" % len(constructors)
specs = [] specs = []
@ -3439,7 +3439,7 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
code.append(CGWrapper(values, pre="%s = [\n" % decl, post="\n];")) code.append(CGWrapper(values, pre="%s = [\n" % decl, post="\n];"))
code.append(CGGeneric("create_named_constructors(cx, global, &named_constructors, prototype.handle());")) code.append(CGGeneric("create_named_constructors(cx, global, &named_constructors, prototype.handle());"))
if self.descriptor.hasUnforgeableMembers: if self.descriptor.hasLegacyUnforgeableMembers:
# We want to use the same JSClass and prototype as the object we'll # We want to use the same JSClass and prototype as the object we'll
# end up defining the unforgeable properties on in the end, so that # end up defining the unforgeable properties on in the end, so that
# we can use JS_InitializePropertiesFromCompatibleNativeObject to do # we can use JS_InitializePropertiesFromCompatibleNativeObject to do
@ -3463,7 +3463,7 @@ unforgeable_holder.handle_mut().set(
JS_NewObjectWithoutMetadata(*cx, %(holderClass)s, %(holderProto)s)); JS_NewObjectWithoutMetadata(*cx, %(holderClass)s, %(holderProto)s));
assert!(!unforgeable_holder.is_null()); assert!(!unforgeable_holder.is_null());
""" % {'holderClass': holderClass, 'holderProto': holderProto})) """ % {'holderClass': holderClass, 'holderProto': holderProto}))
code.append(InitUnforgeablePropertiesOnHolder(self.descriptor, self.properties)) code.append(InitLegacyUnforgeablePropertiesOnHolder(self.descriptor, self.properties))
code.append(CGGeneric("""\ code.append(CGGeneric("""\
let val = ObjectValue(unforgeable_holder.get()); let val = ObjectValue(unforgeable_holder.get());
JS_SetReservedSlot(prototype.get(), DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, &val)""")) JS_SetReservedSlot(prototype.get(), DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, &val)"""))
@ -5631,7 +5631,7 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
namedSetter = self.descriptor.operations['NamedSetter'] namedSetter = self.descriptor.operations['NamedSetter']
if namedSetter: if namedSetter:
if self.descriptor.hasUnforgeableMembers: if self.descriptor.hasLegacyUnforgeableMembers:
raise TypeError("Can't handle a named setter on an interface that has " raise TypeError("Can't handle a named setter on an interface that has "
"unforgeables. Figure out how that should work!") "unforgeables. Figure out how that should work!")
set += ("if id.is_string() || id.is_int() {\n" set += ("if id.is_string() || id.is_int() {\n"
@ -5675,7 +5675,7 @@ class CGDOMJSProxyHandler_delete(CGAbstractExternMethod):
""") """)
if self.descriptor.operations['NamedDeleter']: if self.descriptor.operations['NamedDeleter']:
if self.descriptor.hasUnforgeableMembers: if self.descriptor.hasLegacyUnforgeableMembers:
raise TypeError("Can't handle a deleter on an interface that has " raise TypeError("Can't handle a deleter on an interface that has "
"unforgeables. Figure out how that should work!") "unforgeables. Figure out how that should work!")
set += CGProxyNamedDeleter(self.descriptor).define() set += CGProxyNamedDeleter(self.descriptor).define()
@ -6731,7 +6731,7 @@ class CGDescriptor(CGThing):
if descriptor.interface.hasInterfaceObject(): if descriptor.interface.hasInterfaceObject():
if descriptor.interface.ctor(): if descriptor.interface.ctor():
cgThings.append(CGClassConstructHook(descriptor)) cgThings.append(CGClassConstructHook(descriptor))
for ctor in descriptor.interface.namedConstructors: for ctor in descriptor.interface.legacyFactoryFunctions:
cgThings.append(CGClassConstructHook(descriptor, ctor)) cgThings.append(CGClassConstructHook(descriptor, ctor))
if not descriptor.interface.isCallback(): if not descriptor.interface.isCallback():
cgThings.append(CGInterfaceObjectJSClass(descriptor)) cgThings.append(CGInterfaceObjectJSClass(descriptor))
@ -7943,7 +7943,7 @@ class GlobalGenRoots():
pairs.append((d.name, binding, binding)) pairs.append((d.name, binding, binding))
for alias in d.interface.legacyWindowAliases: for alias in d.interface.legacyWindowAliases:
pairs.append((alias, binding, binding)) pairs.append((alias, binding, binding))
for ctor in d.interface.namedConstructors: for ctor in d.interface.legacyFactoryFunctions:
pairs.append((ctor.identifier.name, binding, binding)) pairs.append((ctor.identifier.name, binding, binding))
pairs.sort(key=operator.itemgetter(0)) pairs.sort(key=operator.itemgetter(0))
mappings = [ mappings = [

View file

@ -167,11 +167,11 @@ class DescriptorProvider:
return self.config.getDescriptor(interfaceName) return self.config.getDescriptor(interfaceName)
def MemberIsUnforgeable(member, descriptor): def MemberIsLegacyUnforgeable(member, descriptor):
return ((member.isAttr() or member.isMethod()) return ((member.isAttr() or member.isMethod())
and not member.isStatic() and not member.isStatic()
and (member.isUnforgeable() and (member.isLegacyUnforgeable()
or bool(descriptor.interface.getExtendedAttribute("Unforgeable")))) or bool(descriptor.interface.getExtendedAttribute("LegacyUnforgeable"))))
class Descriptor(DescriptorProvider): class Descriptor(DescriptorProvider):
@ -244,9 +244,9 @@ class Descriptor(DescriptorProvider):
and not self.interface.getExtendedAttribute("Abstract") and not self.interface.getExtendedAttribute("Abstract")
and not self.interface.getExtendedAttribute("Inline") and not self.interface.getExtendedAttribute("Inline")
and not spiderMonkeyInterface) and not spiderMonkeyInterface)
self.hasUnforgeableMembers = (self.concrete self.hasLegacyUnforgeableMembers = (self.concrete
and any(MemberIsUnforgeable(m, self) for m in and any(MemberIsLegacyUnforgeable(m, self) for m in
self.interface.members)) self.interface.members))
self.operations = { self.operations = {
'IndexedGetter': None, 'IndexedGetter': None,
@ -461,7 +461,7 @@ def getTypesFromDescriptor(descriptor):
members = [m for m in descriptor.interface.members] members = [m for m in descriptor.interface.members]
if descriptor.interface.ctor(): if descriptor.interface.ctor():
members.append(descriptor.interface.ctor()) members.append(descriptor.interface.ctor())
members.extend(descriptor.interface.namedConstructors) members.extend(descriptor.interface.legacyFactoryFunctions)
signatures = [s for m in members if m.isMethod() for s in m.signatures()] signatures = [s for m in members if m.isMethod() for s in m.signatures()]
types = [] types = []
for s in signatures: for s in signatures:

File diff suppressed because it is too large Load diff

View file

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

View file

@ -1,12 +1,10 @@
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -7382,7 +7382,8 @@ class Parser(Tokenizer): @@ -8827,6 +8827,7 @@ class Parser(Tokenizer):
self.parser = yacc.yacc(module=self, module=self,
outputdir=outputdir, outputdir=outputdir,
tabmodule='webidlyacc', errorlog=logger,
- errorlog=logger + debug=False,
+ errorlog=logger, write_tables=False,
+ debug=False # Pickling the grammar is a speedup in
# Pickling the grammar is a speedup in # some cases (older Python?) but a
# some cases (older Python?) but a
# significant slowdown in others.

View file

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

View file

@ -0,0 +1,162 @@
--- WebIDL.py
+++ WebIDL.py
@@ -2498,6 +2498,9 @@ class IDLType(IDLObject):
def isRecord(self):
return False
+ def isReadableStream(self):
+ return False
+
def isArrayBuffer(self):
return False
@@ -2526,7 +2529,7 @@ class IDLType(IDLObject):
def isSpiderMonkeyInterface(self):
"""Returns a boolean indicating whether this type is an 'interface'
type that is implemented in SpiderMonkey."""
- return self.isInterface() and self.isBufferSource()
+ return self.isInterface() and (self.isBufferSource() or self.isReadableStream())
def isAny(self):
return self.tag() == IDLType.Tags.any
@@ -2743,6 +2746,9 @@ class IDLNullableType(IDLParametrizedType):
def isRecord(self):
return self.inner.isRecord()
+ def isReadableStream(self):
+ return self.inner.isReadableStream()
+
def isArrayBuffer(self):
return self.inner.isArrayBuffer()
@@ -3252,6 +3258,9 @@ class IDLTypedefType(IDLType):
def isRecord(self):
return self.inner.isRecord()
+ def isReadableStream(self):
+ return self.inner.isReadableStream()
+
def isDictionary(self):
return self.inner.isDictionary()
@@ -3597,6 +3606,7 @@ class IDLBuiltinType(IDLType):
"Uint32Array",
"Float32Array",
"Float64Array",
+ "ReadableStream",
)
TagLookup = {
@@ -3632,6 +3642,7 @@ class IDLBuiltinType(IDLType):
Types.Uint32Array: IDLType.Tags.interface,
Types.Float32Array: IDLType.Tags.interface,
Types.Float64Array: IDLType.Tags.interface,
+ Types.ReadableStream: IDLType.Tags.interface,
}
PrettyNames = {
@@ -3667,6 +3678,7 @@ class IDLBuiltinType(IDLType):
Types.Uint32Array: "Uint32Array",
Types.Float32Array: "Float32Array",
Types.Float64Array: "Float64Array",
+ Types.ReadableStream: "ReadableStream",
}
def __init__(
@@ -3830,11 +3842,19 @@ class IDLBuiltinType(IDLType):
and self._typeTag <= IDLBuiltinType.Types.Float64Array
)
+ def isReadableStream(self):
+ return self._typeTag == IDLBuiltinType.Types.ReadableStream
+
def isInterface(self):
# TypedArray things are interface types per the TypedArray spec,
# but we handle them as builtins because SpiderMonkey implements
# all of it internally.
- return self.isArrayBuffer() or self.isArrayBufferView() or self.isTypedArray()
+ return (
+ self.isArrayBuffer()
+ or self.isArrayBufferView()
+ or self.isTypedArray()
+ or self.isReadableStream()
+ )
def isNonCallbackInterface(self):
# All the interfaces we can be are non-callback
@@ -3928,6 +3948,7 @@ class IDLBuiltinType(IDLType):
# ArrayBuffer is distinguishable from everything
# that's not an ArrayBuffer or a callback interface
(self.isArrayBuffer() and not other.isArrayBuffer())
+ or (self.isReadableStream() and not other.isReadableStream())
or
# ArrayBufferView is distinguishable from everything
# that's not an ArrayBufferView or typed array.
@@ -4134,6 +4155,11 @@ BuiltinTypes = {
"Float64Array",
IDLBuiltinType.Types.Float64Array,
),
+ IDLBuiltinType.Types.ReadableStream: IDLBuiltinType(
+ BuiltinLocation("<builtin type>"),
+ "ReadableStream",
+ IDLBuiltinType.Types.ReadableStream,
+ ),
}
@@ -6883,6 +6909,9 @@ class Tokenizer(object):
def t_IDENTIFIER(self, t):
r"[_-]?[A-Za-z][0-9A-Z_a-z-]*"
t.type = self.keywords.get(t.value, "IDENTIFIER")
+ # If Builtin readable streams are disabled, mark ReadableStream as an identifier.
+ if t.type == "READABLESTREAM" and not self._use_builtin_readable_streams:
+ t.type = "IDENTIFIER"
return t
def t_STRING(self, t):
@@ -6973,6 +7002,7 @@ class Tokenizer(object):
"setlike": "SETLIKE",
"iterable": "ITERABLE",
"namespace": "NAMESPACE",
+ "ReadableStream": "READABLESTREAM",
"constructor": "CONSTRUCTOR",
"symbol": "SYMBOL",
"async": "ASYNC",
@@ -6993,7 +7023,8 @@ class Tokenizer(object):
],
)
- def __init__(self, outputdir, lexer=None):
+ def __init__(self, outputdir, lexer=None, use_builtin_readable_streams=True):
+ self._use_builtin_readable_streams = use_builtin_readable_streams
if lexer:
self.lexer = lexer
else:
@@ -8482,6 +8513,7 @@ class Parser(Tokenizer):
"""
DistinguishableType : PrimitiveType Null
| ARRAYBUFFER Null
+ | READABLESTREAM Null
| OBJECT Null
| UNDEFINED Null
"""
@@ -8489,6 +8521,8 @@ class Parser(Tokenizer):
type = BuiltinTypes[IDLBuiltinType.Types.object]
elif p[1] == "ArrayBuffer":
type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
+ elif p[1] == "ReadableStream":
+ type = BuiltinTypes[IDLBuiltinType.Types.ReadableStream]
elif p[1] == "undefined":
type = BuiltinTypes[IDLBuiltinType.Types.undefined]
else:
@@ -8827,8 +8861,8 @@ class Parser(Tokenizer):
[Location(self.lexer, p.lineno, p.lexpos, self._filename)],
)
- def __init__(self, outputdir="", lexer=None):
- Tokenizer.__init__(self, outputdir, lexer)
+ def __init__(self, outputdir="", lexer=None, use_builtin_readable_stream=True):
+ Tokenizer.__init__(self, outputdir, lexer, use_builtin_readable_stream)
logger = SqueakyCleanLogger()
try:

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface DoubleNull { interface DoubleNull {
attribute any? foo; attribute any? foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface ArgumentIdentifierConflict { interface ArgumentIdentifierConflict {
undefined foo(boolean arg1, boolean arg1); undefined foo(boolean arg1, boolean arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

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

View file

@ -1,14 +0,0 @@
def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
interface UndefinedArgument1 {
undefined foo(undefined arg2);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestArrayBuffer { interface TestArrayBuffer {
attribute ArrayBuffer bufferAttr; attribute ArrayBuffer bufferAttr;
undefined bufferMethod(ArrayBuffer arg1, ArrayBuffer? arg2, sequence<ArrayBuffer> arg3); undefined bufferMethod(ArrayBuffer arg1, ArrayBuffer? arg2, sequence<ArrayBuffer> arg3);
@ -36,7 +38,8 @@ def WebIDLTest(parser, harness):
attribute Float64Array float64ArrayAttr; attribute Float64Array float64ArrayAttr;
undefined float64ArrayMethod(Float64Array arg1, Float64Array? arg2, sequence<Float64Array> arg3); undefined float64ArrayMethod(Float64Array arg1, Float64Array? arg2, sequence<Float64Array> arg3);
}; };
""") """
)
results = parser.finish() results = parser.finish()
@ -55,24 +58,35 @@ def WebIDLTest(parser, harness):
harness.ok(attr.type.isSpiderMonkeyInterface(), "Should test as a js interface") harness.ok(attr.type.isSpiderMonkeyInterface(), "Should test as a js interface")
(retType, arguments) = method.signatures()[0] (retType, arguments) = method.signatures()[0]
harness.ok(retType.isUndefined(), "Should have a undefined return type") harness.ok(retType.isUndefined(), "Should have an undefined return type")
harness.check(len(arguments), 3, "Expect 3 arguments") harness.check(len(arguments), 3, "Expect 3 arguments")
harness.check(str(arguments[0].type), t, "Expect an ArrayBuffer type") harness.check(str(arguments[0].type), t, "Expect an ArrayBuffer type")
harness.ok(arguments[0].type.isSpiderMonkeyInterface(), "Should test as a js interface") harness.ok(
arguments[0].type.isSpiderMonkeyInterface(), "Should test as a js interface"
)
harness.check(str(arguments[1].type), t + "OrNull", "Expect an ArrayBuffer type") harness.check(
harness.ok(arguments[1].type.inner.isSpiderMonkeyInterface(), "Should test as a js interface") str(arguments[1].type), t + "OrNull", "Expect an ArrayBuffer type"
)
harness.ok(
arguments[1].type.inner.isSpiderMonkeyInterface(),
"Should test as a js interface",
)
harness.check(str(arguments[2].type), t + "Sequence", "Expect an ArrayBuffer type") harness.check(
harness.ok(arguments[2].type.inner.isSpiderMonkeyInterface(), "Should test as a js interface") str(arguments[2].type), t + "Sequence", "Expect an ArrayBuffer type"
)
harness.ok(
arguments[2].type.inner.isSpiderMonkeyInterface(),
"Should test as a js interface",
)
checkStuff(members[0], members[1], "ArrayBuffer")
checkStuff(members[0], members[1], "ArrayBuffer") checkStuff(members[2], members[3], "ArrayBufferView")
checkStuff(members[2], members[3], "ArrayBufferView") checkStuff(members[4], members[5], "Int8Array")
checkStuff(members[4], members[5], "Int8Array") checkStuff(members[6], members[7], "Uint8Array")
checkStuff(members[6], members[7], "Uint8Array") checkStuff(members[8], members[9], "Uint8ClampedArray")
checkStuff(members[8], members[9], "Uint8ClampedArray")
checkStuff(members[10], members[11], "Int16Array") checkStuff(members[10], members[11], "Int16Array")
checkStuff(members[12], members[13], "Uint16Array") checkStuff(members[12], members[13], "Uint16Array")
checkStuff(members[14], members[15], "Int32Array") checkStuff(members[14], members[15], "Int32Array")

View file

@ -1,31 +1,35 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness):
testData = [("::TestAttr%s::b", "b", "Byte%s", False),
("::TestAttr%s::rb", "rb", "Byte%s", True),
("::TestAttr%s::o", "o", "Octet%s", False),
("::TestAttr%s::ro", "ro", "Octet%s", True),
("::TestAttr%s::s", "s", "Short%s", False),
("::TestAttr%s::rs", "rs", "Short%s", True),
("::TestAttr%s::us", "us", "UnsignedShort%s", False),
("::TestAttr%s::rus", "rus", "UnsignedShort%s", True),
("::TestAttr%s::l", "l", "Long%s", False),
("::TestAttr%s::rl", "rl", "Long%s", True),
("::TestAttr%s::ul", "ul", "UnsignedLong%s", False),
("::TestAttr%s::rul", "rul", "UnsignedLong%s", True),
("::TestAttr%s::ll", "ll", "LongLong%s", False),
("::TestAttr%s::rll", "rll", "LongLong%s", True),
("::TestAttr%s::ull", "ull", "UnsignedLongLong%s", False),
("::TestAttr%s::rull", "rull", "UnsignedLongLong%s", True),
("::TestAttr%s::str", "str", "String%s", False),
("::TestAttr%s::rstr", "rstr", "String%s", True),
("::TestAttr%s::obj", "obj", "Object%s", False),
("::TestAttr%s::robj", "robj", "Object%s", True),
("::TestAttr%s::object", "object", "Object%s", False),
("::TestAttr%s::f", "f", "Float%s", False),
("::TestAttr%s::rf", "rf", "Float%s", True)]
parser.parse(""" def WebIDLTest(parser, harness):
testData = [
("::TestAttr%s::b", "b", "Byte%s", False),
("::TestAttr%s::rb", "rb", "Byte%s", True),
("::TestAttr%s::o", "o", "Octet%s", False),
("::TestAttr%s::ro", "ro", "Octet%s", True),
("::TestAttr%s::s", "s", "Short%s", False),
("::TestAttr%s::rs", "rs", "Short%s", True),
("::TestAttr%s::us", "us", "UnsignedShort%s", False),
("::TestAttr%s::rus", "rus", "UnsignedShort%s", True),
("::TestAttr%s::l", "l", "Long%s", False),
("::TestAttr%s::rl", "rl", "Long%s", True),
("::TestAttr%s::ul", "ul", "UnsignedLong%s", False),
("::TestAttr%s::rul", "rul", "UnsignedLong%s", True),
("::TestAttr%s::ll", "ll", "LongLong%s", False),
("::TestAttr%s::rll", "rll", "LongLong%s", True),
("::TestAttr%s::ull", "ull", "UnsignedLongLong%s", False),
("::TestAttr%s::rull", "rull", "UnsignedLongLong%s", True),
("::TestAttr%s::str", "str", "String%s", False),
("::TestAttr%s::rstr", "rstr", "String%s", True),
("::TestAttr%s::obj", "obj", "Object%s", False),
("::TestAttr%s::robj", "robj", "Object%s", True),
("::TestAttr%s::object", "object", "Object%s", False),
("::TestAttr%s::f", "f", "Float%s", False),
("::TestAttr%s::rf", "rf", "Float%s", True),
]
parser.parse(
"""
interface TestAttr { interface TestAttr {
attribute byte b; attribute byte b;
readonly attribute byte rb; readonly attribute byte rb;
@ -77,13 +81,13 @@ def WebIDLTest(parser, harness):
attribute float? f; attribute float? f;
readonly attribute float? rf; readonly attribute float? rf;
}; };
""") """
)
results = parser.finish() results = parser.finish()
def checkAttr(attr, QName, name, type, readonly): def checkAttr(attr, QName, name, type, readonly):
harness.ok(isinstance(attr, WebIDL.IDLAttribute), harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
"Should be an IDLAttribute")
harness.ok(attr.isAttr(), "Attr is an Attr") harness.ok(attr.isAttr(), "Attr is an Attr")
harness.ok(not attr.isMethod(), "Attr is not an method") harness.ok(not attr.isMethod(), "Attr is not an method")
harness.ok(not attr.isConst(), "Attr is not a const") harness.ok(not attr.isConst(), "Attr is not a const")
@ -95,11 +99,14 @@ def WebIDLTest(parser, harness):
harness.ok(True, "TestAttr interface parsed without error.") harness.ok(True, "TestAttr interface parsed without error.")
harness.check(len(results), 2, "Should be two productions.") 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") harness.check(
harness.check(iface.identifier.QName(), "::TestAttr", "Interface has the right QName") iface.identifier.QName(), "::TestAttr", "Interface has the right QName"
)
harness.check(iface.identifier.name, "TestAttr", "Interface has the right name") harness.check(iface.identifier.name, "TestAttr", "Interface has the right name")
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) harness.check(
len(iface.members), len(testData), "Expect %s members" % len(testData)
)
attrs = iface.members attrs = iface.members
@ -110,11 +117,16 @@ def WebIDLTest(parser, harness):
checkAttr(attr, QName % "", name, type % "", readonly) checkAttr(attr, QName % "", name, type % "", readonly)
iface = results[1] iface = results[1]
harness.ok(isinstance(iface, WebIDL.IDLInterface), harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface") harness.check(
harness.check(iface.identifier.QName(), "::TestAttrNullable", "Interface has the right QName") iface.identifier.QName(), "::TestAttrNullable", "Interface has the right QName"
harness.check(iface.identifier.name, "TestAttrNullable", "Interface has the right name") )
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData)) harness.check(
iface.identifier.name, "TestAttrNullable", "Interface has the right name"
)
harness.check(
len(iface.members), len(testData), "Expect %s members" % len(testData)
)
attrs = iface.members attrs = iface.members
@ -127,11 +139,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[SetterThrows] readonly attribute boolean foo; [SetterThrows] readonly attribute boolean foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -140,11 +154,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throw] readonly attribute boolean foo; [Throw] readonly attribute boolean foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -153,24 +169,30 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[SameObject] readonly attribute boolean foo; [SameObject] readonly attribute boolean foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "Should not allow [SameObject] on attributes not of interface type") harness.ok(
threw, "Should not allow [SameObject] on attributes not of interface type"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[SameObject] readonly attribute A foo; [SameObject] readonly attribute A foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface AttrSequenceType { interface AttrSequenceType {
attribute sequence<object> foo; attribute sequence<object> foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -17,51 +19,59 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface AttrUnionWithSequenceType { interface AttrUnionWithSequenceType {
attribute (sequence<object> or DOMString) foo; attribute (sequence<object> or DOMString) foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Attribute type must not be a union with a sequence member type")
"Attribute type must not be a union with a sequence member type")
parser.reset() parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface AttrNullableUnionWithSequenceType { interface AttrNullableUnionWithSequenceType {
attribute (sequence<object>? or DOMString) foo; attribute (sequence<object>? or DOMString) foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Attribute type must not be a union with a nullable sequence " threw,
"member type") "Attribute type must not be a union with a nullable sequence " "member type",
)
parser.reset() parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface AttrUnionWithUnionWithSequenceType { interface AttrUnionWithUnionWithSequenceType {
attribute ((sequence<object> or DOMString) or AttrUnionWithUnionWithSequenceType) foo; attribute ((sequence<object> or DOMString) or AttrUnionWithUnionWithSequenceType) foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Attribute type must not be a union type with a union member " threw,
"type that has a sequence member type") "Attribute type must not be a union type with a union member "
"type that has a sequence member type",
)

View file

@ -1,14 +1,16 @@
# Import the WebIDL module, so we can do isinstance checks and whatnot # Import the WebIDL module, so we can do isinstance checks and whatnot
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
# Basic functionality # Basic functionality
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [EnforceRange] long Foo; typedef [EnforceRange] long Foo;
typedef [Clamp] long Bar; typedef [Clamp] long Bar;
typedef [TreatNullAs=EmptyString] DOMString Baz; typedef [LegacyNullToEmptyString] DOMString Baz;
dictionary A { dictionary A {
required [EnforceRange] long a; required [EnforceRange] long a;
required [Clamp] long b; required [Clamp] long b;
@ -19,11 +21,12 @@ def WebIDLTest(parser, harness):
attribute Foo typedefFoo; attribute Foo typedefFoo;
attribute [EnforceRange] long foo; attribute [EnforceRange] long foo;
attribute [Clamp] long bar; attribute [Clamp] long bar;
attribute [TreatNullAs=EmptyString] DOMString baz; attribute [LegacyNullToEmptyString] DOMString baz;
undefined method([EnforceRange] long foo, [Clamp] long bar, undefined method([EnforceRange] long foo, [Clamp] long bar,
[TreatNullAs=EmptyString] DOMString baz); [LegacyNullToEmptyString] DOMString baz);
undefined method2(optional [EnforceRange] long foo, optional [Clamp] long bar, undefined method2(optional [EnforceRange] long foo, optional [Clamp] long bar,
optional [TreatNullAs=EmptyString] DOMString baz); optional [LegacyNullToEmptyString] DOMString baz);
undefined method3(optional [LegacyNullToEmptyString] UTF8String foo = "");
}; };
interface C { interface C {
attribute [EnforceRange] long? foo; attribute [EnforceRange] long? foo;
@ -40,34 +43,88 @@ def WebIDLTest(parser, harness):
interface Iterable { interface Iterable {
iterable<[Clamp] long, [EnforceRange] long>; iterable<[Clamp] long, [EnforceRange] long>;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, "Should not have thrown on parsing normal") harness.ok(not threw, "Should not have thrown on parsing normal")
if not threw: if not threw:
harness.check(results[0].innerType.hasEnforceRange(), True, "Foo is [EnforceRange]") harness.check(
results[0].innerType.hasEnforceRange(), True, "Foo is [EnforceRange]"
)
harness.check(results[1].innerType.hasClamp(), True, "Bar is [Clamp]") harness.check(results[1].innerType.hasClamp(), True, "Bar is [Clamp]")
harness.check(results[2].innerType.treatNullAsEmpty, True, "Baz is [TreatNullAs=EmptyString]") harness.check(
results[2].innerType.legacyNullToEmptyString,
True,
"Baz is [LegacyNullToEmptyString]",
)
A = results[3] A = results[3]
harness.check(A.members[0].type.hasEnforceRange(), True, "A.a is [EnforceRange]") harness.check(
A.members[0].type.hasEnforceRange(), True, "A.a is [EnforceRange]"
)
harness.check(A.members[1].type.hasClamp(), True, "A.b is [Clamp]") harness.check(A.members[1].type.hasClamp(), True, "A.b is [Clamp]")
harness.check(A.members[2].type.hasEnforceRange(), True, "A.c is [EnforceRange]") harness.check(
harness.check(A.members[3].type.hasEnforceRange(), True, "A.d is [EnforceRange]") A.members[2].type.hasEnforceRange(), True, "A.c is [EnforceRange]"
)
harness.check(
A.members[3].type.hasEnforceRange(), True, "A.d is [EnforceRange]"
)
B = results[4] B = results[4]
harness.check(B.members[0].type.hasEnforceRange(), True, "B.typedefFoo is [EnforceRange]") harness.check(
harness.check(B.members[1].type.hasEnforceRange(), True, "B.foo is [EnforceRange]") B.members[0].type.hasEnforceRange(), True, "B.typedefFoo is [EnforceRange]"
)
harness.check(
B.members[1].type.hasEnforceRange(), True, "B.foo is [EnforceRange]"
)
harness.check(B.members[2].type.hasClamp(), True, "B.bar is [Clamp]") harness.check(B.members[2].type.hasClamp(), True, "B.bar is [Clamp]")
harness.check(B.members[3].type.treatNullAsEmpty, True, "B.baz is [TreatNullAs=EmptyString]") harness.check(
B.members[3].type.legacyNullToEmptyString,
True,
"B.baz is [LegacyNullToEmptyString]",
)
method = B.members[4].signatures()[0][1] method = B.members[4].signatures()[0][1]
harness.check(method[0].type.hasEnforceRange(), True, "foo argument of method is [EnforceRange]") harness.check(
harness.check(method[1].type.hasClamp(), True, "bar argument of method is [Clamp]") method[0].type.hasEnforceRange(),
harness.check(method[2].type.treatNullAsEmpty, True, "baz argument of method is [TreatNullAs=EmptyString]") True,
"foo argument of method is [EnforceRange]",
)
harness.check(
method[1].type.hasClamp(), True, "bar argument of method is [Clamp]"
)
harness.check(
method[2].type.legacyNullToEmptyString,
True,
"baz argument of method is [LegacyNullToEmptyString]",
)
method2 = B.members[5].signatures()[0][1] method2 = B.members[5].signatures()[0][1]
harness.check(method[0].type.hasEnforceRange(), True, "foo argument of method2 is [EnforceRange]") harness.check(
harness.check(method[1].type.hasClamp(), True, "bar argument of method2 is [Clamp]") method2[0].type.hasEnforceRange(),
harness.check(method[2].type.treatNullAsEmpty, True, "baz argument of method2 is [TreatNullAs=EmptyString]") True,
"foo argument of method2 is [EnforceRange]",
)
harness.check(
method2[1].type.hasClamp(), True, "bar argument of method2 is [Clamp]"
)
harness.check(
method2[2].type.legacyNullToEmptyString,
True,
"baz argument of method2 is [LegacyNullToEmptyString]",
)
method3 = B.members[6].signatures()[0][1]
harness.check(
method3[0].type.legacyNullToEmptyString,
True,
"bar argument of method2 is [LegacyNullToEmptyString]",
)
harness.check(
method3[0].defaultValue.type.isUTF8String(),
True,
"default value of bar argument of method2 is correctly coerced to UTF8String",
)
C = results[5] C = results[5]
harness.ok(C.members[0].type.nullable(), "C.foo is nullable") harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
harness.ok(C.members[0].type.hasEnforceRange(), "C.foo has [EnforceRange]") harness.ok(C.members[0].type.hasEnforceRange(), "C.foo has [EnforceRange]")
@ -75,12 +132,18 @@ def WebIDLTest(parser, harness):
harness.ok(C.members[1].type.hasClamp(), "C.bar has [Clamp]") harness.ok(C.members[1].type.hasClamp(), "C.bar has [Clamp]")
method = C.members[2].signatures()[0][1] method = C.members[2].signatures()[0][1]
harness.ok(method[0].type.nullable(), "foo argument of method is nullable") harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
harness.ok(method[0].type.hasEnforceRange(), "foo argument of method has [EnforceRange]") harness.ok(
method[0].type.hasEnforceRange(),
"foo argument of method has [EnforceRange]",
)
harness.ok(method[1].type.nullable(), "bar argument of method is nullable") harness.ok(method[1].type.nullable(), "bar argument of method is nullable")
harness.ok(method[1].type.hasClamp(), "bar argument of method has [Clamp]") harness.ok(method[1].type.hasClamp(), "bar argument of method has [Clamp]")
method2 = C.members[3].signatures()[0][1] method2 = C.members[3].signatures()[0][1]
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable") harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
harness.ok(method2[0].type.hasEnforceRange(), "foo argument of method2 has [EnforceRange]") harness.ok(
method2[0].type.hasEnforceRange(),
"foo argument of method2 has [EnforceRange]",
)
harness.ok(method2[1].type.nullable(), "bar argument of method2 is nullable") harness.ok(method2[1].type.nullable(), "bar argument of method2 is nullable")
harness.ok(method2[1].type.hasClamp(), "bar argument of method2 has [Clamp]") harness.ok(method2[1].type.hasClamp(), "bar argument of method2 has [Clamp]")
@ -88,7 +151,8 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [AllowShared] ArrayBufferView Foo; typedef [AllowShared] ArrayBufferView Foo;
dictionary A { dictionary A {
required [AllowShared] ArrayBufferView a; required [AllowShared] ArrayBufferView a;
@ -115,7 +179,8 @@ def WebIDLTest(parser, harness):
interface Iterable { interface Iterable {
iterable<[Clamp] long, [AllowShared] ArrayBufferView>; iterable<[Clamp] long, [AllowShared] ArrayBufferView>;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -131,63 +196,101 @@ def WebIDLTest(parser, harness):
harness.ok(B.members[0].type.hasAllowShared(), "B.typedefFoo is [AllowShared]") harness.ok(B.members[0].type.hasAllowShared(), "B.typedefFoo is [AllowShared]")
harness.ok(B.members[1].type.hasAllowShared(), "B.foo is [AllowShared]") harness.ok(B.members[1].type.hasAllowShared(), "B.foo is [AllowShared]")
method = B.members[2].signatures()[0][1] method = B.members[2].signatures()[0][1]
harness.ok(method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]") harness.ok(
method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]"
)
method2 = B.members[3].signatures()[0][1] method2 = B.members[3].signatures()[0][1]
harness.ok(method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]") harness.ok(
method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]"
)
C = results[3] C = results[3]
harness.ok(C.members[0].type.nullable(), "C.foo is nullable") harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
harness.ok(C.members[0].type.hasAllowShared(), "C.foo is [AllowShared]") harness.ok(C.members[0].type.hasAllowShared(), "C.foo is [AllowShared]")
method = C.members[1].signatures()[0][1] method = C.members[1].signatures()[0][1]
harness.ok(method[0].type.nullable(), "foo argument of method is nullable") harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
harness.ok(method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]") harness.ok(
method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]"
)
method2 = C.members[2].signatures()[0][1] method2 = C.members[2].signatures()[0][1]
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable") harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
harness.ok(method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]") harness.ok(
method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]"
)
ATTRIBUTES = [("[Clamp]", "long"), ("[EnforceRange]", "long"), ATTRIBUTES = [
("[TreatNullAs=EmptyString]", "DOMString"), ("[AllowShared]", "ArrayBufferView")] ("[Clamp]", "long"),
("[EnforceRange]", "long"),
("[LegacyNullToEmptyString]", "DOMString"),
("[AllowShared]", "ArrayBufferView"),
]
TEMPLATES = [ TEMPLATES = [
("required dictionary members", """ (
"required dictionary members",
"""
dictionary Foo { dictionary Foo {
%s required %s foo; %s required %s foo;
}; };
"""), """,
("optional arguments", """ ),
(
"optional arguments",
"""
interface Foo { interface Foo {
undefined foo(%s optional %s foo); undefined foo(%s optional %s foo);
}; };
"""), """,
("typedefs", """ ),
(
"typedefs",
"""
%s typedef %s foo; %s typedef %s foo;
"""), """,
("attributes", """ ),
(
"attributes",
"""
interface Foo { interface Foo {
%s attribute %s foo; %s attribute %s foo;
}; };
"""), """,
("readonly attributes", """ ),
(
"readonly attributes",
"""
interface Foo { interface Foo {
readonly attribute %s %s foo; readonly attribute %s %s foo;
}; };
"""), """,
("readonly unresolved attributes", """ ),
(
"readonly unresolved attributes",
"""
interface Foo { interface Foo {
readonly attribute Bar baz; readonly attribute Bar baz;
}; };
typedef %s %s Bar; typedef %s %s Bar;
"""), """,
("method", """ ),
(
"method",
"""
interface Foo { interface Foo {
%s %s foo(); %s %s foo();
}; };
"""), """,
("interface",""" ),
(
"interface",
"""
%s %s
interface Foo { interface Foo {
attribute %s foo; attribute %s foo;
}; };
"""), """,
("partial interface",""" ),
(
"partial interface",
"""
interface Foo { interface Foo {
undefined foo(); undefined foo();
}; };
@ -195,20 +298,29 @@ def WebIDLTest(parser, harness):
partial interface Foo { partial interface Foo {
attribute %s bar; attribute %s bar;
}; };
"""), """,
("interface mixin",""" ),
(
"interface mixin",
"""
%s %s
interface mixin Foo { interface mixin Foo {
attribute %s foo; attribute %s foo;
}; };
"""), """,
("namespace",""" ),
(
"namespace",
"""
%s %s
namespace Foo { namespace Foo {
attribute %s foo; attribute %s foo;
}; };
"""), """,
("partial namespace",""" ),
(
"partial namespace",
"""
namespace Foo { namespace Foo {
undefined foo(); undefined foo();
}; };
@ -216,14 +328,18 @@ def WebIDLTest(parser, harness):
partial namespace Foo { partial namespace Foo {
attribute %s bar; attribute %s bar;
}; };
"""), """,
("dictionary",""" ),
(
"dictionary",
"""
%s %s
dictionary Foo { dictionary Foo {
%s foo; %s foo;
}; };
""") """,
]; ),
]
for (name, template) in TEMPLATES: for (name, template) in TEMPLATES:
parser = parser.reset() parser = parser.reset()
@ -242,15 +358,16 @@ def WebIDLTest(parser, harness):
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow %s on %s" % (attribute, name))
"Should not allow %s on %s" % (attribute, name))
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [Clamp, EnforceRange] long Foo; typedef [Clamp, EnforceRange] long Foo;
""") """
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
@ -260,23 +377,26 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [EnforceRange, Clamp] long Foo; typedef [EnforceRange, Clamp] long Foo;
""") """
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange]") harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange]")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [Clamp] long Foo; typedef [Clamp] long Foo;
typedef [EnforceRange] Foo bar; typedef [EnforceRange] Foo bar;
""") """
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
@ -286,25 +406,36 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [EnforceRange] long Foo; typedef [EnforceRange] long Foo;
typedef [Clamp] Foo bar; typedef [Clamp] Foo bar;
""") """
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs") harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
TYPES = ["DOMString", "unrestricted float", "float", "unrestricted double", "double"] TYPES = [
"DOMString",
"unrestricted float",
"float",
"unrestricted double",
"double",
]
for type in TYPES: for type in TYPES:
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [Clamp] %s Foo; typedef [Clamp] %s Foo;
""" % type) """
% type
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
@ -314,58 +445,70 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [EnforceRange] %s Foo; typedef [EnforceRange] %s Foo;
""" % type) """
% type
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [EnforceRange] on %s" % type) harness.ok(threw, "Should not allow [EnforceRange] on %s" % type)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
typedef [TreatNullAs=EmptyString] long Foo; """
""") typedef [LegacyNullToEmptyString] long Foo;
"""
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [TreatNullAs] on long") harness.ok(threw, "Should not allow [LegacyNullToEmptyString] on long")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
typedef [TreatNullAs=EmptyString] JSString Foo; """
""") typedef [LegacyNullToEmptyString] JSString Foo;
"""
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [TreatNullAs] on JSString") harness.ok(threw, "Should not allow [LegacyNullToEmptyString] on JSString")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
typedef [TreatNullAs=EmptyString] DOMString? Foo; """
""") typedef [LegacyNullToEmptyString] DOMString? Foo;
"""
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [TreatNullAs] on nullable DOMString") harness.ok(
threw, "Should not allow [LegacyNullToEmptyString] on nullable DOMString"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [AllowShared] DOMString Foo; typedef [AllowShared] DOMString Foo;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -374,9 +517,11 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef [AllowShared=something] ArrayBufferView Foo; typedef [AllowShared=something] ArrayBufferView Foo;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -385,31 +530,41 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
undefined foo([Clamp] Bar arg); undefined foo([Clamp] Bar arg);
}; };
typedef long Bar; typedef long Bar;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, "Should allow type attributes on unresolved types") harness.ok(not threw, "Should allow type attributes on unresolved types")
harness.check(results[0].members[0].signatures()[0][1][0].type.hasClamp(), True, harness.check(
"Unresolved types with type attributes should correctly resolve with attributes") results[0].members[0].signatures()[0][1][0].type.hasClamp(),
True,
"Unresolved types with type attributes should correctly resolve with attributes",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
undefined foo(Bar arg); undefined foo(Bar arg);
}; };
typedef [Clamp] long Bar; typedef [Clamp] long Bar;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, "Should allow type attributes on typedefs") harness.ok(not threw, "Should allow type attributes on typedefs")
harness.check(results[0].members[0].signatures()[0][1][0].type.hasClamp(), True, harness.check(
"Unresolved types that resolve to typedefs with attributes should correctly resolve with attributes") results[0].members[0].signatures()[0][1][0].type.hasClamp(),
True,
"Unresolved types that resolve to typedefs with attributes should correctly resolve with attributes",
)

View file

@ -1,11 +1,14 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface Test { interface Test {
attribute long b; attribute long b;
}; };
"""); """
)
attr = parser.finish()[0].members[0] attr = parser.finish()[0].members[0]
harness.check(attr.type.filename(), '<builtin>', 'Filename on builtin type') harness.check(attr.type.filename(), "<builtin>", "Filename on builtin type")

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestBuiltins { interface TestBuiltins {
attribute boolean b; attribute boolean b;
attribute byte s8; attribute byte s8;
@ -12,30 +14,46 @@ def WebIDLTest(parser, harness):
attribute unsigned long u32; attribute unsigned long u32;
attribute long long s64; attribute long long s64;
attribute unsigned long long u64; attribute unsigned long long u64;
attribute DOMTimeStamp ts;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "TestBuiltins interface parsed without error.") harness.ok(True, "TestBuiltins interface parsed without error.")
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
iface = results[0] iface = results[0]
harness.check(iface.identifier.QName(), "::TestBuiltins", "Interface has the right QName") harness.check(
iface.identifier.QName(), "::TestBuiltins", "Interface has the right QName"
)
harness.check(iface.identifier.name, "TestBuiltins", "Interface has the right name") harness.check(iface.identifier.name, "TestBuiltins", "Interface has the right name")
harness.check(iface.parent, None, "Interface has no parent") harness.check(iface.parent, None, "Interface has no parent")
members = iface.members members = iface.members
harness.check(len(members), 10, "Should be one production") harness.check(len(members), 9, "Should be one production")
names = ["b", "s8", "u8", "s16", "u16", "s32", "u32", "s64", "u64", "ts"] names = ["b", "s8", "u8", "s16", "u16", "s32", "u32", "s64", "u64", "ts"]
types = ["Boolean", "Byte", "Octet", "Short", "UnsignedShort", "Long", "UnsignedLong", "LongLong", "UnsignedLongLong", "UnsignedLongLong"] types = [
for i in range(10): "Boolean",
"Byte",
"Octet",
"Short",
"UnsignedShort",
"Long",
"UnsignedLong",
"LongLong",
"UnsignedLongLong",
"UnsignedLongLong",
]
for i in range(9):
attr = members[i] attr = members[i]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
harness.check(attr.identifier.QName(), "::TestBuiltins::" + names[i], "Attr has correct QName") harness.check(
attr.identifier.QName(),
"::TestBuiltins::" + names[i],
"Attr has correct QName",
)
harness.check(attr.identifier.name, names[i], "Attr has correct name") harness.check(attr.identifier.name, names[i], "Attr has correct name")
harness.check(str(attr.type), types[i], "Attr type is the correct name") harness.check(str(attr.type), types[i], "Attr type is the correct name")
harness.ok(attr.type.isPrimitive(), "Should be a primitive type") harness.ok(attr.type.isPrimitive(), "Should be a primitive type")

View file

@ -2,24 +2,30 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestByteString { interface TestByteString {
attribute ByteString bs; attribute ByteString bs;
attribute DOMString ds; attribute DOMString ds;
}; };
""") """
)
results = parser.finish(); results = parser.finish()
harness.ok(True, "TestByteString interface parsed without error.") harness.ok(True, "TestByteString interface parsed without error.")
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
iface = results[0] iface = results[0]
harness.check(iface.identifier.QName(), "::TestByteString", "Interface has the right QName") harness.check(
harness.check(iface.identifier.name, "TestByteString", "Interface has the right name") 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") harness.check(iface.parent, None, "Interface has no parent")
members = iface.members members = iface.members
@ -27,7 +33,9 @@ def WebIDLTest(parser, harness):
attr = members[0] attr = members[0]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") 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.QName(), "::TestByteString::bs", "Attr has correct QName"
)
harness.check(attr.identifier.name, "bs", "Attr has correct name") harness.check(attr.identifier.name, "bs", "Attr has correct name")
harness.check(str(attr.type), "ByteString", "Attr type is the 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.isByteString(), "Should be ByteString type")
@ -37,7 +45,9 @@ def WebIDLTest(parser, harness):
# now check we haven't broken DOMStrings in the process. # now check we haven't broken DOMStrings in the process.
attr = members[1] attr = members[1]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") 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.QName(), "::TestByteString::ds", "Attr has correct QName"
)
harness.check(attr.identifier.name, "ds", "Attr has correct name") harness.check(attr.identifier.name, "ds", "Attr has correct name")
harness.check(str(attr.type), "String", "Attr type is the 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.isDOMString(), "Should be DOMString type")
@ -47,53 +57,69 @@ def WebIDLTest(parser, harness):
# Cannot represent constant ByteString in IDL. # Cannot represent constant ByteString in IDL.
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface ConstByteString { interface ConstByteString {
const ByteString foo = "hello" const ByteString foo = "hello"
}; };
""") """
)
except WebIDL.WebIDLError: except WebIDL.WebIDLError:
threw = True threw = True
harness.ok(threw, "Should have thrown a WebIDL error for ByteString default in interface") harness.ok(
threw, "Should have thrown a WebIDL error for ByteString default in interface"
)
# Can have optional ByteStrings with default values # Can have optional ByteStrings with default values
try: try:
parser.parse(""" parser.parse(
"""
interface OptionalByteString { interface OptionalByteString {
undefined passByteString(optional ByteString arg = "hello"); undefined passByteString(optional ByteString arg = "hello");
}; };
""") """
results2 = parser.finish(); )
results2 = parser.finish()
except WebIDL.WebIDLError as e: except WebIDL.WebIDLError as e:
harness.ok(False, harness.ok(
"Should not have thrown a WebIDL error for ByteString " False,
"default in dictionary. " + str(e)) "Should not have thrown a WebIDL error for ByteString "
"default in dictionary. " + str(e),
)
# Can have a default ByteString value in a dictionary # Can have a default ByteString value in a dictionary
try: try:
parser.parse(""" parser.parse(
"""
dictionary OptionalByteStringDict { dictionary OptionalByteStringDict {
ByteString item = "some string"; ByteString item = "some string";
}; };
""") """
results3 = parser.finish(); )
results3 = parser.finish()
except WebIDL.WebIDLError as e: except WebIDL.WebIDLError as e:
harness.ok(False, harness.ok(
"Should not have thrown a WebIDL error for ByteString " False,
"default in dictionary. " + str(e)) "Should not have thrown a WebIDL error for ByteString "
"default in dictionary. " + str(e),
)
# Don't allow control characters in ByteString literals # Don't allow control characters in ByteString literals
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary OptionalByteStringDict2 { dictionary OptionalByteStringDict2 {
ByteString item = "\x03"; ByteString item = "\x03";
}; };
""") """
)
results4 = parser.finish() results4 = parser.finish()
except WebIDL.WebIDLError as e: except WebIDL.WebIDLError as e:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown a WebIDL error for invalid ByteString " threw,
"default in dictionary") "Should have thrown a WebIDL error for invalid ByteString "
"default in dictionary",
)

View file

@ -1,32 +1,37 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestCallback { interface TestCallback {
attribute CallbackType? listener; attribute CallbackType? listener;
}; };
callback CallbackType = boolean (unsigned long arg); callback CallbackType = boolean (unsigned long arg);
""") """
)
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 two productions.") 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") harness.check(
harness.check(iface.identifier.QName(), "::TestCallback", "Interface has the right QName") iface.identifier.QName(), "::TestCallback", "Interface has the right QName"
)
harness.check(iface.identifier.name, "TestCallback", "Interface has the right name") harness.check(iface.identifier.name, "TestCallback", "Interface has the right name")
harness.check(len(iface.members), 1, "Expect %s members" % 1) harness.check(len(iface.members), 1, "Expect %s members" % 1)
attr = iface.members[0] attr = iface.members[0]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
"Should be an IDLAttribute")
harness.ok(attr.isAttr(), "Should be an attribute") harness.ok(attr.isAttr(), "Should be an attribute")
harness.ok(not attr.isMethod(), "Attr is not an method") harness.ok(not attr.isMethod(), "Attr is not an method")
harness.ok(not attr.isConst(), "Attr is not a const") harness.ok(not attr.isConst(), "Attr is not a const")
harness.check(attr.identifier.QName(), "::TestCallback::listener", "Attr has the right QName") harness.check(
attr.identifier.QName(), "::TestCallback::listener", "Attr has the right QName"
)
harness.check(attr.identifier.name, "listener", "Attr has the right name") harness.check(attr.identifier.name, "listener", "Attr has the right name")
t = attr.type t = attr.type
harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type") harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type")

View file

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

View file

@ -1,11 +1,14 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
callback interface TestCallbackInterface { callback interface TestCallbackInterface {
attribute boolean bool; attribute boolean bool;
}; };
""") """
)
results = parser.finish() results = parser.finish()
@ -16,13 +19,15 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestInterface { interface TestInterface {
}; };
callback interface TestCallbackInterface : TestInterface { callback interface TestCallbackInterface : TestInterface {
attribute boolean bool; attribute boolean bool;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -32,13 +37,15 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestInterface : TestCallbackInterface { interface TestInterface : TestCallbackInterface {
}; };
callback interface TestCallbackInterface { callback interface TestCallbackInterface {
attribute boolean bool; attribute boolean bool;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -46,7 +53,8 @@ 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 = parser.reset()
parser.parse(""" parser.parse(
"""
callback interface TestCallbackInterface1 { callback interface TestCallbackInterface1 {
undefined foo(); undefined foo();
}; };
@ -86,9 +94,13 @@ def WebIDLTest(parser, harness):
callback interface TestCallbackInterface10 : TestCallbackInterface1 { callback interface TestCallbackInterface10 : TestCallbackInterface1 {
undefined bar(); undefined bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
for (i, iface) in enumerate(results): for (i, iface) in enumerate(results):
harness.check(iface.isSingleOperationInterface(), i < 4, harness.check(
"Interface %s should be a single operation interface" % iface.isSingleOperationInterface(),
iface.identifier.name) i < 4,
"Interface %s should be a single operation interface"
% iface.identifier.name,
)

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions(DOMString a)] undefined foo(boolean arg2); [CEReactions(DOMString a)] undefined foo(boolean arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -16,11 +18,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions(DOMString b)] readonly attribute boolean bar; [CEReactions(DOMString b)] readonly attribute boolean bar;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -31,54 +35,72 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions] attribute boolean bar; [CEReactions] attribute boolean bar;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as e: except Exception as e:
harness.ok(False, "Shouldn't have thrown for [CEReactions] used on writable attribute. %s" % e) harness.ok(
False,
"Shouldn't have thrown for [CEReactions] used on writable attribute. %s"
% e,
)
threw = True threw = True
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions] undefined foo(boolean arg2); [CEReactions] undefined foo(boolean arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as e: except Exception as e:
harness.ok(False, "Shouldn't have thrown for [CEReactions] used on regular operations. %s" % e) harness.ok(
False,
"Shouldn't have thrown for [CEReactions] used on regular operations. %s"
% e,
)
threw = True threw = True
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions] readonly attribute boolean A; [CEReactions] readonly attribute boolean A;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should have thrown for [CEReactions] used on a readonly attribute") harness.ok(
threw, "Should have thrown for [CEReactions] used on a readonly attribute"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[CEReactions] [CEReactions]
interface Foo { interface Foo {
} }
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -89,45 +111,47 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions] getter any(DOMString name); [CEReactions] getter any(DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should have thrown for [CEReactions] used on a named getter")
"Should have thrown for [CEReactions] used on a named getter")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions] legacycaller double compute(double x); [CEReactions] legacycaller double compute(double x);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should have thrown for [CEReactions] used on a legacycaller")
"Should have thrown for [CEReactions] used on a legacycaller")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
[CEReactions] stringifier DOMString (); [CEReactions] stringifier DOMString ();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should have thrown for [CEReactions] used on a stringifier")
"Should have thrown for [CEReactions] used on a stringifier")

View file

@ -1,23 +1,28 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
dictionary Dict { dictionary Dict {
any foo; any foo;
[ChromeOnly] any bar; [ChromeOnly] any bar;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should have a dictionary") harness.check(len(results), 1, "Should have a dictionary")
members = results[0].members; members = results[0].members
harness.check(len(members), 2, "Should have two members") harness.check(len(members), 2, "Should have two members")
# Note that members are ordered lexicographically, so "bar" comes # Note that members are ordered lexicographically, so "bar" comes
# before "foo". # before "foo".
harness.ok(members[0].getExtendedAttribute("ChromeOnly"), harness.ok(
"First member is not ChromeOnly") members[0].getExtendedAttribute("ChromeOnly"), "First member is not ChromeOnly"
harness.ok(not members[1].getExtendedAttribute("ChromeOnly"), )
"Second member is ChromeOnly") harness.ok(
not members[1].getExtendedAttribute("ChromeOnly"), "Second member is ChromeOnly"
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary Dict { dictionary Dict {
any foo; any foo;
any bar; any bar;
@ -26,14 +31,16 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Constant, Cached] readonly attribute Dict dict; [Constant, Cached] readonly attribute Dict dict;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, "Should have a dictionary and an interface") harness.check(len(results), 2, "Should have a dictionary and an interface")
parser = parser.reset() parser = parser.reset()
exception = None exception = None
try: try:
parser.parse(""" parser.parse(
"""
dictionary Dict { dictionary Dict {
any foo; any foo;
[ChromeOnly] any bar; [ChromeOnly] any bar;
@ -42,21 +49,25 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Constant, Cached] readonly attribute Dict dict; [Constant, Cached] readonly attribute Dict dict;
}; };
""") """
results = parser.finish() )
results = parser.finish()
except Exception as e: except Exception as e:
exception = e exception = e
harness.ok(exception, "Should have thrown.") harness.ok(exception, "Should have thrown.")
harness.check(exception.message, harness.check(
"[Cached] and [StoreInSlot] must not be used on an attribute " exception.message,
"whose type contains a [ChromeOnly] dictionary member", "[Cached] and [StoreInSlot] must not be used on an attribute "
"Should have thrown the right exception") "whose type contains a [ChromeOnly] dictionary member",
"Should have thrown the right exception",
)
parser = parser.reset() parser = parser.reset()
exception = None exception = None
try: try:
parser.parse(""" parser.parse(
"""
dictionary ParentDict { dictionary ParentDict {
[ChromeOnly] any bar; [ChromeOnly] any bar;
}; };
@ -68,21 +79,25 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Constant, Cached] readonly attribute Dict dict; [Constant, Cached] readonly attribute Dict dict;
}; };
""") """
results = parser.finish() )
results = parser.finish()
except Exception as e: except Exception as e:
exception = e exception = e
harness.ok(exception, "Should have thrown (2).") harness.ok(exception, "Should have thrown (2).")
harness.check(exception.message, harness.check(
"[Cached] and [StoreInSlot] must not be used on an attribute " exception.message,
"whose type contains a [ChromeOnly] dictionary member", "[Cached] and [StoreInSlot] must not be used on an attribute "
"Should have thrown the right exception (2)") "whose type contains a [ChromeOnly] dictionary member",
"Should have thrown the right exception (2)",
)
parser = parser.reset() parser = parser.reset()
exception = None exception = None
try: try:
parser.parse(""" parser.parse(
"""
dictionary GrandParentDict { dictionary GrandParentDict {
[ChromeOnly] any baz; [ChromeOnly] any baz;
}; };
@ -98,13 +113,16 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Constant, Cached] readonly attribute Dict dict; [Constant, Cached] readonly attribute Dict dict;
}; };
""") """
results = parser.finish() )
results = parser.finish()
except Exception as e: except Exception as e:
exception = e exception = e
harness.ok(exception, "Should have thrown (3).") harness.ok(exception, "Should have thrown (3).")
harness.check(exception.message, harness.check(
"[Cached] and [StoreInSlot] must not be used on an attribute " exception.message,
"whose type contains a [ChromeOnly] dictionary member", "[Cached] and [StoreInSlot] must not be used on an attribute "
"Should have thrown the right exception (3)") "whose type contains a [ChromeOnly] dictionary member",
"Should have thrown the right exception (3)",
)

View file

@ -22,8 +22,10 @@ expected = [
("::TestConsts::udbi", "udbi", "UnrestrictedDouble", 2), ("::TestConsts::udbi", "udbi", "UnrestrictedDouble", 2),
] ]
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestConsts { interface TestConsts {
const byte zero = 0; const byte zero = 0;
const byte b = -1; const byte b = -1;
@ -45,22 +47,25 @@ def WebIDLTest(parser, harness):
const unrestricted float ufli = 2; const unrestricted float ufli = 2;
const unrestricted double udbi = 2; const unrestricted double udbi = 2;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "TestConsts interface parsed without error.") harness.ok(True, "TestConsts interface parsed without error.")
harness.check(len(results), 1, "Should be one production.") harness.check(len(results), 1, "Should be one production.")
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") harness.check(
harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName") 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), len(expected), "Expect %s members" % len(expected)) harness.check(
len(iface.members), len(expected), "Expect %s members" % len(expected)
)
for (const, (QName, name, type, value)) in zip(iface.members, expected): for (const, (QName, name, type, value)) in zip(iface.members, expected):
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")
harness.ok(not const.isAttr(), "Const is not an attr") harness.ok(not const.isAttr(), "Const is not an attr")
harness.ok(not const.isMethod(), "Const is not a method") harness.ok(not const.isMethod(), "Const is not a method")
@ -68,19 +73,23 @@ def WebIDLTest(parser, harness):
harness.check(const.identifier.name, name, "Const has the right name") harness.check(const.identifier.name, name, "Const has the right name")
harness.check(str(const.type), type, "Const has the right type") harness.check(str(const.type), type, "Const has the right type")
harness.ok(const.type.isPrimitive(), "All consts should be primitive") harness.ok(const.type.isPrimitive(), "All consts should be primitive")
harness.check(str(const.value.type), str(const.type), harness.check(
"Const's value has the same type as the type") str(const.value.type),
str(const.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.")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestConsts { interface TestConsts {
const boolean? zero = 0; const boolean? zero = 0;
}; };
""") """
)
parser.finish() parser.finish()
except: except:
threw = True threw = True

View file

@ -1,21 +1,39 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
def checkArgument(argument, QName, name, type, optional, variadic): def checkArgument(argument, QName, name, type, optional, variadic):
harness.ok(isinstance(argument, WebIDL.IDLArgument), harness.ok(isinstance(argument, WebIDL.IDLArgument), "Should be an IDLArgument")
"Should be an IDLArgument") harness.check(
harness.check(argument.identifier.QName(), QName, "Argument has the right QName") argument.identifier.QName(), QName, "Argument has the right QName"
)
harness.check(argument.identifier.name, name, "Argument has the right name") harness.check(argument.identifier.name, name, "Argument has the right name")
harness.check(str(argument.type), type, "Argument has the right return type") harness.check(str(argument.type), type, "Argument has the right return type")
harness.check(argument.optional, optional, "Argument has the right optional value") harness.check(
harness.check(argument.variadic, variadic, "Argument has the right variadic value") argument.optional, optional, "Argument has the right optional value"
)
harness.check(
argument.variadic, variadic, "Argument has the right variadic value"
)
def checkMethod(method, QName, name, signatures, def checkMethod(
static=True, getter=False, setter=False, deleter=False, method,
legacycaller=False, stringifier=False, chromeOnly=False, QName,
htmlConstructor=False, secureContext=False, pref=None, func=None): name,
harness.ok(isinstance(method, WebIDL.IDLMethod), signatures,
"Should be an IDLMethod") static=True,
getter=False,
setter=False,
deleter=False,
legacycaller=False,
stringifier=False,
chromeOnly=False,
htmlConstructor=False,
secureContext=False,
pref=None,
func=None,
):
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method") harness.ok(method.isMethod(), "Method is a method")
harness.ok(not method.isAttr(), "Method is not an attr") harness.ok(not method.isAttr(), "Method is not an attr")
harness.ok(not method.isConst(), "Method is not a const") harness.ok(not method.isConst(), "Method is not a const")
@ -24,23 +42,58 @@ def WebIDLTest(parser, harness):
harness.check(method.isStatic(), static, "Method has the correct static value") harness.check(method.isStatic(), static, "Method has the correct static value")
harness.check(method.isGetter(), getter, "Method has the correct getter value") harness.check(method.isGetter(), getter, "Method has the correct getter value")
harness.check(method.isSetter(), setter, "Method has the correct setter value") harness.check(method.isSetter(), setter, "Method has the correct setter value")
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value") harness.check(
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value") method.isDeleter(), deleter, "Method has the correct deleter value"
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value") )
harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly") harness.check(
harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value") method.isLegacycaller(),
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures") legacycaller,
harness.check(method.getExtendedAttribute("Pref"), pref, "Method has the correct pref value") "Method has the correct legacycaller value",
harness.check(method.getExtendedAttribute("Func"), func, "Method has the correct func value") )
harness.check(method.getExtendedAttribute("SecureContext") is not None, secureContext, "Method has the correct SecureContext value") harness.check(
method.isStringifier(),
stringifier,
"Method has the correct stringifier value",
)
harness.check(
method.getExtendedAttribute("ChromeOnly") is not None,
chromeOnly,
"Method has the correct value for ChromeOnly",
)
harness.check(
method.isHTMLConstructor(),
htmlConstructor,
"Method has the correct htmlConstructor value",
)
harness.check(
len(method.signatures()),
len(signatures),
"Method has the correct number of signatures",
)
harness.check(
method.getExtendedAttribute("Pref"),
pref,
"Method has the correct pref value",
)
harness.check(
method.getExtendedAttribute("Func"),
func,
"Method has the correct func value",
)
harness.check(
method.getExtendedAttribute("SecureContext") is not None,
secureContext,
"Method has the correct SecureContext value",
)
sigpairs = zip(method.signatures(), signatures) sigpairs = zip(method.signatures(), signatures)
for (gotSignature, expectedSignature) in sigpairs: for (gotSignature, expectedSignature) in sigpairs:
(gotRetType, gotArgs) = gotSignature (gotRetType, gotArgs) = gotSignature
(expectedRetType, expectedArgs) = expectedSignature (expectedRetType, expectedArgs) = expectedSignature
harness.check(str(gotRetType), expectedRetType, harness.check(
"Method has the expected return type.") str(gotRetType), expectedRetType, "Method has the expected return type."
)
for i in range(0, len(gotArgs)): for i in range(0, len(gotArgs)):
(QName, name, type, optional, variadic) = expectedArgs[i] (QName, name, type, optional, variadic) = expectedArgs[i]
@ -48,33 +101,88 @@ def WebIDLTest(parser, harness):
def checkResults(results): def checkResults(results):
harness.check(len(results), 3, "Should be three productions") harness.check(len(results), 3, "Should be three productions")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(
"Should be an IDLInterface") isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface"
harness.ok(isinstance(results[1], WebIDL.IDLInterface), )
"Should be an IDLInterface") harness.ok(
harness.ok(isinstance(results[2], WebIDL.IDLInterface), isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface"
"Should be an IDLInterface") )
harness.ok(
isinstance(results[2], WebIDL.IDLInterface), "Should be an IDLInterface"
)
checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor", checkMethod(
"constructor", [("TestConstructorNoArgs (Wrapper)", [])]) results[0].ctor(),
harness.check(len(results[0].members), 0, "::TestConstructorNoArgs::constructor",
"TestConstructorNoArgs should not have members") "constructor",
checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor", [("TestConstructorNoArgs (Wrapper)", [])],
"constructor", )
[("TestConstructorWithArgs (Wrapper)", harness.check(
[("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])]) len(results[0].members), 0, "TestConstructorNoArgs should not have members"
harness.check(len(results[1].members), 0, )
"TestConstructorWithArgs should not have members") checkMethod(
checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor", results[1].ctor(),
"constructor", "::TestConstructorWithArgs::constructor",
[("TestConstructorOverloads (Wrapper)", "constructor",
[("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]), [
("TestConstructorOverloads (Wrapper)", (
[("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])]) "TestConstructorWithArgs (Wrapper)",
harness.check(len(results[2].members), 0, [
"TestConstructorOverloads should not have members") (
"::TestConstructorWithArgs::constructor::name",
"name",
"String",
False,
False,
)
],
)
],
)
harness.check(
len(results[1].members),
0,
"TestConstructorWithArgs should not have members",
)
checkMethod(
results[2].ctor(),
"::TestConstructorOverloads::constructor",
"constructor",
[
(
"TestConstructorOverloads (Wrapper)",
[
(
"::TestConstructorOverloads::constructor::foo",
"foo",
"Object",
False,
False,
)
],
),
(
"TestConstructorOverloads (Wrapper)",
[
(
"::TestConstructorOverloads::constructor::bar",
"bar",
"Boolean",
False,
False,
)
],
),
],
)
harness.check(
len(results[2].members),
0,
"TestConstructorOverloads should not have members",
)
parser.parse(""" parser.parse(
"""
interface TestConstructorNoArgs { interface TestConstructorNoArgs {
constructor(); constructor();
}; };
@ -87,111 +195,146 @@ def WebIDLTest(parser, harness):
constructor(object foo); constructor(object foo);
constructor(boolean bar); constructor(boolean bar);
}; };
""") """
)
results = parser.finish() results = parser.finish()
checkResults(results) checkResults(results)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestPrefConstructor { interface TestPrefConstructor {
[Pref="dom.webidl.test1"] constructor(); [Pref="dom.webidl.test1"] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestPrefConstructor::constructor", checkMethod(
"constructor", [("TestPrefConstructor (Wrapper)", [])], results[0].ctor(),
pref=["dom.webidl.test1"]) "::TestPrefConstructor::constructor",
"constructor",
[("TestPrefConstructor (Wrapper)", [])],
pref=["dom.webidl.test1"],
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestChromeOnlyConstructor { interface TestChromeOnlyConstructor {
[ChromeOnly] constructor(); [ChromeOnly] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestChromeOnlyConstructor::constructor", checkMethod(
"constructor", [("TestChromeOnlyConstructor (Wrapper)", [])], results[0].ctor(),
chromeOnly=True) "::TestChromeOnlyConstructor::constructor",
"constructor",
[("TestChromeOnlyConstructor (Wrapper)", [])],
chromeOnly=True,
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestSCConstructor { interface TestSCConstructor {
[SecureContext] constructor(); [SecureContext] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestSCConstructor::constructor", checkMethod(
"constructor", [("TestSCConstructor (Wrapper)", [])], results[0].ctor(),
secureContext=True) "::TestSCConstructor::constructor",
"constructor",
[("TestSCConstructor (Wrapper)", [])],
secureContext=True,
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestFuncConstructor { interface TestFuncConstructor {
[Func="Document::IsWebAnimationsEnabled"] constructor(); [Func="Document::IsWebAnimationsEnabled"] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestFuncConstructor::constructor", checkMethod(
"constructor", [("TestFuncConstructor (Wrapper)", [])], results[0].ctor(),
func=["Document::IsWebAnimationsEnabled"]) "::TestFuncConstructor::constructor",
"constructor",
[("TestFuncConstructor (Wrapper)", [])],
func=["Document::IsWebAnimationsEnabled"],
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestPrefChromeOnlySCFuncConstructor { interface TestPrefChromeOnlySCFuncConstructor {
[ChromeOnly, Pref="dom.webidl.test1", SecureContext, Func="Document::IsWebAnimationsEnabled"] [ChromeOnly, Pref="dom.webidl.test1", SecureContext, Func="Document::IsWebAnimationsEnabled"]
constructor(); constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestPrefChromeOnlySCFuncConstructor::constructor", checkMethod(
"constructor", [("TestPrefChromeOnlySCFuncConstructor (Wrapper)", [])], results[0].ctor(),
func=["Document::IsWebAnimationsEnabled"], pref=["dom.webidl.test1"], "::TestPrefChromeOnlySCFuncConstructor::constructor",
chromeOnly=True, secureContext=True) "constructor",
[("TestPrefChromeOnlySCFuncConstructor (Wrapper)", [])],
func=["Document::IsWebAnimationsEnabled"],
pref=["dom.webidl.test1"],
chromeOnly=True,
secureContext=True,
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructor { interface TestHTMLConstructor {
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor", checkMethod(
"constructor", [("TestHTMLConstructor (Wrapper)", [])], results[0].ctor(),
htmlConstructor=True) "::TestHTMLConstructor::constructor",
"constructor",
[("TestHTMLConstructor (Wrapper)", [])],
htmlConstructor=True,
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestChromeOnlyConstructor { interface TestChromeOnlyConstructor {
constructor() constructor()
[ChromeOnly] constructor(DOMString a); [ChromeOnly] constructor(DOMString a);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -202,11 +345,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorWithArgs { interface TestHTMLConstructorWithArgs {
[HTMLConstructor] constructor(DOMString a); [HTMLConstructor] constructor(DOMString a);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -217,11 +362,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
callback interface TestHTMLConstructorOnCallbackInterface { callback interface TestHTMLConstructorOnCallbackInterface {
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -232,12 +379,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
constructor(); constructor();
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -247,165 +396,187 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
[Throws] [Throws]
constructor(); constructor();
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Can't have both a throwing constructor and a HTMLConstructor")
"Can't have both a throwing constructor and a HTMLConstructor")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
constructor(DOMString a); constructor(DOMString a);
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Can't have both a HTMLConstructor and a constructor operation")
"Can't have both a HTMLConstructor and a constructor operation")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
[Throws] [Throws]
constructor(DOMString a); constructor(DOMString a);
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Can't have both a HTMLConstructor and a throwing constructor " threw,
"operation") "Can't have both a HTMLConstructor and a throwing constructor " "operation",
)
# Test HTMLConstructor and [ChromeOnly] constructor operation # Test HTMLConstructor and [ChromeOnly] constructor operation
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
[ChromeOnly] [ChromeOnly]
constructor(); constructor();
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Can't have both a ChromeOnly constructor and a HTMLConstructor")
"Can't have both a ChromeOnly constructor and a HTMLConstructor")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
[Throws, ChromeOnly] [Throws, ChromeOnly]
constructor(); constructor();
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Can't have both a throwing chromeonly constructor and a " threw,
"HTMLConstructor") "Can't have both a throwing chromeonly constructor and a " "HTMLConstructor",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
[ChromeOnly] [ChromeOnly]
constructor(DOMString a); constructor(DOMString a);
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Can't have both a HTMLConstructor and a chromeonly constructor " threw,
"operation") "Can't have both a HTMLConstructor and a chromeonly constructor " "operation",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestHTMLConstructorAndConstructor { interface TestHTMLConstructorAndConstructor {
[Throws, ChromeOnly] [Throws, ChromeOnly]
constructor(DOMString a); constructor(DOMString a);
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Can't have both a HTMLConstructor and a throwing chromeonly " threw,
"constructor operation") "Can't have both a HTMLConstructor and a throwing chromeonly "
"constructor operation",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[NoInterfaceObject] """
[LegacyNoInterfaceObject]
interface InterfaceWithoutInterfaceObject { interface InterfaceWithoutInterfaceObject {
constructor(); constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Can't have a constructor operation on a [NoInterfaceObject] " threw,
"interface") "Can't have a constructor operation on a [LegacyNoInterfaceObject] "
"interface",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface InterfaceWithPartial { interface InterfaceWithPartial {
}; };
partial interface InterfaceWithPartial { partial interface InterfaceWithPartial {
constructor(); constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Can't have a constructor operation on a partial interface")
"Can't have a constructor operation on a partial interface")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface InterfaceWithMixin { interface InterfaceWithMixin {
}; };
@ -414,11 +585,10 @@ def WebIDLTest(parser, harness):
}; };
InterfaceWithMixin includes Mixin InterfaceWithMixin includes Mixin
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Can't have a constructor operation on a mixin")
"Can't have a constructor operation on a mixin")

View file

@ -1,14 +1,17 @@
import traceback import traceback
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=TestConstructorGlobal] [Global, Exposed=TestConstructorGlobal]
interface TestConstructorGlobal { interface TestConstructorGlobal {
constructor(); constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -19,12 +22,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[Global, Exposed=TestNamedConstructorGlobal, """
NamedConstructor=FooBar] [Global, Exposed=TestLegacyFactoryFunctionGlobal,
interface TestNamedConstructorGlobal { LegacyFactoryFunction=FooBar]
interface TestLegacyFactoryFunctionGlobal {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -34,12 +39,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[NamedConstructor=FooBar, Global, """
Exposed=TestNamedConstructorGlobal] [LegacyFactoryFunction=FooBar, Global,
interface TestNamedConstructorGlobal { Exposed=TestLegacyFactoryFunctionGlobal]
interface TestLegacyFactoryFunctionGlobal {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -49,12 +56,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=TestHTMLConstructorGlobal] [Global, Exposed=TestHTMLConstructorGlobal]
interface TestHTMLConstructorGlobal { interface TestHTMLConstructorGlobal {
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,12 +1,14 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[NoInterfaceObject] """
interface TestConstructorNoInterfaceObject { [LegacyNoInterfaceObject]
interface TestConstructorLegacyNoInterfaceObject {
constructor(); constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -16,23 +18,27 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
[NoInterfaceObject, NamedConstructor=FooBar] """
interface TestNamedConstructorNoInterfaceObject { [LegacyNoInterfaceObject, LegacyFactoryFunction=FooBar]
interface TestLegacyFactoryFunctionLegacyNoInterfaceObject {
}; };
""") """
)
# Test HTMLConstructor and NoInterfaceObject # Test HTMLConstructor and LegacyNoInterfaceObject
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[NoInterfaceObject] """
interface TestHTMLConstructorNoInterfaceObject { [LegacyNoInterfaceObject]
interface TestHTMLConstructorLegacyNoInterfaceObject {
[HTMLConstructor] constructor(); [HTMLConstructor] constructor();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,15 +1,20 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface Foo; interface Foo;
interface Bar; interface Bar;
interface Foo; interface Foo;
"""); """
)
results = parser.finish() results = parser.finish()
# There should be no duplicate interfaces in the result. # There should be no duplicate interfaces in the result.
expectedNames = sorted(['Foo', 'Bar']) expectedNames = sorted(["Foo", "Bar"])
actualNames = sorted(map(lambda iface: iface.identifier.name, results)) actualNames = sorted(map(lambda iface: iface.identifier.name, results))
harness.check(actualNames, expectedNames, "Parser shouldn't output duplicate names.") harness.check(
actualNames, expectedNames, "Parser shouldn't output duplicate names."
)

View file

@ -1,5 +1,6 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
dictionary Dict2 : Dict1 { dictionary Dict2 : Dict1 {
long child = 5; long child = 5;
Dict1 aaandAnother; Dict1 aaandAnother;
@ -8,27 +9,33 @@ def WebIDLTest(parser, harness):
long parent; long parent;
double otherParent; double otherParent;
}; };
""") """
)
results = parser.finish() results = parser.finish()
dict1 = results[1]; dict1 = results[1]
dict2 = results[0]; dict2 = results[0]
harness.check(len(dict1.members), 2, "Dict1 has two members") harness.check(len(dict1.members), 2, "Dict1 has two members")
harness.check(len(dict2.members), 2, "Dict2 has four members") harness.check(len(dict2.members), 2, "Dict2 has four members")
harness.check(dict1.members[0].identifier.name, "otherParent", harness.check(
"'o' comes before 'p'") dict1.members[0].identifier.name, "otherParent", "'o' comes before 'p'"
harness.check(dict1.members[1].identifier.name, "parent", )
"'o' really comes before 'p'") harness.check(
harness.check(dict2.members[0].identifier.name, "aaandAnother", dict1.members[1].identifier.name, "parent", "'o' really comes before 'p'"
"'a' comes before 'c'") )
harness.check(dict2.members[1].identifier.name, "child", harness.check(
"'a' really comes before 'c'") dict2.members[0].identifier.name, "aaandAnother", "'a' comes before 'c'"
)
harness.check(
dict2.members[1].identifier.name, "child", "'a' really comes before 'c'"
)
# Test partial dictionary. # Test partial dictionary.
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
long c; long c;
long g; long g;
@ -37,30 +44,29 @@ def WebIDLTest(parser, harness):
long h; long h;
long d; long d;
}; };
""") """
)
results = parser.finish() results = parser.finish()
dict1 = results[0]; dict1 = results[0]
harness.check(len(dict1.members), 4, "Dict1 has four members") harness.check(len(dict1.members), 4, "Dict1 has four members")
harness.check(dict1.members[0].identifier.name, "c", harness.check(dict1.members[0].identifier.name, "c", "c should be first")
"c should be first") harness.check(dict1.members[1].identifier.name, "d", "d should come after c")
harness.check(dict1.members[1].identifier.name, "d", harness.check(dict1.members[2].identifier.name, "g", "g should come after d")
"d should come after c") harness.check(dict1.members[3].identifier.name, "h", "h should be last")
harness.check(dict1.members[2].identifier.name, "g",
"g should come after d")
harness.check(dict1.members[3].identifier.name, "h",
"h should be last")
# Now reset our parser # Now reset our parser
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Dict { dictionary Dict {
long prop = 5; long prop = 5;
long prop; long prop;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -68,28 +74,33 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow name duplication in a dictionary") harness.ok(threw, "Should not allow name duplication in a dictionary")
# Test no name duplication across normal and partial dictionary. # Test no name duplication across normal and partial dictionary.
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
long prop = 5; long prop = 5;
}; };
partial dictionary A { partial dictionary A {
long prop; long prop;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow name duplication across normal and partial dictionary") harness.ok(
threw, "Should not allow name duplication across normal and partial dictionary"
)
# Now reset our parser again # Now reset our parser again
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Dict1 : Dict2 { dictionary Dict1 : Dict2 {
long prop = 5; long prop = 5;
}; };
@ -99,24 +110,28 @@ def WebIDLTest(parser, harness):
dictionary Dict3 { dictionary Dict3 {
double prop; double prop;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow name duplication in a dictionary and " harness.ok(
"its ancestor") threw, "Should not allow name duplication in a dictionary and " "its ancestor"
)
# More reset # More reset
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Iface {}; interface Iface {};
dictionary Dict : Iface { dictionary Dict : Iface {
long prop; long prop;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -127,10 +142,12 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A : B {}; dictionary A : B {};
dictionary B : A {}; dictionary B : A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -140,27 +157,33 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
[TreatNullAs=EmptyString] DOMString foo; [LegacyNullToEmptyString] DOMString foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow [TreatNullAs] on dictionary members"); harness.ok(
threw, "Should not allow [LegacyNullToEmptyString] on dictionary members"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(A arg); undefined doFoo(A arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -170,13 +193,15 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional A arg); undefined doFoo(optional A arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -186,47 +211,53 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo((A or DOMString) arg); undefined doFoo((A or DOMString) arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Trailing union arg containing a dictionary must be optional")
"Trailing union arg containing a dictionary must be optional")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (A or DOMString) arg); undefined doFoo(optional (A or DOMString) arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Trailing union arg containing a dictionary must have a default value") threw, "Trailing union arg containing a dictionary must have a default value"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(A arg1, optional long arg2); undefined doFoo(A arg1, optional long arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -236,13 +267,15 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional A arg1, optional long arg2); undefined doFoo(optional A arg1, optional long arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -252,245 +285,289 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(A arg1, optional long arg2, long arg3); undefined doFoo(A arg1, optional long arg2, long arg3);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, harness.ok(
"Dictionary arg followed by non-optional arg doesn't have to be optional") not threw,
"Dictionary arg followed by non-optional arg doesn't have to be optional",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo((A or DOMString) arg1, optional long arg2); undefined doFoo((A or DOMString) arg1, optional long arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Union arg containing dictionary followed by optional arg must " threw,
"be optional") "Union arg containing dictionary followed by optional arg must " "be optional",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (A or DOMString) arg1, optional long arg2); undefined doFoo(optional (A or DOMString) arg1, optional long arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Union arg containing dictionary followed by optional arg must " threw,
"have a default value") "Union arg containing dictionary followed by optional arg must "
"have a default value",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(A arg1, long arg2); undefined doFoo(A arg1, long arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "Dictionary arg followed by required arg can be required") harness.ok(True, "Dictionary arg followed by required arg can be required")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional A? arg1 = {}); undefined doFoo(optional A? arg1 = {});
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = x threw = x
harness.ok(threw, "Optional dictionary arg must not be nullable") harness.ok(threw, "Optional dictionary arg must not be nullable")
harness.ok("nullable" in str(threw), harness.ok(
"Must have the expected exception for optional nullable dictionary arg") "nullable" in str(threw),
"Must have the expected exception for optional nullable dictionary arg",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
required long x; required long x;
}; };
interface X { interface X {
undefined doFoo(A? arg1); undefined doFoo(A? arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = x threw = x
harness.ok(threw, "Required dictionary arg must not be nullable") harness.ok(threw, "Required dictionary arg must not be nullable")
harness.ok("nullable" in str(threw), harness.ok(
"Must have the expected exception for required nullable " "nullable" in str(threw),
"dictionary arg") "Must have the expected exception for required nullable " "dictionary arg",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (A or long)? arg1 = {}); undefined doFoo(optional (A or long)? arg1 = {});
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = x threw = x
harness.ok(threw, "Dictionary arg must not be in an optional nullable union") harness.ok(threw, "Dictionary arg must not be in an optional nullable union")
harness.ok("nullable" in str(threw), harness.ok(
"Must have the expected exception for optional nullable union " "nullable" in str(threw),
"arg containing dictionary") "Must have the expected exception for optional nullable union "
"arg containing dictionary",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
required long x; required long x;
}; };
interface X { interface X {
undefined doFoo((A or long)? arg1); undefined doFoo((A or long)? arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = x threw = x
harness.ok(threw, "Dictionary arg must not be in a required nullable union") harness.ok(threw, "Dictionary arg must not be in a required nullable union")
harness.ok("nullable" in str(threw), harness.ok(
"Must have the expected exception for required nullable union " "nullable" in str(threw),
"arg containing dictionary") "Must have the expected exception for required nullable union "
"arg containing dictionary",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(sequence<A?> arg1); undefined doFoo(sequence<A?> arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, harness.ok(not threw, "Nullable union should be allowed in a sequence argument")
"Nullable union should be allowed in a sequence argument")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (A or long?) arg1); undefined doFoo(optional (A or long?) arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Dictionary must not be in a union with a nullable type")
"Dictionary must not be in a union with a nullable type")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (long? or A) arg1); undefined doFoo(optional (long? or A) arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "A nullable type must not be in a union with a dictionary")
"A nullable type must not be in a union with a dictionary")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
A? doFoo(); A? doFoo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "Dictionary return value can be nullable") harness.ok(True, "Dictionary return value can be nullable")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional A arg = {}); undefined doFoo(optional A arg = {});
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "Dictionary arg should actually parse") harness.ok(True, "Dictionary arg should actually parse")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (A or DOMString) arg = {}); undefined doFoo(optional (A or DOMString) arg = {});
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "Union arg containing a dictionary should actually parse") harness.ok(True, "Union arg containing a dictionary should actually parse")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
}; };
interface X { interface X {
undefined doFoo(optional (A or DOMString) arg = "abc"); undefined doFoo(optional (A or DOMString) arg = "abc");
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "Union arg containing a dictionary with string default should actually parse") harness.ok(
True,
"Union arg containing a dictionary with string default should actually parse",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
Foo foo; Foo foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -500,7 +577,8 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo3 : Foo { dictionary Foo3 : Foo {
short d; short d;
}; };
@ -516,78 +594,102 @@ def WebIDLTest(parser, harness):
dictionary Foo { dictionary Foo {
Foo1 b; Foo1 b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be a Dictionary that " harness.ok(
"inherits from its Dictionary.") threw,
"Member type must not be a Dictionary that " "inherits from its Dictionary.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
(Foo or DOMString)[]? b; (Foo or DOMString)[]? b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be a Nullable type " harness.ok(
"whose inner type includes its Dictionary.") threw,
"Member type must not be a Nullable type "
"whose inner type includes its Dictionary.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
(DOMString or Foo) b; (DOMString or Foo) b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be a Union type, one of " harness.ok(
"whose member types includes its Dictionary.") threw,
"Member type must not be a Union type, one of "
"whose member types includes its Dictionary.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
sequence<sequence<sequence<Foo>>> c; sequence<sequence<sequence<Foo>>> c;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be a Sequence type " harness.ok(
"whose element type includes its Dictionary.") threw,
"Member type must not be a Sequence type "
"whose element type includes its Dictionary.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
(DOMString or Foo)[] d; (DOMString or Foo)[] d;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be an Array type " harness.ok(
"whose element type includes its Dictionary.") threw,
"Member type must not be an Array type "
"whose element type includes its Dictionary.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
Foo1 b; Foo1 b;
}; };
@ -603,34 +705,41 @@ def WebIDLTest(parser, harness):
dictionary Foo1 : Foo2 { dictionary Foo1 : Foo2 {
long a; long a;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be a Dictionary, one of whose " harness.ok(
"members or inherited members has a type that includes " threw,
"its Dictionary.") "Member type must not be a Dictionary, one of whose "
"members or inherited members has a type that includes "
"its Dictionary.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
}; };
dictionary Bar { dictionary Bar {
Foo? d; Foo? d;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Member type must not be a nullable dictionary") harness.ok(threw, "Member type must not be a nullable dictionary")
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
unrestricted float urFloat = 0; unrestricted float urFloat = 0;
unrestricted float urFloat2 = 1.1; unrestricted float urFloat2 = 1.1;
@ -648,103 +757,117 @@ def WebIDLTest(parser, harness):
unrestricted double negativeInfUrDouble = -Infinity; unrestricted double negativeInfUrDouble = -Infinity;
unrestricted double nanUrDouble = NaN; unrestricted double nanUrDouble = NaN;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "Parsing default values for unrestricted types succeeded.") harness.ok(True, "Parsing default values for unrestricted types succeeded.")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
double f = Infinity; double f = Infinity;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Only unrestricted values can be initialized to Infinity") harness.ok(threw, "Only unrestricted values can be initialized to Infinity")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
double f = -Infinity; double f = -Infinity;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Only unrestricted values can be initialized to -Infinity") harness.ok(threw, "Only unrestricted values can be initialized to -Infinity")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
double f = NaN; double f = NaN;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Only unrestricted values can be initialized to NaN") harness.ok(threw, "Only unrestricted values can be initialized to NaN")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
float f = Infinity; float f = Infinity;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Only unrestricted values can be initialized to Infinity") harness.ok(threw, "Only unrestricted values can be initialized to Infinity")
parser = parser.reset()
parser = parser.reset();
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
float f = -Infinity; float f = -Infinity;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Only unrestricted values can be initialized to -Infinity") harness.ok(threw, "Only unrestricted values can be initialized to -Infinity")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
float f = NaN; float f = NaN;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Only unrestricted values can be initialized to NaN") harness.ok(threw, "Only unrestricted values can be initialized to NaN")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { dictionary Foo {
long module; long module;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True

View file

@ -1,8 +1,13 @@
import traceback
def firstArgType(method): def firstArgType(method):
return method.signatures()[0][1][0].type return method.signatures()[0][1][0].type
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
// Give our dictionary a required member so we don't need to // Give our dictionary a required member so we don't need to
// mess with optional and default values. // mess with optional and default values.
dictionary Dict { dictionary Dict {
@ -17,7 +22,8 @@ def WebIDLTest(parser, harness):
undefined passNullableUnion((object? or DOMString) arg); undefined passNullableUnion((object? or DOMString) arg);
undefined passNullable(Foo? arg); undefined passNullable(Foo? arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
iface = results[2] iface = results[2]
@ -30,31 +36,38 @@ def WebIDLTest(parser, harness):
dictType = firstArgType(dictMethod) dictType = firstArgType(dictMethod)
ifaceType = firstArgType(ifaceMethod) ifaceType = firstArgType(ifaceMethod)
harness.ok(dictType.isDictionary(), "Should have dictionary type"); harness.ok(dictType.isDictionary(), "Should have dictionary type")
harness.ok(ifaceType.isInterface(), "Should have interface type"); harness.ok(ifaceType.isInterface(), "Should have interface type")
harness.ok(ifaceType.isCallbackInterface(), "Should have callback interface type"); harness.ok(ifaceType.isCallbackInterface(), "Should have callback interface type")
harness.ok(not dictType.isDistinguishableFrom(ifaceType), harness.ok(
"Dictionary not distinguishable from callback interface") not dictType.isDistinguishableFrom(ifaceType),
harness.ok(not ifaceType.isDistinguishableFrom(dictType), "Dictionary not distinguishable from callback interface",
"Callback interface not distinguishable from dictionary") )
harness.ok(
not ifaceType.isDistinguishableFrom(dictType),
"Callback interface not distinguishable from dictionary",
)
nullableUnionType = firstArgType(nullableUnionMethod) nullableUnionType = firstArgType(nullableUnionMethod)
nullableIfaceType = firstArgType(nullableIfaceMethod) nullableIfaceType = firstArgType(nullableIfaceMethod)
harness.ok(nullableUnionType.isUnion(), "Should have union type"); harness.ok(nullableUnionType.isUnion(), "Should have union type")
harness.ok(nullableIfaceType.isInterface(), "Should have interface type"); harness.ok(nullableIfaceType.isInterface(), "Should have interface type")
harness.ok(nullableIfaceType.nullable(), "Should have nullable type"); harness.ok(nullableIfaceType.nullable(), "Should have nullable type")
harness.ok(not nullableUnionType.isDistinguishableFrom(nullableIfaceType), harness.ok(
"Nullable type not distinguishable from union with nullable " not nullableUnionType.isDistinguishableFrom(nullableIfaceType),
"member type") "Nullable type not distinguishable from union with nullable " "member type",
harness.ok(not nullableIfaceType.isDistinguishableFrom(nullableUnionType), )
"Union with nullable member type not distinguishable from " harness.ok(
"nullable type") not nullableIfaceType.isDistinguishableFrom(nullableUnionType),
"Union with nullable member type not distinguishable from " "nullable type",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestIface { interface TestIface {
undefined passKid(Kid arg); undefined passKid(Kid arg);
undefined passParent(Parent arg); undefined passParent(Parent arg);
@ -70,7 +83,8 @@ def WebIDLTest(parser, harness):
interface Grandparent {}; interface Grandparent {};
interface Unrelated1 {}; interface Unrelated1 {};
interface Unrelated2 {}; interface Unrelated2 {};
""") """
)
results = parser.finish() results = parser.finish()
iface = results[0] iface = results[0]
@ -80,21 +94,26 @@ def WebIDLTest(parser, harness):
for type1 in argTypes: for type1 in argTypes:
for type2 in argTypes: for type2 in argTypes:
distinguishable = (type1 is not type2 and distinguishable = type1 is not type2 and (
(type1 in unrelatedTypes or type1 in unrelatedTypes or type2 in unrelatedTypes
type2 in unrelatedTypes)) )
harness.check(type1.isDistinguishableFrom(type2), harness.check(
distinguishable, type1.isDistinguishableFrom(type2),
"Type %s should %sbe distinguishable from type %s" % distinguishable,
(type1, "" if distinguishable else "not ", type2)) "Type %s should %sbe distinguishable from type %s"
harness.check(type2.isDistinguishableFrom(type1), % (type1, "" if distinguishable else "not ", type2),
distinguishable, )
"Type %s should %sbe distinguishable from type %s" % harness.check(
(type2, "" if distinguishable else "not ", type1)) type2.isDistinguishableFrom(type1),
distinguishable,
"Type %s should %sbe distinguishable from type %s"
% (type2, "" if distinguishable else "not ", type1),
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Dummy {}; interface Dummy {};
interface TestIface { interface TestIface {
undefined method(long arg1, TestIface arg2); undefined method(long arg1, TestIface arg2);
@ -102,17 +121,19 @@ def WebIDLTest(parser, harness):
undefined method(long arg1, Dummy arg2); undefined method(long arg1, Dummy arg2);
undefined method(DOMString arg1, DOMString arg2, DOMString arg3); undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[1].members), 1, harness.check(len(results[1].members), 1, "Should look like we have one method")
"Should look like we have one method") harness.check(
harness.check(len(results[1].members[0].signatures()), 4, len(results[1].members[0].signatures()), 4, "Should have four signatures"
"Should have four signatures") )
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Dummy {}; interface Dummy {};
interface TestIface { interface TestIface {
undefined method(long arg1, TestIface arg2); undefined method(long arg1, TestIface arg2);
@ -120,19 +141,23 @@ def WebIDLTest(parser, harness):
undefined method(any arg1, Dummy arg2); undefined method(any arg1, Dummy arg2);
undefined method(DOMString arg1, DOMString arg2, DOMString arg3); undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should throw when args before the distinguishing arg are not " threw,
"all the same type") "Should throw when args before the distinguishing arg are not "
"all the same type",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Dummy {}; interface Dummy {};
interface TestIface { interface TestIface {
undefined method(long arg1, TestIface arg2); undefined method(long arg1, TestIface arg2);
@ -140,7 +165,8 @@ def WebIDLTest(parser, harness):
undefined method(any arg1, DOMString arg2); undefined method(any arg1, DOMString arg2);
undefined method(DOMString arg1, DOMString arg2, DOMString arg3); undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -148,57 +174,133 @@ def WebIDLTest(parser, harness):
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 # Now let's test our whole distinguishability table
argTypes = [ "long", "short", "long?", "short?", "boolean", argTypes = [
"boolean?", "DOMString", "ByteString", "UTF8String", "Enum", "Enum2", "long",
"Interface", "Interface?", "short",
"AncestorInterface", "UnrelatedInterface", "CallbackInterface", "long?",
"CallbackInterface?", "CallbackInterface2", "short?",
"object", "Callback", "Callback2", "Dict", "boolean",
"Dict2", "sequence<long>", "sequence<short>", "boolean?",
"record<DOMString, object>", "undefined",
"record<USVString, Dict>", "undefined?",
"record<ByteString, long>", "DOMString",
"record<UTF8String, long>", "ByteString",
"any", "Promise<any>", "Promise<any>?", "UTF8String",
"USVString", "JSString", "ArrayBuffer", "ArrayBufferView", "Enum",
"Uint8Array", "Uint16Array", "Enum2",
"(long or Callback)", "(long or Dict)", "Interface",
"Interface?",
"AncestorInterface",
"UnrelatedInterface",
"CallbackInterface",
"CallbackInterface?",
"CallbackInterface2",
"object",
"Callback",
"Callback2",
"Dict",
"Dict2",
"sequence<long>",
"sequence<short>",
"record<DOMString, object>",
"record<USVString, Dict>",
"record<ByteString, long>",
"record<UTF8String, long>",
"any",
"Promise<any>",
"Promise<any>?",
"USVString",
"JSString",
"ArrayBuffer",
"ArrayBufferView",
"Uint8Array",
"Uint16Array",
"(long or Callback)",
"(long or Dict)",
] ]
# Try to categorize things a bit to keep list lengths down # Try to categorize things a bit to keep list lengths down
def allBut(list1, list2): def allBut(list1, list2):
return [a for a in list1 if a not in list2 and return [
(a != "any" and a != "Promise<any>" and a != "Promise<any>?")] a
unions = [ "(long or Callback)", "(long or Dict)" ] for a in list1
numerics = [ "long", "short", "long?", "short?" ] if a not in list2
booleans = [ "boolean", "boolean?" ] and (a != "any" and a != "Promise<any>" and a != "Promise<any>?")
]
unions = ["(long or Callback)", "(long or Dict)"]
numerics = ["long", "short", "long?", "short?"]
booleans = ["boolean", "boolean?"]
undefineds = ["undefined", "undefined?"]
primitives = numerics + booleans primitives = numerics + booleans
nonNumerics = allBut(argTypes, numerics + unions) nonNumerics = allBut(argTypes, numerics + unions)
nonBooleans = allBut(argTypes, booleans) nonBooleans = allBut(argTypes, booleans)
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString", "JSString", "UTF8String" ] strings = [
"DOMString",
"ByteString",
"Enum",
"Enum2",
"USVString",
"JSString",
"UTF8String",
]
nonStrings = allBut(argTypes, strings) nonStrings = allBut(argTypes, strings)
nonObjects = primitives + strings nonObjects = undefineds + primitives + strings
objects = allBut(argTypes, nonObjects ) objects = allBut(argTypes, nonObjects)
bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"] bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
interfaces = [ "Interface", "Interface?", "AncestorInterface", interfaces = [
"UnrelatedInterface" ] + bufferSourceTypes "Interface",
nullables = (["long?", "short?", "boolean?", "Interface?", "Interface?",
"CallbackInterface?", "Dict", "Dict2", "AncestorInterface",
"Date?", "any", "Promise<any>?"] + "UnrelatedInterface",
allBut(unions, [ "(long or Callback)" ])) ] + bufferSourceTypes
sequences = [ "sequence<long>", "sequence<short>" ] nullables = [
"long?",
"short?",
"boolean?",
"undefined?",
"Interface?",
"CallbackInterface?",
"Dict",
"Dict2",
"Date?",
"any",
"Promise<any>?",
] + allBut(unions, ["(long or Callback)"])
sequences = ["sequence<long>", "sequence<short>"]
nonUserObjects = nonObjects + interfaces + sequences nonUserObjects = nonObjects + interfaces + sequences
otherObjects = allBut(argTypes, nonUserObjects + ["object"]) otherObjects = allBut(argTypes, nonUserObjects + ["object"])
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] + notRelatedInterfaces = (
otherObjects + sequences + bufferSourceTypes) nonObjects
records = [ "record<DOMString, object>", "record<USVString, Dict>", + ["UnrelatedInterface"]
"record<ByteString, long>", "record<UTF8String, long>" ] # JSString not supported in records + otherObjects
+ sequences
+ bufferSourceTypes
)
records = [
"record<DOMString, object>",
"record<USVString, Dict>",
"record<ByteString, long>",
"record<UTF8String, long>",
] # JSString not supported in records
dictionaryLike = (
[
"Dict",
"Dict2",
"CallbackInterface",
"CallbackInterface?",
"CallbackInterface2",
]
+ records
+ allBut(unions, ["(long or Callback)"])
)
# Build a representation of the distinguishability table as a dict # Build a representation of the distinguishability table as a dict
# of dicts, holding True values where needed, holes elsewhere. # of dicts, holding True values where needed, holes elsewhere.
data = dict(); data = dict()
for type in argTypes: for type in argTypes:
data[type] = dict() data[type] = dict()
def setDistinguishable(type, types): def setDistinguishable(type, types):
for other in types: for other in types:
data[type][other] = True data[type][other] = True
@ -209,6 +311,10 @@ def WebIDLTest(parser, harness):
setDistinguishable("short?", allBut(nonNumerics, nullables)) setDistinguishable("short?", allBut(nonNumerics, nullables))
setDistinguishable("boolean", nonBooleans) setDistinguishable("boolean", nonBooleans)
setDistinguishable("boolean?", allBut(nonBooleans, nullables)) setDistinguishable("boolean?", allBut(nonBooleans, nullables))
setDistinguishable("undefined", allBut(argTypes, undefineds + dictionaryLike))
setDistinguishable(
"undefined?", allBut(argTypes, undefineds + dictionaryLike + nullables)
)
setDistinguishable("DOMString", nonStrings) setDistinguishable("DOMString", nonStrings)
setDistinguishable("ByteString", nonStrings) setDistinguishable("ByteString", nonStrings)
setDistinguishable("UTF8String", nonStrings) setDistinguishable("UTF8String", nonStrings)
@ -219,36 +325,44 @@ def WebIDLTest(parser, harness):
setDistinguishable("Interface", notRelatedInterfaces) setDistinguishable("Interface", notRelatedInterfaces)
setDistinguishable("Interface?", allBut(notRelatedInterfaces, nullables)) setDistinguishable("Interface?", allBut(notRelatedInterfaces, nullables))
setDistinguishable("AncestorInterface", notRelatedInterfaces) setDistinguishable("AncestorInterface", notRelatedInterfaces)
setDistinguishable("UnrelatedInterface", setDistinguishable(
allBut(argTypes, ["object", "UnrelatedInterface"])) "UnrelatedInterface", allBut(argTypes, ["object", "UnrelatedInterface"])
setDistinguishable("CallbackInterface", nonUserObjects) )
setDistinguishable("CallbackInterface?", allBut(nonUserObjects, nullables)) setDistinguishable("CallbackInterface", allBut(nonUserObjects, undefineds))
setDistinguishable("CallbackInterface2", nonUserObjects) setDistinguishable(
"CallbackInterface?", allBut(nonUserObjects, nullables + undefineds)
)
setDistinguishable("CallbackInterface2", allBut(nonUserObjects, undefineds))
setDistinguishable("object", nonObjects) setDistinguishable("object", nonObjects)
setDistinguishable("Callback", nonUserObjects) setDistinguishable("Callback", nonUserObjects)
setDistinguishable("Callback2", nonUserObjects) setDistinguishable("Callback2", nonUserObjects)
setDistinguishable("Dict", allBut(nonUserObjects, nullables)) setDistinguishable("Dict", allBut(nonUserObjects, nullables + undefineds))
setDistinguishable("Dict2", allBut(nonUserObjects, nullables)) setDistinguishable("Dict2", allBut(nonUserObjects, nullables + undefineds))
setDistinguishable("sequence<long>", setDistinguishable("sequence<long>", allBut(argTypes, sequences + ["object"]))
allBut(argTypes, sequences + ["object"])) setDistinguishable("sequence<short>", allBut(argTypes, sequences + ["object"]))
setDistinguishable("sequence<short>", setDistinguishable("record<DOMString, object>", allBut(nonUserObjects, undefineds))
allBut(argTypes, sequences + ["object"])) setDistinguishable("record<USVString, Dict>", allBut(nonUserObjects, undefineds))
setDistinguishable("record<DOMString, object>", nonUserObjects)
setDistinguishable("record<USVString, Dict>", nonUserObjects)
# JSString not supported in records # JSString not supported in records
setDistinguishable("record<ByteString, long>", nonUserObjects) setDistinguishable("record<ByteString, long>", allBut(nonUserObjects, undefineds))
setDistinguishable("record<UTF8String, long>", nonUserObjects) setDistinguishable("record<UTF8String, long>", allBut(nonUserObjects, undefineds))
setDistinguishable("any", []) setDistinguishable("any", [])
setDistinguishable("Promise<any>", []) setDistinguishable("Promise<any>", [])
setDistinguishable("Promise<any>?", []) setDistinguishable("Promise<any>?", [])
setDistinguishable("ArrayBuffer", allBut(argTypes, ["ArrayBuffer", "object"])) setDistinguishable("ArrayBuffer", allBut(argTypes, ["ArrayBuffer", "object"]))
setDistinguishable("ArrayBufferView", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"])) setDistinguishable(
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"])) "ArrayBufferView",
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])) allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"]),
setDistinguishable("(long or Callback)", )
allBut(nonUserObjects, numerics)) setDistinguishable(
setDistinguishable("(long or Dict)", "Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"])
allBut(nonUserObjects, numerics + nullables)) )
setDistinguishable(
"Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])
)
setDistinguishable("(long or Callback)", allBut(nonUserObjects, numerics))
setDistinguishable(
"(long or Dict)", allBut(nonUserObjects, numerics + nullables + undefineds)
)
def areDistinguishable(type1, type2): def areDistinguishable(type1, type2):
return data[type1].get(type2, False) return data[type1].get(type2, False)
@ -271,10 +385,18 @@ def WebIDLTest(parser, harness):
interface TestInterface {%s interface TestInterface {%s
}; };
""" """
methodTemplate = """ if type1 in undefineds or type2 in undefineds:
undefined myMethod(%s arg);""" methods = """
methods = (methodTemplate % type1) + (methodTemplate % type2) (%s or %s) myMethod();""" % (
type1,
type2,
)
else:
methodTemplate = """
undefined myMethod(%s arg);"""
methods = (methodTemplate % type1) + (methodTemplate % type2)
idl = idlTemplate % methods idl = idlTemplate % methods
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
@ -284,11 +406,17 @@ def WebIDLTest(parser, harness):
threw = True threw = True
if areDistinguishable(type1, type2): if areDistinguishable(type1, type2):
harness.ok(not threw, harness.ok(
"Should not throw for '%s' and '%s' because they are distinguishable" % (type1, type2)) not threw,
"Should not throw for '%s' and '%s' because they are distinguishable"
% (type1, type2),
)
else: else:
harness.ok(threw, harness.ok(
"Should throw for '%s' and '%s' because they are not distinguishable" % (type1, type2)) threw,
"Should throw for '%s' and '%s' because they are not distinguishable"
% (type1, type2),
)
# Enumerate over everything in both orders, since order matters in # Enumerate over everything in both orders, since order matters in
# terms of our implementation of distinguishability checks # terms of our implementation of distinguishability checks

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface DoubleNull { interface DoubleNull {
attribute byte?? foo; attribute byte?? foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface DuplicateQualifiers1 { interface DuplicateQualifiers1 {
getter getter byte foo(unsigned long index); getter getter byte foo(unsigned long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -15,11 +17,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface DuplicateQualifiers2 { interface DuplicateQualifiers2 {
setter setter byte foo(unsigned long index, byte value); setter setter byte foo(unsigned long index, byte value);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -29,11 +33,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface DuplicateQualifiers4 { interface DuplicateQualifiers4 {
deleter deleter byte foo(unsigned long index); deleter deleter byte foo(unsigned long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -43,11 +49,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface DuplicateQualifiers5 { interface DuplicateQualifiers5 {
getter deleter getter byte foo(unsigned long index); getter deleter getter byte foo(unsigned long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,11 +1,14 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
try: try:
parser.parse(""" parser.parse(
"""
enum TestEmptyEnum { enum TestEmptyEnum {
}; };
""") """
)
harness.ok(False, "Should have thrown!") harness.ok(False, "Should have thrown!")
except: except:

View file

@ -1,13 +1,16 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface X { interface X {
const sequence<long> foo = []; const sequence<long> foo = [];
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -17,29 +20,35 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface X { interface X {
undefined foo(optional sequence<long> arg = []); undefined foo(optional sequence<long> arg = []);
}; };
""") """
results = parser.finish(); )
results = parser.finish()
harness.ok(isinstance( harness.ok(
results[0].members[0].signatures()[0][1][0].defaultValue, isinstance(
WebIDL.IDLEmptySequenceValue), results[0].members[0].signatures()[0][1][0].defaultValue,
"Should have IDLEmptySequenceValue as default value of argument") WebIDL.IDLEmptySequenceValue,
),
"Should have IDLEmptySequenceValue as default value of argument",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary X { dictionary X {
sequence<long> foo = []; sequence<long> foo = [];
}; };
""") """
results = parser.finish(); )
results = parser.finish()
harness.ok(isinstance(results[0].members[0].defaultValue,
WebIDL.IDLEmptySequenceValue),
"Should have IDLEmptySequenceValue as default value of "
"dictionary member")
harness.ok(
isinstance(results[0].members[0].defaultValue, WebIDL.IDLEmptySequenceValue),
"Should have IDLEmptySequenceValue as default value of " "dictionary member",
)

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
enum TestEnum { enum TestEnum {
"", "",
"foo", "foo",
@ -12,16 +14,15 @@ def WebIDLTest(parser, harness):
TestEnum doFoo(boolean arg); TestEnum doFoo(boolean arg);
readonly attribute TestEnum foo; readonly attribute TestEnum foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "TestEnumInterfaces interface parsed without error.") harness.ok(True, "TestEnumInterfaces interface parsed without error.")
harness.check(len(results), 2, "Should be one production") harness.check(len(results), 2, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLEnum), harness.ok(isinstance(results[0], WebIDL.IDLEnum), "Should be an IDLEnum")
"Should be an IDLEnum") harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
"Should be an IDLInterface")
enum = results[0] enum = results[0]
harness.check(enum.identifier.QName(), "::TestEnum", "Enum has the right QName") harness.check(enum.identifier.QName(), "::TestEnum", "Enum has the right QName")
@ -30,32 +31,41 @@ def WebIDLTest(parser, harness):
iface = results[1] iface = results[1]
harness.check(iface.identifier.QName(), "::TestEnumInterface", "Interface has the right QName") harness.check(
harness.check(iface.identifier.name, "TestEnumInterface", "Interface has the right name") iface.identifier.QName(), "::TestEnumInterface", "Interface has the right QName"
)
harness.check(
iface.identifier.name, "TestEnumInterface", "Interface has the right name"
)
harness.check(iface.parent, None, "Interface has no parent") harness.check(iface.parent, None, "Interface has no parent")
members = iface.members members = iface.members
harness.check(len(members), 2, "Should be one production") harness.check(len(members), 2, "Should be one production")
harness.ok(isinstance(members[0], WebIDL.IDLMethod), harness.ok(isinstance(members[0], WebIDL.IDLMethod), "Should be an IDLMethod")
"Should be an IDLMethod")
method = members[0] method = members[0]
harness.check(method.identifier.QName(), "::TestEnumInterface::doFoo", harness.check(
"Method has correct QName") method.identifier.QName(),
"::TestEnumInterface::doFoo",
"Method has correct QName",
)
harness.check(method.identifier.name, "doFoo", "Method has correct name") harness.check(method.identifier.name, "doFoo", "Method has correct name")
signatures = method.signatures() signatures = method.signatures()
harness.check(len(signatures), 1, "Expect one signature") harness.check(len(signatures), 1, "Expect one signature")
(returnType, arguments) = signatures[0] (returnType, arguments) = signatures[0]
harness.check(str(returnType), "TestEnum (Wrapper)", "Method type is the correct name") harness.check(
str(returnType), "TestEnum (Wrapper)", "Method type is the correct name"
)
harness.check(len(arguments), 1, "Method has the right number of arguments") harness.check(len(arguments), 1, "Method has the right number of arguments")
arg = arguments[0] arg = arguments[0]
harness.ok(isinstance(arg, WebIDL.IDLArgument), "Should be an IDLArgument") harness.ok(isinstance(arg, WebIDL.IDLArgument), "Should be an IDLArgument")
harness.check(str(arg.type), "Boolean", "Argument has the right type") harness.check(str(arg.type), "Boolean", "Argument has the right type")
attr = members[1] attr = members[1]
harness.check(attr.identifier.QName(), "::TestEnumInterface::foo", harness.check(
"Attr has correct QName") attr.identifier.QName(), "::TestEnumInterface::foo", "Attr has correct QName"
)
harness.check(attr.identifier.name, "foo", "Attr has correct name") harness.check(attr.identifier.name, "foo", "Attr has correct name")
harness.check(str(attr.type), "TestEnum (Wrapper)", "Attr type is the correct name") harness.check(str(attr.type), "TestEnum (Wrapper)", "Attr type is the correct name")
@ -64,7 +74,8 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
enum Enum { enum Enum {
"a", "a",
"b", "b",
@ -73,7 +84,8 @@ def WebIDLTest(parser, harness):
interface TestInterface { interface TestInterface {
undefined foo(optional Enum e = "d"); undefined foo(optional Enum e = "d");
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -82,12 +94,14 @@ def WebIDLTest(parser, harness):
# Now reset our parser # Now reset our parser
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
enum Enum { enum Enum {
"a", "a",
"b", "b",
"c", "c",
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should allow trailing comma in enum") harness.check(len(results), 1, "Should allow trailing comma in enum")

View file

@ -1,13 +1,16 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
try: try:
parser.parse(""" parser.parse(
"""
enum TestEnumDuplicateValue { enum TestEnumDuplicateValue {
"", "",
"" ""
}; };
""") """
)
harness.ok(False, "Should have thrown!") harness.ok(False, "Should have thrown!")
except: except:
harness.ok(True, "Enum TestEnumDuplicateValue should throw") harness.ok(True, "Enum TestEnumDuplicateValue should throw")

View file

@ -1,20 +1,24 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
# Check that error messages put the '^' in the right place. # Check that error messages put the '^' in the right place.
threw = False threw = False
input = 'interface ?' input = "interface ?"
try: try:
parser.parse(input) parser.parse(input)
results = parser.finish() results = parser.finish()
except WebIDL.WebIDLError as e: except WebIDL.WebIDLError as e:
threw = True threw = True
lines = str(e).split('\n') lines = str(e).split("\n")
harness.check(len(lines), 3, 'Expected number of lines in error message') harness.check(len(lines), 3, "Expected number of lines in error message")
harness.check(lines[1], input, 'Second line shows error') harness.check(lines[1], input, "Second line shows error")
harness.check(lines[2], ' ' * (len(input) - 1) + '^', harness.check(
'Correct column pointer in error message') lines[2],
" " * (len(input) - 1) + "^",
"Correct column pointer in error message",
)
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")

View file

@ -1,5 +1,6 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
# Check that error messages put the '^' in the right place. # Check that error messages put the '^' in the right place.
@ -16,13 +17,22 @@ interface ?"""
results = parser.finish() results = parser.finish()
except WebIDL.WebIDLError as e: except WebIDL.WebIDLError as e:
threw = True threw = True
lines = str(e).split('\n') lines = str(e).split("\n")
harness.check(len(lines), 3, 'Expected number of lines in error message') harness.check(len(lines), 3, "Expected number of lines in error message")
harness.ok(lines[0].endswith('line 6:10'), 'First line of error should end with "line 6:10", but was "%s".' % lines[0]) harness.ok(
harness.check(lines[1], 'interface ?', 'Second line of error message is the line which caused the error.') lines[0].endswith("line 6:10"),
harness.check(lines[2], ' ' * (len('interface ?') - 1) + '^', 'First line of error should end with "line 6:10", but was "%s".' % lines[0],
'Correct column pointer in error message.') )
harness.check(
lines[1],
"interface ?",
"Second line of error message is the line which caused the error.",
)
harness.check(
lines[2],
" " * (len("interface ?") - 1) + "^",
"Correct column pointer in error message.",
)
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] interface Foo {}; [Global, Exposed=Foo] interface Foo {};
[Global=(Bar, Bar1,Bar2), Exposed=Bar] interface Bar {}; [Global=(Bar, Bar1,Bar2), Exposed=Bar] interface Bar {};
[Global=(Baz, Baz2), Exposed=Baz] interface Baz {}; [Global=(Baz, Baz2), Exposed=Baz] interface Baz {};
@ -18,39 +20,56 @@ def WebIDLTest(parser, harness):
partial interface Iface { partial interface Iface {
undefined method2(); undefined method2();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 5, "Should know about five things"); harness.check(len(results), 5, "Should know about five things")
iface = results[3] iface = results[3]
harness.ok(isinstance(iface, WebIDL.IDLInterface), harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
"Should have an interface here");
members = iface.members members = iface.members
harness.check(len(members), 3, "Should have three members") harness.check(len(members), 3, "Should have three members")
harness.ok(members[0].exposureSet == set(["Foo", "Bar"]), harness.ok(
"method1 should have the right exposure set") members[0].exposureSet == set(["Foo", "Bar"]),
harness.ok(members[0]._exposureGlobalNames == set(["Foo", "Bar1"]), "method1 should have the right exposure set",
"method1 should have the right exposure global names") )
harness.ok(
members[0]._exposureGlobalNames == set(["Foo", "Bar1"]),
"method1 should have the right exposure global names",
)
harness.ok(members[1].exposureSet == set(["Bar"]), harness.ok(
"attr should have the right exposure set") members[1].exposureSet == set(["Bar"]),
harness.ok(members[1]._exposureGlobalNames == set(["Bar1"]), "attr should have the right exposure set",
"attr should have the right exposure global names") )
harness.ok(
members[1]._exposureGlobalNames == set(["Bar1"]),
"attr should have the right exposure global names",
)
harness.ok(members[2].exposureSet == set(["Foo"]), harness.ok(
"method2 should have the right exposure set") members[2].exposureSet == set(["Foo"]),
harness.ok(members[2]._exposureGlobalNames == set(["Foo"]), "method2 should have the right exposure set",
"method2 should have the right exposure global names") )
harness.ok(
members[2]._exposureGlobalNames == set(["Foo"]),
"method2 should have the right exposure global names",
)
harness.ok(iface.exposureSet == set(["Foo", "Bar"]), harness.ok(
"Iface should have the right exposure set") iface.exposureSet == set(["Foo", "Bar"]),
harness.ok(iface._exposureGlobalNames == set(["Foo", "Bar1"]), "Iface should have the right exposure set",
"Iface should have the right exposure global names") )
harness.ok(
iface._exposureGlobalNames == set(["Foo", "Bar1"]),
"Iface should have the right exposure global names",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] interface Foo {}; [Global, Exposed=Foo] interface Foo {};
[Global=(Bar, Bar1, Bar2), Exposed=Bar] interface Bar {}; [Global=(Bar, Bar1, Bar2), Exposed=Bar] interface Bar {};
[Global=(Baz, Baz2), Exposed=Baz] interface Baz {}; [Global=(Baz, Baz2), Exposed=Baz] interface Baz {};
@ -59,28 +78,36 @@ def WebIDLTest(parser, harness):
interface Iface2 { interface Iface2 {
undefined method3(); undefined method3();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 4, "Should know about four things"); harness.check(len(results), 4, "Should know about four things")
iface = results[3] iface = results[3]
harness.ok(isinstance(iface, WebIDL.IDLInterface), harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
"Should have an interface here");
members = iface.members members = iface.members
harness.check(len(members), 1, "Should have one member") harness.check(len(members), 1, "Should have one member")
harness.ok(members[0].exposureSet == set(["Foo"]), harness.ok(
"method3 should have the right exposure set") members[0].exposureSet == set(["Foo"]),
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]), "method3 should have the right exposure set",
"method3 should have the right exposure global names") )
harness.ok(
members[0]._exposureGlobalNames == set(["Foo"]),
"method3 should have the right exposure global names",
)
harness.ok(iface.exposureSet == set(["Foo"]), harness.ok(
"Iface2 should have the right exposure set") 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") harness.ok(
iface._exposureGlobalNames == set(["Foo"]),
"Iface2 should have the right exposure global names",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] interface Foo {}; [Global, Exposed=Foo] interface Foo {};
[Global=(Bar, Bar1, Bar2), Exposed=Bar] interface Bar {}; [Global=(Bar, Bar1, Bar2), Exposed=Bar] interface Bar {};
[Global=(Baz, Baz2), Exposed=Baz] interface Baz {}; [Global=(Baz, Baz2), Exposed=Baz] interface Baz {};
@ -96,33 +123,43 @@ def WebIDLTest(parser, harness):
}; };
Iface3 includes Mixin; Iface3 includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 6, "Should know about six things"); harness.check(len(results), 6, "Should know about six things")
iface = results[3] iface = results[3]
harness.ok(isinstance(iface, WebIDL.IDLInterface), harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
"Should have an interface here");
members = iface.members members = iface.members
harness.check(len(members), 2, "Should have two members") harness.check(len(members), 2, "Should have two members")
harness.ok(members[0].exposureSet == set(["Foo"]), harness.ok(
"method4 should have the right exposure set") members[0].exposureSet == set(["Foo"]),
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]), "method4 should have the right exposure set",
"method4 should have the right exposure global names") )
harness.ok(
members[0]._exposureGlobalNames == set(["Foo"]),
"method4 should have the right exposure global names",
)
harness.ok(members[1].exposureSet == set(["Foo", "Bar"]), harness.ok(
"method5 should have the right exposure set") members[1].exposureSet == set(["Foo", "Bar"]),
harness.ok(members[1]._exposureGlobalNames == set(["Foo", "Bar1"]), "method5 should have the right exposure set",
"method5 should have the right exposure global names") )
harness.ok(
members[1]._exposureGlobalNames == set(["Foo", "Bar1"]),
"method5 should have the right exposure global names",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Exposed=Foo] [Exposed=Foo]
interface Bar { interface Bar {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -133,12 +170,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Bar { interface Bar {
[Exposed=Foo] [Exposed=Foo]
readonly attribute bool attr; readonly attribute bool attr;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -149,12 +188,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Bar { interface Bar {
[Exposed=Foo] [Exposed=Foo]
undefined operation(); undefined operation();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -165,12 +206,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Bar { interface Bar {
[Exposed=Foo] [Exposed=Foo]
const long constant = 5; const long constant = 5;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -181,7 +224,8 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] interface Foo {}; [Global, Exposed=Foo] interface Foo {};
[Global, Exposed=Bar] interface Bar {}; [Global, Exposed=Bar] interface Bar {};
@ -190,16 +234,20 @@ def WebIDLTest(parser, harness):
[Exposed=Bar] [Exposed=Bar]
undefined method(); undefined method();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "Should have thrown on member exposed where its interface is not.") harness.ok(
threw, "Should have thrown on member exposed where its interface is not."
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] interface Foo {}; [Global, Exposed=Foo] interface Foo {};
[Global, Exposed=Bar] interface Bar {}; [Global, Exposed=Bar] interface Bar {};
@ -214,25 +262,122 @@ def WebIDLTest(parser, harness):
}; };
Baz includes Mixin; Baz includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 5, "Should know about five things"); harness.check(len(results), 5, "Should know about five things")
iface = results[2] iface = results[2]
harness.ok(isinstance(iface, WebIDL.IDLInterface), harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should have an interface here")
"Should have an interface here");
members = iface.members members = iface.members
harness.check(len(members), 2, "Should have two members") harness.check(len(members), 2, "Should have two members")
harness.ok(members[0].exposureSet == set(["Foo"]), harness.ok(
"method should have the right exposure set") members[0].exposureSet == set(["Foo"]),
harness.ok(members[0]._exposureGlobalNames == set(["Foo"]), "method should have the right exposure set",
"method should have the right exposure global names") )
harness.ok(
members[0]._exposureGlobalNames == set(["Foo"]),
"method should have the right exposure global names",
)
harness.ok(members[1].exposureSet == set(["Bar"]), harness.ok(
"otherMethod should have the right exposure set") members[1].exposureSet == set(["Bar"]),
harness.ok(members[1]._exposureGlobalNames == set(["Bar"]), "otherMethod should have the right exposure set",
"otherMethod should have the right exposure global names") )
harness.ok(
members[1]._exposureGlobalNames == set(["Bar"]),
"otherMethod should have the right exposure global names",
)
parser = parser.reset()
parser.parse(
"""
[Global, Exposed=Foo] interface Foo {};
[Global, Exposed=Bar] interface Bar {};
[Exposed=*]
interface Baz {
undefined methodWild();
};
[Exposed=Bar]
interface mixin Mixin {
undefined methodNotWild();
};
Baz includes Mixin;
"""
)
results = parser.finish()
harness.check(len(results), 5, "Should know about five things")
iface = results[2]
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", "Bar"]),
"methodWild should have the right exposure set",
)
harness.ok(
members[0]._exposureGlobalNames == set(["Foo", "Bar"]),
"methodWild should have the right exposure global names",
)
harness.ok(
members[1].exposureSet == set(["Bar"]),
"methodNotWild should have the right exposure set",
)
harness.ok(
members[1]._exposureGlobalNames == set(["Bar"]),
"methodNotWild should have the right exposure global names",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
[Global, Exposed=Foo] interface Foo {};
[Global, Exposed=Bar] interface Bar {};
[Exposed=Foo]
interface Baz {
[Exposed=*]
undefined method();
};
"""
)
results = parser.finish()
except Exception as 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, Exposed=Foo] interface Foo {};
[Global, Exposed=Bar] interface Bar {};
[Exposed=(Foo,*)]
interface Baz {
undefined method();
};
"""
)
results = parser.finish()
except Exception as x:
threw = True
harness.ok(threw, "Should have thrown on a wildcard in an identifier list.")

View file

@ -1,74 +1,91 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
[NoInterfaceObject] """
[LegacyNoInterfaceObject]
interface TestExtendedAttr { interface TestExtendedAttr {
[Unforgeable] readonly attribute byte b; [LegacyUnforgeable] readonly attribute byte b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Pref="foo.bar",Pref=flop] [Pref="foo.bar",Pref=flop]
interface TestExtendedAttr { interface TestExtendedAttr {
[Pref="foo.bar"] attribute byte b; [Pref="foo.bar"] attribute byte b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
interface TestLenientThis { """
[LenientThis] attribute byte b; interface TestLegacyLenientThis {
[LegacyLenientThis] attribute byte b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(results[0].members[0].hasLenientThis(), harness.ok(
"Should have a lenient this") results[0].members[0].hasLegacyLenientThis(), "Should have a lenient this"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
interface TestLenientThis2 { """
[LenientThis=something] attribute byte b; interface TestLegacyLenientThis2 {
[LegacyLenientThis=something] attribute byte b;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "[LenientThis] must take no arguments") harness.ok(threw, "[LegacyLenientThis] must take no arguments")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestClamp { interface TestClamp {
undefined testClamp([Clamp] long foo); undefined testClamp([Clamp] long foo);
undefined testNotClamp(long foo); undefined testNotClamp(long foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
# Pull out the first argument out of the arglist of the first (and # Pull out the first argument out of the arglist of the first (and
# only) signature. # only) signature.
harness.ok(results[0].members[0].signatures()[0][1][0].type.hasClamp(), harness.ok(
"Should be clamped") results[0].members[0].signatures()[0][1][0].type.hasClamp(), "Should be clamped"
harness.ok(not results[0].members[1].signatures()[0][1][0].type.hasClamp(), )
"Should not be clamped") harness.ok(
not results[0].members[1].signatures()[0][1][0].type.hasClamp(),
"Should not be clamped",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestClamp2 { interface TestClamp2 {
undefined testClamp([Clamp=something] long foo); undefined testClamp([Clamp=something] long foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -76,32 +93,39 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "[Clamp] must take no arguments") harness.ok(threw, "[Clamp] must take no arguments")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestEnforceRange { interface TestEnforceRange {
undefined testEnforceRange([EnforceRange] long foo); undefined testEnforceRange([EnforceRange] long foo);
undefined testNotEnforceRange(long foo); undefined testNotEnforceRange(long foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
# Pull out the first argument out of the arglist of the first (and # Pull out the first argument out of the arglist of the first (and
# only) signature. # only) signature.
harness.ok(results[0].members[0].signatures()[0][1][0].type.hasEnforceRange(), harness.ok(
"Should be enforceRange") results[0].members[0].signatures()[0][1][0].type.hasEnforceRange(),
harness.ok(not results[0].members[1].signatures()[0][1][0].type.hasEnforceRange(), "Should be enforceRange",
"Should not be enforceRange") )
harness.ok(
not results[0].members[1].signatures()[0][1][0].type.hasEnforceRange(),
"Should not be enforceRange",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestEnforceRange2 { interface TestEnforceRange2 {
undefined testEnforceRange([EnforceRange=something] long foo); undefined testEnforceRange([EnforceRange=something] long foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "[EnforceRange] must take no arguments") harness.ok(threw, "[EnforceRange] must take no arguments")

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
typedef float myFloat; typedef float myFloat;
typedef unrestricted float myUnrestrictedFloat; typedef unrestricted float myUnrestrictedFloat;
interface FloatTypes { interface FloatTypes {
@ -15,14 +17,14 @@ def WebIDLTest(parser, harness):
attribute double ld; attribute double ld;
undefined m1(float arg1, double arg2, float? arg3, double? arg4, undefined m1(float arg1, double arg2, float? arg3, double? arg4,
myFloat arg5, unrestricted float arg6, myFloat arg5, unrestricted float arg6,
unrestricted double arg7, unrestricted float? arg8, unrestricted double arg7, unrestricted float? arg8,
unrestricted double? arg9, myUnrestrictedFloat arg10); unrestricted double? arg9, myUnrestrictedFloat arg10);
[LenientFloat] [LenientFloat]
undefined m2(float arg1, double arg2, float? arg3, double? arg4, undefined m2(float arg1, double arg2, float? arg3, double? arg4,
myFloat arg5, unrestricted float arg6, myFloat arg5, unrestricted float arg6,
unrestricted double arg7, unrestricted float? arg8, unrestricted double arg7, unrestricted float? arg8,
unrestricted double? arg9, myUnrestrictedFloat arg10); unrestricted double? arg9, myUnrestrictedFloat arg10);
[LenientFloat] [LenientFloat]
undefined m3(float arg); undefined m3(float arg);
[LenientFloat] [LenientFloat]
@ -32,14 +34,14 @@ def WebIDLTest(parser, harness):
[LenientFloat] [LenientFloat]
undefined m6(sequence<float> arg); undefined m6(sequence<float> arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 3, "Should be two typedefs and one interface.") harness.check(len(results), 3, "Should be two typedefs and one interface.")
iface = results[2] iface = results[2]
harness.ok(isinstance(iface, WebIDL.IDLInterface), harness.ok(isinstance(iface, WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
types = [a.type for a in iface.members if a.isAttr()] types = [a.type for a in iface.members if a.isAttr()]
harness.ok(types[0].isFloat(), "'float' is a float") harness.ok(types[0].isFloat(), "'float' is a float")
harness.ok(not types[0].isUnrestricted(), "'float' is not unrestricted") harness.ok(not types[0].isUnrestricted(), "'float' is not unrestricted")
@ -55,71 +57,89 @@ def WebIDLTest(parser, harness):
argtypes = [a.type for a in method.signatures()[0][1]] argtypes = [a.type for a in method.signatures()[0][1]]
for (idx, type) in enumerate(argtypes): for (idx, type) in enumerate(argtypes):
harness.ok(type.isFloat(), "Type %d should be float" % idx) harness.ok(type.isFloat(), "Type %d should be float" % idx)
harness.check(type.isUnrestricted(), idx >= 5, harness.check(
"Type %d should %sbe unrestricted" % ( type.isUnrestricted(),
idx, "" if idx >= 4 else "not ")) idx >= 5,
"Type %d should %sbe unrestricted" % (idx, "" if idx >= 4 else "not "),
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface FloatTypes { interface FloatTypes {
[LenientFloat] [LenientFloat]
long m(float arg); long m(float arg);
}; };
""") """
)
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "[LenientFloat] only allowed on undefined-retuning methods") harness.ok(threw, "[LenientFloat] only allowed on methods returning undefined")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface FloatTypes { interface FloatTypes {
[LenientFloat] [LenientFloat]
undefined m(unrestricted float arg); undefined m(unrestricted float arg);
}; };
""") """
)
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args") harness.ok(
threw, "[LenientFloat] only allowed on methods with unrestricted float args"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface FloatTypes { interface FloatTypes {
[LenientFloat] [LenientFloat]
undefined m(sequence<unrestricted float> arg); undefined m(sequence<unrestricted float> arg);
}; };
""") """
)
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)") harness.ok(
threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface FloatTypes { interface FloatTypes {
[LenientFloat] [LenientFloat]
undefined m((unrestricted float or FloatTypes) arg); undefined m((unrestricted float or FloatTypes) arg);
}; };
""") """
)
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)") harness.ok(
threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface FloatTypes { interface FloatTypes {
[LenientFloat] [LenientFloat]
readonly attribute float foo; readonly attribute float foo;
}; };
""") """
)
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "[LenientFloat] only allowed on writable attributes") harness.ok(threw, "[LenientFloat] only allowed on writable attributes")

View file

@ -1,14 +1,17 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface ForwardDeclared; interface ForwardDeclared;
interface ForwardDeclared; interface ForwardDeclared;
interface TestForwardDecl { interface TestForwardDecl {
attribute ForwardDeclared foo; attribute ForwardDeclared foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()

View file

@ -1,106 +1,129 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] [Global, Exposed=Foo]
interface Foo : Bar { interface Foo : Bar {
getter any(DOMString name); getter any(DOMString name);
}; };
[Exposed=Foo] [Exposed=Foo]
interface Bar {}; interface Bar {};
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(results[0].isOnGlobalProtoChain(), harness.ok(
"[Global] interface should be on global's proto chain") results[0].isOnGlobalProtoChain(),
harness.ok(results[1].isOnGlobalProtoChain(), "[Global] interface should be on global's proto chain",
"[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() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] [Global, Exposed=Foo]
interface Foo { interface Foo {
getter any(DOMString name); getter any(DOMString name);
setter undefined(DOMString name, any arg); setter undefined(DOMString name, any arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown for [Global] used on an interface with a " threw,
"named setter") "Should have thrown for [Global] used on an interface with a " "named setter",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] [Global, Exposed=Foo]
interface Foo { interface Foo {
getter any(DOMString name); getter any(DOMString name);
deleter undefined(DOMString name); deleter undefined(DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown for [Global] used on an interface with a " threw,
"named deleter") "Should have thrown for [Global] used on an interface with a " "named deleter",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[Global, OverrideBuiltins, Exposed=Foo] """
[Global, LegacyOverrideBuiltIns, Exposed=Foo]
interface Foo { interface Foo {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown for [Global] used on an interface with a " threw,
"[OverrideBuiltins]") "Should have thrown for [Global] used on an interface with a "
"[LegacyOverrideBuiltIns]",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] [Global, Exposed=Foo]
interface Foo : Bar { interface Foo : Bar {
}; };
[OverrideBuiltins, Exposed=Foo] [LegacyOverrideBuiltIns, Exposed=Foo]
interface Bar { interface Bar {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown for [Global] used on an interface with an " threw,
"[OverrideBuiltins] ancestor") "Should have thrown for [Global] used on an interface with an "
"[LegacyOverrideBuiltIns] ancestor",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Foo] [Global, Exposed=Foo]
interface Foo { interface Foo {
}; };
[Exposed=Foo] [Exposed=Foo]
interface Bar : Foo { interface Bar : Foo {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown for [Global] used on an interface with a " threw,
"descendant") "Should have thrown for [Global] used on an interface with a " "descendant",
)

View file

@ -1,39 +1,49 @@
# Import the WebIDL module, so we can do isinstance checks and whatnot # Import the WebIDL module, so we can do isinstance checks and whatnot
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
try: try:
parser.parse(""" parser.parse(
"""
enum Foo { "a" }; enum Foo { "a" };
interface Foo; interface Foo;
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(False, "Should fail to parse") harness.ok(False, "Should fail to parse")
except Exception as e: except Exception as e:
harness.ok("Name collision" in e.message, harness.ok(
"Should have name collision for interface") "Name collision" in str(e), "Should have name collision for interface"
)
parser = parser.reset() parser = parser.reset()
try: try:
parser.parse(""" parser.parse(
"""
dictionary Foo { long x; }; dictionary Foo { long x; };
enum Foo { "a" }; enum Foo { "a" };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(False, "Should fail to parse") harness.ok(False, "Should fail to parse")
except Exception as e: except Exception as e:
harness.ok("Name collision" in e.message, harness.ok(
"Should have name collision for dictionary") "Name collision" in str(e), "Should have name collision for dictionary"
)
parser = parser.reset() parser = parser.reset()
try: try:
parser.parse(""" parser.parse(
"""
enum Foo { "a" }; enum Foo { "a" };
enum Foo { "b" }; enum Foo { "b" };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(False, "Should fail to parse") harness.ok(False, "Should fail to parse")
except Exception as e: except Exception as e:
harness.ok("Multiple unresolvable definitions" in e.message, harness.ok(
"Should have name collision for dictionary") "Multiple unresolvable definitions" in str(e),
"Should have name collision for dictionary",
)

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestIncompleteParent : NotYetDefined { interface TestIncompleteParent : NotYetDefined {
undefined foo(); undefined foo();
}; };
@ -11,7 +13,8 @@ def WebIDLTest(parser, harness):
interface EvenHigherOnTheChain { interface EvenHigherOnTheChain {
}; };
""") """
)
parser.finish() parser.finish()

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestIncompleteTypes { interface TestIncompleteTypes {
attribute FooInterface attr1; attribute FooInterface attr1;
@ -10,35 +12,50 @@ def WebIDLTest(parser, harness):
interface FooInterface { interface FooInterface {
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "TestIncompleteTypes interface parsed without error.") harness.ok(True, "TestIncompleteTypes interface parsed without error.")
harness.check(len(results), 2, "Should be two productions.") 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") harness.check(
harness.check(iface.identifier.QName(), "::TestIncompleteTypes", "Interface has the right QName") iface.identifier.QName(),
harness.check(iface.identifier.name, "TestIncompleteTypes", "Interface has the right name") "::TestIncompleteTypes",
"Interface has the right QName",
)
harness.check(
iface.identifier.name, "TestIncompleteTypes", "Interface has the right name"
)
harness.check(len(iface.members), 2, "Expect 2 members") harness.check(len(iface.members), 2, "Expect 2 members")
attr = iface.members[0] attr = iface.members[0]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
"Should be an IDLAttribute")
method = iface.members[1] method = iface.members[1]
harness.ok(isinstance(method, WebIDL.IDLMethod), harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
"Should be an IDLMethod")
harness.check(attr.identifier.QName(), "::TestIncompleteTypes::attr1", harness.check(
"Attribute has the right QName") attr.identifier.QName(),
harness.check(attr.type.name, "FooInterface", "::TestIncompleteTypes::attr1",
"Previously unresolved type has the right name") "Attribute has the right QName",
)
harness.check(
attr.type.name, "FooInterface", "Previously unresolved type has the right name"
)
harness.check(method.identifier.QName(), "::TestIncompleteTypes::method1", harness.check(
"Attribute has the right QName") method.identifier.QName(),
"::TestIncompleteTypes::method1",
"Attribute has the right QName",
)
(returnType, args) = method.signatures()[0] (returnType, args) = method.signatures()[0]
harness.check(returnType.name, "FooInterface", harness.check(
"Previously unresolved type has the right name") returnType.name, "FooInterface", "Previously unresolved type has the right name"
harness.check(args[0].type.name, "FooInterface", )
"Previously unresolved type has the right name") harness.check(
args[0].type.name,
"FooInterface",
"Previously unresolved type has the right name",
)

View file

@ -1,12 +1,12 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse("interface Foo { };") parser.parse("interface Foo { };")
results = parser.finish() results = parser.finish()
harness.ok(True, "Empty interface parsed without error.") harness.ok(True, "Empty interface parsed without error.")
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
iface = results[0] iface = results[0]
harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName") harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName")
harness.check(iface.identifier.name, "Foo", "Interface has the right name") harness.check(iface.identifier.name, "Foo", "Interface has the right name")
@ -16,16 +16,15 @@ def WebIDLTest(parser, harness):
results = parser.finish() results = parser.finish()
harness.ok(True, "Empty interface parsed without error.") harness.ok(True, "Empty interface parsed without error.")
harness.check(len(results), 2, "Should be two productions") harness.check(len(results), 2, "Should be two productions")
harness.ok(isinstance(results[1], WebIDL.IDLInterface), harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
iface = results[1] iface = results[1]
harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName") harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName")
harness.check(iface.identifier.name, "Bar", "Interface has the right name") harness.check(iface.identifier.name, "Bar", "Interface has the right name")
harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), "Interface has a parent")
"Interface has a parent")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface QNameBase { interface QNameBase {
attribute long foo; attribute long foo;
}; };
@ -34,32 +33,42 @@ def WebIDLTest(parser, harness):
attribute long long foo; attribute long long foo;
attribute byte bar; attribute byte bar;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, "Should be two productions") harness.check(len(results), 2, "Should be two productions")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface") harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.check(results[1].parent, results[0], "Inheritance chain is right") harness.check(results[1].parent, results[0], "Inheritance chain is right")
harness.check(len(results[0].members), 1, "Expect 1 productions") harness.check(len(results[0].members), 1, "Expect 1 productions")
harness.check(len(results[1].members), 2, "Expect 2 productions") harness.check(len(results[1].members), 2, "Expect 2 productions")
base = results[0] base = results[0]
derived = results[1] derived = results[1]
harness.check(base.members[0].identifier.QName(), "::QNameBase::foo", harness.check(
"Member has the right QName") base.members[0].identifier.QName(),
harness.check(derived.members[0].identifier.QName(), "::QNameDerived::foo", "::QNameBase::foo",
"Member has the right QName") "Member has the right QName",
harness.check(derived.members[1].identifier.QName(), "::QNameDerived::bar", )
"Member has the right QName") harness.check(
derived.members[0].identifier.QName(),
"::QNameDerived::foo",
"Member has the right QName",
)
harness.check(
derived.members[1].identifier.QName(),
"::QNameDerived::bar",
"Member has the right QName",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A : B {}; interface A : B {};
interface B : A {}; interface B : A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -69,32 +78,42 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A : C {}; interface A : C {};
interface C : B {}; interface C : B {};
interface B : A {}; interface B : A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow indirect cycles in interface inheritance chains") harness.ok(
threw, "Should not allow indirect cycles in interface inheritance chains"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A; interface A;
interface B : A {}; interface B : A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
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 = parser.reset()
parser.parse(""" parser.parse(
"""
interface A { interface A {
constructor(); constructor();
constructor(long arg); constructor(long arg);
@ -105,26 +124,43 @@ def WebIDLTest(parser, harness):
readonly attribute boolean y; readonly attribute boolean y;
undefined foo(long arg); undefined foo(long arg);
}; };
"""); """
results = parser.finish(); )
harness.check(len(results), 2, results = parser.finish()
"Should have two results with partial interface") harness.check(len(results), 2, "Should have two results with partial interface")
iface = results[0] iface = results[0]
harness.check(len(iface.members), 3, harness.check(
"Should have three members with partial interface") 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(
harness.check(iface.members[1].identifier.name, "foo", iface.members[0].identifier.name,
"Second member should be foo with partial interface") "x",
harness.check(len(iface.members[1].signatures()), 2, "First member should be x with partial interface",
"Should have two foo signatures with partial interface") )
harness.check(iface.members[2].identifier.name, "y", harness.check(
"Third member should be y with partial interface") iface.members[1].identifier.name,
harness.check(len(iface.ctor().signatures()), 2, "foo",
"Should have two constructors with partial interface") "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 = parser.reset()
parser.parse(""" parser.parse(
"""
partial interface A { partial interface A {
readonly attribute boolean y; readonly attribute boolean y;
undefined foo(long arg); undefined foo(long arg);
@ -135,236 +171,289 @@ def WebIDLTest(parser, harness):
readonly attribute boolean x; readonly attribute boolean x;
undefined foo(); undefined foo();
}; };
"""); """
results = parser.finish(); )
harness.check(len(results), 2, results = parser.finish()
"Should have two results with reversed partial interface") harness.check(
len(results), 2, "Should have two results with reversed partial interface"
)
iface = results[1] iface = results[1]
harness.check(len(iface.members), 3, harness.check(
"Should have three members with reversed partial interface") len(iface.members),
harness.check(iface.members[0].identifier.name, "x", 3,
"First member should be x with reversed partial interface") "Should have three members with reversed partial interface",
harness.check(iface.members[1].identifier.name, "foo", )
"Second member should be foo with reversed partial interface") harness.check(
harness.check(len(iface.members[1].signatures()), 2, iface.members[0].identifier.name,
"Should have two foo signatures with reversed partial interface") "x",
harness.check(iface.members[2].identifier.name, "y", "First member should be x with reversed partial interface",
"Third member should be y with reversed partial interface") )
harness.check(len(iface.ctor().signatures()), 2, harness.check(
"Should have two constructors with reversed partial interface") 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() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
readonly attribute boolean x; readonly attribute boolean x;
}; };
interface A { interface A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow two non-partial interfaces with the same name")
"Should not allow two non-partial interfaces with the same name")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
partial interface A { partial interface A {
readonly attribute boolean x; readonly attribute boolean x;
}; };
partial interface A { partial interface A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Must have a non-partial interface for a given name")
"Must have a non-partial interface for a given name")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
boolean x; boolean x;
}; };
partial interface A { partial interface A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between partial interface " threw,
"and other object") "Should not allow a name collision between partial interface "
"and other object",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
boolean x; boolean x;
}; };
interface A { interface A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between interface " threw, "Should not allow a name collision between interface " "and other object"
"and other object") )
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
boolean x; boolean x;
}; };
interface A; interface A;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between external interface " threw,
"and other object") "Should not allow a name collision between external interface "
"and other object",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
readonly attribute boolean x; readonly attribute boolean x;
}; };
interface A; interface A;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between external interface " threw,
"and interface") "Should not allow a name collision between external interface " "and interface",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface A; interface A;
interface A; interface A;
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(len(results) == 1 and harness.ok(
isinstance(results[0], WebIDL.IDLExternalInterface), len(results) == 1 and isinstance(results[0], WebIDL.IDLExternalInterface),
"Should allow name collisions between external interface " "Should allow name collisions between external interface " "declarations",
"declarations") )
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[SomeRandomAnnotation] [SomeRandomAnnotation]
interface A { interface A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow unknown extended attributes on interfaces")
"Should not allow unknown extended attributes on interfaces")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Exposed=Window, LegacyWindowAlias=A] [Exposed=Window, LegacyWindowAlias=A]
interface B {}; interface B {};
[Exposed=Window, LegacyWindowAlias=(C, D)] [Exposed=Window, LegacyWindowAlias=(C, D)]
interface E {}; interface E {};
"""); """
results = parser.finish(); )
harness.check(results[1].legacyWindowAliases, ["A"], results = parser.finish()
"Should support a single identifier") harness.check(
harness.check(results[2].legacyWindowAliases, ["C", "D"], results[1].legacyWindowAliases, ["A"], "Should support a single identifier"
"Should support an identifier list") )
harness.check(
results[2].legacyWindowAliases, ["C", "D"], "Should support an identifier list"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[LegacyWindowAlias] [LegacyWindowAlias]
interface A {}; interface A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow [LegacyWindowAlias] with no value")
"Should not allow [LegacyWindowAlias] with no value")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Exposed=Worker, LegacyWindowAlias=B] [Exposed=Worker, LegacyWindowAlias=B]
interface A {}; interface A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow [LegacyWindowAlias] without Window exposure")
"Should not allow [LegacyWindowAlias] without Window exposure")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Exposed=Window] [Exposed=Window]
interface A {}; interface A {};
[Exposed=Window, LegacyWindowAlias=A] [Exposed=Window, LegacyWindowAlias=A]
interface B {}; interface B {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow [LegacyWindowAlias] to conflict with other identifiers") threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Exposed=Window, LegacyWindowAlias=A] [Exposed=Window, LegacyWindowAlias=A]
interface B {}; interface B {};
[Exposed=Window] [Exposed=Window]
interface A {}; interface A {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow [LegacyWindowAlias] to conflict with other identifiers") threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Exposed=Window, LegacyWindowAlias=A] [Exposed=Window, LegacyWindowAlias=A]
interface B {}; interface B {};
[Exposed=Window, LegacyWindowAlias=A] [Exposed=Window, LegacyWindowAlias=A]
interface C {}; interface C {};
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow [LegacyWindowAlias] to conflict with other identifiers") threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
)

View file

@ -1,12 +1,14 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface IdentifierConflict { interface IdentifierConflict {
const byte thing1 = 1; const byte thing1 = 1;
const unsigned long thing1 = 1; const unsigned long thing1 = 1;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,12 +1,14 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface IdentifierConflictAcrossMembers1 { interface IdentifierConflictAcrossMembers1 {
const byte thing1 = 1; const byte thing1 = 1;
readonly attribute long thing1; readonly attribute long thing1;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -16,12 +18,14 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface IdentifierConflictAcrossMembers2 { interface IdentifierConflictAcrossMembers2 {
readonly attribute long thing1; readonly attribute long thing1;
const byte thing1 = 1; const byte thing1 = 1;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -31,12 +35,14 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface IdentifierConflictAcrossMembers3 { interface IdentifierConflictAcrossMembers3 {
getter boolean thing1(DOMString name); getter boolean thing1(DOMString name);
readonly attribute long thing1; readonly attribute long thing1;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -46,12 +52,14 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface IdentifierConflictAcrossMembers1 { interface IdentifierConflictAcrossMembers1 {
const byte thing1 = 1; const byte thing1 = 1;
long thing1(); long thing1();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,33 +1,46 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse("interface mixin Foo { };") parser.parse("interface mixin Foo { };")
results = parser.finish() results = parser.finish()
harness.ok(True, "Empty interface mixin parsed without error.") harness.ok(True, "Empty interface mixin parsed without error.")
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterfaceMixin), harness.ok(
"Should be an IDLInterfaceMixin") isinstance(results[0], WebIDL.IDLInterfaceMixin),
"Should be an IDLInterfaceMixin",
)
mixin = results[0] mixin = results[0]
harness.check(mixin.identifier.QName(), "::Foo", "Interface mixin has the right QName") harness.check(
mixin.identifier.QName(), "::Foo", "Interface mixin has the right QName"
)
harness.check(mixin.identifier.name, "Foo", "Interface mixin has the right name") harness.check(mixin.identifier.name, "Foo", "Interface mixin has the right name")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface mixin QNameBase { interface mixin QNameBase {
const long foo = 3; const long foo = 3;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should be one productions") harness.check(len(results), 1, "Should be one productions")
harness.ok(isinstance(results[0], WebIDL.IDLInterfaceMixin), harness.ok(
"Should be an IDLInterfaceMixin") isinstance(results[0], WebIDL.IDLInterfaceMixin),
"Should be an IDLInterfaceMixin",
)
harness.check(len(results[0].members), 1, "Expect 1 productions") harness.check(len(results[0].members), 1, "Expect 1 productions")
mixin = results[0] mixin = results[0]
harness.check(mixin.members[0].identifier.QName(), "::QNameBase::foo", harness.check(
"Member has the right QName") mixin.members[0].identifier.QName(),
"::QNameBase::foo",
"Member has the right QName",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
readonly attribute boolean x; readonly attribute boolean x;
undefined foo(); undefined foo();
@ -36,24 +49,40 @@ def WebIDLTest(parser, harness):
readonly attribute boolean y; readonly attribute boolean y;
undefined foo(long arg); undefined foo(long arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, harness.check(
"Should have two results with partial interface mixin") len(results), 2, "Should have two results with partial interface mixin"
)
mixin = results[0] mixin = results[0]
harness.check(len(mixin.members), 3, harness.check(
"Should have three members with partial interface mixin") len(mixin.members), 3, "Should have three members with partial interface mixin"
harness.check(mixin.members[0].identifier.name, "x", )
"First member should be x with partial interface mixin") harness.check(
harness.check(mixin.members[1].identifier.name, "foo", mixin.members[0].identifier.name,
"Second member should be foo with partial interface mixin") "x",
harness.check(len(mixin.members[1].signatures()), 2, "First member should be x with partial interface mixin",
"Should have two foo signatures with partial interface mixin") )
harness.check(mixin.members[2].identifier.name, "y", harness.check(
"Third member should be y with partial interface mixin") mixin.members[1].identifier.name,
"foo",
"Second member should be foo with partial interface mixin",
)
harness.check(
len(mixin.members[1].signatures()),
2,
"Should have two foo signatures with partial interface mixin",
)
harness.check(
mixin.members[2].identifier.name,
"y",
"Third member should be y with partial interface mixin",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
partial interface mixin A { partial interface mixin A {
readonly attribute boolean y; readonly attribute boolean y;
undefined foo(long arg); undefined foo(long arg);
@ -62,285 +91,334 @@ def WebIDLTest(parser, harness):
readonly attribute boolean x; readonly attribute boolean x;
undefined foo(); undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, harness.check(
"Should have two results with reversed partial interface mixin") len(results), 2, "Should have two results with reversed partial interface mixin"
)
mixin = results[1] mixin = results[1]
harness.check(len(mixin.members), 3, harness.check(
"Should have three members with reversed partial interface mixin") len(mixin.members),
harness.check(mixin.members[0].identifier.name, "x", 3,
"First member should be x with reversed partial interface mixin") "Should have three members with reversed partial interface mixin",
harness.check(mixin.members[1].identifier.name, "foo", )
"Second member should be foo with reversed partial interface mixin") harness.check(
harness.check(len(mixin.members[1].signatures()), 2, mixin.members[0].identifier.name,
"Should have two foo signatures with reversed partial interface mixin") "x",
harness.check(mixin.members[2].identifier.name, "y", "First member should be x with reversed partial interface mixin",
"Third member should be y with reversed partial interface mixin") )
harness.check(
mixin.members[1].identifier.name,
"foo",
"Second member should be foo with reversed partial interface mixin",
)
harness.check(
len(mixin.members[1].signatures()),
2,
"Should have two foo signatures with reversed partial interface mixin",
)
harness.check(
mixin.members[2].identifier.name,
"y",
"Third member should be y with reversed partial interface mixin",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Interface {}; interface Interface {};
interface mixin Mixin { interface mixin Mixin {
attribute short x; attribute short x;
}; };
Interface includes Mixin; Interface includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
iface = results[0] iface = results[0]
harness.check(len(iface.members), 1, "Should merge members from mixins") harness.check(len(iface.members), 1, "Should merge members from mixins")
harness.check(iface.members[0].identifier.name, "x", harness.check(
"Should merge members from mixins") iface.members[0].identifier.name, "x", "Should merge members from mixins"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
readonly attribute boolean x; readonly attribute boolean x;
}; };
interface mixin A { interface mixin A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow two non-partial interface mixins with the same name") threw, "Should not allow two non-partial interface mixins with the same name"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
partial interface mixin A { partial interface mixin A {
readonly attribute boolean x; readonly attribute boolean x;
}; };
partial interface mixin A { partial interface mixin A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Must have a non-partial interface mixin for a given name")
"Must have a non-partial interface mixin for a given name")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
boolean x; boolean x;
}; };
partial interface mixin A { partial interface mixin A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between partial interface " threw,
"mixin and other object") "Should not allow a name collision between partial interface "
"mixin and other object",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary A { dictionary A {
boolean x; boolean x;
}; };
interface mixin A { interface mixin A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between interface mixin " threw,
"and other object") "Should not allow a name collision between interface mixin " "and other object",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
readonly attribute boolean x; readonly attribute boolean x;
}; };
interface A; interface A;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow a name collision between external interface " threw,
"and interface mixin") "Should not allow a name collision between external interface "
"and interface mixin",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[SomeRandomAnnotation] [SomeRandomAnnotation]
interface mixin A { interface mixin A {
readonly attribute boolean y; readonly attribute boolean y;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow unknown extended attributes on interface mixins") threw, "Should not allow unknown extended attributes on interface mixins"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
getter double (DOMString propertyName); getter double (DOMString propertyName);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow getters on interface mixins")
"Should not allow getters on interface mixins")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
setter undefined (DOMString propertyName, double propertyValue); setter undefined (DOMString propertyName, double propertyValue);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow setters on interface mixins")
"Should not allow setters on interface mixins")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
deleter undefined (DOMString propertyName); deleter undefined (DOMString propertyName);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow deleters on interface mixins")
"Should not allow deleters on interface mixins")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
legacycaller double compute(double x); legacycaller double compute(double x);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow legacycallers on interface mixins")
"Should not allow legacycallers on interface mixins")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin A { interface mixin A {
inherit attribute x; inherit attribute x;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow inherited attribute on interface mixins")
"Should not allow inherited attribute on interface mixins")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Interface {}; interface Interface {};
interface NotMixin { interface NotMixin {
attribute short x; attribute short x;
}; };
Interface includes NotMixin; Interface includes NotMixin;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should fail if the right side does not point an interface mixin")
"Should fail if the right side does not point an interface mixin")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin NotInterface {}; interface mixin NotInterface {};
interface mixin Mixin { interface mixin Mixin {
attribute short x; attribute short x;
}; };
NotInterface includes Mixin; NotInterface includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should fail if the left side does not point an interface")
"Should fail if the left side does not point an interface")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin Mixin { interface mixin Mixin {
iterable<DOMString>; iterable<DOMString>;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should fail if an interface mixin includes iterable")
"Should fail if an interface mixin includes iterable")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin Mixin { interface mixin Mixin {
setlike<DOMString>; setlike<DOMString>;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should fail if an interface mixin includes setlike")
"Should fail if an interface mixin includes setlike")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface mixin Mixin { interface mixin Mixin {
maplike<DOMString, DOMString>; maplike<DOMString, DOMString>;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should fail if an interface mixin includes maplike")
"Should fail if an interface mixin includes maplike")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Interface { interface Interface {
attribute short attr; attribute short attr;
}; };
@ -348,17 +426,20 @@ def WebIDLTest(parser, harness):
attribute short attr; attribute short attr;
}; };
Interface includes Mixin; Interface includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should fail if the included mixin interface has duplicated member") threw, "Should fail if the included mixin interface has duplicated member"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Interface {}; interface Interface {};
interface mixin Mixin1 { interface mixin Mixin1 {
attribute short attr; attribute short attr;
@ -368,15 +449,18 @@ def WebIDLTest(parser, harness):
}; };
Interface includes Mixin1; Interface includes Mixin1;
Interface includes Mixin2; Interface includes Mixin2;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should fail if the included mixin interfaces have duplicated member") threw, "Should fail if the included mixin interfaces have duplicated member"
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Global, Exposed=Worker] interface Worker {}; [Global, Exposed=Worker] interface Worker {};
[Exposed=Window] [Exposed=Window]
@ -385,15 +469,20 @@ def WebIDLTest(parser, harness):
Base returnSelf(); Base returnSelf();
}; };
Base includes Mixin; Base includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
base = results[2] base = results[2]
attr = base.members[0] attr = base.members[0]
harness.check(attr.exposureSet, set(["Window"]), harness.check(
"Should expose on globals where the base interfaces are exposed") attr.exposureSet,
set(["Window"]),
"Should expose on globals where the base interfaces are exposed",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Global, Exposed=Worker] interface Worker {}; [Global, Exposed=Worker] interface Worker {};
[Exposed=Window] [Exposed=Window]
@ -403,15 +492,18 @@ def WebIDLTest(parser, harness):
attribute short a; attribute short a;
}; };
Base includes Mixin; Base includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
base = results[2] base = results[2]
attr = base.members[0] attr = base.members[0]
harness.check(attr.exposureSet, set(["Window"]), harness.check(
"Should follow [Exposed] on interface mixin") attr.exposureSet, set(["Window"]), "Should follow [Exposed] on interface mixin"
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[Global, Exposed=Window] interface Window {}; [Global, Exposed=Window] interface Window {};
[Global, Exposed=Worker] interface Worker {}; [Global, Exposed=Worker] interface Worker {};
[Exposed=Window] [Exposed=Window]
@ -423,15 +515,20 @@ def WebIDLTest(parser, harness):
}; };
Base1 includes Mixin; Base1 includes Mixin;
Base2 includes Mixin; Base2 includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
base = results[2] base = results[2]
attr = base.members[0] attr = base.members[0]
harness.check(attr.exposureSet, set(["Window", "Worker"]), harness.check(
"Should expose on all globals where including interfaces are " attr.exposureSet,
"exposed") set(["Window", "Worker"]),
"Should expose on all globals where including interfaces are " "exposed",
)
base = results[3] base = results[3]
attr = base.members[0] attr = base.members[0]
harness.check(attr.exposureSet, set(["Window", "Worker"]), harness.check(
"Should expose on all globals where including interfaces are " attr.exposureSet,
"exposed") set(["Window", "Worker"]),
"Should expose on all globals where including interfaces are " "exposed",
)

View file

@ -2,8 +2,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code): def should_throw(parser, harness, message, code):
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(code) parser.parse(code)
@ -15,44 +16,69 @@ def should_throw(parser, harness, message, code):
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
# The [LenientSetter] extended attribute MUST take no arguments. # The [LegacyLenientSetter] extended attribute MUST take no arguments.
should_throw(parser, harness, "no arguments", """ should_throw(
parser,
harness,
"no arguments",
"""
interface I { interface I {
[LenientSetter=X] readonly attribute long A; [LegacyLenientSetter=X] readonly attribute long A;
}; };
""") """,
)
# An attribute with the [LenientSetter] extended attribute MUST NOT # An attribute with the [LegacyLenientSetter] extended attribute MUST NOT
# also be declared with the [PutForwards] extended attribute. # also be declared with the [PutForwards] extended attribute.
should_throw(parser, harness, "PutForwards", """ should_throw(
parser,
harness,
"PutForwards",
"""
interface I { interface I {
[PutForwards=B, LenientSetter] readonly attribute J A; [PutForwards=B, LegacyLenientSetter] readonly attribute J A;
}; };
interface J { interface J {
attribute long B; attribute long B;
}; };
""") """,
)
# An attribute with the [LenientSetter] extended attribute MUST NOT # An attribute with the [LegacyLenientSetter] extended attribute MUST NOT
# also be declared with the [Replaceable] extended attribute. # also be declared with the [Replaceable] extended attribute.
should_throw(parser, harness, "Replaceable", """ should_throw(
parser,
harness,
"Replaceable",
"""
interface I { interface I {
[Replaceable, LenientSetter] readonly attribute J A; [Replaceable, LegacyLenientSetter] readonly attribute J A;
}; };
""") """,
)
# The [LenientSetter] extended attribute MUST NOT be used on an # The [LegacyLenientSetter] extended attribute MUST NOT be used on an
# attribute that is not read only. # attribute that is not read only.
should_throw(parser, harness, "writable attribute", """ should_throw(
parser,
harness,
"writable attribute",
"""
interface I { interface I {
[LenientSetter] attribute long A; [LegacyLenientSetter] attribute long A;
}; };
""") """,
)
# The [LenientSetter] extended attribute MUST NOT be used on a # The [LegacyLenientSetter] extended attribute MUST NOT be used on a
# static attribute. # static attribute.
should_throw(parser, harness, "static attribute", """ should_throw(
parser,
harness,
"static attribute",
"""
interface I { interface I {
[LenientSetter] static readonly attribute long A; [LegacyLenientSetter] static readonly attribute long A;
}; };
""") """,
)

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestMethods { interface TestMethods {
undefined basic(); undefined basic();
static undefined basicStatic(); static undefined basicStatic();
@ -16,35 +18,50 @@ def WebIDLTest(parser, harness):
undefined setAny(any arg1); undefined setAny(any arg1);
float doFloats(float arg1); float doFloats(float arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "TestMethods interface parsed without error.") harness.ok(True, "TestMethods interface parsed without error.")
harness.check(len(results), 1, "Should be one production.") harness.check(len(results), 1, "Should be one production.")
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") harness.check(
harness.check(iface.identifier.QName(), "::TestMethods", "Interface has the right QName") iface.identifier.QName(), "::TestMethods", "Interface has the right QName"
)
harness.check(iface.identifier.name, "TestMethods", "Interface has the right name") harness.check(iface.identifier.name, "TestMethods", "Interface has the right name")
harness.check(len(iface.members), 12, "Expect 12 members") harness.check(len(iface.members), 12, "Expect 12 members")
methods = iface.members methods = iface.members
def checkArgument(argument, QName, name, type, optional, variadic): def checkArgument(argument, QName, name, type, optional, variadic):
harness.ok(isinstance(argument, WebIDL.IDLArgument), harness.ok(isinstance(argument, WebIDL.IDLArgument), "Should be an IDLArgument")
"Should be an IDLArgument") harness.check(
harness.check(argument.identifier.QName(), QName, "Argument has the right QName") argument.identifier.QName(), QName, "Argument has the right QName"
)
harness.check(argument.identifier.name, name, "Argument has the right name") harness.check(argument.identifier.name, name, "Argument has the right name")
harness.check(str(argument.type), type, "Argument has the right return type") harness.check(str(argument.type), type, "Argument has the right return type")
harness.check(argument.optional, optional, "Argument has the right optional value") harness.check(
harness.check(argument.variadic, variadic, "Argument has the right variadic value") argument.optional, optional, "Argument has the right optional value"
)
harness.check(
argument.variadic, variadic, "Argument has the right variadic value"
)
def checkMethod(method, QName, name, signatures, def checkMethod(
static=False, getter=False, setter=False, method,
deleter=False, legacycaller=False, stringifier=False): QName,
harness.ok(isinstance(method, WebIDL.IDLMethod), name,
"Should be an IDLMethod") signatures,
static=False,
getter=False,
setter=False,
deleter=False,
legacycaller=False,
stringifier=False,
):
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method") harness.ok(method.isMethod(), "Method is a method")
harness.ok(not method.isAttr(), "Method is not an attr") harness.ok(not method.isAttr(), "Method is not an attr")
harness.ok(not method.isConst(), "Method is not a const") harness.ok(not method.isConst(), "Method is not a const")
@ -53,72 +70,202 @@ def WebIDLTest(parser, harness):
harness.check(method.isStatic(), static, "Method has the correct static value") harness.check(method.isStatic(), static, "Method has the correct static value")
harness.check(method.isGetter(), getter, "Method has the correct getter value") harness.check(method.isGetter(), getter, "Method has the correct getter value")
harness.check(method.isSetter(), setter, "Method has the correct setter value") harness.check(method.isSetter(), setter, "Method has the correct setter value")
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value") harness.check(
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value") method.isDeleter(), deleter, "Method has the correct deleter value"
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value") )
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures") harness.check(
method.isLegacycaller(),
legacycaller,
"Method has the correct legacycaller value",
)
harness.check(
method.isStringifier(),
stringifier,
"Method has the correct stringifier value",
)
harness.check(
len(method.signatures()),
len(signatures),
"Method has the correct number of signatures",
)
sigpairs = zip(method.signatures(), signatures) sigpairs = zip(method.signatures(), signatures)
for (gotSignature, expectedSignature) in sigpairs: for (gotSignature, expectedSignature) in sigpairs:
(gotRetType, gotArgs) = gotSignature (gotRetType, gotArgs) = gotSignature
(expectedRetType, expectedArgs) = expectedSignature (expectedRetType, expectedArgs) = expectedSignature
harness.check(str(gotRetType), expectedRetType, harness.check(
"Method has the expected return type.") str(gotRetType), expectedRetType, "Method has the expected return type."
)
for i in range(0, len(gotArgs)): for i in range(0, len(gotArgs)):
(QName, name, type, optional, variadic) = expectedArgs[i] (QName, name, type, optional, variadic) = expectedArgs[i]
checkArgument(gotArgs[i], QName, name, type, optional, variadic) checkArgument(gotArgs[i], QName, name, type, optional, variadic)
checkMethod(methods[0], "::TestMethods::basic", "basic", [("Undefined", [])]) checkMethod(methods[0], "::TestMethods::basic", "basic", [("Undefined", [])])
checkMethod(methods[1], "::TestMethods::basicStatic", "basicStatic", checkMethod(
[("Undefined", [])], static=True) methods[1],
checkMethod(methods[2], "::TestMethods::basicWithSimpleArgs", "::TestMethods::basicStatic",
"basicWithSimpleArgs", "basicStatic",
[("Undefined", [("Undefined", [])],
[("::TestMethods::basicWithSimpleArgs::arg1", "arg1", "Boolean", False, False), static=True,
("::TestMethods::basicWithSimpleArgs::arg2", "arg2", "Byte", False, False), )
("::TestMethods::basicWithSimpleArgs::arg3", "arg3", "UnsignedLong", False, False)])]) checkMethod(
checkMethod(methods[3], "::TestMethods::basicBoolean", "basicBoolean", [("Boolean", [])]) methods[2],
checkMethod(methods[4], "::TestMethods::basicStaticBoolean", "basicStaticBoolean", [("Boolean", [])], static=True) "::TestMethods::basicWithSimpleArgs",
checkMethod(methods[5], "::TestMethods::basicBooleanWithSimpleArgs", "basicWithSimpleArgs",
"basicBooleanWithSimpleArgs", [
[("Boolean", (
[("::TestMethods::basicBooleanWithSimpleArgs::arg1", "arg1", "Boolean", False, False), "Undefined",
("::TestMethods::basicBooleanWithSimpleArgs::arg2", "arg2", "Byte", False, False), [
("::TestMethods::basicBooleanWithSimpleArgs::arg3", "arg3", "UnsignedLong", False, False)])]) (
checkMethod(methods[6], "::TestMethods::optionalArg", "::TestMethods::basicWithSimpleArgs::arg1",
"optionalArg", "arg1",
[("Undefined", "Boolean",
[("::TestMethods::optionalArg::arg1", "arg1", "ByteOrNull", True, False), False,
("::TestMethods::optionalArg::arg2", "arg2", "ByteSequence", True, False)])]) False,
checkMethod(methods[7], "::TestMethods::variadicArg", ),
"variadicArg", (
[("Undefined", "::TestMethods::basicWithSimpleArgs::arg2",
[("::TestMethods::variadicArg::arg1", "arg1", "ByteOrNull", True, True)])]) "arg2",
checkMethod(methods[8], "::TestMethods::getObject", "Byte",
"getObject", [("Object", [])]) False,
checkMethod(methods[9], "::TestMethods::setObject", False,
"setObject", ),
[("Undefined", (
[("::TestMethods::setObject::arg1", "arg1", "Object", False, False)])]) "::TestMethods::basicWithSimpleArgs::arg3",
checkMethod(methods[10], "::TestMethods::setAny", "arg3",
"setAny", "UnsignedLong",
[("Undefined", False,
[("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])]) False,
checkMethod(methods[11], "::TestMethods::doFloats", ),
"doFloats", ],
[("Float", )
[("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])]) ],
)
checkMethod(
methods[3], "::TestMethods::basicBoolean", "basicBoolean", [("Boolean", [])]
)
checkMethod(
methods[4],
"::TestMethods::basicStaticBoolean",
"basicStaticBoolean",
[("Boolean", [])],
static=True,
)
checkMethod(
methods[5],
"::TestMethods::basicBooleanWithSimpleArgs",
"basicBooleanWithSimpleArgs",
[
(
"Boolean",
[
(
"::TestMethods::basicBooleanWithSimpleArgs::arg1",
"arg1",
"Boolean",
False,
False,
),
(
"::TestMethods::basicBooleanWithSimpleArgs::arg2",
"arg2",
"Byte",
False,
False,
),
(
"::TestMethods::basicBooleanWithSimpleArgs::arg3",
"arg3",
"UnsignedLong",
False,
False,
),
],
)
],
)
checkMethod(
methods[6],
"::TestMethods::optionalArg",
"optionalArg",
[
(
"Undefined",
[
(
"::TestMethods::optionalArg::arg1",
"arg1",
"ByteOrNull",
True,
False,
),
(
"::TestMethods::optionalArg::arg2",
"arg2",
"ByteSequence",
True,
False,
),
],
)
],
)
checkMethod(
methods[7],
"::TestMethods::variadicArg",
"variadicArg",
[
(
"Undefined",
[
(
"::TestMethods::variadicArg::arg1",
"arg1",
"ByteOrNull",
True,
True,
)
],
)
],
)
checkMethod(methods[8], "::TestMethods::getObject", "getObject", [("Object", [])])
checkMethod(
methods[9],
"::TestMethods::setObject",
"setObject",
[
(
"Undefined",
[("::TestMethods::setObject::arg1", "arg1", "Object", False, False)],
)
],
)
checkMethod(
methods[10],
"::TestMethods::setAny",
"setAny",
[("Undefined", [("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])],
)
checkMethod(
methods[11],
"::TestMethods::doFloats",
"doFloats",
[("Float", [("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])],
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
undefined foo(optional float bar = 1); undefined foo(optional float bar = 1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -127,11 +274,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[GetterThrows] undefined foo(); [GetterThrows] undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -140,11 +289,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[SetterThrows] undefined foo(); [SetterThrows] undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -153,11 +304,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throw] undefined foo(); [Throw] undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -166,11 +319,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
undefined __noSuchMethod__(); undefined __noSuchMethod__();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
@ -179,77 +334,96 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throws, LenientFloat] [Throws, LenientFloat]
undefined foo(float myFloat); undefined foo(float myFloat);
[Throws] [Throws]
undefined foo(); undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(not threw, "Should allow LenientFloat to be only in a specific overload") harness.ok(not threw, "Should allow LenientFloat to be only in a specific overload")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throws] [Throws]
undefined foo(); undefined foo();
[Throws, LenientFloat] [Throws, LenientFloat]
undefined foo(float myFloat); undefined foo(float myFloat);
}; };
""") """
)
results = parser.finish() results = parser.finish()
iface = results[0] iface = results[0]
methods = iface.members methods = iface.members
lenientFloat = methods[0].getExtendedAttribute("LenientFloat") lenientFloat = methods[0].getExtendedAttribute("LenientFloat")
harness.ok(lenientFloat is not None, "LenientFloat in overloads must be added to the method") harness.ok(
lenientFloat is not None,
"LenientFloat in overloads must be added to the method",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throws, LenientFloat] [Throws, LenientFloat]
undefined foo(float myFloat); undefined foo(float myFloat);
[Throws] [Throws]
undefined foo(float myFloat, float yourFloat); undefined foo(float myFloat, float yourFloat);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "Should prevent overloads from getting different restricted float behavior") harness.ok(
threw,
"Should prevent overloads from getting different restricted float behavior",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throws] [Throws]
undefined foo(float myFloat, float yourFloat); undefined foo(float myFloat, float yourFloat);
[Throws, LenientFloat] [Throws, LenientFloat]
undefined foo(float myFloat); undefined foo(float myFloat);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "Should prevent overloads from getting different restricted float behavior (2)") harness.ok(
threw,
"Should prevent overloads from getting different restricted float behavior (2)",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Throws, LenientFloat] [Throws, LenientFloat]
undefined foo(float myFloat); undefined foo(float myFloat);
[Throws, LenientFloat] [Throws, LenientFloat]
undefined foo(short myShort); undefined foo(short myShort);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True

View file

@ -5,13 +5,13 @@ def WebIDLTest(parser, harness):
attribute any foo; attribute any foo;
any bar(); any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, "Should have a thing.") harness.check(len(results), 1, "Should have a thing.")
harness.ok(results[0].isNamespace(), "Our thing should be a namespace"); harness.ok(results[0].isNamespace(), "Our thing should be a namespace")
harness.check(len(results[0].members), 2, harness.check(len(results[0].members), 2, "Should have two things in our namespace")
"Should have two things in our namespace")
harness.ok(results[0].members[0].isAttr(), "First member is attribute") harness.ok(results[0].members[0].isAttr(), "First member is attribute")
harness.ok(results[0].members[0].isStatic(), "Attribute should be static") harness.ok(results[0].members[0].isStatic(), "Attribute should be static")
harness.ok(results[0].members[1].isMethod(), "Second member is method") harness.ok(results[0].members[1].isMethod(), "Second member is method")
@ -26,17 +26,17 @@ def WebIDLTest(parser, harness):
partial namespace MyNamespace { partial namespace MyNamespace {
any bar(); any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, "Should have things.") harness.check(len(results), 2, "Should have things.")
harness.ok(results[0].isNamespace(), "Our thing should be a namespace"); harness.ok(results[0].isNamespace(), "Our thing should be a namespace")
harness.check(len(results[0].members), 2, harness.check(len(results[0].members), 2, "Should have two things in our namespace")
"Should have two things in our namespace")
harness.ok(results[0].members[0].isAttr(), "First member is attribute") harness.ok(results[0].members[0].isAttr(), "First member is attribute")
harness.ok(results[0].members[0].isStatic(), "Attribute should be static"); harness.ok(results[0].members[0].isStatic(), "Attribute should be static")
harness.ok(results[0].members[1].isMethod(), "Second member is method") harness.ok(results[0].members[1].isMethod(), "Second member is method")
harness.ok(results[0].members[1].isStatic(), "Operation should be static"); harness.ok(results[0].members[1].isStatic(), "Operation should be static")
parser = parser.reset() parser = parser.reset()
parser.parse( parser.parse(
@ -47,17 +47,17 @@ def WebIDLTest(parser, harness):
namespace MyNamespace { namespace MyNamespace {
attribute any foo; attribute any foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, "Should have things.") harness.check(len(results), 2, "Should have things.")
harness.ok(results[1].isNamespace(), "Our thing should be a namespace"); harness.ok(results[1].isNamespace(), "Our thing should be a namespace")
harness.check(len(results[1].members), 2, harness.check(len(results[1].members), 2, "Should have two things in our namespace")
"Should have two things in our namespace")
harness.ok(results[1].members[0].isAttr(), "First member is attribute") harness.ok(results[1].members[0].isAttr(), "First member is attribute")
harness.ok(results[1].members[0].isStatic(), "Attribute should be static"); harness.ok(results[1].members[0].isStatic(), "Attribute should be static")
harness.ok(results[1].members[1].isMethod(), "Second member is method") harness.ok(results[1].members[1].isMethod(), "Second member is method")
harness.ok(results[1].members[1].isStatic(), "Operation should be static"); harness.ok(results[1].members[1].isStatic(), "Operation should be static")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
@ -67,7 +67,8 @@ def WebIDLTest(parser, harness):
namespace MyNamespace { namespace MyNamespace {
static attribute any foo; static attribute any foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -82,7 +83,8 @@ def WebIDLTest(parser, harness):
namespace MyNamespace { namespace MyNamespace {
static any bar(); static any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -101,7 +103,8 @@ def WebIDLTest(parser, harness):
interface MyNamespace { interface MyNamespace {
any baz(); any baz();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -120,7 +123,8 @@ def WebIDLTest(parser, harness):
namespace MyNamespace { namespace MyNamespace {
any bar(); any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -139,7 +143,8 @@ def WebIDLTest(parser, harness):
namespace MyNamespace { namespace MyNamespace {
any bar(); any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -158,7 +163,8 @@ def WebIDLTest(parser, harness):
interface MyNamespace { interface MyNamespace {
any bar(); any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -177,7 +183,8 @@ def WebIDLTest(parser, harness):
partial interface MyNamespace { partial interface MyNamespace {
any baz(); any baz();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -196,7 +203,8 @@ def WebIDLTest(parser, harness):
namespace MyNamespace { namespace MyNamespace {
any bar(); any bar();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -215,7 +223,8 @@ def WebIDLTest(parser, harness):
partial namespace MyNamespace { partial namespace MyNamespace {
any baz(); any baz();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:

View file

@ -1,6 +1,7 @@
# Import the WebIDL module, so we can do isinstance checks and whatnot # Import the WebIDL module, so we can do isinstance checks and whatnot
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
# Basic functionality # Basic functionality
parser.parse( parser.parse(
@ -9,7 +10,8 @@ def WebIDLTest(parser, harness):
[NewObject] readonly attribute Iface attr; [NewObject] readonly attribute Iface attr;
[NewObject] Iface method(); [NewObject] Iface method();
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(results, "Should not have thrown on basic [NewObject] usage") harness.ok(results, "Should not have thrown on basic [NewObject] usage")
@ -21,7 +23,8 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Pure, NewObject] readonly attribute Iface attr; [Pure, NewObject] readonly attribute Iface attr;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -35,7 +38,8 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Pure, NewObject] Iface method(); [Pure, NewObject] Iface method();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -49,7 +53,8 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[Cached, NewObject, Affects=Nothing] readonly attribute Iface attr; [Cached, NewObject, Affects=Nothing] readonly attribute Iface attr;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -63,7 +68,8 @@ def WebIDLTest(parser, harness):
interface Iface { interface Iface {
[StoreInSlot, NewObject, Affects=Nothing] readonly attribute Iface attr; [StoreInSlot, NewObject, Affects=Nothing] readonly attribute Iface attr;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestNullableEquivalency1 { interface TestNullableEquivalency1 {
attribute long a; attribute long a;
attribute long? b; attribute long? b;
@ -53,22 +55,24 @@ def WebIDLTest(parser, harness):
attribute object a; attribute object a;
attribute object? b; attribute object? b;
}; };
""") """
)
for decl in parser.finish(): for decl in parser.finish():
if decl.isInterface(): if decl.isInterface():
checkEquivalent(decl, harness) checkEquivalent(decl, harness)
def checkEquivalent(iface, harness): def checkEquivalent(iface, harness):
type1 = iface.members[0].type type1 = iface.members[0].type
type2 = iface.members[1].type type2 = iface.members[1].type
harness.check(type1.nullable(), False, 'attr1 should not be nullable') harness.check(type1.nullable(), False, "attr1 should not be nullable")
harness.check(type2.nullable(), True, 'attr2 should be nullable') harness.check(type2.nullable(), True, "attr2 should be nullable")
# We don't know about type1, but type2, the nullable type, definitely # We don't know about type1, but type2, the nullable type, definitely
# shouldn't be builtin. # shouldn't be builtin.
harness.check(type2.builtin, False, 'attr2 should not be builtin') harness.check(type2.builtin, False, "attr2 should not be builtin")
# Ensure that all attributes of type2 match those in type1, except for: # Ensure that all attributes of type2 match those in type1, except for:
# - names on an ignore list, # - names on an ignore list,
@ -78,10 +82,22 @@ def checkEquivalent(iface, harness):
# #
# Yes, this is an ugly, fragile hack. But it finds bugs... # Yes, this is an ugly, fragile hack. But it finds bugs...
for attr in dir(type1): for attr in dir(type1):
if attr.startswith('_') or \ if (
attr in ['nullable', 'builtin', 'filename', 'location', attr.startswith("_")
'inner', 'QName', 'getDeps', 'name', 'prettyName'] or \ or attr
(hasattr(type(type1), attr) and not callable(getattr(type1, attr))): in [
"nullable",
"builtin",
"filename",
"location",
"inner",
"QName",
"getDeps",
"name",
"prettyName",
]
or (hasattr(type(type1), attr) and not callable(getattr(type1, attr)))
):
continue continue
a1 = getattr(type1, attr) a1 = getattr(type1, attr)
@ -96,20 +112,30 @@ def checkEquivalent(iface, harness):
try: try:
a2 = getattr(type2, attr) a2 = getattr(type2, attr)
except: except:
harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) harness.ok(
False,
"Missing %s attribute on type %s in %s" % (attr, type2, iface),
)
continue continue
if not callable(a2): if not callable(a2):
harness.ok(False, "%s attribute on type %s in %s wasn't callable" % (attr, type2, iface)) harness.ok(
False,
"%s attribute on type %s in %s wasn't callable"
% (attr, type2, iface),
)
continue continue
v2 = a2() v2 = a2()
harness.check(v2, v1, '%s method return value' % attr) harness.check(v2, v1, "%s method return value" % attr)
else: else:
try: try:
a2 = getattr(type2, attr) a2 = getattr(type2, attr)
except: except:
harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) harness.ok(
False,
"Missing %s attribute on type %s in %s" % (attr, type2, iface),
)
continue continue
harness.check(a2, a1, '%s attribute should match' % attr) harness.check(a2, a1, "%s attribute should match" % attr)

View file

@ -1,14 +0,0 @@
def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
interface NullableUndefined {
undefined? foo();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")

View file

@ -0,0 +1,288 @@
# 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 WebIDLTest(parser, harness):
# Test dictionary as inner type
harness.should_throw(
parser,
"""
dictionary A {
boolean member;
};
interface B {
attribute ObservableArray<A> foo;
};
""",
"use dictionary as inner type",
)
# Test sequence as inner type
harness.should_throw(
parser,
"""
interface A {
attribute ObservableArray<sequence<boolean>> foo;
};
""",
"use sequence as inner type",
)
# Test sequence<dictionary> as inner type
harness.should_throw(
parser,
"""
dictionary A {
boolean member;
};
interface B {
attribute ObservableArray<sequence<A>> foo;
};
""",
"use sequence<dictionary> as inner type",
)
# Test record as inner type
harness.should_throw(
parser,
"""
interface A {
attribute ObservableArray<record<DOMString, boolean>> foo;
};
""",
"use record as inner type",
)
# Test record<dictionary> as inner type
harness.should_throw(
parser,
"""
dictionary A {
boolean member;
};
interface B {
attribute ObservableArray<record<DOMString, A>> foo;
};
""",
"use record<dictionary> as inner type",
)
# Test observable array as inner type
harness.should_throw(
parser,
"""
interface A {
attribute ObservableArray<ObservableArray<boolean>> foo;
};
""",
"use ObservableArray as inner type",
)
# Test nullable attribute
harness.should_throw(
parser,
"""
interface A {
attribute ObservableArray<boolean>? foo;
};
""",
"nullable",
)
# Test sequence
harness.should_throw(
parser,
"""
interface A {
undefined foo(sequence<ObservableArray<boolean>> foo);
};
""",
"used in sequence",
)
# Test record
harness.should_throw(
parser,
"""
interface A {
undefined foo(record<DOMString, ObservableArray<boolean>> foo);
};
""",
"used in record",
)
# Test promise
harness.should_throw(
parser,
"""
interface A {
Promise<ObservableArray<boolean>> foo();
};
""",
"used in promise",
)
# Test union
harness.should_throw(
parser,
"""
interface A {
attribute (DOMString or ObservableArray<boolean>>) foo;
};
""",
"used in union",
)
# Test dictionary member
harness.should_throw(
parser,
"""
dictionary A {
ObservableArray<boolean> foo;
};
""",
"used on dictionary member type",
)
# Test argument
harness.should_throw(
parser,
"""
interface A {
undefined foo(ObservableArray<boolean> foo);
};
""",
"used on argument",
)
# Test static attribute
harness.should_throw(
parser,
"""
interface A {
static attribute ObservableArray<boolean> foo;
};
""",
"used on static attribute type",
)
# Test iterable
harness.should_throw(
parser,
"""
interface A {
iterable<ObservableArray<boolean>>;
};
""",
"used in iterable",
)
# Test maplike
harness.should_throw(
parser,
"""
interface A {
maplike<long, ObservableArray<boolean>>;
};
""",
"used in maplike",
)
# Test setlike
harness.should_throw(
parser,
"""
interface A {
setlike<ObservableArray<boolean>>;
};
""",
"used in setlike",
)
# Test JS implemented interface
harness.should_throw(
parser,
"""
[JSImplementation="@mozilla.org/dom/test-interface-js;1"]
interface A {
readonly attribute ObservableArray<boolean> foo;
};
""",
"used in JS implemented interface",
)
# Test namespace
harness.should_throw(
parser,
"""
namespace A {
readonly attribute ObservableArray<boolean> foo;
};
""",
"used in namespaces",
)
# Test [Cached] extended attribute
harness.should_throw(
parser,
"""
interface A {
[Cached, Pure]
readonly attribute ObservableArray<boolean> foo;
};
""",
"have Cached extended attribute",
)
# Test [StoreInSlot] extended attribute
harness.should_throw(
parser,
"""
interface A {
[StoreInSlot, Pure]
readonly attribute ObservableArray<boolean> foo;
};
""",
"have StoreInSlot extended attribute",
)
# Test regular attribute
parser = parser.reset()
parser.parse(
"""
interface A {
readonly attribute ObservableArray<boolean> foo;
attribute ObservableArray<[Clamp] octet> bar;
attribute ObservableArray<long?> baz;
attribute ObservableArray<(boolean or long)> qux;
};
"""
)
results = parser.finish()
A = results[0]
foo = A.members[0]
harness.ok(foo.readonly, "A.foo is readonly attribute")
harness.ok(foo.type.isObservableArray(), "A.foo is ObservableArray type")
harness.check(
foo.slotIndices[A.identifier.name], 0, "A.foo should be stored in slot"
)
bar = A.members[1]
harness.ok(bar.type.isObservableArray(), "A.bar is ObservableArray type")
harness.check(
bar.slotIndices[A.identifier.name], 1, "A.bar should be stored in slot"
)
harness.ok(bar.type.inner.hasClamp(), "A.bar's inner type should be clamped")
baz = A.members[2]
harness.ok(baz.type.isObservableArray(), "A.baz is ObservableArray type")
harness.check(
baz.slotIndices[A.identifier.name], 2, "A.baz should be stored in slot"
)
harness.ok(baz.type.inner.nullable(), "A.baz's inner type should be nullable")
qux = A.members[3]
harness.ok(qux.type.isObservableArray(), "A.qux is ObservableArray type")
harness.check(
qux.slotIndices[A.identifier.name], 3, "A.qux should be stored in slot"
)
harness.ok(qux.type.inner.isUnion(), "A.qux's inner type should be union")

View file

@ -1,30 +1,35 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface OptionalConstraints1 { interface OptionalConstraints1 {
undefined foo(optional byte arg1, byte arg2); undefined foo(optional byte arg1, byte arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, harness.ok(
"Should not have thrown on non-optional argument following " not threw,
"optional argument.") "Should not have thrown on non-optional argument following "
"optional argument.",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface OptionalConstraints2 { interface OptionalConstraints2 {
undefined foo(optional byte arg1 = 1, optional byte arg2 = 2, undefined foo(optional byte arg1 = 1, optional byte arg2 = 2,
optional byte arg3, optional byte arg4 = 4, optional byte arg3, optional byte arg4 = 4,
optional byte arg5, optional byte arg6 = 9); optional byte arg5, optional byte arg6 = 9);
}; };
""") """
)
results = parser.finish() results = parser.finish()
args = results[0].members[0].signatures()[0][1] args = results[0].members[0].signatures()[0][1]
harness.check(len(args), 6, "Should have 6 arguments") harness.check(len(args), 6, "Should have 6 arguments")
harness.check(args[5].defaultValue.value, 9, harness.check(args[5].defaultValue.value, 9, "Should have correct default value")
"Should have correct default value")

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestOverloads { interface TestOverloads {
undefined basic(); undefined basic();
undefined basic(long arg1); undefined basic(long arg1);
@ -14,21 +16,29 @@ def WebIDLTest(parser, harness):
undefined optionalTest(); undefined optionalTest();
undefined optionalTest(optional long num1, long num2); undefined optionalTest(optional long num1, long num2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(True, "TestOverloads interface parsed without error.") harness.ok(True, "TestOverloads interface parsed without error.")
harness.check(len(results), 1, "Should be one production.") harness.check(len(results), 1, "Should be one production.")
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") harness.check(
harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName") 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), 4, "Expect %s members" % 4) 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",
)
harness.check(member.identifier.name, "basic", "Method has the right name") harness.check(member.identifier.name, "basic", "Method has the right name")
harness.check(member.hasOverloads(), True, "Method has overloads") harness.check(member.hasOverloads(), True, "Method has overloads")
@ -37,24 +47,28 @@ def WebIDLTest(parser, harness):
(retval, argumentSet) = signatures[0] (retval, argumentSet) = signatures[0]
harness.check(str(retval), "Undefined", "Expect a undefined retval") harness.check(str(retval), "Undefined", "Expect an undefined retval")
harness.check(len(argumentSet), 0, "Expect an empty argument set") harness.check(len(argumentSet), 0, "Expect an empty argument set")
(retval, argumentSet) = signatures[1] (retval, argumentSet) = signatures[1]
harness.check(str(retval), "Undefined", "Expect a undefined retval") harness.check(str(retval), "Undefined", "Expect an undefined retval")
harness.check(len(argumentSet), 1, "Expect an argument set with one argument") harness.check(len(argumentSet), 1, "Expect an argument set with one argument")
argument = argumentSet[0] argument = argumentSet[0]
harness.ok(isinstance(argument, WebIDL.IDLArgument), harness.ok(isinstance(argument, WebIDL.IDLArgument), "Should be an IDLArgument")
"Should be an IDLArgument") harness.check(
harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName") 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] member = iface.members[3]
harness.check(len(member.overloadsForArgCount(0)), 1, harness.check(
"Only one overload for no args") 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(1)), 0, "No overloads for one arg")
harness.check(len(member.overloadsForArgCount(2)), 1, harness.check(
"Only one overload for two args") len(member.overloadsForArgCount(2)), 1, "Only one overload for two args"
)

View file

@ -1,157 +1,177 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
legacycaller Promise<any> foo(); legacycaller Promise<any> foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow Promise return values for legacycaller.")
"Should not allow Promise return values for legacycaller.")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
Promise<any> foo(); Promise<any> foo();
long foo(long arg); long foo(long arg);
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow overloads which have both Promise and " threw,
"non-Promise return types.") "Should not allow overloads which have both Promise and "
"non-Promise return types.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
long foo(long arg); long foo(long arg);
Promise<any> foo(); Promise<any> foo();
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow overloads which have both Promise and " threw,
"non-Promise return types.") "Should not allow overloads which have both Promise and "
"non-Promise return types.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
Promise<any>? foo(); Promise<any>? foo();
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow nullable Promise return values.")
"Should not allow nullable Promise return values.")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
undefined foo(Promise<any>? arg); undefined foo(Promise<any>? arg);
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow nullable Promise arguments.")
"Should not allow nullable Promise arguments.")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface A { interface A {
Promise<any> foo(); Promise<any> foo();
Promise<any> foo(long arg); Promise<any> foo(long arg);
}; };
""") """
results = parser.finish(); )
results = parser.finish()
harness.ok(True, harness.ok(
"Should allow overloads which only have Promise and return " True, "Should allow overloads which only have Promise and return " "types."
"types.") )
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
attribute Promise<any> attr; attribute Promise<any> attr;
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow writable Promise-typed attributes.")
"Should not allow writable Promise-typed attributes.")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[LenientSetter] readonly attribute Promise<any> attr; [LegacyLenientSetter] readonly attribute Promise<any> attr;
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should not allow [LenientSetter] Promise-typed attributes.") threw, "Should not allow [LegacyLenientSetter] Promise-typed attributes."
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[PutForwards=bar] readonly attribute Promise<any> attr; [PutForwards=bar] readonly attribute Promise<any> attr;
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow [PutForwards] Promise-typed attributes.")
"Should not allow [PutForwards] Promise-typed attributes.")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[Replaceable] readonly attribute Promise<any> attr; [Replaceable] readonly attribute Promise<any> attr;
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow [Replaceable] Promise-typed attributes.")
"Should not allow [Replaceable] Promise-typed attributes.")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface A { interface A {
[SameObject] readonly attribute Promise<any> attr; [SameObject] readonly attribute Promise<any> attr;
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should not allow [SameObject] Promise-typed attributes.")
"Should not allow [SameObject] Promise-typed attributes.")

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestIface { interface TestIface {
static attribute boolean prototype; static attribute boolean prototype;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -15,11 +17,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestIface { interface TestIface {
static boolean prototype(); static boolean prototype();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -29,11 +33,13 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestIface { interface TestIface {
const boolean prototype = true; const boolean prototype = true;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -42,39 +48,60 @@ def WebIDLTest(parser, harness):
# Make sure that we can parse non-static attributes with 'prototype' as identifier. # Make sure that we can parse non-static attributes with 'prototype' as identifier.
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestIface { interface TestIface {
attribute boolean prototype; attribute boolean prototype;
}; };
""") """
)
results = parser.finish() results = parser.finish()
testIface = results[0]; testIface = results[0]
harness.check(testIface.members[0].isStatic(), False, "Attribute should not be static") harness.check(
harness.check(testIface.members[0].identifier.name, "prototype", "Attribute identifier should be 'prototype'") 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. # Make sure that we can parse non-static operations with 'prototype' as identifier.
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestIface { interface TestIface {
boolean prototype(); boolean prototype();
}; };
""") """
)
results = parser.finish() results = parser.finish()
testIface = results[0]; testIface = results[0]
harness.check(testIface.members[0].isStatic(), False, "Operation should not be static") harness.check(
harness.check(testIface.members[0].identifier.name, "prototype", "Operation identifier should be 'prototype'") 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. # Make sure that we can parse dictionary members with 'prototype' as identifier.
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
dictionary TestDict { dictionary TestDict {
boolean prototype; boolean prototype;
}; };
""") """
)
results = parser.finish() results = parser.finish()
testDict = results[0]; testDict = results[0]
harness.check(testDict.members[0].identifier.name, "prototype", "Dictionary member should be 'prototype'") harness.check(
testDict.members[0].identifier.name,
"prototype",
"Dictionary member should be 'prototype'",
)

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface I { interface I {
[PutForwards=B] readonly attribute long A; [PutForwards=B] readonly attribute long A;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -13,16 +15,18 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface I { interface I {
[PutForwards=B] readonly attribute J A; [PutForwards=B] readonly attribute J A;
}; };
interface J { interface J {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -30,17 +34,19 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface I { interface I {
[PutForwards=B] attribute J A; [PutForwards=B] attribute J A;
}; };
interface J { interface J {
attribute long B; attribute long B;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -48,17 +54,19 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface I { interface I {
[PutForwards=B] static readonly attribute J A; [PutForwards=B] static readonly attribute J A;
}; };
interface J { interface J {
attribute long B; attribute long B;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -66,17 +74,19 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
callback interface I { callback interface I {
[PutForwards=B] readonly attribute J A; [PutForwards=B] readonly attribute J A;
}; };
interface J { interface J {
attribute long B; attribute long B;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -84,10 +94,11 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should have thrown.") harness.ok(threw, "Should have thrown.")
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface I { interface I {
[PutForwards=C] readonly attribute J A; [PutForwards=C] readonly attribute J A;
[PutForwards=C] readonly attribute J B; [PutForwards=C] readonly attribute J B;
@ -98,7 +109,8 @@ def WebIDLTest(parser, harness):
interface K { interface K {
[PutForwards=A] readonly attribute I D; [PutForwards=A] readonly attribute I D;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,18 +1,22 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
dictionary Dict {}; dictionary Dict {};
interface RecordArg { interface RecordArg {
undefined foo(record<DOMString, Dict> arg); undefined foo(record<DOMString, Dict> arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, "Should know about two things"); harness.check(len(results), 2, "Should know about two things")
harness.ok(isinstance(results[1], WebIDL.IDLInterface), harness.ok(
"Should have an interface here"); isinstance(results[1], WebIDL.IDLInterface), "Should have an interface here"
)
members = results[1].members members = results[1].members
harness.check(len(members), 1, "Should have one member") harness.check(len(members), 1, "Should have one member")
harness.ok(members[0].isMethod(), "Should have method") harness.ok(members[0].isMethod(), "Should have method")
@ -20,34 +24,38 @@ def WebIDLTest(parser, harness):
args = signature[1] args = signature[1]
harness.check(len(args), 1, "Should have one arg") harness.check(len(args), 1, "Should have one arg")
harness.ok(args[0].type.isRecord(), "Should have a record type here") harness.ok(args[0].type.isRecord(), "Should have a record type here")
harness.ok(args[0].type.inner.isDictionary(), harness.ok(args[0].type.inner.isDictionary(), "Should have a dictionary inner type")
"Should have a dictionary inner type")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface RecordUndefinedArg { interface RecordUndefinedArg {
undefined foo(record<DOMString, undefined> arg); undefined foo(record<DOMString, undefined> arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, "Should have thrown because record can't have undefined as value type.") harness.ok(
threw, "Should have thrown because record can't have undefined as value type."
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
dictionary Dict { dictionary Dict {
record<DOMString, Dict> val; record<DOMString, Dict> val;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Should have thrown on dictionary containing itself via record.")
"Should have thrown on dictionary containing itself via record.")

View file

@ -2,8 +2,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code): def should_throw(parser, harness, message, code):
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(code) parser.parse(code)
@ -16,43 +17,68 @@ def should_throw(parser, harness, message, code):
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
# The [Replaceable] extended attribute MUST take no arguments. # The [Replaceable] extended attribute MUST take no arguments.
should_throw(parser, harness, "no arguments", """ should_throw(
parser,
harness,
"no arguments",
"""
interface I { interface I {
[Replaceable=X] readonly attribute long A; [Replaceable=X] readonly attribute long A;
}; };
""") """,
)
# An attribute with the [Replaceable] extended attribute MUST NOT also be # An attribute with the [Replaceable] extended attribute MUST NOT also be
# declared with the [PutForwards] extended attribute. # declared with the [PutForwards] extended attribute.
should_throw(parser, harness, "PutForwards", """ should_throw(
parser,
harness,
"PutForwards",
"""
interface I { interface I {
[PutForwards=B, Replaceable] readonly attribute J A; [PutForwards=B, Replaceable] readonly attribute J A;
}; };
interface J { interface J {
attribute long B; attribute long B;
}; };
""") """,
)
# The [Replaceable] extended attribute MUST NOT be used on an attribute # The [Replaceable] extended attribute MUST NOT be used on an attribute
# that is not read only. # that is not read only.
should_throw(parser, harness, "writable attribute", """ should_throw(
parser,
harness,
"writable attribute",
"""
interface I { interface I {
[Replaceable] attribute long A; [Replaceable] attribute long A;
}; };
""") """,
)
# The [Replaceable] extended attribute MUST NOT be used on a static # The [Replaceable] extended attribute MUST NOT be used on a static
# attribute. # attribute.
should_throw(parser, harness, "static attribute", """ should_throw(
parser,
harness,
"static attribute",
"""
interface I { interface I {
[Replaceable] static readonly attribute long A; [Replaceable] static readonly attribute long A;
}; };
""") """,
)
# The [Replaceable] extended attribute MUST NOT be used on an attribute # The [Replaceable] extended attribute MUST NOT be used on an attribute
# declared on a callback interface. # declared on a callback interface.
should_throw(parser, harness, "callback interface", """ should_throw(
parser,
harness,
"callback interface",
"""
callback interface I { callback interface I {
[Replaceable] readonly attribute long A; [Replaceable] readonly attribute long A;
}; };
""") """,
)

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
[SecureContext] [SecureContext]
interface TestSecureContextOnInterface { interface TestSecureContextOnInterface {
const octet TEST_CONSTANT = 0; const octet TEST_CONSTANT = 0;
@ -13,27 +15,47 @@ def WebIDLTest(parser, harness):
readonly attribute byte testAttribute2; readonly attribute byte testAttribute2;
undefined testMethod2(byte foo); undefined testMethod2(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[0].members), 6, "TestSecureContextOnInterface should have six members") harness.check(
harness.ok(results[0].getExtendedAttribute("SecureContext"), len(results[0].members),
"Interface should have [SecureContext] extended attribute") 6,
harness.ok(results[0].members[0].getExtendedAttribute("SecureContext"), "TestSecureContextOnInterface should have six members",
"[SecureContext] should propagate from interface to constant members") )
harness.ok(results[0].members[1].getExtendedAttribute("SecureContext"), harness.ok(
"[SecureContext] should propagate from interface to attribute members") results[0].getExtendedAttribute("SecureContext"),
harness.ok(results[0].members[2].getExtendedAttribute("SecureContext"), "Interface should have [SecureContext] extended attribute",
"[SecureContext] should propagate from interface to method members") )
harness.ok(results[0].members[3].getExtendedAttribute("SecureContext"), harness.ok(
"[SecureContext] should propagate from interface to constant members from partial interface") results[0].members[0].getExtendedAttribute("SecureContext"),
harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"), "[SecureContext] should propagate from interface to constant members",
"[SecureContext] should propagate from interface to attribute members from partial interface") )
harness.ok(results[0].members[5].getExtendedAttribute("SecureContext"), harness.ok(
"[SecureContext] should propagate from interface to method members from partial interface") results[0].members[1].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to attribute members",
)
harness.ok(
results[0].members[2].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to method members",
)
harness.ok(
results[0].members[3].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to constant members from partial interface",
)
harness.ok(
results[0].members[4].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to attribute members from partial interface",
)
harness.ok(
results[0].members[5].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to method members from partial interface",
)
# Same thing, but with the partial interface specified first: # Same thing, but with the partial interface specified first:
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
partial interface TestSecureContextOnInterfaceAfterPartialInterface { partial interface TestSecureContextOnInterfaceAfterPartialInterface {
const octet TEST_CONSTANT_2 = 0; const octet TEST_CONSTANT_2 = 0;
readonly attribute byte testAttribute2; readonly attribute byte testAttribute2;
@ -45,26 +67,46 @@ def WebIDLTest(parser, harness):
readonly attribute byte testAttribute; readonly attribute byte testAttribute;
undefined testMethod(byte foo); undefined testMethod(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[1].members), 6, "TestSecureContextOnInterfaceAfterPartialInterface should have six members") harness.check(
harness.ok(results[1].getExtendedAttribute("SecureContext"), len(results[1].members),
"Interface should have [SecureContext] extended attribute") 6,
harness.ok(results[1].members[0].getExtendedAttribute("SecureContext"), "TestSecureContextOnInterfaceAfterPartialInterface should have six members",
"[SecureContext] should propagate from interface to constant members") )
harness.ok(results[1].members[1].getExtendedAttribute("SecureContext"), harness.ok(
"[SecureContext] should propagate from interface to attribute members") results[1].getExtendedAttribute("SecureContext"),
harness.ok(results[1].members[2].getExtendedAttribute("SecureContext"), "Interface should have [SecureContext] extended attribute",
"[SecureContext] should propagate from interface to method members") )
harness.ok(results[1].members[3].getExtendedAttribute("SecureContext"), harness.ok(
"[SecureContext] should propagate from interface to constant members from partial interface") results[1].members[0].getExtendedAttribute("SecureContext"),
harness.ok(results[1].members[4].getExtendedAttribute("SecureContext"), "[SecureContext] should propagate from interface to constant members",
"[SecureContext] should propagate from interface to attribute members from partial interface") )
harness.ok(results[1].members[5].getExtendedAttribute("SecureContext"), harness.ok(
"[SecureContext] should propagate from interface to method members from partial interface") results[1].members[1].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to attribute members",
)
harness.ok(
results[1].members[2].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to method members",
)
harness.ok(
results[1].members[3].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to constant members from partial interface",
)
harness.ok(
results[1].members[4].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to attribute members from partial interface",
)
harness.ok(
results[1].members[5].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to method members from partial interface",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestSecureContextOnPartialInterface { interface TestSecureContextOnPartialInterface {
const octet TEST_CONSTANT = 0; const octet TEST_CONSTANT = 0;
readonly attribute byte testAttribute; readonly attribute byte testAttribute;
@ -76,26 +118,46 @@ def WebIDLTest(parser, harness):
readonly attribute byte testAttribute2; readonly attribute byte testAttribute2;
undefined testMethod2(byte foo); undefined testMethod2(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[0].members), 6, "TestSecureContextOnPartialInterface should have six members") harness.check(
harness.ok(results[0].getExtendedAttribute("SecureContext") is None, len(results[0].members),
"[SecureContext] should not propagate from a partial interface to the interface") 6,
harness.ok(results[0].members[0].getExtendedAttribute("SecureContext") is None, "TestSecureContextOnPartialInterface should have six members",
"[SecureContext] should not propagate from a partial interface to the interface's constant members") )
harness.ok(results[0].members[1].getExtendedAttribute("SecureContext") is None, harness.ok(
"[SecureContext] should not propagate from a partial interface to the interface's attribute members") results[0].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None, "[SecureContext] should not propagate from a partial interface to the interface",
"[SecureContext] should not propagate from a partial interface to the interface's method members") )
harness.ok(results[0].members[3].getExtendedAttribute("SecureContext"), harness.ok(
"Constant members from [SecureContext] partial interface should be [SecureContext]") results[0].members[0].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"), "[SecureContext] should not propagate from a partial interface to the interface's constant members",
"Attribute members from [SecureContext] partial interface should be [SecureContext]") )
harness.ok(results[0].members[5].getExtendedAttribute("SecureContext"), harness.ok(
"Method members from [SecureContext] partial interface should be [SecureContext]") results[0].members[1].getExtendedAttribute("SecureContext") is None,
"[SecureContext] should not propagate from a partial interface to the interface's attribute members",
)
harness.ok(
results[0].members[2].getExtendedAttribute("SecureContext") is None,
"[SecureContext] should not propagate from a partial interface to the interface's method members",
)
harness.ok(
results[0].members[3].getExtendedAttribute("SecureContext"),
"Constant members from [SecureContext] partial interface should be [SecureContext]",
)
harness.ok(
results[0].members[4].getExtendedAttribute("SecureContext"),
"Attribute members from [SecureContext] partial interface should be [SecureContext]",
)
harness.ok(
results[0].members[5].getExtendedAttribute("SecureContext"),
"Method members from [SecureContext] partial interface should be [SecureContext]",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestSecureContextOnInterfaceMembers { interface TestSecureContextOnInterfaceMembers {
const octet TEST_NON_SECURE_CONSTANT_1 = 0; const octet TEST_NON_SECURE_CONSTANT_1 = 0;
[SecureContext] [SecureContext]
@ -110,32 +172,58 @@ def WebIDLTest(parser, harness):
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
undefined testNonSecureMethod2(byte foo); undefined testNonSecureMethod2(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[0].members), 9, "TestSecureContextOnInterfaceMembers should have nine members") harness.check(
harness.ok(results[0].getExtendedAttribute("SecureContext") is None, len(results[0].members),
"[SecureContext] on members should not propagate up to the interface") 9,
harness.ok(results[0].members[0].getExtendedAttribute("SecureContext") is None, "TestSecureContextOnInterfaceMembers should have nine members",
"Constant should not have [SecureContext] extended attribute") )
harness.ok(results[0].members[1].getExtendedAttribute("SecureContext"), harness.ok(
"Constant should have [SecureContext] extended attribute") results[0].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None, "[SecureContext] on members should not propagate up to the interface",
"Constant should not have [SecureContext] extended attribute") )
harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None, harness.ok(
"Attribute should not have [SecureContext] extended attribute") results[0].members[0].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"), "Constant should not have [SecureContext] extended attribute",
"Attribute should have [SecureContext] extended attribute") )
harness.ok(results[0].members[5].getExtendedAttribute("SecureContext") is None, harness.ok(
"Attribute should not have [SecureContext] extended attribute") results[0].members[1].getExtendedAttribute("SecureContext"),
harness.ok(results[0].members[6].getExtendedAttribute("SecureContext") is None, "Constant should have [SecureContext] extended attribute",
"Method should not have [SecureContext] extended attribute") )
harness.ok(results[0].members[7].getExtendedAttribute("SecureContext"), harness.ok(
"Method should have [SecureContext] extended attribute") results[0].members[2].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[8].getExtendedAttribute("SecureContext") is None, "Constant should not have [SecureContext] extended attribute",
"Method should not have [SecureContext] extended attribute") )
harness.ok(
results[0].members[3].getExtendedAttribute("SecureContext") is None,
"Attribute should not have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[4].getExtendedAttribute("SecureContext"),
"Attribute should have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[5].getExtendedAttribute("SecureContext") is None,
"Attribute should not have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[6].getExtendedAttribute("SecureContext") is None,
"Method should not have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[7].getExtendedAttribute("SecureContext"),
"Method should have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[8].getExtendedAttribute("SecureContext") is None,
"Method should not have [SecureContext] extended attribute",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestSecureContextOnPartialInterfaceMembers { interface TestSecureContextOnPartialInterfaceMembers {
}; };
partial interface TestSecureContextOnPartialInterfaceMembers { partial interface TestSecureContextOnPartialInterfaceMembers {
@ -152,37 +240,62 @@ def WebIDLTest(parser, harness):
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
undefined testNonSecureMethod2(byte foo); undefined testNonSecureMethod2(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[0].members), 9, "TestSecureContextOnPartialInterfaceMembers should have nine members") harness.check(
harness.ok(results[0].members[0].getExtendedAttribute("SecureContext") is None, len(results[0].members),
"Constant from partial interface should not have [SecureContext] extended attribute") 9,
harness.ok(results[0].members[1].getExtendedAttribute("SecureContext"), "TestSecureContextOnPartialInterfaceMembers should have nine members",
"Constant from partial interface should have [SecureContext] extended attribute") )
harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None, harness.ok(
"Constant from partial interface should not have [SecureContext] extended attribute") results[0].members[0].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None, "Constant from partial interface should not have [SecureContext] extended attribute",
"Attribute from partial interface should not have [SecureContext] extended attribute") )
harness.ok(results[0].members[4].getExtendedAttribute("SecureContext"), harness.ok(
"Attribute from partial interface should have [SecureContext] extended attribute") results[0].members[1].getExtendedAttribute("SecureContext"),
harness.ok(results[0].members[5].getExtendedAttribute("SecureContext") is None, "Constant from partial interface should have [SecureContext] extended attribute",
"Attribute from partial interface should not have [SecureContext] extended attribute") )
harness.ok(results[0].members[6].getExtendedAttribute("SecureContext") is None, harness.ok(
"Method from partial interface should not have [SecureContext] extended attribute") results[0].members[2].getExtendedAttribute("SecureContext") is None,
harness.ok(results[0].members[7].getExtendedAttribute("SecureContext"), "Constant from partial interface should not have [SecureContext] extended attribute",
"Method from partial interface should have [SecureContext] extended attribute") )
harness.ok(results[0].members[8].getExtendedAttribute("SecureContext") is None, harness.ok(
"Method from partial interface should not have [SecureContext] extended attribute") results[0].members[3].getExtendedAttribute("SecureContext") is None,
"Attribute from partial interface should not have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[4].getExtendedAttribute("SecureContext"),
"Attribute from partial interface should have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[5].getExtendedAttribute("SecureContext") is None,
"Attribute from partial interface should not have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[6].getExtendedAttribute("SecureContext") is None,
"Method from partial interface should not have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[7].getExtendedAttribute("SecureContext"),
"Method from partial interface should have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[8].getExtendedAttribute("SecureContext") is None,
"Method from partial interface should not have [SecureContext] extended attribute",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[SecureContext=something] [SecureContext=something]
interface TestSecureContextTakesNoValue1 { interface TestSecureContextTakesNoValue1 {
const octet TEST_SECURE_CONSTANT = 0; const octet TEST_SECURE_CONSTANT = 0;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -191,7 +304,8 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestSecureContextForOverloads1 { interface TestSecureContextForOverloads1 {
[SecureContext] [SecureContext]
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
@ -199,16 +313,21 @@ def WebIDLTest(parser, harness):
partial interface TestSecureContextForOverloads1 { partial interface TestSecureContextForOverloads1 {
undefined testSecureMethod(byte foo, byte bar); undefined testSecureMethod(byte foo, byte bar);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "If [SecureContext] appears on an overloaded operation, then it MUST appear on all overloads") harness.ok(
threw,
"If [SecureContext] appears on an overloaded operation, then it MUST appear on all overloads",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestSecureContextForOverloads2 { interface TestSecureContextForOverloads2 {
[SecureContext] [SecureContext]
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
@ -217,31 +336,40 @@ def WebIDLTest(parser, harness):
[SecureContext] [SecureContext]
undefined testSecureMethod(byte foo, byte bar); undefined testSecureMethod(byte foo, byte bar);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, "[SecureContext] can appear on an overloaded operation if it appears on all overloads") harness.ok(
not threw,
"[SecureContext] can appear on an overloaded operation if it appears on all overloads",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[SecureContext] [SecureContext]
interface TestSecureContextOnInterfaceAndMember { interface TestSecureContextOnInterfaceAndMember {
[SecureContext] [SecureContext]
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "[SecureContext] must not appear on an interface and interface member") harness.ok(
threw, "[SecureContext] must not appear on an interface and interface member"
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestSecureContextOnPartialInterfaceAndMember { interface TestSecureContextOnPartialInterfaceAndMember {
}; };
[SecureContext] [SecureContext]
@ -249,16 +377,21 @@ def WebIDLTest(parser, harness):
[SecureContext] [SecureContext]
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "[SecureContext] must not appear on a partial interface and one of the partial interface's member's") harness.ok(
threw,
"[SecureContext] must not appear on a partial interface and one of the partial interface's member's",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[SecureContext] [SecureContext]
interface TestSecureContextOnInterfaceAndPartialInterfaceMember { interface TestSecureContextOnInterfaceAndPartialInterfaceMember {
}; };
@ -266,31 +399,41 @@ def WebIDLTest(parser, harness):
[SecureContext] [SecureContext]
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "[SecureContext] must not appear on an interface and one of its partial interface's member's") harness.ok(
threw,
"[SecureContext] must not appear on an interface and one of its partial interface's member's",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[SecureContext] [SecureContext]
interface TestSecureContextOnInheritedInterface { interface TestSecureContextOnInheritedInterface {
}; };
interface TestSecureContextNotOnInheritingInterface : TestSecureContextOnInheritedInterface { interface TestSecureContextNotOnInheritingInterface : TestSecureContextOnInheritedInterface {
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "[SecureContext] must appear on interfaces that inherit from another [SecureContext] interface") harness.ok(
threw,
"[SecureContext] must appear on interfaces that inherit from another [SecureContext] interface",
)
# Test 'includes'. # Test 'includes'.
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
[SecureContext] [SecureContext]
interface TestSecureContextInterfaceThatIncludesNonSecureContextMixin { interface TestSecureContextInterfaceThatIncludesNonSecureContextMixin {
const octet TEST_CONSTANT = 0; const octet TEST_CONSTANT = 0;
@ -301,31 +444,56 @@ def WebIDLTest(parser, harness):
undefined testMethod2(byte foo); undefined testMethod2(byte foo);
}; };
TestSecureContextInterfaceThatIncludesNonSecureContextMixin includes TestNonSecureContextMixin; TestSecureContextInterfaceThatIncludesNonSecureContextMixin includes TestNonSecureContextMixin;
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[0].members), 4, "TestSecureContextInterfaceThatImplementsNonSecureContextInterface should have four members") harness.check(
harness.ok(results[0].getExtendedAttribute("SecureContext"), len(results[0].members),
"Interface should have [SecureContext] extended attribute") 4,
harness.ok(results[0].members[0].getExtendedAttribute("SecureContext"), "TestSecureContextInterfaceThatImplementsNonSecureContextInterface should have four members",
"[SecureContext] should propagate from interface to constant members even when other members are copied from a non-[SecureContext] interface") )
harness.ok(results[0].members[1].getExtendedAttribute("SecureContext") is None, harness.ok(
"Constants copied from non-[SecureContext] mixin should not be [SecureContext]") results[0].getExtendedAttribute("SecureContext"),
harness.ok(results[0].members[2].getExtendedAttribute("SecureContext") is None, "Interface should have [SecureContext] extended attribute",
"Attributes copied from non-[SecureContext] mixin should not be [SecureContext]") )
harness.ok(results[0].members[3].getExtendedAttribute("SecureContext") is None, harness.ok(
"Methods copied from non-[SecureContext] mixin should not be [SecureContext]") results[0].members[0].getExtendedAttribute("SecureContext"),
"[SecureContext] should propagate from interface to constant members even when other members are copied from a non-[SecureContext] interface",
)
harness.ok(
results[0].members[1].getExtendedAttribute("SecureContext") is None,
"Constants copied from non-[SecureContext] mixin should not be [SecureContext]",
)
harness.ok(
results[0].members[2].getExtendedAttribute("SecureContext") is None,
"Attributes copied from non-[SecureContext] mixin should not be [SecureContext]",
)
harness.ok(
results[0].members[3].getExtendedAttribute("SecureContext") is None,
"Methods copied from non-[SecureContext] mixin should not be [SecureContext]",
)
# Test SecureContext and NoInterfaceObject # Test SecureContext and LegacyNoInterfaceObject
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
[NoInterfaceObject, SecureContext] """
interface TestSecureContextNoInterfaceObject { [LegacyNoInterfaceObject, SecureContext]
interface TestSecureContextLegacyNoInterfaceObject {
undefined testSecureMethod(byte foo); undefined testSecureMethod(byte foo);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results[0].members), 1, "TestSecureContextNoInterfaceObject should have only one member") harness.check(
harness.ok(results[0].getExtendedAttribute("SecureContext"), len(results[0].members),
"Interface should have [SecureContext] extended attribute") 1,
harness.ok(results[0].members[0].getExtendedAttribute("SecureContext"), "TestSecureContextLegacyNoInterfaceObject should have only one member",
"Interface member should have [SecureContext] extended attribute") )
harness.ok(
results[0].getExtendedAttribute("SecureContext"),
"Interface should have [SecureContext] extended attribute",
)
harness.ok(
results[0].members[0].getExtendedAttribute("SecureContext"),
"Interface member should have [SecureContext] extended attribute",
)

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch1 { interface SpecialMethodSignatureMismatch1 {
getter long long foo(long index); getter long long foo(long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -15,11 +17,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch2 { interface SpecialMethodSignatureMismatch2 {
getter undefined foo(unsigned long index); getter undefined foo(unsigned long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -29,11 +33,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch3 { interface SpecialMethodSignatureMismatch3 {
getter boolean foo(unsigned long index, boolean extraArg); getter boolean foo(unsigned long index, boolean extraArg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -43,11 +49,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch4 { interface SpecialMethodSignatureMismatch4 {
getter boolean foo(unsigned long... index); getter boolean foo(unsigned long... index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -57,11 +65,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch5 { interface SpecialMethodSignatureMismatch5 {
getter boolean foo(optional unsigned long index); getter boolean foo(optional unsigned long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -71,11 +81,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch6 { interface SpecialMethodSignatureMismatch6 {
getter boolean foo(); getter boolean foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -85,11 +97,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch7 { interface SpecialMethodSignatureMismatch7 {
deleter long long foo(long index); deleter long long foo(long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -99,11 +113,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch9 { interface SpecialMethodSignatureMismatch9 {
deleter boolean foo(unsigned long index, boolean extraArg); deleter boolean foo(unsigned long index, boolean extraArg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -113,11 +129,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch10 { interface SpecialMethodSignatureMismatch10 {
deleter boolean foo(unsigned long... index); deleter boolean foo(unsigned long... index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -127,11 +145,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch11 { interface SpecialMethodSignatureMismatch11 {
deleter boolean foo(optional unsigned long index); deleter boolean foo(optional unsigned long index);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -141,11 +161,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch12 { interface SpecialMethodSignatureMismatch12 {
deleter boolean foo(); deleter boolean foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -155,11 +177,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch13 { interface SpecialMethodSignatureMismatch13 {
setter long long foo(long index, long long value); setter long long foo(long index, long long value);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -169,11 +193,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch15 { interface SpecialMethodSignatureMismatch15 {
setter boolean foo(unsigned long index, boolean value, long long extraArg); setter boolean foo(unsigned long index, boolean value, long long extraArg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -183,11 +209,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch16 { interface SpecialMethodSignatureMismatch16 {
setter boolean foo(unsigned long index, boolean... value); setter boolean foo(unsigned long index, boolean... value);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -197,11 +225,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch17 { interface SpecialMethodSignatureMismatch17 {
setter boolean foo(unsigned long index, optional boolean value); setter boolean foo(unsigned long index, optional boolean value);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -211,11 +241,13 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodSignatureMismatch18 { interface SpecialMethodSignatureMismatch18 {
setter boolean foo(); setter boolean foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,7 +1,9 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface SpecialMethods { interface SpecialMethods {
getter long long (unsigned long index); getter long long (unsigned long index);
setter long long (unsigned long index, long long value); setter long long (unsigned long index, long long value);
@ -14,47 +16,90 @@ def WebIDLTest(parser, harness):
interface SpecialMethodsCombination { interface SpecialMethodsCombination {
getter deleter boolean (DOMString name); getter deleter boolean (DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
def checkMethod(method, QName, name, def checkMethod(
static=False, getter=False, setter=False, method,
deleter=False, legacycaller=False, stringifier=False): QName,
harness.ok(isinstance(method, WebIDL.IDLMethod), name,
"Should be an IDLMethod") static=False,
getter=False,
setter=False,
deleter=False,
legacycaller=False,
stringifier=False,
):
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
harness.check(method.identifier.QName(), QName, "Method has the right QName") harness.check(method.identifier.QName(), QName, "Method has the right QName")
harness.check(method.identifier.name, name, "Method has the right name") harness.check(method.identifier.name, name, "Method has the right name")
harness.check(method.isStatic(), static, "Method has the correct static value") harness.check(method.isStatic(), static, "Method has the correct static value")
harness.check(method.isGetter(), getter, "Method has the correct getter value") harness.check(method.isGetter(), getter, "Method has the correct getter value")
harness.check(method.isSetter(), setter, "Method has the correct setter value") harness.check(method.isSetter(), setter, "Method has the correct setter value")
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value") harness.check(
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value") method.isDeleter(), deleter, "Method has the correct deleter value"
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value") )
harness.check(
method.isLegacycaller(),
legacycaller,
"Method has the correct legacycaller value",
)
harness.check(
method.isStringifier(),
stringifier,
"Method has the correct stringifier value",
)
harness.check(len(results), 2, "Expect 2 interfaces") harness.check(len(results), 2, "Expect 2 interfaces")
iface = results[0] iface = results[0]
harness.check(len(iface.members), 6, "Expect 6 members") harness.check(len(iface.members), 6, "Expect 6 members")
checkMethod(iface.members[0], "::SpecialMethods::__indexedgetter", "__indexedgetter", checkMethod(
getter=True) iface.members[0],
checkMethod(iface.members[1], "::SpecialMethods::__indexedsetter", "__indexedsetter", "::SpecialMethods::__indexedgetter",
setter=True) "__indexedgetter",
checkMethod(iface.members[2], "::SpecialMethods::__namedgetter", "__namedgetter", getter=True,
getter=True) )
checkMethod(iface.members[3], "::SpecialMethods::__namedsetter", "__namedsetter", checkMethod(
setter=True) iface.members[1],
checkMethod(iface.members[4], "::SpecialMethods::__nameddeleter", "__nameddeleter", "::SpecialMethods::__indexedsetter",
deleter=True) "__indexedsetter",
setter=True,
)
checkMethod(
iface.members[2],
"::SpecialMethods::__namedgetter",
"__namedgetter",
getter=True,
)
checkMethod(
iface.members[3],
"::SpecialMethods::__namedsetter",
"__namedsetter",
setter=True,
)
checkMethod(
iface.members[4],
"::SpecialMethods::__nameddeleter",
"__nameddeleter",
deleter=True,
)
iface = results[1] iface = results[1]
harness.check(len(iface.members), 1, "Expect 1 member") harness.check(len(iface.members), 1, "Expect 1 member")
checkMethod(iface.members[0], "::SpecialMethodsCombination::__namedgetterdeleter", checkMethod(
"__namedgetterdeleter", getter=True, deleter=True) iface.members[0],
"::SpecialMethodsCombination::__namedgetterdeleter",
"__namedgetterdeleter",
getter=True,
deleter=True,
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
@ -63,11 +108,10 @@ def WebIDLTest(parser, harness):
interface IndexedDeleter { interface IndexedDeleter {
deleter undefined(unsigned long index); deleter undefined(unsigned long index);
}; };
""") """
)
parser.finish() parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "There are no indexed deleters") harness.ok(threw, "There are no indexed deleters")

View file

@ -1,14 +1,17 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodUniqueness1 { interface SpecialMethodUniqueness1 {
getter deleter boolean (DOMString name); getter deleter boolean (DOMString name);
getter boolean (DOMString name); getter boolean (DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -18,12 +21,14 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodUniqueness1 { interface SpecialMethodUniqueness1 {
deleter boolean (DOMString name); deleter boolean (DOMString name);
getter deleter boolean (DOMString name); getter deleter boolean (DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -33,12 +38,14 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface SpecialMethodUniqueness1 { interface SpecialMethodUniqueness1 {
setter boolean (DOMString name); setter boolean (DOMString name);
setter boolean (DOMString name); setter boolean (DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,27 +1,34 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier; stringifier;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(isinstance(results[0].members[0], WebIDL.IDLMethod), harness.ok(
"Stringifer should be method") isinstance(results[0].members[0], WebIDL.IDLMethod),
"Stringifer should be method",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier; stringifier;
stringifier; stringifier;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -32,12 +39,14 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier; stringifier;
stringifier DOMString foo(); stringifier DOMString foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -45,70 +54,107 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow a 'stringifier;' and a 'stringifier()'") harness.ok(threw, "Should not allow a 'stringifier;' and a 'stringifier()'")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier attribute DOMString foo; stringifier attribute DOMString foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(isinstance(results[0].members[0], WebIDL.IDLAttribute), harness.ok(
"Stringifier attribute should be an attribute") isinstance(results[0].members[0], WebIDL.IDLAttribute),
"Stringifier attribute should be an attribute",
)
stringifier = results[0].members[1] stringifier = results[0].members[1]
harness.ok(isinstance(stringifier, WebIDL.IDLMethod), harness.ok(
"Stringifier attribute should insert a method") isinstance(stringifier, WebIDL.IDLMethod),
harness.ok(stringifier.isStringifier(), "Stringifier attribute should insert a method",
"Inserted method should be a stringifier") )
harness.ok(stringifier.isStringifier(), "Inserted method should be a stringifier")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestStringifier {}; interface TestStringifier {};
interface mixin TestStringifierMixin { interface mixin TestStringifierMixin {
stringifier attribute DOMString foo; stringifier attribute DOMString foo;
}; };
TestStringifier includes TestStringifierMixin; TestStringifier includes TestStringifierMixin;
""") """
)
results = parser.finish() results = parser.finish()
harness.ok(isinstance(results[0].members[0], WebIDL.IDLAttribute), harness.ok(
"Stringifier attribute should be an attribute") isinstance(results[0].members[0], WebIDL.IDLAttribute),
"Stringifier attribute should be an attribute",
)
stringifier = results[0].members[1] stringifier = results[0].members[1]
harness.ok(isinstance(stringifier, WebIDL.IDLMethod), harness.ok(
"Stringifier attribute should insert a method") isinstance(stringifier, WebIDL.IDLMethod),
harness.ok(stringifier.isStringifier(), "Stringifier attribute should insert a method",
"Inserted method should be a stringifier") )
harness.ok(stringifier.isStringifier(), "Inserted method should be a stringifier")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier attribute USVString foo; stringifier attribute USVString foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
stringifier = results[0].members[1] stringifier = results[0].members[1]
harness.ok(stringifier.signatures()[0][0].isUSVString(), harness.ok(
"Stringifier attributes should allow USVString") stringifier.signatures()[0][0].isUSVString(),
"Stringifier attributes should allow USVString",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
[Throws, NeedsSubjectPrincipal] [Throws, NeedsSubjectPrincipal]
stringifier attribute USVString foo; stringifier attribute USVString foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
stringifier = results[0].members[1] stringifier = results[0].members[1]
harness.ok(stringifier.getExtendedAttribute("Throws"), harness.ok(
"Stringifier attributes should support [Throws]") stringifier.getExtendedAttribute("Throws"),
harness.ok(stringifier.getExtendedAttribute("NeedsSubjectPrincipal"), "Stringifier attributes should support [Throws]",
"Stringifier attributes should support [NeedsSubjectPrincipal]") )
harness.ok(
stringifier.getExtendedAttribute("NeedsSubjectPrincipal"),
"Stringifier attributes should support [NeedsSubjectPrincipal]",
)
parser = parser.reset()
parser.parse(
"""
interface TestStringifier {
stringifier attribute UTF8String foo;
};
"""
)
results = parser.finish()
stringifier = results[0].members[1]
harness.ok(
stringifier.signatures()[0][0].isUTF8String(),
"Stringifier attributes should allow UTF8String",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier attribute ByteString foo; stringifier attribute ByteString foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -118,12 +164,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier; stringifier;
stringifier attribute DOMString foo; stringifier attribute DOMString foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -133,12 +181,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface TestStringifier { interface TestStringifier {
stringifier attribute DOMString foo; stringifier attribute DOMString foo;
stringifier attribute DOMString bar; stringifier attribute DOMString bar;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True

View file

@ -6,7 +6,8 @@ def WebIDLTest(parser, harness):
interface Test { interface Test {
object toJSON(); object toJSON();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -21,7 +22,8 @@ def WebIDLTest(parser, harness):
object toJSON(object arg); object toJSON(object arg);
object toJSON(long arg); object toJSON(long arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -35,7 +37,8 @@ def WebIDLTest(parser, harness):
interface Test { interface Test {
object toJSON(object arg); object toJSON(object arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -49,7 +52,8 @@ def WebIDLTest(parser, harness):
interface Test { interface Test {
long toJSON(); long toJSON();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -63,11 +67,14 @@ def WebIDLTest(parser, harness):
interface Test { interface Test {
[Default] object toJSON(); [Default] object toJSON();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(not threw, "Should allow a default toJSON method with 'object' as return type.") harness.ok(
not threw, "Should allow a default toJSON method with 'object' as return type."
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
@ -77,119 +84,226 @@ def WebIDLTest(parser, harness):
interface Test { interface Test {
[Default] long toJSON(); [Default] long toJSON();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should not allow a default toJSON method with non-'object' as return type.") harness.ok(
threw,
"Should not allow a default toJSON method with non-'object' as return type.",
)
JsonTypes = [ "byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", JsonTypes = [
"unsigned long long", "float", "unrestricted float", "double", "unrestricted double", "boolean", "byte",
"DOMString", "ByteString", "UTF8String", "USVString", "Enum", "InterfaceWithToJSON", "object" ] "octet",
"short",
"unsigned short",
"long",
"unsigned long",
"long long",
"unsigned long long",
"float",
"unrestricted float",
"double",
"unrestricted double",
"boolean",
"DOMString",
"ByteString",
"UTF8String",
"USVString",
"Enum",
"InterfaceWithToJSON",
"object",
]
nonJsonTypes = [ "InterfaceWithoutToJSON", "any", "Int8Array", "Int16Array", "Int32Array","Uint8Array", nonJsonTypes = [
"Uint16Array", "Uint32Array", "Uint8ClampedArray", "Float32Array", "Float64Array", "ArrayBuffer" ] "InterfaceWithoutToJSON",
"any",
"Int8Array",
"Int16Array",
"Int32Array",
"Uint8Array",
"Uint16Array",
"Uint32Array",
"Uint8ClampedArray",
"Float32Array",
"Float64Array",
"ArrayBuffer",
]
def doTest(testIDL, shouldThrow, description): def doTest(testIDL, shouldThrow, description):
p = parser.reset() p = parser.reset()
threw = False threw = False
try: try:
p.parse(testIDL + p.parse(
""" testIDL
+ """
enum Enum { "a", "b", "c" }; enum Enum { "a", "b", "c" };
interface InterfaceWithToJSON { long toJSON(); }; interface InterfaceWithToJSON { long toJSON(); };
interface InterfaceWithoutToJSON {}; interface InterfaceWithoutToJSON {};
"""); """
p.finish(); )
p.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(x.message == "toJSON method has non-JSON return type", x) harness.ok(x.message == "toJSON method has non-JSON return type", x)
harness.check(threw, shouldThrow, description) harness.check(threw, shouldThrow, description)
for type in JsonTypes: for type in JsonTypes:
doTest("interface Test { %s toJSON(); };" % type, False, doTest(
"%s should be a JSON type" % type) "interface Test { %s toJSON(); };" % type,
False,
"%s should be a JSON type" % type,
)
doTest("interface Test { sequence<%s> toJSON(); };" % type, False, doTest(
"sequence<%s> should be a JSON type" % type) "interface Test { sequence<%s> toJSON(); };" % type,
False,
"sequence<%s> should be a JSON type" % type,
)
doTest("dictionary Foo { %s foo; }; " doTest(
"interface Test { Foo toJSON(); }; " % type, False, "dictionary Foo { %s foo; }; " "interface Test { Foo toJSON(); }; " % type,
"dictionary containing only JSON type (%s) should be a JSON type" % type) False,
"dictionary containing only JSON type (%s) should be a JSON type" % type,
)
doTest("dictionary Foo { %s foo; }; dictionary Bar : Foo { }; " doTest(
"interface Test { Bar toJSON(); }; " % type, False, "dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
"dictionary whose ancestors only contain JSON types should be a JSON type") "interface Test { Bar toJSON(); }; " % type,
False,
"dictionary whose ancestors only contain JSON types should be a JSON type",
)
doTest("dictionary Foo { any foo; }; dictionary Bar : Foo { %s bar; };" doTest(
"interface Test { Bar toJSON(); };" % type, True, "dictionary Foo { any foo; }; dictionary Bar : Foo { %s bar; };"
"dictionary whose ancestors contain non-JSON types should not be a JSON type") "interface Test { Bar toJSON(); };" % type,
True,
"dictionary whose ancestors contain non-JSON types should not be a JSON type",
)
doTest("interface Test { record<DOMString, %s> toJSON(); };" % type, False, doTest(
"record<DOMString, %s> should be a JSON type" % type) "interface Test { record<DOMString, %s> toJSON(); };" % type,
False,
"record<DOMString, %s> should be a JSON type" % type,
)
doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, False, doTest(
"record<ByteString, %s> should be a JSON type" % type) "interface Test { record<ByteString, %s> toJSON(); };" % type,
False,
"record<ByteString, %s> should be a JSON type" % type,
)
doTest("interface Test { record<UTF8String, %s> toJSON(); };" % type, False, doTest(
"record<UTF8String, %s> should be a JSON type" % type) "interface Test { record<UTF8String, %s> toJSON(); };" % type,
False,
"record<UTF8String, %s> should be a JSON type" % type,
)
doTest("interface Test { record<USVString, %s> toJSON(); };" % type, False, doTest(
"record<USVString, %s> should be a JSON type" % type) "interface Test { record<USVString, %s> toJSON(); };" % type,
False,
"record<USVString, %s> should be a JSON type" % type,
)
otherUnionType = "Foo" if type != "object" else "long" otherUnionType = "Foo" if type != "object" else "long"
doTest("interface Foo { object toJSON(); };" doTest(
"interface Test { (%s or %s) toJSON(); };" % (otherUnionType, type), False, "interface Foo { object toJSON(); };"
"union containing only JSON types (%s or %s) should be a JSON type" %(otherUnionType, type)) "interface Test { (%s or %s) toJSON(); };" % (otherUnionType, type),
False,
"union containing only JSON types (%s or %s) should be a JSON type"
% (otherUnionType, type),
)
doTest("interface test { %s? toJSON(); };" % type, False, doTest(
"Nullable type (%s) should be a JSON type" % type) "interface test { %s? toJSON(); };" % type,
False,
"Nullable type (%s) should be a JSON type" % type,
)
doTest("interface Foo : InterfaceWithoutToJSON { %s toJSON(); };" doTest(
"interface Test { Foo toJSON(); };" % type, False, "interface Foo : InterfaceWithoutToJSON { %s toJSON(); };"
"interface with toJSON should be a JSON type") "interface Test { Foo toJSON(); };" % type,
False,
"interface with toJSON should be a JSON type",
)
doTest("interface Foo : InterfaceWithToJSON { };" doTest(
"interface Test { Foo toJSON(); };", False, "interface Foo : InterfaceWithToJSON { };" "interface Test { Foo toJSON(); };",
"inherited interface with toJSON should be a JSON type") False,
"inherited interface with toJSON should be a JSON type",
)
for type in nonJsonTypes: for type in nonJsonTypes:
doTest("interface Test { %s toJSON(); };" % type, True, doTest(
"%s should not be a JSON type" % type) "interface Test { %s toJSON(); };" % type,
True,
"%s should not be a JSON type" % type,
)
doTest("interface Test { sequence<%s> toJSON(); };" % type, True, doTest(
"sequence<%s> should not be a JSON type" % type) "interface Test { sequence<%s> toJSON(); };" % type,
True,
"sequence<%s> should not be a JSON type" % type,
)
doTest("dictionary Foo { %s foo; }; " doTest(
"interface Test { Foo toJSON(); }; " % type, True, "dictionary Foo { %s foo; }; " "interface Test { Foo toJSON(); }; " % type,
"Dictionary containing a non-JSON type (%s) should not be a JSON type" % type) True,
"Dictionary containing a non-JSON type (%s) should not be a JSON type"
% type,
)
doTest("dictionary Foo { %s foo; }; dictionary Bar : Foo { }; " doTest(
"interface Test { Bar toJSON(); }; " % type, True, "dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
"dictionary whose ancestors only contain non-JSON types should not be a JSON type") "interface Test { Bar toJSON(); }; " % type,
True,
"dictionary whose ancestors only contain non-JSON types should not be a JSON type",
)
doTest("interface Test { record<DOMString, %s> toJSON(); };" % type, True, doTest(
"record<DOMString, %s> should not be a JSON type" % type) "interface Test { record<DOMString, %s> toJSON(); };" % type,
True,
"record<DOMString, %s> should not be a JSON type" % type,
)
doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, True, doTest(
"record<ByteString, %s> should not be a JSON type" % type) "interface Test { record<ByteString, %s> toJSON(); };" % type,
True,
"record<ByteString, %s> should not be a JSON type" % type,
)
doTest("interface Test { record<USVString, %s> toJSON(); };" % type, True, doTest(
"record<USVString, %s> should not be a JSON type" % type) "interface Test { record<USVString, %s> toJSON(); };" % type,
True,
"record<USVString, %s> should not be a JSON type" % type,
)
if type != "any": if type != "any":
doTest("interface Foo { object toJSON(); }; " doTest(
"interface Test { (Foo or %s) toJSON(); };" % type, True, "interface Foo { object toJSON(); }; "
"union containing a non-JSON type (%s) should not be a JSON type" % type) "interface Test { (Foo or %s) toJSON(); };" % type,
True,
"union containing a non-JSON type (%s) should not be a JSON type"
% type,
)
doTest("interface test { %s? toJSON(); };" % type, True, doTest(
"Nullable type (%s) should not be a JSON type" % type) "interface test { %s? toJSON(); };" % type,
True,
"Nullable type (%s) should not be a JSON type" % type,
)
doTest("dictionary Foo { long foo; any bar; };" doTest(
"interface Test { Foo toJSON(); };", True, "dictionary Foo { long foo; any bar; };" "interface Test { Foo toJSON(); };",
"dictionary containing a non-JSON type should not be a JSON type") True,
"dictionary containing a non-JSON type should not be a JSON type",
)
doTest("interface Foo : InterfaceWithoutToJSON { }; " doTest(
"interface Test { Foo toJSON(); };", True, "interface Foo : InterfaceWithoutToJSON { }; "
"interface without toJSON should not be a JSON type") "interface Test { Foo toJSON(); };",
True,
"interface without toJSON should not be a JSON type",
)

View file

@ -1,14 +1,17 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
[TreatNonCallableAsNull] callback Function = any(any... arguments); [TreatNonCallableAsNull] callback Function = any(any... arguments);
interface TestTreatNonCallableAsNull1 { interface TestTreatNonCallableAsNull1 {
attribute Function? onfoo; attribute Function? onfoo;
attribute Function onbar; attribute Function onbar;
}; };
""") """
)
results = parser.finish() results = parser.finish()
@ -22,13 +25,15 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
callback Function = any(any... arguments); callback Function = any(any... arguments);
interface TestTreatNonCallableAsNull2 { interface TestTreatNonCallableAsNull2 {
[TreatNonCallableAsNull] attribute Function onfoo; [TreatNonCallableAsNull] attribute Function onfoo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -40,14 +45,16 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
callback Function = any(any... arguments); callback Function = any(any... arguments);
[TreatNonCallableAsNull] [TreatNonCallableAsNull]
interface TestTreatNonCallableAsNull3 { interface TestTreatNonCallableAsNull3 {
attribute Function onfoo; attribute Function onfoo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
@ -59,10 +66,12 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
[TreatNonCallableAsNull, TreatNonObjectAsNull] """
[TreatNonCallableAsNull, LegacyTreatNonObjectAsNull]
callback Function = any(any... arguments); callback Function = any(any... arguments);
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,5 +1,6 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
typedef long mylong; typedef long mylong;
typedef long? mynullablelong; typedef long? mynullablelong;
interface Foo { interface Foo {
@ -8,22 +9,28 @@ def WebIDLTest(parser, harness):
undefined bar(optional mynullablelong arg = null); undefined bar(optional mynullablelong arg = null);
undefined baz(mylong arg); undefined baz(mylong arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(results[2].members[1].signatures()[0][1][0].type.name, "LongOrNull", harness.check(
"Should expand typedefs") results[2].members[1].signatures()[0][1][0].type.name,
"LongOrNull",
"Should expand typedefs",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef long? mynullablelong; typedef long? mynullablelong;
interface Foo { interface Foo {
undefined foo(mynullablelong? Y); undefined foo(mynullablelong? Y);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -33,12 +40,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
typedef long? mynullablelong; typedef long? mynullablelong;
interface Foo { interface Foo {
const mynullablelong? X = 5; const mynullablelong? X = 5;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
@ -48,29 +57,38 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
const mynullablelong? X = 5; const mynullablelong? X = 5;
}; };
typedef long? mynullablelong; typedef long? mynullablelong;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown on nullable inside nullable const typedef " threw,
"after interface.") "Should have thrown on nullable inside nullable const typedef "
"after interface.",
)
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Foo { interface Foo {
const mylong X = 5; const mylong X = 5;
}; };
typedef long mylong; typedef long mylong;
""") """
)
results = parser.finish() results = parser.finish()
harness.check(results[0].members[0].type.name, "Long", harness.check(
"Should expand typedefs that come before interface") results[0].members[0].type.name,
"Long",
"Should expand typedefs that come before interface",
)

View file

@ -5,12 +5,15 @@ def WebIDLTest(parser, harness):
""" """
typedef long foo; typedef long foo;
typedef long foo; typedef long foo;
""") """
)
results = parser.finish() results = parser.finish()
except Exception as e: except Exception as e:
exception = e exception = e
harness.ok(exception, "Should have thrown.") harness.ok(exception, "Should have thrown.")
harness.ok("Multiple unresolvable definitions of identifier 'foo'" in str(exception), harness.ok(
"Should have a sane exception message") "Multiple unresolvable definitions of identifier 'foo'" in str(exception),
"Should have a sane exception message",
)

View file

@ -0,0 +1,246 @@
import WebIDL
def WebIDLTest(parser, harness):
try:
parser.parse(
"""
dictionary Dict {
undefined undefinedMember;
double bar;
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(threw, "undefined must not be used as the type of a dictionary member")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
dictionary Dict {
(undefined or double) undefinedMemberOfUnionInDict;
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of a dictionary member, "
"whether directly or in a union",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
double bar(undefined foo);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a regular operation)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
getter double(undefined name);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a getter)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
setter undefined(DOMString name, undefined value);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a setter)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
deleter undefined (undefined name);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a deleter)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
constructor (undefined foo);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a constructor)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
callback Callback = undefined (undefined foo);
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a callback)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
async iterable(undefined name);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of an async iterable "
"iterator)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
static double bar(undefined foo);
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined must not be used as the type of an argument in any "
"circumstance (so not as the argument of a static operation)",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
const undefined FOO = undefined;
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined is not a valid type for a constant",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
const any FOO = undefined;
};
"""
)
results = parser.finish()
except:
threw = True
harness.ok(
threw,
"undefined is not a valid value for a constant",
)

View file

@ -10,18 +10,21 @@ def WebIDLTest(parser, harness):
interface Baz : Bar { interface Baz : Bar {
getter long(DOMString name); getter long(DOMString name);
}; };
"""); """
results = parser.finish(); )
results = parser.finish()
harness.check(len(results), 3, "Should have three interfaces") harness.check(len(results), 3, "Should have three interfaces")
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[LegacyUnenumerableNamedProperties] [LegacyUnenumerableNamedProperties]
interface NoNamedGetter { interface NoNamedGetter {
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -31,12 +34,14 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[LegacyUnenumerableNamedProperties=Foo] [LegacyUnenumerableNamedProperties=Foo]
interface ShouldNotHaveArg { interface ShouldNotHaveArg {
getter long(DOMString name); getter long(DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
@ -46,7 +51,8 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
[LegacyUnenumerableNamedProperties] [LegacyUnenumerableNamedProperties]
interface Foo { interface Foo {
getter long(DOMString name); getter long(DOMString name);
@ -56,7 +62,8 @@ def WebIDLTest(parser, harness):
interface Baz : Bar { interface Baz : Bar {
getter long(DOMString name); getter long(DOMString name);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:

View file

@ -1,253 +1,311 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
}; };
interface Parent { interface Parent {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, harness.check(
"Should be able to inherit from an interface with " len(results),
"[Unforgeable] properties.") 2,
"Should be able to inherit from an interface with "
"[LegacyUnforgeable] properties.",
)
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
const short foo = 10; const short foo = 10;
}; };
interface Parent { interface Parent {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, harness.check(
"Should be able to inherit from an interface with " len(results),
"[Unforgeable] properties even if we have a constant with " 2,
"the same name.") "Should be able to inherit from an interface with "
"[LegacyUnforgeable] properties even if we have a constant with "
"the same name.",
)
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
static attribute short foo; static attribute short foo;
}; };
interface Parent { interface Parent {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, harness.check(
"Should be able to inherit from an interface with " len(results),
"[Unforgeable] properties even if we have a static attribute " 2,
"with the same name.") "Should be able to inherit from an interface with "
"[LegacyUnforgeable] properties even if we have a static attribute "
"with the same name.",
)
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
static undefined foo(); static undefined foo();
}; };
interface Parent { interface Parent {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 2, harness.check(
"Should be able to inherit from an interface with " len(results),
"[Unforgeable] properties even if we have a static operation " 2,
"with the same name.") "Should be able to inherit from an interface with "
"[LegacyUnforgeable] properties even if we have a static operation "
"with the same name.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
undefined foo(); undefined foo();
}; };
interface Parent { interface Parent {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when shadowing unforgeable attribute on " threw,
"parent with operation.") "Should have thrown when shadowing unforgeable attribute on "
"parent with operation.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
undefined foo(); undefined foo();
}; };
interface Parent { interface Parent {
[Unforgeable] undefined foo(); [LegacyUnforgeable] undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when shadowing unforgeable operation on " threw,
"parent with operation.") "Should have thrown when shadowing unforgeable operation on "
"parent with operation.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
attribute short foo; attribute short foo;
}; };
interface Parent { interface Parent {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when shadowing unforgeable attribute on " threw,
"parent with attribute.") "Should have thrown when shadowing unforgeable attribute on "
"parent with attribute.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
attribute short foo; attribute short foo;
}; };
interface Parent { interface Parent {
[Unforgeable] undefined foo(); [LegacyUnforgeable] undefined foo();
}; };
""") """
)
results = parser.finish() results = parser.finish()
except Exception as x: except Exception as x:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when shadowing unforgeable operation on " threw,
"parent with attribute.") "Should have thrown when shadowing unforgeable operation on "
"parent with attribute.",
)
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
}; };
interface Parent {}; interface Parent {};
interface mixin Mixin { interface mixin Mixin {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
Parent includes Mixin; Parent includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 4, harness.check(
"Should be able to inherit from an interface with a " len(results),
"mixin with [Unforgeable] properties.") 4,
"Should be able to inherit from an interface with a "
"mixin with [LegacyUnforgeable] properties.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
undefined foo(); undefined foo();
}; };
interface Parent {}; interface Parent {};
interface mixin Mixin { interface mixin Mixin {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
Parent includes Mixin; Parent includes Mixin;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when shadowing unforgeable attribute " threw,
"of parent's consequential interface.") "Should have thrown when shadowing unforgeable attribute "
"of parent's consequential interface.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
}; };
interface Parent : GrandParent {}; interface Parent : GrandParent {};
interface GrandParent {}; interface GrandParent {};
interface mixin Mixin { interface mixin Mixin {
[Unforgeable] readonly attribute long foo; [LegacyUnforgeable] readonly attribute long foo;
}; };
GrandParent includes Mixin; GrandParent includes Mixin;
interface mixin ChildMixin { interface mixin ChildMixin {
undefined foo(); undefined foo();
}; };
Child includes ChildMixin; Child includes ChildMixin;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when our consequential interface shadows unforgeable attribute " threw,
"of ancestor's consequential interface.") "Should have thrown when our consequential interface shadows unforgeable attribute "
"of ancestor's consequential interface.",
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface Child : Parent { interface Child : Parent {
}; };
interface Parent : GrandParent {}; interface Parent : GrandParent {};
interface GrandParent {}; interface GrandParent {};
interface mixin Mixin { interface mixin Mixin {
[Unforgeable] undefined foo(); [LegacyUnforgeable] undefined foo();
}; };
GrandParent includes Mixin; GrandParent includes Mixin;
interface mixin ChildMixin { interface mixin ChildMixin {
undefined foo(); undefined foo();
}; };
Child includes ChildMixin; Child includes ChildMixin;
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown when our consequential interface shadows unforgeable operation " threw,
"of ancestor's consequential interface.") "Should have thrown when our consequential interface shadows unforgeable operation "
"of ancestor's consequential interface.",
)
parser = parser.reset(); parser = parser.reset()
parser.parse(""" parser.parse(
"""
interface iface { interface iface {
[Unforgeable] attribute long foo; [LegacyUnforgeable] attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
harness.check(len(results), 1, harness.check(
"Should allow writable [Unforgeable] attribute.") len(results), 1, "Should allow writable [LegacyUnforgeable] attribute."
)
parser = parser.reset(); parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface iface { interface iface {
[Unforgeable] static readonly attribute long foo; [LegacyUnforgeable] static readonly attribute long foo;
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, "Should have thrown for static [Unforgeable] attribute.") harness.ok(threw, "Should have thrown for static [LegacyUnforgeable] attribute.")

View file

@ -3,12 +3,15 @@ import itertools
import string import string
# We'd like to use itertools.chain but it's 2.6 or higher. # We'd like to use itertools.chain but it's 2.6 or higher.
def chain(*iterables): def chain(*iterables):
# chain('ABC', 'DEF') --> A B C D E F # chain('ABC', 'DEF') --> A B C D E F
for it in iterables: for it in iterables:
for element in it: for element in it:
yield element yield element
# We'd like to use itertools.combinations but it's 2.6 or higher. # We'd like to use itertools.combinations but it's 2.6 or higher.
def combinations(iterable, r): def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD # combinations('ABCD', 2) --> AB AC AD BC BD CD
@ -26,10 +29,11 @@ def combinations(iterable, r):
else: else:
return return
indices[i] += 1 indices[i] += 1
for j in range(i+1, r): for j in range(i + 1, r):
indices[j] = indices[j-1] + 1 indices[j] = indices[j - 1] + 1
yield tuple(pool[i] for i in indices) yield tuple(pool[i] for i in indices)
# We'd like to use itertools.combinations_with_replacement but it's 2.7 or # We'd like to use itertools.combinations_with_replacement but it's 2.7 or
# higher. # higher.
def combinations_with_replacement(iterable, r): def combinations_with_replacement(iterable, r):
@ -49,27 +53,30 @@ def combinations_with_replacement(iterable, r):
indices[i:] = [indices[i] + 1] * (r - i) indices[i:] = [indices[i] + 1] * (r - i)
yield tuple(pool[i] for i in indices) yield tuple(pool[i] for i in indices)
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
types = ["float", types = [
"double", "float",
"short", "double",
"unsigned short", "short",
"long", "unsigned short",
"unsigned long", "long",
"long long", "unsigned long",
"unsigned long long", "long long",
"boolean", "unsigned long long",
"byte", "boolean",
"octet", "byte",
"DOMString", "octet",
"ByteString", "DOMString",
"USVString", "ByteString",
#"sequence<float>", "USVString",
"object", # "sequence<float>",
"ArrayBuffer", "object",
#"Date", "ArrayBuffer",
"TestInterface1", # "Date",
"TestInterface2"] "TestInterface1",
"TestInterface2",
]
testPre = """ testPre = """
interface TestInterface1 { interface TestInterface1 {
@ -78,13 +85,18 @@ def WebIDLTest(parser, harness):
}; };
""" """
interface = testPre + """ interface = (
testPre
+ """
interface PrepareForTest { interface PrepareForTest {
""" """
)
for (i, type) in enumerate(types): for (i, type) in enumerate(types):
interface += string.Template(""" interface += string.Template(
"""
readonly attribute ${type} attr${i}; readonly attribute ${type} attr${i};
""").substitute(i=i, type=type) """
).substitute(i=i, type=type)
interface += """ interface += """
}; };
""" """
@ -98,8 +110,10 @@ def WebIDLTest(parser, harness):
def typesAreDistinguishable(t): def typesAreDistinguishable(t):
return all(u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2)) return all(u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2))
def typesAreNotDistinguishable(t): def typesAreNotDistinguishable(t):
return any(not u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2)) return any(not u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2))
def unionTypeName(t): def unionTypeName(t):
if len(t) > 2: if len(t) > 2:
t[0:2] = [unionTypeName(t[0:2])] t[0:2] = [unionTypeName(t[0:2])]
@ -118,29 +132,40 @@ def WebIDLTest(parser, harness):
# as a string and the parsed IDL type. # as a string and the parsed IDL type.
def invalidUnionWithUnion(typeCombinations): def invalidUnionWithUnion(typeCombinations):
for c in typeCombinations: for c in typeCombinations:
if (typesAreNotDistinguishable((c[0][1], c[1][1])) and if (
typesAreDistinguishable((c[1][1], c[2][1])) and typesAreNotDistinguishable((c[0][1], c[1][1]))
typesAreDistinguishable((c[0][1], c[2][1]))): and typesAreDistinguishable((c[1][1], c[2][1]))
and typesAreDistinguishable((c[0][1], c[2][1]))
):
yield unionTypeName([t[0] for t in c]) yield unionTypeName([t[0] for t in c])
# Create a list of tuples containing the name of the type as a string and # Create a list of tuples containing the name of the type as a string and
# the parsed IDL type. # the parsed IDL type.
types = zip(types, (a.type for a in iface.members)) types = zip(types, (a.type for a in iface.members))
validUnionTypes = chain(unionTypes(combinations(types, 2), typesAreDistinguishable), validUnionTypes = chain(
unionTypes(combinations(types, 3), typesAreDistinguishable)) unionTypes(combinations(types, 2), typesAreDistinguishable),
invalidUnionTypes = chain(unionTypes(combinations_with_replacement(types, 2), typesAreNotDistinguishable), unionTypes(combinations(types, 3), typesAreDistinguishable),
invalidUnionWithUnion(combinations(types, 3))) )
interface = testPre + """ invalidUnionTypes = chain(
unionTypes(combinations_with_replacement(types, 2), typesAreNotDistinguishable),
invalidUnionWithUnion(combinations(types, 3)),
)
interface = (
testPre
+ """
interface TestUnion { interface TestUnion {
""" """
)
for (i, type) in enumerate(validUnionTypes): for (i, type) in enumerate(validUnionTypes):
interface += string.Template(""" interface += string.Template(
"""
undefined method${i}(${type} arg); undefined method${i}(${type} arg);
${type} returnMethod${i}(); ${type} returnMethod${i}();
attribute ${type} attr${i}; attribute ${type} attr${i};
undefined optionalMethod${i}(${type}? arg); undefined optionalMethod${i}(${type}? arg);
""").substitute(i=i, type=type) """
).substitute(i=i, type=type)
interface += """ interface += """
}; };
""" """
@ -150,11 +175,16 @@ def WebIDLTest(parser, harness):
parser = parser.reset() parser = parser.reset()
for invalid in invalidUnionTypes: for invalid in invalidUnionTypes:
interface = testPre + string.Template(""" interface = (
testPre
+ string.Template(
"""
interface TestUnion { interface TestUnion {
undefined method(${type} arg); undefined method(${type} arg);
}; };
""").substitute(type=invalid) """
).substitute(type=invalid)
)
threw = False threw = False
try: try:

View file

@ -1,11 +1,13 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface AnyNotInUnion { interface AnyNotInUnion {
undefined foo((any or DOMString) arg); undefined foo((any or DOMString) arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:

View file

@ -1,53 +1,60 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface OneNullableInUnion { interface OneNullableInUnion {
undefined foo((object? or DOMString?) arg); undefined foo((object? or DOMString?) arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(threw, "Two nullable member types of a union should have thrown.")
"Two nullable member types of a union should have thrown.")
parser.reset() parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface NullableInNullableUnion { interface NullableInNullableUnion {
undefined foo((object? or DOMString)? arg); undefined foo((object? or DOMString)? arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"A nullable union type with a nullable member type should have " threw,
"thrown.") "A nullable union type with a nullable member type should have " "thrown.",
)
parser.reset() parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface NullableInUnionNullableUnionHelper { interface NullableInUnionNullableUnionHelper {
}; };
interface NullableInUnionNullableUnion { interface NullableInUnionNullableUnion {
undefined foo(((object? or DOMString) or NullableInUnionNullableUnionHelper)? arg); undefined foo(((object? or DOMString) or NullableInUnionNullableUnionHelper)? arg);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"A nullable union type with a nullable member type should have " threw,
"thrown.") "A nullable union type with a nullable member type should have " "thrown.",
)

View file

@ -2,23 +2,27 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
interface TestUSVString { interface TestUSVString {
attribute USVString svs; attribute USVString svs;
}; };
""") """
)
results = parser.finish(); results = parser.finish()
harness.check(len(results), 1, "Should be one production") harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface), harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
"Should be an IDLInterface")
iface = results[0] iface = results[0]
harness.check(iface.identifier.QName(), "::TestUSVString", harness.check(
"Interface has the right QName") iface.identifier.QName(), "::TestUSVString", "Interface has the right QName"
harness.check(iface.identifier.name, "TestUSVString", )
"Interface has the right name") harness.check(
iface.identifier.name, "TestUSVString", "Interface has the right name"
)
harness.check(iface.parent, None, "Interface has no parent") harness.check(iface.parent, None, "Interface has no parent")
members = iface.members members = iface.members
@ -26,11 +30,11 @@ def WebIDLTest(parser, harness):
attr = members[0] attr = members[0]
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute") harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
harness.check(attr.identifier.QName(), "::TestUSVString::svs", harness.check(
"Attr has correct QName") attr.identifier.QName(), "::TestUSVString::svs", "Attr has correct QName"
)
harness.check(attr.identifier.name, "svs", "Attr has correct name") harness.check(attr.identifier.name, "svs", "Attr has correct name")
harness.check(str(attr.type), "USVString", harness.check(str(attr.type), "USVString", "Attr type is the correct name")
"Attr type is the correct name")
harness.ok(attr.type.isUSVString(), "Should be USVString type") harness.ok(attr.type.isUSVString(), "Should be USVString type")
harness.ok(attr.type.isString(), "Should be String collective type") harness.ok(attr.type.isString(), "Should be String collective type")
harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type") harness.ok(not attr.type.isDOMString(), "Should be not be DOMString type")

View file

@ -1,9 +1,12 @@
import WebIDL import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse(
"""
callback TestVariadicCallback = any(any... arguments); callback TestVariadicCallback = any(any... arguments);
""") """
)
results = parser.finish() results = parser.finish()

View file

@ -1,61 +1,72 @@
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface VariadicConstraints1 { interface VariadicConstraints1 {
undefined foo(byte... arg1, byte arg2); undefined foo(byte... arg1, byte arg2);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown on variadic argument followed by required " threw,
"argument.") "Should have thrown on variadic argument followed by required " "argument.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface VariadicConstraints2 { interface VariadicConstraints2 {
undefined foo(byte... arg1, optional byte arg2); undefined foo(byte... arg1, optional byte arg2);
}; };
""") """
results = parser.finish(); )
results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown on variadic argument followed by optional " threw,
"argument.") "Should have thrown on variadic argument followed by optional " "argument.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface VariadicConstraints3 { interface VariadicConstraints3 {
undefined foo(optional byte... arg1); undefined foo(optional byte... arg1);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True
harness.ok(threw, harness.ok(
"Should have thrown on variadic argument explicitly flagged as " threw,
"optional.") "Should have thrown on variadic argument explicitly flagged as " "optional.",
)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
parser.parse(""" parser.parse(
"""
interface VariadicConstraints4 { interface VariadicConstraints4 {
undefined foo(byte... arg1 = 0); undefined foo(byte... arg1 = 0);
}; };
""") """
)
results = parser.finish() results = parser.finish()
except: except:
threw = True threw = True

View file

@ -4,6 +4,7 @@ patch < debug.patch
patch < callback-location.patch patch < callback-location.patch
patch < union-typedef.patch patch < union-typedef.patch
patch < inline.patch patch < inline.patch
patch < readable-stream.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.zip/dom/bindings/parser/tests/ -O tests.zip wget https://hg.mozilla.org/mozilla-central/archive/tip.zip/dom/bindings/parser/tests/ -O tests.zip
rm -r tests rm -r tests

View file

@ -0,0 +1,40 @@
January 31, 2017
Announcing : PLY-3.10 (Python Lex-Yacc)
http://www.dabeaz.com/ply
I'm pleased to announce PLY-3.10--a pure Python implementation of the
common parsing tools lex and yacc. PLY-3.10 is a minor bug fix
release. It supports both Python 2 and Python 3.
If you are new to PLY, here are a few highlights:
- PLY is closely modeled after traditional lex/yacc. If you know how
to use these or similar tools in other languages, you will find
PLY to be comparable.
- PLY provides very extensive error reporting and diagnostic
information to assist in parser construction. The original
implementation was developed for instructional purposes. As
a result, the system tries to identify the most common types
of errors made by novice users.
- PLY provides full support for empty productions, error recovery,
precedence rules, and ambiguous grammars.
- Parsing is based on LR-parsing which is fast, memory efficient,
better suited to large grammars, and which has a number of nice
properties when dealing with syntax errors and other parsing
problems. Currently, PLY can build its parsing tables using
either SLR or LALR(1) algorithms.
More information about PLY can be obtained on the PLY webpage at:
http://www.dabeaz.com/ply
PLY is freely available.
Cheers,
David Beazley (http://www.dabeaz.com)

File diff suppressed because it is too large Load diff

View file

@ -1,28 +0,0 @@
Copyright (C) 2001-2009,
David M. Beazley (Dabeaz LLC)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the David Beazley or Dabeaz LLC may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,8 @@
recursive-include example *
recursive-include doc *
recursive-include test *
include ANNOUNCE
include README.md
include CHANGES
include TODO
global-exclude *.pyc

View file

@ -0,0 +1,22 @@
Metadata-Version: 1.1
Name: ply
Version: 3.10
Summary: Python Lex & Yacc
Home-page: http://www.dabeaz.com/ply/
Author: David Beazley
Author-email: dave@dabeaz.com
License: BSD
Description:
PLY is yet another implementation of lex and yacc for Python. Some notable
features include the fact that its implemented entirely in Python and it
uses LALR(1) parsing which is efficient and well suited for larger grammars.
PLY provides most of the standard lex/yacc features including support for empty
productions, precedence rules, error recovery, and support for ambiguous grammars.
PLY is extremely easy to use and provides very extensive error checking.
It is compatible with both Python 2 and Python 3.
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2

View file

@ -1,9 +0,0 @@
David Beazley's PLY (Python Lex-Yacc)
http://www.dabeaz.com/ply/
Licensed under BSD.
This directory contains just the code and license from PLY version 4.0;
the full distribution (see the URL) also contains examples, tests,
documentation, and a longer README.

View file

@ -0,0 +1,273 @@
PLY (Python Lex-Yacc) Version 3.10
Copyright (C) 2001-2017
David M. Beazley (Dabeaz LLC)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the David Beazley or Dabeaz LLC may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Introduction
============
PLY is a 100% Python implementation of the common parsing tools lex
and yacc. Here are a few highlights:
- PLY is very closely modeled after traditional lex/yacc.
If you know how to use these tools in C, you will find PLY
to be similar.
- PLY provides *very* extensive error reporting and diagnostic
information to assist in parser construction. The original
implementation was developed for instructional purposes. As
a result, the system tries to identify the most common types
of errors made by novice users.
- PLY provides full support for empty productions, error recovery,
precedence specifiers, and moderately ambiguous grammars.
- Parsing is based on LR-parsing which is fast, memory efficient,
better suited to large grammars, and which has a number of nice
properties when dealing with syntax errors and other parsing problems.
Currently, PLY builds its parsing tables using the LALR(1)
algorithm used in yacc.
- PLY uses Python introspection features to build lexers and parsers.
This greatly simplifies the task of parser construction since it reduces
the number of files and eliminates the need to run a separate lex/yacc
tool before running your program.
- PLY can be used to build parsers for "real" programming languages.
Although it is not ultra-fast due to its Python implementation,
PLY can be used to parse grammars consisting of several hundred
rules (as might be found for a language like C). The lexer and LR
parser are also reasonably efficient when parsing typically
sized programs. People have used PLY to build parsers for
C, C++, ADA, and other real programming languages.
How to Use
==========
PLY consists of two files : lex.py and yacc.py. These are contained
within the 'ply' directory which may also be used as a Python package.
To use PLY, simply copy the 'ply' directory to your project and import
lex and yacc from the associated 'ply' package. For example:
import ply.lex as lex
import ply.yacc as yacc
Alternatively, you can copy just the files lex.py and yacc.py
individually and use them as modules. For example:
import lex
import yacc
The file setup.py can be used to install ply using distutils.
The file doc/ply.html contains complete documentation on how to use
the system.
The example directory contains several different examples including a
PLY specification for ANSI C as given in K&R 2nd Ed.
A simple example is found at the end of this document
Requirements
============
PLY requires the use of Python 2.6 or greater. However, you should
use the latest Python release if possible. It should work on just
about any platform. PLY has been tested with both CPython and Jython.
It also seems to work with IronPython.
Resources
=========
More information about PLY can be obtained on the PLY webpage at:
http://www.dabeaz.com/ply
For a detailed overview of parsing theory, consult the excellent
book "Compilers : Principles, Techniques, and Tools" by Aho, Sethi, and
Ullman. The topics found in "Lex & Yacc" by Levine, Mason, and Brown
may also be useful.
The GitHub page for PLY can be found at:
https://github.com/dabeaz/ply
An old and relatively inactive discussion group for PLY is found at:
http://groups.google.com/group/ply-hack
Acknowledgments
===============
A special thanks is in order for all of the students in CS326 who
suffered through about 25 different versions of these tools :-).
The CHANGES file acknowledges those who have contributed patches.
Elias Ioup did the first implementation of LALR(1) parsing in PLY-1.x.
Andrew Waters and Markus Schoepflin were instrumental in reporting bugs
and testing a revised LALR(1) implementation for PLY-2.0.
Special Note for PLY-3.0
========================
PLY-3.0 the first PLY release to support Python 3. However, backwards
compatibility with Python 2.6 is still preserved. PLY provides dual
Python 2/3 compatibility by restricting its implementation to a common
subset of basic language features. You should not convert PLY using
2to3--it is not necessary and may in fact break the implementation.
Example
=======
Here is a simple example showing a PLY implementation of a calculator
with variables.
# -----------------------------------------------------------------------------
# calc.py
#
# A simple calculator with variables.
# -----------------------------------------------------------------------------
tokens = (
'NAME','NUMBER',
'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
'LPAREN','RPAREN',
)
# Tokens
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_EQUALS = r'='
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
def t_NUMBER(t):
r'\d+'
t.value = int(t.value)
return t
# Ignored characters
t_ignore = " \t"
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
# Build the lexer
import ply.lex as lex
lex.lex()
# Precedence rules for the arithmetic operators
precedence = (
('left','PLUS','MINUS'),
('left','TIMES','DIVIDE'),
('right','UMINUS'),
)
# dictionary of names (for storing variables)
names = { }
def p_statement_assign(p):
'statement : NAME EQUALS expression'
names[p[1]] = p[3]
def p_statement_expr(p):
'statement : expression'
print(p[1])
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
if p[2] == '+' : p[0] = p[1] + p[3]
elif p[2] == '-': p[0] = p[1] - p[3]
elif p[2] == '*': p[0] = p[1] * p[3]
elif p[2] == '/': p[0] = p[1] / p[3]
def p_expression_uminus(p):
'expression : MINUS expression %prec UMINUS'
p[0] = -p[2]
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_expression_number(p):
'expression : NUMBER'
p[0] = p[1]
def p_expression_name(p):
'expression : NAME'
try:
p[0] = names[p[1]]
except LookupError:
print("Undefined name '%s'" % p[1])
p[0] = 0
def p_error(p):
print("Syntax error at '%s'" % p.value)
import ply.yacc as yacc
yacc.yacc()
while True:
try:
s = raw_input('calc > ') # use input() on Python 3
except EOFError:
break
yacc.parse(s)
Bug Reports and Patches
=======================
My goal with PLY is to simply have a decent lex/yacc implementation
for Python. As a general rule, I don't spend huge amounts of time
working on it unless I receive very specific bug reports and/or
patches to fix problems. I also try to incorporate submitted feature
requests and enhancements into each new version. Please visit the PLY
github page at https://github.com/dabeaz/ply to submit issues and pull
requests. To contact me about bugs and/or new features, please send
email to dave@dabeaz.com.
-- Dave

View file

@ -0,0 +1,16 @@
The PLY to-do list:
1. Finish writing the C Preprocessor module. Started in the
file ply/cpp.py
2. Create and document libraries of useful tokens.
3. Expand the examples/yply tool that parses bison/yacc
files.
4. Think of various diabolical things to do with the
new yacc internals. For example, it is now possible
to specify grammrs using completely different schemes
than the reflection approach used by PLY.

View file

@ -0,0 +1,79 @@
Inspired by a September 14, 2006 Salon article "Why Johnny Can't Code" by
David Brin (http://www.salon.com/tech/feature/2006/09/14/basic/index.html),
I thought that a fully working BASIC interpreter might be an interesting,
if not questionable, PLY example. Uh, okay, so maybe it's just a bad idea,
but in any case, here it is.
In this example, you'll find a rough implementation of 1964 Dartmouth BASIC
as described in the manual at:
http://www.bitsavers.org/pdf/dartmouth/BASIC_Oct64.pdf
See also:
http://en.wikipedia.org/wiki/Dartmouth_BASIC
This dialect is downright primitive---there are no string variables
and no facilities for interactive input. Moreover, subroutines and functions
are brain-dead even more than they usually are for BASIC. Of course,
the GOTO statement is provided.
Nevertheless, there are a few interesting aspects of this example:
- It illustrates a fully working interpreter including lexing, parsing,
and interpretation of instructions.
- The parser shows how to catch and report various kinds of parsing
errors in a more graceful way.
- The example both parses files (supplied on command line) and
interactive input entered line by line.
- It shows how you might represent parsed information. In this case,
each BASIC statement is encoded into a Python tuple containing the
statement type and parameters. These tuples are then stored in
a dictionary indexed by program line numbers.
- Even though it's just BASIC, the parser contains more than 80
rules and 150 parsing states. Thus, it's a little more meaty than
the calculator example.
To use the example, run it as follows:
% python basic.py hello.bas
HELLO WORLD
%
or use it interactively:
% python basic.py
[BASIC] 10 PRINT "HELLO WORLD"
[BASIC] 20 END
[BASIC] RUN
HELLO WORLD
[BASIC]
The following files are defined:
basic.py - High level script that controls everything
basiclex.py - BASIC tokenizer
basparse.py - BASIC parser
basinterp.py - BASIC interpreter that runs parsed programs.
In addition, a number of sample BASIC programs (.bas suffix) are
provided. These were taken out of the Dartmouth manual.
Disclaimer: I haven't spent a ton of time testing this and it's likely that
I've skimped here and there on a few finer details (e.g., strictly enforcing
variable naming rules). However, the interpreter seems to be able to run
the examples in the BASIC manual.
Have fun!
-Dave

View file

@ -0,0 +1,65 @@
# An implementation of Dartmouth BASIC (1964)
#
import sys
sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
import basiclex
import basparse
import basinterp
# If a filename has been specified, we try to run it.
# If a runtime error occurs, we bail out and enter
# interactive mode below
if len(sys.argv) == 2:
data = open(sys.argv[1]).read()
prog = basparse.parse(data)
if not prog:
raise SystemExit
b = basinterp.BasicInterpreter(prog)
try:
b.run()
raise SystemExit
except RuntimeError:
pass
else:
b = basinterp.BasicInterpreter({})
# Interactive mode. This incrementally adds/deletes statements
# from the program stored in the BasicInterpreter object. In
# addition, special commands 'NEW','LIST',and 'RUN' are added.
# Specifying a line number with no code deletes that line from
# the program.
while 1:
try:
line = raw_input("[BASIC] ")
except EOFError:
raise SystemExit
if not line:
continue
line += "\n"
prog = basparse.parse(line)
if not prog:
continue
keys = list(prog)
if keys[0] > 0:
b.add_statements(prog)
else:
stat = prog[keys[0]]
if stat[0] == 'RUN':
try:
b.run()
except RuntimeError:
pass
elif stat[0] == 'LIST':
b.list()
elif stat[0] == 'BLANK':
b.del_line(stat[1])
elif stat[0] == 'NEW':
b.new()

View file

@ -0,0 +1,61 @@
# An implementation of Dartmouth BASIC (1964)
from ply import *
keywords = (
'LET', 'READ', 'DATA', 'PRINT', 'GOTO', 'IF', 'THEN', 'FOR', 'NEXT', 'TO', 'STEP',
'END', 'STOP', 'DEF', 'GOSUB', 'DIM', 'REM', 'RETURN', 'RUN', 'LIST', 'NEW',
)
tokens = keywords + (
'EQUALS', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'POWER',
'LPAREN', 'RPAREN', 'LT', 'LE', 'GT', 'GE', 'NE',
'COMMA', 'SEMI', 'INTEGER', 'FLOAT', 'STRING',
'ID', 'NEWLINE'
)
t_ignore = ' \t'
def t_REM(t):
r'REM .*'
return t
def t_ID(t):
r'[A-Z][A-Z0-9]*'
if t.value in keywords:
t.type = t.value
return t
t_EQUALS = r'='
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_POWER = r'\^'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LT = r'<'
t_LE = r'<='
t_GT = r'>'
t_GE = r'>='
t_NE = r'<>'
t_COMMA = r'\,'
t_SEMI = r';'
t_INTEGER = r'\d+'
t_FLOAT = r'((\d*\.\d+)(E[\+-]?\d+)?|([1-9]\d*E[\+-]?\d+))'
t_STRING = r'\".*?\"'
def t_NEWLINE(t):
r'\n'
t.lexer.lineno += 1
return t
def t_error(t):
print("Illegal character %s" % t.value[0])
t.lexer.skip(1)
lex.lex(debug=0)

View file

@ -0,0 +1,73 @@
# An implementation of Dartmouth BASIC (1964)
#
import sys
sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
import logging
logging.basicConfig(
level=logging.INFO,
filename="parselog.txt",
filemode="w"
)
log = logging.getLogger()
import basiclex
import basparse
import basinterp
# If a filename has been specified, we try to run it.
# If a runtime error occurs, we bail out and enter
# interactive mode below
if len(sys.argv) == 2:
data = open(sys.argv[1]).read()
prog = basparse.parse(data, debug=log)
if not prog:
raise SystemExit
b = basinterp.BasicInterpreter(prog)
try:
b.run()
raise SystemExit
except RuntimeError:
pass
else:
b = basinterp.BasicInterpreter({})
# Interactive mode. This incrementally adds/deletes statements
# from the program stored in the BasicInterpreter object. In
# addition, special commands 'NEW','LIST',and 'RUN' are added.
# Specifying a line number with no code deletes that line from
# the program.
while 1:
try:
line = raw_input("[BASIC] ")
except EOFError:
raise SystemExit
if not line:
continue
line += "\n"
prog = basparse.parse(line, debug=log)
if not prog:
continue
keys = list(prog)
if keys[0] > 0:
b.add_statements(prog)
else:
stat = prog[keys[0]]
if stat[0] == 'RUN':
try:
b.run()
except RuntimeError:
pass
elif stat[0] == 'LIST':
b.list()
elif stat[0] == 'BLANK':
b.del_line(stat[1])
elif stat[0] == 'NEW':
b.new()

View file

@ -0,0 +1,496 @@
# This file provides the runtime support for running a basic program
# Assumes the program has been parsed using basparse.py
import sys
import math
import random
class BasicInterpreter:
# Initialize the interpreter. prog is a dictionary
# containing (line,statement) mappings
def __init__(self, prog):
self.prog = prog
self.functions = { # Built-in function table
'SIN': lambda z: math.sin(self.eval(z)),
'COS': lambda z: math.cos(self.eval(z)),
'TAN': lambda z: math.tan(self.eval(z)),
'ATN': lambda z: math.atan(self.eval(z)),
'EXP': lambda z: math.exp(self.eval(z)),
'ABS': lambda z: abs(self.eval(z)),
'LOG': lambda z: math.log(self.eval(z)),
'SQR': lambda z: math.sqrt(self.eval(z)),
'INT': lambda z: int(self.eval(z)),
'RND': lambda z: random.random()
}
# Collect all data statements
def collect_data(self):
self.data = []
for lineno in self.stat:
if self.prog[lineno][0] == 'DATA':
self.data = self.data + self.prog[lineno][1]
self.dc = 0 # Initialize the data counter
# Check for end statements
def check_end(self):
has_end = 0
for lineno in self.stat:
if self.prog[lineno][0] == 'END' and not has_end:
has_end = lineno
if not has_end:
print("NO END INSTRUCTION")
self.error = 1
return
if has_end != lineno:
print("END IS NOT LAST")
self.error = 1
# Check loops
def check_loops(self):
for pc in range(len(self.stat)):
lineno = self.stat[pc]
if self.prog[lineno][0] == 'FOR':
forinst = self.prog[lineno]
loopvar = forinst[1]
for i in range(pc + 1, len(self.stat)):
if self.prog[self.stat[i]][0] == 'NEXT':
nextvar = self.prog[self.stat[i]][1]
if nextvar != loopvar:
continue
self.loopend[pc] = i
break
else:
print("FOR WITHOUT NEXT AT LINE %s" % self.stat[pc])
self.error = 1
# Evaluate an expression
def eval(self, expr):
etype = expr[0]
if etype == 'NUM':
return expr[1]
elif etype == 'GROUP':
return self.eval(expr[1])
elif etype == 'UNARY':
if expr[1] == '-':
return -self.eval(expr[2])
elif etype == 'BINOP':
if expr[1] == '+':
return self.eval(expr[2]) + self.eval(expr[3])
elif expr[1] == '-':
return self.eval(expr[2]) - self.eval(expr[3])
elif expr[1] == '*':
return self.eval(expr[2]) * self.eval(expr[3])
elif expr[1] == '/':
return float(self.eval(expr[2])) / self.eval(expr[3])
elif expr[1] == '^':
return abs(self.eval(expr[2]))**self.eval(expr[3])
elif etype == 'VAR':
var, dim1, dim2 = expr[1]
if not dim1 and not dim2:
if var in self.vars:
return self.vars[var]
else:
print("UNDEFINED VARIABLE %s AT LINE %s" %
(var, self.stat[self.pc]))
raise RuntimeError
# May be a list lookup or a function evaluation
if dim1 and not dim2:
if var in self.functions:
# A function
return self.functions[var](dim1)
else:
# A list evaluation
if var in self.lists:
dim1val = self.eval(dim1)
if dim1val < 1 or dim1val > len(self.lists[var]):
print("LIST INDEX OUT OF BOUNDS AT LINE %s" %
self.stat[self.pc])
raise RuntimeError
return self.lists[var][dim1val - 1]
if dim1 and dim2:
if var in self.tables:
dim1val = self.eval(dim1)
dim2val = self.eval(dim2)
if dim1val < 1 or dim1val > len(self.tables[var]) or dim2val < 1 or dim2val > len(self.tables[var][0]):
print("TABLE INDEX OUT OUT BOUNDS AT LINE %s" %
self.stat[self.pc])
raise RuntimeError
return self.tables[var][dim1val - 1][dim2val - 1]
print("UNDEFINED VARIABLE %s AT LINE %s" %
(var, self.stat[self.pc]))
raise RuntimeError
# Evaluate a relational expression
def releval(self, expr):
etype = expr[1]
lhs = self.eval(expr[2])
rhs = self.eval(expr[3])
if etype == '<':
if lhs < rhs:
return 1
else:
return 0
elif etype == '<=':
if lhs <= rhs:
return 1
else:
return 0
elif etype == '>':
if lhs > rhs:
return 1
else:
return 0
elif etype == '>=':
if lhs >= rhs:
return 1
else:
return 0
elif etype == '=':
if lhs == rhs:
return 1
else:
return 0
elif etype == '<>':
if lhs != rhs:
return 1
else:
return 0
# Assignment
def assign(self, target, value):
var, dim1, dim2 = target
if not dim1 and not dim2:
self.vars[var] = self.eval(value)
elif dim1 and not dim2:
# List assignment
dim1val = self.eval(dim1)
if not var in self.lists:
self.lists[var] = [0] * 10
if dim1val > len(self.lists[var]):
print ("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc])
raise RuntimeError
self.lists[var][dim1val - 1] = self.eval(value)
elif dim1 and dim2:
dim1val = self.eval(dim1)
dim2val = self.eval(dim2)
if not var in self.tables:
temp = [0] * 10
v = []
for i in range(10):
v.append(temp[:])
self.tables[var] = v
# Variable already exists
if dim1val > len(self.tables[var]) or dim2val > len(self.tables[var][0]):
print("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc])
raise RuntimeError
self.tables[var][dim1val - 1][dim2val - 1] = self.eval(value)
# Change the current line number
def goto(self, linenum):
if not linenum in self.prog:
print("UNDEFINED LINE NUMBER %d AT LINE %d" %
(linenum, self.stat[self.pc]))
raise RuntimeError
self.pc = self.stat.index(linenum)
# Run it
def run(self):
self.vars = {} # All variables
self.lists = {} # List variables
self.tables = {} # Tables
self.loops = [] # Currently active loops
self.loopend = {} # Mapping saying where loops end
self.gosub = None # Gosub return point (if any)
self.error = 0 # Indicates program error
self.stat = list(self.prog) # Ordered list of all line numbers
self.stat.sort()
self.pc = 0 # Current program counter
# Processing prior to running
self.collect_data() # Collect all of the data statements
self.check_end()
self.check_loops()
if self.error:
raise RuntimeError
while 1:
line = self.stat[self.pc]
instr = self.prog[line]
op = instr[0]
# END and STOP statements
if op == 'END' or op == 'STOP':
break # We're done
# GOTO statement
elif op == 'GOTO':
newline = instr[1]
self.goto(newline)
continue
# PRINT statement
elif op == 'PRINT':
plist = instr[1]
out = ""
for label, val in plist:
if out:
out += ' ' * (15 - (len(out) % 15))
out += label
if val:
if label:
out += " "
eval = self.eval(val)
out += str(eval)
sys.stdout.write(out)
end = instr[2]
if not (end == ',' or end == ';'):
sys.stdout.write("\n")
if end == ',':
sys.stdout.write(" " * (15 - (len(out) % 15)))
if end == ';':
sys.stdout.write(" " * (3 - (len(out) % 3)))
# LET statement
elif op == 'LET':
target = instr[1]
value = instr[2]
self.assign(target, value)
# READ statement
elif op == 'READ':
for target in instr[1]:
if self.dc < len(self.data):
value = ('NUM', self.data[self.dc])
self.assign(target, value)
self.dc += 1
else:
# No more data. Program ends
return
elif op == 'IF':
relop = instr[1]
newline = instr[2]
if (self.releval(relop)):
self.goto(newline)
continue
elif op == 'FOR':
loopvar = instr[1]
initval = instr[2]
finval = instr[3]
stepval = instr[4]
# Check to see if this is a new loop
if not self.loops or self.loops[-1][0] != self.pc:
# Looks like a new loop. Make the initial assignment
newvalue = initval
self.assign((loopvar, None, None), initval)
if not stepval:
stepval = ('NUM', 1)
stepval = self.eval(stepval) # Evaluate step here
self.loops.append((self.pc, stepval))
else:
# It's a repeat of the previous loop
# Update the value of the loop variable according to the
# step
stepval = ('NUM', self.loops[-1][1])
newvalue = (
'BINOP', '+', ('VAR', (loopvar, None, None)), stepval)
if self.loops[-1][1] < 0:
relop = '>='
else:
relop = '<='
if not self.releval(('RELOP', relop, newvalue, finval)):
# Loop is done. Jump to the NEXT
self.pc = self.loopend[self.pc]
self.loops.pop()
else:
self.assign((loopvar, None, None), newvalue)
elif op == 'NEXT':
if not self.loops:
print("NEXT WITHOUT FOR AT LINE %s" % line)
return
nextvar = instr[1]
self.pc = self.loops[-1][0]
loopinst = self.prog[self.stat[self.pc]]
forvar = loopinst[1]
if nextvar != forvar:
print("NEXT DOESN'T MATCH FOR AT LINE %s" % line)
return
continue
elif op == 'GOSUB':
newline = instr[1]
if self.gosub:
print("ALREADY IN A SUBROUTINE AT LINE %s" % line)
return
self.gosub = self.stat[self.pc]
self.goto(newline)
continue
elif op == 'RETURN':
if not self.gosub:
print("RETURN WITHOUT A GOSUB AT LINE %s" % line)
return
self.goto(self.gosub)
self.gosub = None
elif op == 'FUNC':
fname = instr[1]
pname = instr[2]
expr = instr[3]
def eval_func(pvalue, name=pname, self=self, expr=expr):
self.assign((pname, None, None), pvalue)
return self.eval(expr)
self.functions[fname] = eval_func
elif op == 'DIM':
for vname, x, y in instr[1]:
if y == 0:
# Single dimension variable
self.lists[vname] = [0] * x
else:
# Double dimension variable
temp = [0] * y
v = []
for i in range(x):
v.append(temp[:])
self.tables[vname] = v
self.pc += 1
# Utility functions for program listing
def expr_str(self, expr):
etype = expr[0]
if etype == 'NUM':
return str(expr[1])
elif etype == 'GROUP':
return "(%s)" % self.expr_str(expr[1])
elif etype == 'UNARY':
if expr[1] == '-':
return "-" + str(expr[2])
elif etype == 'BINOP':
return "%s %s %s" % (self.expr_str(expr[2]), expr[1], self.expr_str(expr[3]))
elif etype == 'VAR':
return self.var_str(expr[1])
def relexpr_str(self, expr):
return "%s %s %s" % (self.expr_str(expr[2]), expr[1], self.expr_str(expr[3]))
def var_str(self, var):
varname, dim1, dim2 = var
if not dim1 and not dim2:
return varname
if dim1 and not dim2:
return "%s(%s)" % (varname, self.expr_str(dim1))
return "%s(%s,%s)" % (varname, self.expr_str(dim1), self.expr_str(dim2))
# Create a program listing
def list(self):
stat = list(self.prog) # Ordered list of all line numbers
stat.sort()
for line in stat:
instr = self.prog[line]
op = instr[0]
if op in ['END', 'STOP', 'RETURN']:
print("%s %s" % (line, op))
continue
elif op == 'REM':
print("%s %s" % (line, instr[1]))
elif op == 'PRINT':
_out = "%s %s " % (line, op)
first = 1
for p in instr[1]:
if not first:
_out += ", "
if p[0] and p[1]:
_out += '"%s"%s' % (p[0], self.expr_str(p[1]))
elif p[1]:
_out += self.expr_str(p[1])
else:
_out += '"%s"' % (p[0],)
first = 0
if instr[2]:
_out += instr[2]
print(_out)
elif op == 'LET':
print("%s LET %s = %s" %
(line, self.var_str(instr[1]), self.expr_str(instr[2])))
elif op == 'READ':
_out = "%s READ " % line
first = 1
for r in instr[1]:
if not first:
_out += ","
_out += self.var_str(r)
first = 0
print(_out)
elif op == 'IF':
print("%s IF %s THEN %d" %
(line, self.relexpr_str(instr[1]), instr[2]))
elif op == 'GOTO' or op == 'GOSUB':
print("%s %s %s" % (line, op, instr[1]))
elif op == 'FOR':
_out = "%s FOR %s = %s TO %s" % (
line, instr[1], self.expr_str(instr[2]), self.expr_str(instr[3]))
if instr[4]:
_out += " STEP %s" % (self.expr_str(instr[4]))
print(_out)
elif op == 'NEXT':
print("%s NEXT %s" % (line, instr[1]))
elif op == 'FUNC':
print("%s DEF %s(%s) = %s" %
(line, instr[1], instr[2], self.expr_str(instr[3])))
elif op == 'DIM':
_out = "%s DIM " % line
first = 1
for vname, x, y in instr[1]:
if not first:
_out += ","
first = 0
if y == 0:
_out += "%s(%d)" % (vname, x)
else:
_out += "%s(%d,%d)" % (vname, x, y)
print(_out)
elif op == 'DATA':
_out = "%s DATA " % line
first = 1
for v in instr[1]:
if not first:
_out += ","
first = 0
_out += v
print(_out)
# Erase the current program
def new(self):
self.prog = {}
# Insert statements
def add_statements(self, prog):
for line, stat in prog.items():
self.prog[line] = stat
# Delete a statement
def del_line(self, lineno):
try:
del self.prog[lineno]
except KeyError:
pass

View file

@ -0,0 +1,474 @@
# An implementation of Dartmouth BASIC (1964)
#
from ply import *
import basiclex
tokens = basiclex.tokens
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('left', 'POWER'),
('right', 'UMINUS')
)
# A BASIC program is a series of statements. We represent the program as a
# dictionary of tuples indexed by line number.
def p_program(p):
'''program : program statement
| statement'''
if len(p) == 2 and p[1]:
p[0] = {}
line, stat = p[1]
p[0][line] = stat
elif len(p) == 3:
p[0] = p[1]
if not p[0]:
p[0] = {}
if p[2]:
line, stat = p[2]
p[0][line] = stat
# This catch-all rule is used for any catastrophic errors. In this case,
# we simply return nothing
def p_program_error(p):
'''program : error'''
p[0] = None
p.parser.error = 1
# Format of all BASIC statements.
def p_statement(p):
'''statement : INTEGER command NEWLINE'''
if isinstance(p[2], str):
print("%s %s %s" % (p[2], "AT LINE", p[1]))
p[0] = None
p.parser.error = 1
else:
lineno = int(p[1])
p[0] = (lineno, p[2])
# Interactive statements.
def p_statement_interactive(p):
'''statement : RUN NEWLINE
| LIST NEWLINE
| NEW NEWLINE'''
p[0] = (0, (p[1], 0))
# Blank line number
def p_statement_blank(p):
'''statement : INTEGER NEWLINE'''
p[0] = (0, ('BLANK', int(p[1])))
# Error handling for malformed statements
def p_statement_bad(p):
'''statement : INTEGER error NEWLINE'''
print("MALFORMED STATEMENT AT LINE %s" % p[1])
p[0] = None
p.parser.error = 1
# Blank line
def p_statement_newline(p):
'''statement : NEWLINE'''
p[0] = None
# LET statement
def p_command_let(p):
'''command : LET variable EQUALS expr'''
p[0] = ('LET', p[2], p[4])
def p_command_let_bad(p):
'''command : LET variable EQUALS error'''
p[0] = "BAD EXPRESSION IN LET"
# READ statement
def p_command_read(p):
'''command : READ varlist'''
p[0] = ('READ', p[2])
def p_command_read_bad(p):
'''command : READ error'''
p[0] = "MALFORMED VARIABLE LIST IN READ"
# DATA statement
def p_command_data(p):
'''command : DATA numlist'''
p[0] = ('DATA', p[2])
def p_command_data_bad(p):
'''command : DATA error'''
p[0] = "MALFORMED NUMBER LIST IN DATA"
# PRINT statement
def p_command_print(p):
'''command : PRINT plist optend'''
p[0] = ('PRINT', p[2], p[3])
def p_command_print_bad(p):
'''command : PRINT error'''
p[0] = "MALFORMED PRINT STATEMENT"
# Optional ending on PRINT. Either a comma (,) or semicolon (;)
def p_optend(p):
'''optend : COMMA
| SEMI
|'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = None
# PRINT statement with no arguments
def p_command_print_empty(p):
'''command : PRINT'''
p[0] = ('PRINT', [], None)
# GOTO statement
def p_command_goto(p):
'''command : GOTO INTEGER'''
p[0] = ('GOTO', int(p[2]))
def p_command_goto_bad(p):
'''command : GOTO error'''
p[0] = "INVALID LINE NUMBER IN GOTO"
# IF-THEN statement
def p_command_if(p):
'''command : IF relexpr THEN INTEGER'''
p[0] = ('IF', p[2], int(p[4]))
def p_command_if_bad(p):
'''command : IF error THEN INTEGER'''
p[0] = "BAD RELATIONAL EXPRESSION"
def p_command_if_bad2(p):
'''command : IF relexpr THEN error'''
p[0] = "INVALID LINE NUMBER IN THEN"
# FOR statement
def p_command_for(p):
'''command : FOR ID EQUALS expr TO expr optstep'''
p[0] = ('FOR', p[2], p[4], p[6], p[7])
def p_command_for_bad_initial(p):
'''command : FOR ID EQUALS error TO expr optstep'''
p[0] = "BAD INITIAL VALUE IN FOR STATEMENT"
def p_command_for_bad_final(p):
'''command : FOR ID EQUALS expr TO error optstep'''
p[0] = "BAD FINAL VALUE IN FOR STATEMENT"
def p_command_for_bad_step(p):
'''command : FOR ID EQUALS expr TO expr STEP error'''
p[0] = "MALFORMED STEP IN FOR STATEMENT"
# Optional STEP qualifier on FOR statement
def p_optstep(p):
'''optstep : STEP expr
| empty'''
if len(p) == 3:
p[0] = p[2]
else:
p[0] = None
# NEXT statement
def p_command_next(p):
'''command : NEXT ID'''
p[0] = ('NEXT', p[2])
def p_command_next_bad(p):
'''command : NEXT error'''
p[0] = "MALFORMED NEXT"
# END statement
def p_command_end(p):
'''command : END'''
p[0] = ('END',)
# REM statement
def p_command_rem(p):
'''command : REM'''
p[0] = ('REM', p[1])
# STOP statement
def p_command_stop(p):
'''command : STOP'''
p[0] = ('STOP',)
# DEF statement
def p_command_def(p):
'''command : DEF ID LPAREN ID RPAREN EQUALS expr'''
p[0] = ('FUNC', p[2], p[4], p[7])
def p_command_def_bad_rhs(p):
'''command : DEF ID LPAREN ID RPAREN EQUALS error'''
p[0] = "BAD EXPRESSION IN DEF STATEMENT"
def p_command_def_bad_arg(p):
'''command : DEF ID LPAREN error RPAREN EQUALS expr'''
p[0] = "BAD ARGUMENT IN DEF STATEMENT"
# GOSUB statement
def p_command_gosub(p):
'''command : GOSUB INTEGER'''
p[0] = ('GOSUB', int(p[2]))
def p_command_gosub_bad(p):
'''command : GOSUB error'''
p[0] = "INVALID LINE NUMBER IN GOSUB"
# RETURN statement
def p_command_return(p):
'''command : RETURN'''
p[0] = ('RETURN',)
# DIM statement
def p_command_dim(p):
'''command : DIM dimlist'''
p[0] = ('DIM', p[2])
def p_command_dim_bad(p):
'''command : DIM error'''
p[0] = "MALFORMED VARIABLE LIST IN DIM"
# List of variables supplied to DIM statement
def p_dimlist(p):
'''dimlist : dimlist COMMA dimitem
| dimitem'''
if len(p) == 4:
p[0] = p[1]
p[0].append(p[3])
else:
p[0] = [p[1]]
# DIM items
def p_dimitem_single(p):
'''dimitem : ID LPAREN INTEGER RPAREN'''
p[0] = (p[1], eval(p[3]), 0)
def p_dimitem_double(p):
'''dimitem : ID LPAREN INTEGER COMMA INTEGER RPAREN'''
p[0] = (p[1], eval(p[3]), eval(p[5]))
# Arithmetic expressions
def p_expr_binary(p):
'''expr : expr PLUS expr
| expr MINUS expr
| expr TIMES expr
| expr DIVIDE expr
| expr POWER expr'''
p[0] = ('BINOP', p[2], p[1], p[3])
def p_expr_number(p):
'''expr : INTEGER
| FLOAT'''
p[0] = ('NUM', eval(p[1]))
def p_expr_variable(p):
'''expr : variable'''
p[0] = ('VAR', p[1])
def p_expr_group(p):
'''expr : LPAREN expr RPAREN'''
p[0] = ('GROUP', p[2])
def p_expr_unary(p):
'''expr : MINUS expr %prec UMINUS'''
p[0] = ('UNARY', '-', p[2])
# Relational expressions
def p_relexpr(p):
'''relexpr : expr LT expr
| expr LE expr
| expr GT expr
| expr GE expr
| expr EQUALS expr
| expr NE expr'''
p[0] = ('RELOP', p[2], p[1], p[3])
# Variables
def p_variable(p):
'''variable : ID
| ID LPAREN expr RPAREN
| ID LPAREN expr COMMA expr RPAREN'''
if len(p) == 2:
p[0] = (p[1], None, None)
elif len(p) == 5:
p[0] = (p[1], p[3], None)
else:
p[0] = (p[1], p[3], p[5])
# Builds a list of variable targets as a Python list
def p_varlist(p):
'''varlist : varlist COMMA variable
| variable'''
if len(p) > 2:
p[0] = p[1]
p[0].append(p[3])
else:
p[0] = [p[1]]
# Builds a list of numbers as a Python list
def p_numlist(p):
'''numlist : numlist COMMA number
| number'''
if len(p) > 2:
p[0] = p[1]
p[0].append(p[3])
else:
p[0] = [p[1]]
# A number. May be an integer or a float
def p_number(p):
'''number : INTEGER
| FLOAT'''
p[0] = eval(p[1])
# A signed number.
def p_number_signed(p):
'''number : MINUS INTEGER
| MINUS FLOAT'''
p[0] = eval("-" + p[2])
# List of targets for a print statement
# Returns a list of tuples (label,expr)
def p_plist(p):
'''plist : plist COMMA pitem
| pitem'''
if len(p) > 3:
p[0] = p[1]
p[0].append(p[3])
else:
p[0] = [p[1]]
def p_item_string(p):
'''pitem : STRING'''
p[0] = (p[1][1:-1], None)
def p_item_string_expr(p):
'''pitem : STRING expr'''
p[0] = (p[1][1:-1], p[2])
def p_item_expr(p):
'''pitem : expr'''
p[0] = ("", p[1])
# Empty
def p_empty(p):
'''empty : '''
# Catastrophic error handler
def p_error(p):
if not p:
print("SYNTAX ERROR AT EOF")
bparser = yacc.yacc()
def parse(data, debug=0):
bparser.error = 0
p = bparser.parse(data, debug=debug)
if bparser.error:
return None
return p

View file

@ -0,0 +1,14 @@
5 DIM A(50,15)
10 FOR I = 1 TO 50
20 FOR J = 1 TO 15
30 LET A(I,J) = I + J
35 REM PRINT I,J, A(I,J)
40 NEXT J
50 NEXT I
100 FOR I = 1 TO 50
110 FOR J = 1 TO 15
120 PRINT A(I,J),
130 NEXT J
140 PRINT
150 NEXT I
999 END

View file

@ -0,0 +1,5 @@
10 DEF FDX(X) = 2*X
20 FOR I = 0 TO 100
30 PRINT FDX(I)
40 NEXT I
50 END

Some files were not shown because too many files have changed in this diff Show more