Update the WebIDL parser

This commit is contained in:
Anthony Ramine 2017-06-09 13:57:30 +02:00
parent 2439672983
commit e566bc7b1c
18 changed files with 1183 additions and 318 deletions

View file

@ -17,11 +17,12 @@ import functools
from WebIDL import ( from WebIDL import (
BuiltinTypes, BuiltinTypes,
IDLBuiltinType, IDLBuiltinType,
IDLNullValue,
IDLNullableType,
IDLObject,
IDLType,
IDLInterfaceMember, IDLInterfaceMember,
IDLNullableType,
IDLNullValue,
IDLObject,
IDLPromiseType,
IDLType,
IDLUndefinedValue, IDLUndefinedValue,
IDLWrapperType, IDLWrapperType,
) )
@ -94,14 +95,14 @@ def stripTrailingWhitespace(text):
def innerContainerType(type): def innerContainerType(type):
assert type.isSequence() or type.isMozMap() assert type.isSequence() or type.isRecord()
return type.inner.inner if type.nullable() else type.inner return type.inner.inner if type.nullable() else type.inner
def wrapInNativeContainerType(type, inner): def wrapInNativeContainerType(type, inner):
if type.isSequence(): if type.isSequence():
containerType = "Vec" containerType = "Vec"
elif type.isMozMap(): elif type.isRecord():
containerType = "MozMap" containerType = "MozMap"
else: else:
raise TypeError("Unexpected container type %s", type) raise TypeError("Unexpected container type %s", type)
@ -697,7 +698,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not (isEnforceRange and isClamp) # These are mutually exclusive assert not (isEnforceRange and isClamp) # These are mutually exclusive
if type.isSequence() or type.isMozMap(): if type.isSequence() or type.isRecord():
innerInfo = getJSToNativeConversionInfo(innerContainerType(type), innerInfo = getJSToNativeConversionInfo(innerContainerType(type),
descriptorProvider, descriptorProvider,
isMember=isMember) isMember=isMember)
@ -754,6 +755,56 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
return handleOptional(templateBody, declType, default) return handleOptional(templateBody, declType, default)
if type.isPromise():
assert not type.nullable()
# Per spec, what we're supposed to do is take the original
# Promise.resolve and call it with the original Promise as this
# value to make a Promise out of whatever value we actually have
# here. The question is which global we should use. There are
# a couple cases to consider:
#
# 1) Normal call to API with a Promise argument. This is a case the
# spec covers, and we should be using the current Realm's
# Promise. That means the current compartment.
# 2) Promise return value from a callback or callback interface.
# This is in theory a case the spec covers but in practice it
# really doesn't define behavior here because it doesn't define
# what Realm we're in after the callback returns, which is when
# the argument conversion happens. We will use the current
# compartment, which is the compartment of the callable (which
# may itself be a cross-compartment wrapper itself), which makes
# as much sense as anything else. In practice, such an API would
# once again be providing a Promise to signal completion of an
# operation, which would then not be exposed to anyone other than
# our own implementation code.
templateBody = fill(
"""
{ // Scope for our JSAutoCompartment.
rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get());
rooted!(in(cx) let mut valueToResolve = $${val}.get());
if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
$*{exceptionCode}
}
match Promise::Resolve(&promiseGlobal, cx, valueToResolve.handle()) {
Ok(value) => value,
Err(error) => {
throw_dom_exception(cx, &promiseGlobal, error);
$*{exceptionCode}
}
}
}
""",
exceptionCode=exceptionCode)
if isArgument:
declType = CGGeneric("&Promise")
else:
declType = CGGeneric("Rc<Promise>")
return handleOptional(templateBody, declType, handleDefaultNull("None"))
if type.isGeckoInterface(): if type.isGeckoInterface():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
@ -780,79 +831,34 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
elif isArgument: elif isArgument:
descriptorType = descriptor.argumentType descriptorType = descriptor.argumentType
templateBody = "" if descriptor.interface.isConsequential():
isPromise = descriptor.interface.identifier.name == "Promise" raise TypeError("Consequential interface %s being used as an "
if isPromise: "argument" % descriptor.interface.identifier.name)
# Per spec, what we're supposed to do is take the original
# Promise.resolve and call it with the original Promise as this
# value to make a Promise out of whatever value we actually have
# here. The question is which global we should use. There are
# a couple cases to consider:
#
# 1) Normal call to API with a Promise argument. This is a case the
# spec covers, and we should be using the current Realm's
# Promise. That means the current compartment.
# 2) Promise return value from a callback or callback interface.
# This is in theory a case the spec covers but in practice it
# really doesn't define behavior here because it doesn't define
# what Realm we're in after the callback returns, which is when
# the argument conversion happens. We will use the current
# compartment, which is the compartment of the callable (which
# may itself be a cross-compartment wrapper itself), which makes
# as much sense as anything else. In practice, such an API would
# once again be providing a Promise to signal completion of an
# operation, which would then not be exposed to anyone other than
# our own implementation code.
templateBody = fill(
"""
{ // Scope for our JSAutoCompartment.
rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx)); if failureCode is None:
let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get()); substitutions = {
"sourceDescription": sourceDescription,
rooted!(in(cx) let mut valueToResolve = $${val}.get()); "interface": descriptor.interface.identifier.name,
if !JS_WrapValue(cx, valueToResolve.handle_mut()) { "exceptionCode": exceptionCode,
$*{exceptionCode} }
} unwrapFailureCode = string.Template(
match Promise::Resolve(&promiseGlobal, cx, valueToResolve.handle()) { 'throw_type_error(cx, "${sourceDescription} does not '
Ok(value) => value, 'implement interface ${interface}.");\n'
Err(error) => { '${exceptionCode}').substitute(substitutions)
throw_dom_exception(cx, &promiseGlobal, error);
$*{exceptionCode}
}
}
}
""",
exceptionCode=exceptionCode)
else: else:
if descriptor.interface.isConsequential(): unwrapFailureCode = failureCode
raise TypeError("Consequential interface %s being used as an "
"argument" % descriptor.interface.identifier.name)
if failureCode is None: templateBody = fill(
substitutions = { """
"sourceDescription": sourceDescription, match ${function}($${val}) {
"interface": descriptor.interface.identifier.name, Ok(val) => val,
"exceptionCode": exceptionCode, Err(()) => {
$*{failureCode}
} }
unwrapFailureCode = string.Template( }
'throw_type_error(cx, "${sourceDescription} does not ' """,
'implement interface ${interface}.");\n' failureCode=unwrapFailureCode + "\n",
'${exceptionCode}').substitute(substitutions) function=conversionFunction)
else:
unwrapFailureCode = failureCode
templateBody = fill(
"""
match ${function}($${val}) {
Ok(val) => val,
Err(()) => {
$*{failureCode}
}
}
""",
failureCode=unwrapFailureCode + "\n",
function=conversionFunction)
declType = CGGeneric(descriptorType) declType = CGGeneric(descriptorType)
if type.nullable(): if type.nullable():
@ -1323,7 +1329,7 @@ def typeNeedsCx(type, retVal=False):
# Returns a conversion behavior suitable for a type # Returns a conversion behavior suitable for a type
def getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs): def getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs):
if type.isSequence() or type.isMozMap(): if type.isSequence() or type.isRecord():
return getConversionConfigForType(innerContainerType(type), isEnforceRange, isClamp, treatNullAs) return getConversionConfigForType(innerContainerType(type), isEnforceRange, isClamp, treatNullAs)
if type.isDOMString(): if type.isDOMString():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
@ -1381,6 +1387,9 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
if returnType.nullable(): if returnType.nullable():
result = CGWrapper(result, pre="Option<", post=">") result = CGWrapper(result, pre="Option<", post=">")
return result return result
if returnType.isPromise():
assert not returnType.nullable()
return CGGeneric("Rc<Promise>")
if returnType.isGeckoInterface(): if returnType.isGeckoInterface():
descriptor = descriptorProvider.getDescriptor( descriptor = descriptorProvider.getDescriptor(
returnType.unroll().inner.identifier.name) returnType.unroll().inner.identifier.name)
@ -1408,7 +1417,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
if returnType.nullable(): if returnType.nullable():
result = CGWrapper(result, pre="Option<", post=">") result = CGWrapper(result, pre="Option<", post=">")
return result return result
if returnType.isSequence() or returnType.isMozMap(): if returnType.isSequence() or returnType.isRecord():
result = getRetvalDeclarationForType(innerContainerType(returnType), descriptorProvider) result = getRetvalDeclarationForType(innerContainerType(returnType), descriptorProvider)
result = wrapInNativeContainerType(returnType, result) result = wrapInNativeContainerType(returnType, result)
if returnType.nullable(): if returnType.nullable():
@ -1946,8 +1955,10 @@ class CGImports(CGWrapper):
if parentName: if parentName:
descriptor = descriptorProvider.getDescriptor(parentName) descriptor = descriptorProvider.getDescriptor(parentName)
extras += [descriptor.path, descriptor.bindingPath] extras += [descriptor.path, descriptor.bindingPath]
elif t.isType() and t.isMozMap(): elif t.isType() and t.isRecord():
extras += ['dom::bindings::mozmap::MozMap'] extras += ['dom::bindings::mozmap::MozMap']
elif isinstance(t, IDLPromiseType):
extras += ["dom::promise::Promise"]
else: else:
if t.isEnum(): if t.isEnum():
extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name + 'Values'] extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name + 'Values']
@ -3819,7 +3830,9 @@ class CGMemberJITInfo(CGThing):
return "JSVAL_TYPE_UNDEFINED" return "JSVAL_TYPE_UNDEFINED"
if t.isSequence(): if t.isSequence():
return "JSVAL_TYPE_OBJECT" return "JSVAL_TYPE_OBJECT"
if t.isMozMap(): if t.isRecord():
return "JSVAL_TYPE_OBJECT"
if t.isPromise():
return "JSVAL_TYPE_OBJECT" return "JSVAL_TYPE_OBJECT"
if t.isGeckoInterface(): if t.isGeckoInterface():
return "JSVAL_TYPE_OBJECT" return "JSVAL_TYPE_OBJECT"
@ -4055,7 +4068,7 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
elif type.isDictionary(): elif type.isDictionary():
name = type.name name = type.name
typeName = name typeName = name
elif type.isSequence() or type.isMozMap(): elif type.isSequence() or type.isRecord():
name = type.name name = type.name
inner = getUnionTypeTemplateVars(innerContainerType(type), descriptorProvider) inner = getUnionTypeTemplateVars(innerContainerType(type), descriptorProvider)
typeName = wrapInNativeContainerType(type, CGGeneric(inner["typeName"])).define() typeName = wrapInNativeContainerType(type, CGGeneric(inner["typeName"])).define()
@ -4208,7 +4221,7 @@ class CGUnionConversionStruct(CGThing):
else: else:
object = None object = None
mozMapMemberTypes = filter(lambda t: t.isMozMap(), memberTypes) mozMapMemberTypes = filter(lambda t: t.isRecord(), memberTypes)
if len(mozMapMemberTypes) > 0: if len(mozMapMemberTypes) > 0:
assert len(mozMapMemberTypes) == 1 assert len(mozMapMemberTypes) == 1
typeName = mozMapMemberTypes[0].name typeName = mozMapMemberTypes[0].name
@ -6870,6 +6883,8 @@ def process_arg(expr, arg):
expr += ".r()" expr += ".r()"
else: else:
expr = "&" + expr expr = "&" + expr
elif isinstance(arg.type, IDLPromiseType):
expr = "&" + expr
return expr return expr

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,162 @@
def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions(DOMString a)] void foo(boolean arg2);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions(DOMString b)] readonly attribute boolean bar;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] attribute boolean bar;
};
""")
results = parser.finish()
except Exception, e:
harness.ok(False, "Shouldn't have thrown for [CEReactions] used on writable attribute. %s" % e)
threw = True
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] void foo(boolean arg2);
};
""")
results = parser.finish()
except Exception, e:
harness.ok(False, "Shouldn't have thrown for [CEReactions] used on regular operations. %s" % e)
threw = True
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] readonly attribute boolean A;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for [CEReactions] used on a readonly attribute")
parser = parser.reset()
threw = False
try:
parser.parse("""
[CEReactions]
interface Foo {
}
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for [CEReactions] used on a interface")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] getter any(DOMString name);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [CEReactions] used on a named getter")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] creator boolean (DOMString name, boolean value);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [CEReactions] used on a named creator")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] legacycaller double compute(double x);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [CEReactions] used on a legacycaller")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] stringifier DOMString ();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [CEReactions] used on a stringifier")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] jsonifier;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for [CEReactions] used on a jsonifier")

View file

@ -13,7 +13,7 @@ def WebIDLTest(parser, harness):
def checkMethod(method, QName, name, signatures, def checkMethod(method, QName, name, signatures,
static=True, getter=False, setter=False, creator=False, static=True, getter=False, setter=False, creator=False,
deleter=False, legacycaller=False, stringifier=False, deleter=False, legacycaller=False, stringifier=False,
chromeOnly=False): chromeOnly=False, htmlConstructor=False):
harness.ok(isinstance(method, WebIDL.IDLMethod), harness.ok(isinstance(method, WebIDL.IDLMethod),
"Should be an IDLMethod") "Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method") harness.ok(method.isMethod(), "Method is a method")
@ -29,6 +29,7 @@ def WebIDLTest(parser, harness):
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller 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(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.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(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
sigpairs = zip(method.signatures(), signatures) sigpairs = zip(method.signatures(), signatures)
@ -93,6 +94,21 @@ def WebIDLTest(parser, harness):
"constructor", [("TestChromeConstructor (Wrapper)", [])], "constructor", [("TestChromeConstructor (Wrapper)", [])],
chromeOnly=True) chromeOnly=True)
parser = parser.reset()
parser.parse("""
[HTMLConstructor]
interface TestHTMLConstructor {
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor",
"constructor", [("TestHTMLConstructor (Wrapper)", [])],
htmlConstructor=True)
parser = parser.reset() parser = parser.reset()
threw = False threw = False
try: try:
@ -107,3 +123,151 @@ def WebIDLTest(parser, harness):
threw = True threw = True
harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor") harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")
# Test HTMLConstructor with argument
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor(DOMString a)]
interface TestHTMLConstructorWithArgs {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "HTMLConstructor should take no argument")
# Test HTMLConstructor on a callback interface
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor]
callback interface TestHTMLConstructorOnCallbackInterface {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
# Test HTMLConstructor and Constructor
parser = parser.reset()
threw = False
try:
parser.parse("""
[Constructor,
HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a Constructor and a HTMLConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
Constructor]
interface TestHTMLConstructorAndConstructor {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
Constructor(DOMString a)]
interface TestHTMLConstructorAndConstructor {
};
""")
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Constructor(DOMString a),
HTMLConstructor]
interface TestHTMLConstructorAndConstructor {
};
""")
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
# Test HTMLConstructor and ChromeConstructor
parser = parser.reset()
threw = False
try:
parser.parse("""
[ChromeConstructor,
HTMLConstructor]
interface TestHTMLConstructorAndChromeConstructor {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
ChromeConstructor]
interface TestHTMLConstructorAndChromeConstructor {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[ChromeConstructor(DOMString a),
HTMLConstructor]
interface TestHTMLConstructorAndChromeConstructor {
};
""")
results = parser.finish()
except:
threw = True
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor,
ChromeConstructor(DOMString a)]
interface TestHTMLConstructorAndChromeConstructor {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")

View file

@ -34,3 +34,36 @@ def WebIDLTest(parser, harness):
interface TestNamedConstructorNoInterfaceObject { interface TestNamedConstructorNoInterfaceObject {
}; };
""") """)
# Test HTMLConstructor and NoInterfaceObject
parser = parser.reset()
threw = False
try:
parser.parse("""
[NoInterfaceObject, HTMLConstructor]
interface TestHTMLConstructorNoInterfaceObject {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
threw = False
try:
parser.parse("""
[HTMLConstructor, NoInterfaceObject]
interface TestHTMLConstructorNoInterfaceObject {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")

View file

@ -158,21 +158,27 @@ def WebIDLTest(parser, harness):
"CallbackInterface?", "CallbackInterface2", "CallbackInterface?", "CallbackInterface2",
"object", "Callback", "Callback2", "optional Dict", "object", "Callback", "Callback2", "optional Dict",
"optional Dict2", "sequence<long>", "sequence<short>", "optional Dict2", "sequence<long>", "sequence<short>",
"MozMap<object>", "MozMap<Dict>", "MozMap<long>", "record<DOMString, object>",
"record<USVString, Dict>",
"record<ByteString, long>",
"Date", "Date?", "any", "Date", "Date?", "any",
"Promise<any>", "Promise<any>?", "Promise<any>", "Promise<any>?",
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer", "USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"Uint8Array", "Uint16Array" ] "Uint8Array", "Uint16Array",
# When we can parse Date and RegExp, we need to add them here. "(long or Callback)", "optional (long or Dict)",
]
# When we can parse Date, we need to add it here.
# XXXbz we can, and should really do that...
# 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 for a in list1 if a not in list2 and
(a != "any" and a != "Promise<any>" and a != "Promise<any>?")] (a != "any" and a != "Promise<any>" and a != "Promise<any>?")]
unions = [ "(long or Callback)", "optional (long or Dict)" ]
numerics = [ "long", "short", "long?", "short?" ] numerics = [ "long", "short", "long?", "short?" ]
booleans = [ "boolean", "boolean?" ] booleans = [ "boolean", "boolean?" ]
primitives = numerics + booleans primitives = numerics + booleans
nonNumerics = allBut(argTypes, numerics) nonNumerics = allBut(argTypes, numerics + unions)
nonBooleans = allBut(argTypes, booleans) nonBooleans = allBut(argTypes, booleans)
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString" ] strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString" ]
nonStrings = allBut(argTypes, strings) nonStrings = allBut(argTypes, strings)
@ -182,16 +188,18 @@ def WebIDLTest(parser, harness):
sharedBufferSourceTypes = ["SharedArrayBuffer"] sharedBufferSourceTypes = ["SharedArrayBuffer"]
interfaces = [ "Interface", "Interface?", "AncestorInterface", interfaces = [ "Interface", "Interface?", "AncestorInterface",
"UnrelatedInterface", "ImplementedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes "UnrelatedInterface", "ImplementedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes
nullables = ["long?", "short?", "boolean?", "Interface?", nullables = (["long?", "short?", "boolean?", "Interface?",
"CallbackInterface?", "optional Dict", "optional Dict2", "CallbackInterface?", "optional Dict", "optional Dict2",
"Date?", "any", "Promise<any>?"] "Date?", "any", "Promise<any>?"] +
allBut(unions, [ "(long or Callback)" ]))
dates = [ "Date", "Date?" ] dates = [ "Date", "Date?" ]
sequences = [ "sequence<long>", "sequence<short>" ] sequences = [ "sequence<long>", "sequence<short>" ]
nonUserObjects = nonObjects + interfaces + dates + sequences nonUserObjects = nonObjects + interfaces + dates + sequences
otherObjects = allBut(argTypes, nonUserObjects + ["object"]) otherObjects = allBut(argTypes, nonUserObjects + ["object"])
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] + notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] +
otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes) otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes)
mozMaps = [ "MozMap<object>", "MozMap<Dict>", "MozMap<long>" ] records = [ "record<DOMString, object>", "record<USVString, Dict>",
"record<ByteString, long>" ]
# 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.
@ -231,9 +239,9 @@ def WebIDLTest(parser, harness):
allBut(argTypes, sequences + ["object"])) allBut(argTypes, sequences + ["object"]))
setDistinguishable("sequence<short>", setDistinguishable("sequence<short>",
allBut(argTypes, sequences + ["object"])) allBut(argTypes, sequences + ["object"]))
setDistinguishable("MozMap<object>", nonUserObjects) setDistinguishable("record<DOMString, object>", nonUserObjects)
setDistinguishable("MozMap<Dict>", nonUserObjects) setDistinguishable("record<USVString, Dict>", nonUserObjects)
setDistinguishable("MozMap<long>", nonUserObjects) setDistinguishable("record<ByteString, long>", nonUserObjects)
setDistinguishable("Date", allBut(argTypes, dates + ["object"])) setDistinguishable("Date", allBut(argTypes, dates + ["object"]))
setDistinguishable("Date?", allBut(argTypes, dates + nullables + ["object"])) setDistinguishable("Date?", allBut(argTypes, dates + nullables + ["object"]))
setDistinguishable("any", []) setDistinguishable("any", [])
@ -244,6 +252,10 @@ def WebIDLTest(parser, harness):
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"])) setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"]))
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])) setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"]))
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"])) setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
setDistinguishable("(long or Callback)",
allBut(nonUserObjects, numerics))
setDistinguishable("optional (long or Dict)",
allBut(nonUserObjects, numerics + nullables))
def areDistinguishable(type1, type2): def areDistinguishable(type1, type2):
return data[type1].get(type2, False) return data[type1].get(type2, False)
@ -263,7 +275,6 @@ def WebIDLTest(parser, harness):
callback Callback2 = long(short arg); callback Callback2 = long(short arg);
dictionary Dict {}; dictionary Dict {};
dictionary Dict2 {}; dictionary Dict2 {};
interface _Promise {};
interface TestInterface {%s interface TestInterface {%s
}; };
""" """

View file

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

View file

@ -88,6 +88,8 @@ def WebIDLTest(parser, harness):
disallowedNonMethodNames = ["clear", "delete"] disallowedNonMethodNames = ["clear", "delete"]
mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames
setDisallowedNonMethodNames = ["add"] + disallowedNonMethodNames setDisallowedNonMethodNames = ["add"] + disallowedNonMethodNames
unrelatedMembers = [("unrelatedAttribute", WebIDL.IDLAttribute),
("unrelatedMethod", WebIDL.IDLMethod)]
# #
# Simple Usage Tests # Simple Usage Tests
@ -99,52 +101,147 @@ def WebIDLTest(parser, harness):
iterable<long>; iterable<long>;
readonly attribute unsigned long length; readonly attribute unsigned long length;
getter long(unsigned long index); getter long(unsigned long index);
attribute long unrelatedAttribute;
long unrelatedMethod();
}; };
""", valueIterableMembers) """, valueIterableMembers + unrelatedMembers)
shouldPass("Iterable (key only) inheriting from parent",
"""
interface Foo1 : Foo2 {
iterable<long>;
readonly attribute unsigned long length;
getter long(unsigned long index);
};
interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", valueIterableMembers, numProductions=2)
shouldPass("Iterable (key and value)", shouldPass("Iterable (key and value)",
""" """
interface Foo1 { interface Foo1 {
iterable<long, long>; iterable<long, long>;
attribute long unrelatedAttribute;
long unrelatedMethod();
}; };
""", iterableMembers, """, iterableMembers + unrelatedMembers,
# numProductions == 2 because of the generated iterator iface, # numProductions == 2 because of the generated iterator iface,
numProductions=2) numProductions=2)
shouldPass("Maplike (readwrite)", shouldPass("Iterable (key and value) inheriting from parent",
""" """
interface Foo1 { interface Foo1 : Foo2 {
maplike<long, long>; iterable<long, long>;
}; };
""", mapRWMembers) interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", iterableMembers,
# numProductions == 3 because of the generated iterator iface,
numProductions=3)
shouldPass("Maplike (readwrite)", shouldPass("Maplike (readwrite)",
""" """
interface Foo1 { interface Foo1 {
maplike<long, long>; maplike<long, long>;
attribute long unrelatedAttribute;
long unrelatedMethod();
}; };
""", mapRWMembers) """, mapRWMembers + unrelatedMembers)
shouldPass("Maplike (readwrite) inheriting from parent",
"""
interface Foo1 : Foo2 {
maplike<long, long>;
};
interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", mapRWMembers, numProductions=2)
shouldPass("Maplike (readwrite)",
"""
interface Foo1 {
maplike<long, long>;
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", mapRWMembers + unrelatedMembers)
shouldPass("Maplike (readwrite) inheriting from parent",
"""
interface Foo1 : Foo2 {
maplike<long, long>;
};
interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", mapRWMembers, numProductions=2)
shouldPass("Maplike (readonly)", shouldPass("Maplike (readonly)",
""" """
interface Foo1 { interface Foo1 {
readonly maplike<long, long>; readonly maplike<long, long>;
attribute long unrelatedAttribute;
long unrelatedMethod();
}; };
""", mapROMembers) """, mapROMembers + unrelatedMembers)
shouldPass("Maplike (readonly) inheriting from parent",
"""
interface Foo1 : Foo2 {
readonly maplike<long, long>;
};
interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", mapROMembers, numProductions=2)
shouldPass("Setlike (readwrite)", shouldPass("Setlike (readwrite)",
""" """
interface Foo1 { interface Foo1 {
setlike<long>; setlike<long>;
attribute long unrelatedAttribute;
long unrelatedMethod();
}; };
""", setRWMembers) """, setRWMembers + unrelatedMembers)
shouldPass("Setlike (readwrite) inheriting from parent",
"""
interface Foo1 : Foo2 {
setlike<long>;
};
interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", setRWMembers, numProductions=2)
shouldPass("Setlike (readonly)", shouldPass("Setlike (readonly)",
""" """
interface Foo1 { interface Foo1 {
readonly setlike<long>; readonly setlike<long>;
attribute long unrelatedAttribute;
long unrelatedMethod();
}; };
""", setROMembers) """, setROMembers + unrelatedMembers)
shouldPass("Setlike (readonly) inheriting from parent",
"""
interface Foo1 : Foo2 {
readonly setlike<long>;
};
interface Foo2 {
attribute long unrelatedAttribute;
long unrelatedMethod();
};
""", setROMembers, numProductions=2)
shouldPass("Inheritance of maplike/setlike", shouldPass("Inheritance of maplike/setlike",
""" """

View file

@ -0,0 +1,70 @@
# Import the WebIDL module, so we can do isinstance checks and whatnot
import WebIDL
def WebIDLTest(parser, harness):
# Basic functionality
parser.parse(
"""
interface Iface {
[NewObject] readonly attribute Iface attr;
[NewObject] Iface method();
};
""")
results = parser.finish()
harness.ok(results, "Should not have thrown on basic [NewObject] usage")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Iface {
[Pure, NewObject] readonly attribute Iface attr;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "[NewObject] attributes must depend on something")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Iface {
[Pure, NewObject] Iface method();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "[NewObject] methods must depend on something")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Iface {
[Cached, NewObject, Affects=Nothing] readonly attribute Iface attr;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "[NewObject] attributes must not be [Cached]")
parser = parser.reset()
threw = False
try:
parser.parse(
"""
interface Iface {
[StoreInSlot, NewObject, Affects=Nothing] readonly attribute Iface attr;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "[NewObject] attributes must not be [StoreInSlot]")

View file

@ -2,7 +2,6 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse("""
interface _Promise {};
interface A { interface A {
legacycaller Promise<any> foo(); legacycaller Promise<any> foo();
}; };
@ -18,7 +17,6 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse("""
interface _Promise {};
interface A { interface A {
Promise<any> foo(); Promise<any> foo();
long foo(long arg); long foo(long arg);
@ -35,7 +33,6 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse("""
interface _Promise {};
interface A { interface A {
long foo(long arg); long foo(long arg);
Promise<any> foo(); Promise<any> foo();
@ -48,9 +45,36 @@ def WebIDLTest(parser, harness):
"Should not allow overloads which have both Promise and " "Should not allow overloads which have both Promise and "
"non-Promise return types.") "non-Promise return types.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
Promise<any>? foo();
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow nullable Promise return values.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
void foo(Promise<any>? arg);
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow nullable Promise arguments.")
parser = parser.reset() parser = parser.reset()
parser.parse(""" parser.parse("""
interface _Promise {};
interface A { interface A {
Promise<any> foo(); Promise<any> foo();
Promise<any> foo(long arg); Promise<any> foo(long arg);
@ -61,3 +85,73 @@ def WebIDLTest(parser, harness):
harness.ok(True, harness.ok(True,
"Should allow overloads which only have Promise and return " "Should allow overloads which only have Promise and return "
"types.") "types.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
attribute Promise<any> attr;
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow writable Promise-typed attributes.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[LenientSetter] readonly attribute Promise<any> attr;
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow [LenientSetter] Promise-typed attributes.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[PutForwards=bar] readonly attribute Promise<any> attr;
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow [PutForwards] Promise-typed attributes.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[Replaceable] readonly attribute Promise<any> attr;
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow [Replaceable] Promise-typed attributes.")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface A {
[SameObject] readonly attribute Promise<any> attr;
};
""")
results = parser.finish();
except:
threw = True
harness.ok(threw,
"Should not allow [SameObject] Promise-typed attributes.")

View file

@ -3,8 +3,8 @@ import WebIDL
def WebIDLTest(parser, harness): def WebIDLTest(parser, harness):
parser.parse(""" parser.parse("""
dictionary Dict {}; dictionary Dict {};
interface MozMapArg { interface RecordArg {
void foo(MozMap<Dict> arg); void foo(record<DOMString, Dict> arg);
}; };
""") """)
@ -19,7 +19,7 @@ def WebIDLTest(parser, harness):
signature = members[0].signatures()[0] signature = members[0].signatures()[0]
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.isMozMap(), "Should have a MozMap 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")
@ -27,13 +27,27 @@ def WebIDLTest(parser, harness):
threw = False threw = False
try: try:
parser.parse(""" parser.parse("""
interface MozMapVoidArg { interface RecordVoidArg {
void foo(MozMap<void> arg); void foo(record<DOMString, void> arg);
}; };
""") """)
results = parser.finish() results = parser.finish()
except Exception,x: except Exception,x:
threw = True threw = True
harness.ok(threw, "Should have thrown because record can't have void as value type.")
parser = parser.reset()
threw = False
try:
parser.parse("""
dictionary Dict {
record<DOMString, Dict> val;
};
""")
harness.ok(threw, "Should have thrown.") results = parser.finish()
except Exception,x:
threw = True
harness.ok(threw,
"Should have thrown on dictionary containing itself via record.")

View file

@ -6,15 +6,14 @@ def WebIDLTest(parser, harness):
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);
creator long long (unsigned long index, long long value); creator long long (unsigned long index, long long value);
deleter long long (unsigned long index);
getter boolean (DOMString name); getter boolean (DOMString name);
setter boolean (DOMString name, boolean value); setter boolean (DOMString name, boolean value);
creator boolean (DOMString name, boolean value); creator boolean (DOMString name, boolean value);
deleter boolean (DOMString name); deleter boolean (DOMString name);
readonly attribute unsigned long length;
}; };
interface SpecialMethodsCombination { interface SpecialMethodsCombination {
getter deleter long long (unsigned long index);
setter creator long long (unsigned long index, long long value); setter creator long long (unsigned long index, long long value);
getter deleter boolean (DOMString name); getter deleter boolean (DOMString name);
setter creator boolean (DOMString name, boolean value); setter creator boolean (DOMString name, boolean value);
@ -49,25 +48,39 @@ def WebIDLTest(parser, harness):
setter=True) setter=True)
checkMethod(iface.members[2], "::SpecialMethods::__indexedcreator", "__indexedcreator", checkMethod(iface.members[2], "::SpecialMethods::__indexedcreator", "__indexedcreator",
creator=True) creator=True)
checkMethod(iface.members[3], "::SpecialMethods::__indexeddeleter", "__indexeddeleter", checkMethod(iface.members[3], "::SpecialMethods::__namedgetter", "__namedgetter",
deleter=True)
checkMethod(iface.members[4], "::SpecialMethods::__namedgetter", "__namedgetter",
getter=True) getter=True)
checkMethod(iface.members[5], "::SpecialMethods::__namedsetter", "__namedsetter", checkMethod(iface.members[4], "::SpecialMethods::__namedsetter", "__namedsetter",
setter=True) setter=True)
checkMethod(iface.members[6], "::SpecialMethods::__namedcreator", "__namedcreator", checkMethod(iface.members[5], "::SpecialMethods::__namedcreator", "__namedcreator",
creator=True) creator=True)
checkMethod(iface.members[7], "::SpecialMethods::__nameddeleter", "__nameddeleter", checkMethod(iface.members[6], "::SpecialMethods::__nameddeleter", "__nameddeleter",
deleter=True) deleter=True)
iface = results[1] iface = results[1]
harness.check(len(iface.members), 4, "Expect 4 members") harness.check(len(iface.members), 3, "Expect 3 members")
checkMethod(iface.members[0], "::SpecialMethodsCombination::__indexedgetterdeleter", checkMethod(iface.members[0], "::SpecialMethodsCombination::__indexedsettercreator",
"__indexedgetterdeleter", getter=True, deleter=True)
checkMethod(iface.members[1], "::SpecialMethodsCombination::__indexedsettercreator",
"__indexedsettercreator", setter=True, creator=True) "__indexedsettercreator", setter=True, creator=True)
checkMethod(iface.members[2], "::SpecialMethodsCombination::__namedgetterdeleter", checkMethod(iface.members[1], "::SpecialMethodsCombination::__namedgetterdeleter",
"__namedgetterdeleter", getter=True, deleter=True) "__namedgetterdeleter", getter=True, deleter=True)
checkMethod(iface.members[3], "::SpecialMethodsCombination::__namedsettercreator", checkMethod(iface.members[2], "::SpecialMethodsCombination::__namedsettercreator",
"__namedsettercreator", setter=True, creator=True) "__namedsettercreator", setter=True, creator=True)
parser = parser.reset();
threw = False
try:
parser.parse(
"""
interface IndexedDeleter {
deleter void(unsigned long index);
};
""")
parser.finish()
except:
threw = True
harness.ok(threw, "There are no indexed deleters")

View file

@ -194,7 +194,7 @@ impl Headers {
} }
Ok(()) Ok(())
}, },
Some(HeadersInit::ByteStringMozMap(m)) => { Some(HeadersInit::StringByteStringRecord(m)) => {
for (key, value) in m.iter() { for (key, value) in m.iter() {
let key_vec = key.as_ref().to_string().into(); let key_vec = key.as_ref().to_string().into();
let headers_key = ByteString::new(key_vec); let headers_key = ByteString::new(key_vec);

View file

@ -311,9 +311,9 @@ impl Request {
try!(headers_copy.fill(Some( try!(headers_copy.fill(Some(
HeadersInit::ByteStringSequenceSequence(init_sequence.clone())))); HeadersInit::ByteStringSequenceSequence(init_sequence.clone()))));
}, },
&HeadersInit::ByteStringMozMap(ref init_map) => { &HeadersInit::StringByteStringRecord(ref init_map) => {
try!(headers_copy.fill(Some( try!(headers_copy.fill(Some(
HeadersInit::ByteStringMozMap(init_map.clone())))); HeadersInit::StringByteStringRecord(init_map.clone()))));
}, },
} }
} }
@ -880,8 +880,8 @@ impl Clone for HeadersInit {
HeadersInit::Headers(h.clone()), HeadersInit::Headers(h.clone()),
&HeadersInit::ByteStringSequenceSequence(ref b) => &HeadersInit::ByteStringSequenceSequence(ref b) =>
HeadersInit::ByteStringSequenceSequence(b.clone()), HeadersInit::ByteStringSequenceSequence(b.clone()),
&HeadersInit::ByteStringMozMap(ref m) => &HeadersInit::StringByteStringRecord(ref m) =>
HeadersInit::ByteStringMozMap(m.clone()), HeadersInit::StringByteStringRecord(m.clone()),
} }
} }
} }

View file

@ -662,9 +662,9 @@ impl TestBindingMethods for TestBinding {
fn PassStringMozMap(&self, _: MozMap<DOMString>) {} fn PassStringMozMap(&self, _: MozMap<DOMString>) {}
fn PassByteStringMozMap(&self, _: MozMap<ByteString>) {} fn PassByteStringMozMap(&self, _: MozMap<ByteString>) {}
fn PassMozMapOfMozMaps(&self, _: MozMap<MozMap<i32>>) {} fn PassMozMapOfMozMaps(&self, _: MozMap<MozMap<i32>>) {}
fn PassMozMapUnion(&self, _: UnionTypes::LongOrByteStringMozMap) {} fn PassMozMapUnion(&self, _: UnionTypes::LongOrStringByteStringRecord) {}
fn PassMozMapUnion2(&self, _: UnionTypes::TestBindingOrByteStringMozMap) {} fn PassMozMapUnion2(&self, _: UnionTypes::TestBindingOrStringByteStringRecord) {}
fn PassMozMapUnion3(&self, _: UnionTypes::TestBindingOrByteStringSequenceSequenceOrByteStringMozMap) {} fn PassMozMapUnion3(&self, _: UnionTypes::TestBindingOrByteStringSequenceSequenceOrStringByteStringRecord) {}
fn ReceiveMozMap(&self) -> MozMap<i32> { MozMap::new() } fn ReceiveMozMap(&self) -> MozMap<i32> { MozMap::new() }
fn ReceiveNullableMozMap(&self) -> Option<MozMap<i32>> { Some(MozMap::new()) } fn ReceiveNullableMozMap(&self) -> Option<MozMap<i32>> { Some(MozMap::new()) }
fn ReceiveMozMapOfNullableInts(&self) -> MozMap<Option<i32>> { MozMap::new() } fn ReceiveMozMapOfNullableInts(&self) -> MozMap<Option<i32>> { MozMap::new() }
@ -750,9 +750,6 @@ impl TestBindingMethods for TestBinding {
fn AcceptPromise(&self, _promise: &Promise) { fn AcceptPromise(&self, _promise: &Promise) {
} }
fn AcceptNullablePromise(&self, _promise: Option<&Promise>) {
}
fn PassSequenceSequence(&self, _seq: Vec<Vec<i32>>) {} fn PassSequenceSequence(&self, _seq: Vec<Vec<i32>>) {}
fn ReturnSequenceSequence(&self) -> Vec<Vec<i32>> { vec![] } fn ReturnSequenceSequence(&self) -> Vec<Vec<i32>> { vec![] }
fn PassUnionSequenceSequence(&self, seq: LongOrLongSequenceSequence) { fn PassUnionSequenceSequence(&self, seq: LongOrLongSequenceSequence) {

View file

@ -16,9 +16,9 @@ dictionary BluetoothLEScanFilterInit {
DOMString name; DOMString name;
DOMString namePrefix; DOMString namePrefix;
// Maps unsigned shorts to BluetoothDataFilters. // Maps unsigned shorts to BluetoothDataFilters.
MozMap<BluetoothDataFilterInit> manufacturerData; record<DOMString, BluetoothDataFilterInit> manufacturerData;
// Maps BluetoothServiceUUIDs to BluetoothDataFilters. // Maps BluetoothServiceUUIDs to BluetoothDataFilters.
MozMap<BluetoothDataFilterInit> serviceData; record<DOMString, BluetoothDataFilterInit> serviceData;
}; };
dictionary RequestDeviceOptions { dictionary RequestDeviceOptions {

View file

@ -4,7 +4,7 @@
// https://fetch.spec.whatwg.org/#headers-class // https://fetch.spec.whatwg.org/#headers-class
typedef (Headers or sequence<sequence<ByteString>> or MozMap<ByteString>) HeadersInit; typedef (Headers or sequence<sequence<ByteString>> or record<DOMString, ByteString>) HeadersInit;
[Constructor(optional HeadersInit init), [Constructor(optional HeadersInit init),
Exposed=(Window,Worker)] Exposed=(Window,Worker)]

View file

@ -434,33 +434,33 @@ interface TestBinding {
sequence<sequence<long>> returnSequenceSequence(); sequence<sequence<long>> returnSequenceSequence();
void passUnionSequenceSequence((long or sequence<sequence<long>>) seq); void passUnionSequenceSequence((long or sequence<sequence<long>>) seq);
void passMozMap(MozMap<long> arg); void passMozMap(record<DOMString, long> arg);
void passNullableMozMap(MozMap<long>? arg); void passNullableMozMap(record<DOMString, long>? arg);
void passMozMapOfNullableInts(MozMap<long?> arg); void passMozMapOfNullableInts(record<DOMString, long?> arg);
void passOptionalMozMapOfNullableInts(optional MozMap<long?> arg); void passOptionalMozMapOfNullableInts(optional record<DOMString, long?> arg);
void passOptionalNullableMozMapOfNullableInts(optional MozMap<long?>? arg); void passOptionalNullableMozMapOfNullableInts(optional record<DOMString, long?>? arg);
void passCastableObjectMozMap(MozMap<TestBinding> arg); void passCastableObjectMozMap(record<DOMString, TestBinding> arg);
void passNullableCastableObjectMozMap(MozMap<TestBinding?> arg); void passNullableCastableObjectMozMap(record<DOMString, TestBinding?> arg);
void passCastableObjectNullableMozMap(MozMap<TestBinding>? arg); void passCastableObjectNullableMozMap(record<DOMString, TestBinding>? arg);
void passNullableCastableObjectNullableMozMap(MozMap<TestBinding?>? arg); void passNullableCastableObjectNullableMozMap(record<DOMString, TestBinding?>? arg);
void passOptionalMozMap(optional MozMap<long> arg); void passOptionalMozMap(optional record<DOMString, long> arg);
void passOptionalNullableMozMap(optional MozMap<long>? arg); void passOptionalNullableMozMap(optional record<DOMString, long>? arg);
void passOptionalNullableMozMapWithDefaultValue(optional MozMap<long>? arg = null); void passOptionalNullableMozMapWithDefaultValue(optional record<DOMString, long>? arg = null);
void passOptionalObjectMozMap(optional MozMap<TestBinding> arg); void passOptionalObjectMozMap(optional record<DOMString, TestBinding> arg);
void passStringMozMap(MozMap<DOMString> arg); void passStringMozMap(record<DOMString, DOMString> arg);
void passByteStringMozMap(MozMap<ByteString> arg); void passByteStringMozMap(record<DOMString, ByteString> arg);
void passMozMapOfMozMaps(MozMap<MozMap<long>> arg); void passMozMapOfMozMaps(record<DOMString, record<DOMString, long>> arg);
void passMozMapUnion((long or MozMap<ByteString>) init); void passMozMapUnion((long or record<DOMString, ByteString>) init);
void passMozMapUnion2((TestBinding or MozMap<ByteString>) init); void passMozMapUnion2((TestBinding or record<DOMString, ByteString>) init);
void passMozMapUnion3((TestBinding or sequence<sequence<ByteString>> or MozMap<ByteString>) init); void passMozMapUnion3((TestBinding or sequence<sequence<ByteString>> or record<DOMString, ByteString>) init);
MozMap<long> receiveMozMap(); record<DOMString, long> receiveMozMap();
MozMap<long>? receiveNullableMozMap(); record<DOMString, long>? receiveNullableMozMap();
MozMap<long?> receiveMozMapOfNullableInts(); record<DOMString, long?> receiveMozMapOfNullableInts();
MozMap<long?>? receiveNullableMozMapOfNullableInts(); record<DOMString, long?>? receiveNullableMozMapOfNullableInts();
MozMap<MozMap<long>> receiveMozMapOfMozMaps(); record<DOMString, record<DOMString, long>> receiveMozMapOfMozMaps();
MozMap<any> receiveAnyMozMap(); record<DOMString, any> receiveAnyMozMap();
static attribute boolean booleanAttributeStatic; static attribute boolean booleanAttributeStatic;
static void receiveVoidStatic(); static void receiveVoidStatic();
@ -519,7 +519,6 @@ interface TestBinding {
Promise<any> returnRejectedPromise(any value); Promise<any> returnRejectedPromise(any value);
readonly attribute Promise<boolean> promiseAttribute; readonly attribute Promise<boolean> promiseAttribute;
void acceptPromise(Promise<DOMString> string); void acceptPromise(Promise<DOMString> string);
void acceptNullablePromise(Promise<DOMString>? string);
Promise<any> promiseNativeHandler(SimpleCallback? resolve, SimpleCallback? reject); Promise<any> promiseNativeHandler(SimpleCallback? resolve, SimpleCallback? reject);
void promiseResolveNative(Promise<any> p, any value); void promiseResolveNative(Promise<any> p, any value);
void promiseRejectNative(Promise<any> p, any value); void promiseRejectNative(Promise<any> p, any value);