mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1781730 - Support optional arguments in async iterable declarations. r=edgar
Differential Revision: https://phabricator.services.mozilla.com/D155422
This commit is contained in:
parent
79ce0456b5
commit
d81d165c25
@ -9519,6 +9519,7 @@ class CGPerSignatureCall(CGThing):
|
||||
descriptor,
|
||||
idlNode.maplikeOrSetlikeOrIterable,
|
||||
idlNode.identifier.name,
|
||||
self.getArgumentNames(),
|
||||
)
|
||||
)
|
||||
elif idlNode.isAttr() and idlNode.type.isObservableArray():
|
||||
@ -9602,8 +9603,11 @@ class CGPerSignatureCall(CGThing):
|
||||
|
||||
self.cgRoot = CGList(cgThings)
|
||||
|
||||
def getArgumentNames(self):
|
||||
return ["arg" + str(i) for i in range(len(self.arguments))]
|
||||
|
||||
def getArguments(self):
|
||||
return [(a, "arg" + str(i)) for i, a in enumerate(self.arguments)]
|
||||
return list(zip(self.arguments, self.getArgumentNames()))
|
||||
|
||||
def processWebExtensionStubAttribute(self, idlNode, cgThings):
|
||||
nativeMethodName = "CallWebExtMethod"
|
||||
@ -22107,8 +22111,10 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||
using CGCallGenerator.
|
||||
"""
|
||||
|
||||
def __init__(self, descriptor, iterable, methodName):
|
||||
def __init__(self, descriptor, iterable, methodName, args):
|
||||
if methodName == "forEach":
|
||||
assert len(args) == 2
|
||||
|
||||
CGGeneric.__init__(
|
||||
self,
|
||||
fill(
|
||||
@ -22144,6 +22150,8 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||
return
|
||||
|
||||
if descriptor.interface.isIterable():
|
||||
assert len(args) == 0
|
||||
|
||||
binding = descriptor.interface.identifier.name + "Iterator_Binding"
|
||||
init = ""
|
||||
else:
|
||||
@ -22154,12 +22162,13 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||
"""
|
||||
{
|
||||
ErrorResult initError;
|
||||
self->InitAsyncIterator(result.get(), initError);
|
||||
self->InitAsyncIterator(result.get(), ${args}initError);
|
||||
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for ${ifaceName} failed")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
""",
|
||||
args="".join(a + ", " for a in args),
|
||||
ifaceName=descriptor.interface.identifier.name,
|
||||
)
|
||||
CGGeneric.__init__(
|
||||
|
@ -132,6 +132,7 @@ if CONFIG["MOZ_DEBUG"] and CONFIG["ENABLE_TESTS"]:
|
||||
"test/TestInterfaceAsyncIterableDouble.h",
|
||||
"test/TestInterfaceAsyncIterableDoubleUnion.h",
|
||||
"test/TestInterfaceAsyncIterableSingle.h",
|
||||
"test/TestInterfaceAsyncIterableSingleWithArgs.h",
|
||||
"test/TestInterfaceIterableDouble.h",
|
||||
"test/TestInterfaceIterableDoubleUnion.h",
|
||||
"test/TestInterfaceIterableSingle.h",
|
||||
@ -150,6 +151,7 @@ if CONFIG["MOZ_DEBUG"] and CONFIG["ENABLE_TESTS"]:
|
||||
"test/TestInterfaceAsyncIterableDouble.cpp",
|
||||
"test/TestInterfaceAsyncIterableDoubleUnion.cpp",
|
||||
"test/TestInterfaceAsyncIterableSingle.cpp",
|
||||
"test/TestInterfaceAsyncIterableSingleWithArgs.cpp",
|
||||
"test/TestInterfaceIterableDouble.cpp",
|
||||
"test/TestInterfaceIterableDoubleUnion.cpp",
|
||||
"test/TestInterfaceIterableSingle.cpp",
|
||||
|
@ -13,6 +13,7 @@ import math
|
||||
import string
|
||||
from collections import defaultdict, OrderedDict
|
||||
from itertools import chain
|
||||
import copy
|
||||
|
||||
# Machinery
|
||||
|
||||
@ -4723,7 +4724,7 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
# Iterable adds ES6 iterator style functions and traits
|
||||
# (keys/values/entries/@@iterator) to an interface.
|
||||
class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
def __init__(self, location, identifier, keyType, valueType=None, scope=None):
|
||||
def __init__(self, location, identifier, keyType, valueType, scope):
|
||||
IDLMaplikeOrSetlikeOrIterableBase.__init__(
|
||||
self,
|
||||
location,
|
||||
@ -4798,9 +4799,15 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
|
||||
|
||||
class IDLAsyncIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
def __init__(
|
||||
self, location, identifier, keyType, valueType=None, argList=None, scope=None
|
||||
):
|
||||
def __init__(self, location, identifier, keyType, valueType, argList, scope):
|
||||
for arg in argList:
|
||||
if not arg.optional:
|
||||
raise WebIDLError(
|
||||
"The arguments of the asynchronously iterable declaration on "
|
||||
"%s must all be optional arguments." % identifier,
|
||||
[arg.location],
|
||||
)
|
||||
|
||||
IDLMaplikeOrSetlikeOrIterableBase.__init__(
|
||||
self,
|
||||
location,
|
||||
@ -4812,10 +4819,6 @@ class IDLAsyncIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
)
|
||||
self.iteratorType = None
|
||||
self.argList = argList
|
||||
if argList is not None:
|
||||
raise WebIDLError(
|
||||
"Arguments of async iterable are not supported yet. Please reference Bug 1781730."
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return "declared async iterable with key '%s' and value '%s'" % (
|
||||
@ -4835,6 +4838,7 @@ class IDLAsyncIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
members,
|
||||
False,
|
||||
self.iteratorType,
|
||||
self.argList,
|
||||
affectsNothing=True,
|
||||
newObject=True,
|
||||
isIteratorAlias=(not self.isPairIterator()),
|
||||
@ -4844,12 +4848,17 @@ class IDLAsyncIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
if not self.isPairIterator():
|
||||
return
|
||||
|
||||
# Methods can't share their IDLArguments, so we need to make copies here.
|
||||
def copyArgList(argList):
|
||||
return map(copy.copy, argList)
|
||||
|
||||
# object entries()
|
||||
self.addMethod(
|
||||
"entries",
|
||||
members,
|
||||
False,
|
||||
self.iteratorType,
|
||||
copyArgList(self.argList),
|
||||
affectsNothing=True,
|
||||
newObject=True,
|
||||
isIteratorAlias=True,
|
||||
@ -4860,6 +4869,7 @@ class IDLAsyncIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
members,
|
||||
False,
|
||||
self.iteratorType,
|
||||
copyArgList(self.argList),
|
||||
affectsNothing=True,
|
||||
newObject=True,
|
||||
)
|
||||
@ -7753,11 +7763,11 @@ class Parser(Tokenizer):
|
||||
elif len(p) == 9:
|
||||
keyType = p[4]
|
||||
valueType = p[6]
|
||||
argList = None
|
||||
argList = []
|
||||
else:
|
||||
keyType = None
|
||||
valueType = p[4]
|
||||
argList = None
|
||||
argList = []
|
||||
|
||||
p[0] = IDLAsyncIterable(
|
||||
location, identifier, keyType, valueType, argList, self.globalScope()
|
||||
|
@ -89,10 +89,18 @@ def WebIDLTest(parser, harness):
|
||||
# __iterable to it for the iterable<> case.
|
||||
iterableMembers.append(("__iterable", WebIDL.IDLIterable))
|
||||
|
||||
asyncIterableMembers = [
|
||||
(x, WebIDL.IDLMethod) for x in ["entries", "keys", "values"]
|
||||
]
|
||||
asyncIterableMembers.append(("__iterable", WebIDL.IDLAsyncIterable))
|
||||
|
||||
valueIterableMembers = [("__iterable", WebIDL.IDLIterable)]
|
||||
valueIterableMembers.append(("__indexedgetter", WebIDL.IDLMethod))
|
||||
valueIterableMembers.append(("length", WebIDL.IDLAttribute))
|
||||
|
||||
valueAsyncIterableMembers = [("__iterable", WebIDL.IDLAsyncIterable)]
|
||||
valueAsyncIterableMembers.append(("values", WebIDL.IDLMethod))
|
||||
|
||||
disallowedIterableNames = ["keys", "entries", "values"]
|
||||
disallowedMemberNames = ["forEach", "has", "size"] + disallowedIterableNames
|
||||
mapDisallowedMemberNames = ["get"] + disallowedMemberNames
|
||||
@ -169,6 +177,94 @@ def WebIDLTest(parser, harness):
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key only)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueAsyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key only) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
async iterable<long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueAsyncIterableMembers,
|
||||
# numProductions == 3 because of the generated iterator iface,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable with argument (key only)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>(optional long foo);
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
valueAsyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key and value)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long, long>;
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
asyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable (key and value) inheriting from parent",
|
||||
"""
|
||||
interface Foo1 : Foo2 {
|
||||
async iterable<long, long>;
|
||||
};
|
||||
interface Foo2 {
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
asyncIterableMembers,
|
||||
# numProductions == 3 because of the generated iterator iface,
|
||||
numProductions=3,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Async iterable with argument (key and value)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long, long>(optional long foo);
|
||||
attribute long unrelatedAttribute;
|
||||
long unrelatedMethod();
|
||||
};
|
||||
""",
|
||||
asyncIterableMembers + unrelatedMembers,
|
||||
# numProductions == 2 because of the generated iterator iface,
|
||||
numProductions=2,
|
||||
)
|
||||
|
||||
shouldPass(
|
||||
"Maplike (readwrite)",
|
||||
"""
|
||||
@ -373,6 +469,53 @@ def WebIDLTest(parser, harness):
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two iterables on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
async iterable<long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two iterables on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>;
|
||||
async iterable<long, long>;
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Async iterable with non-optional arguments",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>(long foo);
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Async iterable with non-optional arguments",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long>(optional long foo, long bar);
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Async iterable with non-optional arguments",
|
||||
"""
|
||||
interface Foo1 {
|
||||
async iterable<long, long>(long foo);
|
||||
};
|
||||
""",
|
||||
)
|
||||
|
||||
shouldFail(
|
||||
"Two maplike/setlikes in partials",
|
||||
"""
|
||||
|
@ -59,7 +59,7 @@ void TestInterfaceAsyncIterableSingle::InitAsyncIterator(Iterator* aIterator,
|
||||
return;
|
||||
}
|
||||
|
||||
UniquePtr<IteratorData> data(new IteratorData(0));
|
||||
UniquePtr<IteratorData> data(new IteratorData(0, 1));
|
||||
aIterator->SetData((void*)data.release());
|
||||
}
|
||||
|
||||
@ -71,21 +71,31 @@ void TestInterfaceAsyncIterableSingle::DestroyAsyncIterator(
|
||||
|
||||
already_AddRefed<Promise> TestInterfaceAsyncIterableSingle::GetNextPromise(
|
||||
JSContext* aCx, Iterator* aIterator, ErrorResult& aRv) {
|
||||
return GetNextPromise(aCx, aIterator,
|
||||
reinterpret_cast<IteratorData*>(aIterator->GetData()),
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> TestInterfaceAsyncIterableSingle::GetNextPromise(
|
||||
JSContext* aCx, IterableIteratorBase* aIterator, IteratorData* aData,
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData());
|
||||
data->mPromise = promise;
|
||||
aData->mPromise = promise;
|
||||
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"TestInterfaceAsyncIterableSingle::GetNextPromise",
|
||||
[data, self = RefPtr{this}] { self->ResolvePromise(data); }));
|
||||
[iterator = RefPtr{aIterator}, aData, self = RefPtr{this}] {
|
||||
self->ResolvePromise(iterator, aData);
|
||||
}));
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void TestInterfaceAsyncIterableSingle::ResolvePromise(IteratorData* aData) {
|
||||
void TestInterfaceAsyncIterableSingle::ResolvePromise(
|
||||
IterableIteratorBase* aIterator, IteratorData* aData) {
|
||||
AutoJSAPI jsapi;
|
||||
if (NS_WARN_IF(!jsapi.Init(mParent))) {
|
||||
return;
|
||||
@ -96,7 +106,8 @@ void TestInterfaceAsyncIterableSingle::ResolvePromise(IteratorData* aData) {
|
||||
iterator_utils::ResolvePromiseForFinished(cx, aData->mPromise, rv);
|
||||
} else {
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
Unused << ToJSValue(cx, (int32_t)(aData->mIndex * 9 % 7), &value);
|
||||
Unused << ToJSValue(
|
||||
cx, (int32_t)(aData->mIndex * 9 % 7 * aData->mMultiplier), &value);
|
||||
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, value,
|
||||
rv);
|
||||
|
||||
|
@ -25,14 +25,14 @@ struct TestInterfaceAsyncIterableSingleOptions;
|
||||
|
||||
// Implementation of test binding for webidl iterable interfaces, using
|
||||
// primitives for value type
|
||||
class TestInterfaceAsyncIterableSingle final : public nsISupports,
|
||||
public nsWrapperCache {
|
||||
class TestInterfaceAsyncIterableSingle : public nsISupports,
|
||||
public nsWrapperCache {
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceAsyncIterableSingle)
|
||||
|
||||
TestInterfaceAsyncIterableSingle(nsPIDOMWindowInner* aParent,
|
||||
bool aFailToInit);
|
||||
explicit TestInterfaceAsyncIterableSingle(nsPIDOMWindowInner* aParent,
|
||||
bool aFailToInit = false);
|
||||
nsPIDOMWindowInner* GetParentObject() const;
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
@ -46,9 +46,10 @@ class TestInterfaceAsyncIterableSingle final : public nsISupports,
|
||||
already_AddRefed<Promise> GetNextPromise(JSContext* aCx, Iterator* aIterator,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
protected:
|
||||
struct IteratorData {
|
||||
explicit IteratorData(int32_t aIndex) : mIndex(aIndex) {}
|
||||
IteratorData(int32_t aIndex, uint32_t aMultiplier)
|
||||
: mIndex(aIndex), mMultiplier(aMultiplier) {}
|
||||
~IteratorData() {
|
||||
if (mPromise) {
|
||||
mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
@ -57,9 +58,18 @@ class TestInterfaceAsyncIterableSingle final : public nsISupports,
|
||||
}
|
||||
RefPtr<Promise> mPromise;
|
||||
uint32_t mIndex;
|
||||
uint32_t mMultiplier;
|
||||
};
|
||||
|
||||
already_AddRefed<Promise> GetNextPromise(JSContext* aCx,
|
||||
IterableIteratorBase* aIterator,
|
||||
IteratorData* aData,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual ~TestInterfaceAsyncIterableSingle() = default;
|
||||
void ResolvePromise(IteratorData* aData);
|
||||
|
||||
private:
|
||||
void ResolvePromise(IterableIteratorBase* aIterator, IteratorData* aData);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mParent;
|
||||
bool mFailToInit;
|
||||
|
@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/TestInterfaceAsyncIterableSingleWithArgs.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/IterableIterator.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
// static
|
||||
already_AddRefed<TestInterfaceAsyncIterableSingleWithArgs>
|
||||
TestInterfaceAsyncIterableSingleWithArgs::Constructor(
|
||||
const GlobalObject& aGlobal, ErrorResult& aRv) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<TestInterfaceAsyncIterableSingleWithArgs> r =
|
||||
new TestInterfaceAsyncIterableSingleWithArgs(window);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
JSObject* TestInterfaceAsyncIterableSingleWithArgs::WrapObject(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
||||
return TestInterfaceAsyncIterableSingleWithArgs_Binding::Wrap(aCx, this,
|
||||
aGivenProto);
|
||||
}
|
||||
|
||||
void TestInterfaceAsyncIterableSingleWithArgs::InitAsyncIterator(
|
||||
Iterator* aIterator, const TestInterfaceAsyncIteratorOptions& aOptions,
|
||||
ErrorResult& aError) {
|
||||
UniquePtr<IteratorData> data(new IteratorData(0, aOptions.mMultiplier));
|
||||
aIterator->SetData((void*)data.release());
|
||||
}
|
||||
|
||||
void TestInterfaceAsyncIterableSingleWithArgs::DestroyAsyncIterator(
|
||||
Iterator* aIterator) {
|
||||
auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData());
|
||||
delete data;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
TestInterfaceAsyncIterableSingleWithArgs::GetNextPromise(JSContext* aCx,
|
||||
Iterator* aIterator,
|
||||
ErrorResult& aRv) {
|
||||
return TestInterfaceAsyncIterableSingle::GetNextPromise(
|
||||
aCx, aIterator, reinterpret_cast<IteratorData*>(aIterator->GetData()),
|
||||
aRv);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
40
dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h
Normal file
40
dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_TestInterfaceAsyncIterableSingleWithArgs_h
|
||||
#define mozilla_dom_TestInterfaceAsyncIterableSingleWithArgs_h
|
||||
|
||||
#include "mozilla/dom/TestInterfaceAsyncIterableSingle.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
struct TestInterfaceAsyncIteratorOptions;
|
||||
|
||||
// Implementation of test binding for webidl iterable interfaces, using
|
||||
// primitives for value type
|
||||
class TestInterfaceAsyncIterableSingleWithArgs final
|
||||
: public TestInterfaceAsyncIterableSingle {
|
||||
public:
|
||||
using TestInterfaceAsyncIterableSingle::TestInterfaceAsyncIterableSingle;
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
static already_AddRefed<TestInterfaceAsyncIterableSingleWithArgs> Constructor(
|
||||
const GlobalObject& aGlobal, ErrorResult& rv);
|
||||
|
||||
using Iterator =
|
||||
AsyncIterableIterator<TestInterfaceAsyncIterableSingleWithArgs>;
|
||||
void InitAsyncIterator(Iterator* aIterator,
|
||||
const TestInterfaceAsyncIteratorOptions& aOptions,
|
||||
ErrorResult& aError);
|
||||
void DestroyAsyncIterator(Iterator* aIterator);
|
||||
|
||||
already_AddRefed<Promise> GetNextPromise(JSContext* aCx, Iterator* aIterator,
|
||||
ErrorResult& aRv);
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif // mozilla_dom_TestInterfaceAsyncIterableSingleWithArgs_h
|
@ -14,6 +14,19 @@ add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]});
|
||||
});
|
||||
|
||||
async function check_single_result(itr, multiplier = 1) {
|
||||
let values = [];
|
||||
for await (let v of itr) {
|
||||
values.push(v);
|
||||
}
|
||||
is(values.length, 10, `AsyncIterableSingle: should returns 10 elements`);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let expected = i * 9 % 7 * multiplier;
|
||||
is(values[i], expected,
|
||||
`AsyncIterableSingle: should be ${expected}, get ${values[i]}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function test_data_single() {
|
||||
info(`AsyncIterableSingle: Testing simple iterable creation and functionality`);
|
||||
|
||||
@ -35,27 +48,16 @@ async function test_data_single() {
|
||||
is(itr.values, itr[Symbol.asyncIterator],
|
||||
`AsyncIterableSingle: Should be using @@asyncIterator for 'values'`);
|
||||
|
||||
let values = [];
|
||||
for await (let v of itr) {
|
||||
values.push(v);
|
||||
}
|
||||
is(values.length, 10, `AsyncIterableSingle: should returns 10 elements`);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let expected = i * 9 % 7;
|
||||
is(values[i], i * 9 % 7,
|
||||
`AsyncIterableSingle: should be ${expected}, get ${values[i]}`);
|
||||
}
|
||||
await check_single_result(itr);
|
||||
await check_single_result(itr.values());
|
||||
|
||||
values = [];
|
||||
for await (let v of itr.values()) {
|
||||
values.push(v);
|
||||
}
|
||||
is(values.length, 10, `AsyncIterableSingle: should returns 10 elements`);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let expected = i * 9 % 7;
|
||||
is(values[i], i * 9 % 7,
|
||||
`AsyncIterableSingle: should be ${expected}, get ${values[i]}`);
|
||||
}
|
||||
// eslint-disable-next-line no-undef
|
||||
itr = new TestInterfaceAsyncIterableSingleWithArgs();
|
||||
is(itr.values, itr[Symbol.asyncIterator],
|
||||
`AsyncIterableSingleWithArgs: Should be using @@asyncIterator for 'values'`);
|
||||
|
||||
await check_single_result(itr, 1);
|
||||
await check_single_result(itr.values({ multiplier: 2 }), 2);
|
||||
}
|
||||
|
||||
async function test_data_double() {
|
||||
|
@ -109,6 +109,19 @@ interface TestInterfaceAsyncIterableSingle {
|
||||
async iterable<long>;
|
||||
};
|
||||
|
||||
dictionary TestInterfaceAsyncIteratorOptions {
|
||||
unsigned long multiplier = 1;
|
||||
};
|
||||
|
||||
[Pref="dom.expose_test_interfaces",
|
||||
Exposed=Window]
|
||||
interface TestInterfaceAsyncIterableSingleWithArgs {
|
||||
[Throws]
|
||||
constructor();
|
||||
|
||||
async iterable<long>(optional TestInterfaceAsyncIteratorOptions options = {});
|
||||
};
|
||||
|
||||
[Pref="dom.expose_test_interfaces",
|
||||
Exposed=Window]
|
||||
interface TestInterfaceAsyncIterableDouble {
|
||||
|
Loading…
Reference in New Issue
Block a user