Source code

Revision control

Copy as Markdown

Other Tools

import WebIDL
def WebIDLTest(parser, harness):
# Basic functionality
threw = False
try:
parser.parse(
"""
typedef [EnforceRange] long Foo;
typedef [Clamp] long Bar;
typedef [LegacyNullToEmptyString] DOMString Baz;
dictionary A {
required [EnforceRange] long a;
required [Clamp] long b;
[ChromeOnly, EnforceRange] long c;
Foo d;
};
interface B {
attribute Foo typedefFoo;
attribute [EnforceRange] long foo;
attribute [Clamp] long bar;
attribute [LegacyNullToEmptyString] DOMString baz;
undefined method([EnforceRange] long foo, [Clamp] long bar,
[LegacyNullToEmptyString] DOMString baz);
undefined method2(optional [EnforceRange] long foo, optional [Clamp] long bar,
optional [LegacyNullToEmptyString] DOMString baz);
undefined method3(optional [LegacyNullToEmptyString] UTF8String foo = "");
};
interface C {
attribute [EnforceRange] long? foo;
attribute [Clamp] long? bar;
undefined method([EnforceRange] long? foo, [Clamp] long? bar);
undefined method2(optional [EnforceRange] long? foo, optional [Clamp] long? bar);
};
interface Setlike {
setlike<[Clamp] long>;
};
interface Maplike {
maplike<[Clamp] long, [EnforceRange] long>;
};
interface Iterable {
iterable<[Clamp] long, [EnforceRange] long>;
};
"""
)
results = parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(not threw, "Should not have thrown on parsing normal")
if not threw:
harness.check(
results[0].innerType.hasEnforceRange(), True, "Foo is [EnforceRange]"
)
harness.check(results[1].innerType.hasClamp(), True, "Bar is [Clamp]")
harness.check(
results[2].innerType.legacyNullToEmptyString,
True,
"Baz is [LegacyNullToEmptyString]",
)
A = results[3]
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[2].type.hasEnforceRange(), True, "A.c is [EnforceRange]"
)
harness.check(
A.members[3].type.hasEnforceRange(), True, "A.d is [EnforceRange]"
)
B = results[4]
harness.check(
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[3].type.legacyNullToEmptyString,
True,
"B.baz is [LegacyNullToEmptyString]",
)
method = B.members[4].signatures()[0][1]
harness.check(
method[0].type.hasEnforceRange(),
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]
harness.check(
method2[0].type.hasEnforceRange(),
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]
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[1].type.nullable(), "C.bar is nullable")
harness.ok(C.members[1].type.hasClamp(), "C.bar has [Clamp]")
method = C.members[2].signatures()[0][1]
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[1].type.nullable(), "bar argument of method is nullable")
harness.ok(method[1].type.hasClamp(), "bar argument of method has [Clamp]")
method2 = C.members[3].signatures()[0][1]
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[1].type.nullable(), "bar argument of method2 is nullable")
harness.ok(method2[1].type.hasClamp(), "bar argument of method2 has [Clamp]")
# Test [AllowShared]
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [AllowShared] ArrayBufferView Foo;
dictionary A {
required [AllowShared] ArrayBufferView a;
[ChromeOnly, AllowShared] ArrayBufferView b;
Foo c;
};
interface B {
attribute Foo typedefFoo;
attribute [AllowShared] ArrayBufferView foo;
undefined method([AllowShared] ArrayBufferView foo);
undefined method2(optional [AllowShared] ArrayBufferView foo);
};
interface C {
attribute [AllowShared] ArrayBufferView? foo;
undefined method([AllowShared] ArrayBufferView? foo);
undefined method2(optional [AllowShared] ArrayBufferView? foo);
};
interface Setlike {
setlike<[AllowShared] ArrayBufferView>;
};
interface Maplike {
maplike<[Clamp] long, [AllowShared] ArrayBufferView>;
};
interface Iterable {
iterable<[Clamp] long, [AllowShared] ArrayBufferView>;
};
"""
)
results = parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(not threw, "Should not have thrown on parsing normal")
if not threw:
harness.ok(results[0].innerType.hasAllowShared(), "Foo is [AllowShared]")
A = results[1]
harness.ok(A.members[0].type.hasAllowShared(), "A.a is [AllowShared]")
harness.ok(A.members[1].type.hasAllowShared(), "A.b is [AllowShared]")
harness.ok(A.members[2].type.hasAllowShared(), "A.c is [AllowShared]")
B = results[2]
harness.ok(B.members[0].type.hasAllowShared(), "B.typedefFoo is [AllowShared]")
harness.ok(B.members[1].type.hasAllowShared(), "B.foo is [AllowShared]")
method = B.members[2].signatures()[0][1]
harness.ok(
method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]"
)
method2 = B.members[3].signatures()[0][1]
harness.ok(
method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]"
)
C = results[3]
harness.ok(C.members[0].type.nullable(), "C.foo is nullable")
harness.ok(C.members[0].type.hasAllowShared(), "C.foo is [AllowShared]")
method = C.members[1].signatures()[0][1]
harness.ok(method[0].type.nullable(), "foo argument of method is nullable")
harness.ok(
method[0].type.hasAllowShared(), "foo argument of method is [AllowShared]"
)
method2 = C.members[2].signatures()[0][1]
harness.ok(method2[0].type.nullable(), "foo argument of method2 is nullable")
harness.ok(
method2[0].type.hasAllowShared(), "foo argument of method2 is [AllowShared]"
)
ATTRIBUTES = [
("[Clamp]", "long"),
("[EnforceRange]", "long"),
("[LegacyNullToEmptyString]", "DOMString"),
("[AllowShared]", "ArrayBufferView"),
]
TEMPLATES = [
(
"required dictionary members",
"""
dictionary Foo {
%s required %s foo;
};
""",
),
(
"optional arguments",
"""
interface Foo {
undefined foo(%s optional %s foo);
};
""",
),
(
"typedefs",
"""
%s typedef %s foo;
""",
),
(
"attributes",
"""
interface Foo {
%s attribute %s foo;
};
""",
),
(
"readonly attributes",
"""
interface Foo {
readonly attribute %s %s foo;
};
""",
),
(
"readonly unresolved attributes",
"""
interface Foo {
readonly attribute Bar baz;
};
typedef %s %s Bar;
""",
),
(
"method",
"""
interface Foo {
%s %s foo();
};
""",
),
(
"interface",
"""
%s
interface Foo {
attribute %s foo;
};
""",
),
(
"partial interface",
"""
interface Foo {
undefined foo();
};
%s
partial interface Foo {
attribute %s bar;
};
""",
),
(
"interface mixin",
"""
%s
interface mixin Foo {
attribute %s foo;
};
""",
),
(
"namespace",
"""
%s
namespace Foo {
attribute %s foo;
};
""",
),
(
"partial namespace",
"""
namespace Foo {
undefined foo();
};
%s
partial namespace Foo {
attribute %s bar;
};
""",
),
(
"dictionary",
"""
%s
dictionary Foo {
%s foo;
};
""",
),
]
for name, template in TEMPLATES:
parser = parser.reset()
threw = False
try:
parser.parse(template % ("", "long"))
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(not threw, "Template for %s parses without attributes" % name)
for attribute, type in ATTRIBUTES:
parser = parser.reset()
threw = False
try:
parser.parse(template % (attribute, type))
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow %s on %s" % (attribute, name))
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [Clamp, EnforceRange] long Foo;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange]")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [EnforceRange, Clamp] long Foo;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange]")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [Clamp] long Foo;
typedef [EnforceRange] Foo bar;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [EnforceRange] long Foo;
typedef [Clamp] Foo bar;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow mixing [Clamp] and [EnforceRange] via typedefs")
TYPES = [
"DOMString",
"unrestricted float",
"float",
"unrestricted double",
"double",
]
for type in TYPES:
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [Clamp] %s Foo;
"""
% type
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow [Clamp] on %s" % type)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [EnforceRange] %s Foo;
"""
% type
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow [EnforceRange] on %s" % type)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [LegacyNullToEmptyString] long Foo;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow [LegacyNullToEmptyString] on long")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [LegacyNullToEmptyString] JSString Foo;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "Should not allow [LegacyNullToEmptyString] on JSString")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [LegacyNullToEmptyString] DOMString? Foo;
"""
)
parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(
threw, "Should not allow [LegacyNullToEmptyString] on nullable DOMString"
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [AllowShared] DOMString Foo;
"""
)
results = parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "[AllowShared] only allowed on buffer source types")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
typedef [AllowShared=something] ArrayBufferView Foo;
"""
)
results = parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(threw, "[AllowShared] must take no arguments")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
undefined foo([Clamp] Bar arg);
};
typedef long Bar;
"""
)
results = parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(not threw, "Should allow type attributes on unresolved types")
harness.check(
results[0].members[0].signatures()[0][1][0].type.hasClamp(),
True,
"Unresolved types with type attributes should correctly resolve with attributes",
)
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Foo {
undefined foo(Bar arg);
};
typedef [Clamp] long Bar;
"""
)
results = parser.finish()
except WebIDL.WebIDLError:
threw = True
harness.ok(not threw, "Should allow type attributes on typedefs")
harness.check(
results[0].members[0].signatures()[0][1][0].type.hasClamp(),
True,
"Unresolved types that resolve to typedefs with attributes should correctly resolve with "
"attributes",
)