/* -*- 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/. */
// Due to IterableIterator being a templated class, we implement the necessary // CC bits in a superclass that IterableIterator then inherits from. This allows // us to put the macros outside of the header. The base class has pure virtual // functions for Traverse/Unlink that the templated subclasses will override.
void KeyAndValueReturn(JSContext* aCx, JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aValue,
JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv) {
RootedDictionary<IterableKeyAndValueResult> dict(aCx);
dict.mDone = false; // Dictionary values are a Sequence, which is a FallibleTArray, so we need // to check returns when appending. if (!dict.mValue.AppendElement(aKey, mozilla::fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return;
} if (!dict.mValue.AppendElement(aValue, mozilla::fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return;
}
JS::Rooted<JS::Value> dictValue(aCx); if (!ToJSValue(aCx, dict, &dictValue)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
aResult.set(&dictValue.toObject());
}
// 4. Let nextPromise be the result of getting the next iteration result with // object’s target and object.
RefPtr<Promise> nextPromise;
{
ErrorResult error;
nextPromise = GetNextResult(error);
// 5. Let fulfillSteps be the following steps, given next: auto fulfillSteps = [](JSContext* aCx, JS::Handle<JS::Value> aNext,
ErrorResult& aRv, const RefPtr<AsyncIterableIteratorBase>& aObject, const nsCOMPtr<nsIGlobalObject>& aGlobalObject)
-> already_AddRefed<Promise> { // 1. Set object’s ongoing promise to null.
aObject->mOngoingPromise = nullptr;
// 2. If next is end of iteration, then:
JS::Rooted<JS::Value> dict(aCx); if (aNext.isMagic(binding_details::END_OF_ITERATION)) { // 1. Set object’s is finished to true.
aObject->mIsFinished = true; // 2. Return CreateIterResultObject(undefined, true).
iterator_utils::DictReturn(aCx, &dict, true, JS::UndefinedHandleValue,
aRv); if (aRv.Failed()) { return nullptr;
}
} else { // 3. Otherwise, if interface has a pair asynchronously iterable // declaration: // 1. Assert: next is a value pair. // 2. Return the iterator result for next and kind. // 4. Otherwise: // 1. Assert: interface has a value asynchronously iterable declaration. // 2. Assert: next is a value of the type that appears in the // declaration. // 3. Let value be next, converted to an ECMAScript value. // 4. Return CreateIterResultObject(value, false).
iterator_utils::DictReturn(aCx, &dict, false, aNext, aRv); if (aRv.Failed()) { return nullptr;
}
} // Note that ThenCatchWithCycleCollectedArgs expects a Promise, so // we use Promise::Resolve here. The specs do convert this to a // promise too at another point, but the end result should be the // same. return Promise::Resolve(aGlobalObject, aCx, dict, aRv);
}; // 7. Let rejectSteps be the following steps, given reason: auto rejectSteps = [](JSContext* aCx, JS::Handle<JS::Value> aReason,
ErrorResult& aRv, const RefPtr<AsyncIterableIteratorBase>& aObject, const nsCOMPtr<nsIGlobalObject>& aGlobalObject) { // 1. Set object’s ongoing promise to null.
aObject->mOngoingPromise = nullptr; // 2. Set object’s is finished to true.
aObject->mIsFinished = true; // 3. Throw reason. return Promise::Reject(aGlobalObject, aCx, aReason, aRv);
}; // 9. Perform PerformPromiseThen(nextPromise, onFulfilled, onRejected, // nextPromiseCapability).
Result<RefPtr<Promise>, nsresult> result =
nextPromise->ThenCatchWithCycleCollectedArgs(
std::move(fulfillSteps), std::move(rejectSteps), RefPtr{aObject},
nsCOMPtr{aGlobalObject});
// 3.7.10.2. Asynchronous iterator prototype object // … // 10. If ongoingPromise is not null, then: if (aObject->mOngoingPromise) { // 1. Let afterOngoingPromiseCapability be // ! NewPromiseCapability(%Promise%). // 2. Let onSettled be CreateBuiltinFunction(nextSteps, « »).
// aObject is the same object as 'this', so it's fine to capture 'this' // without taking a strong reference, because we already take a strong // reference to it through aObject. auto onSettled = [this](JSContext* aCx, JS::Handle<JS::Value> aValue,
ErrorResult& aRv, const RefPtr<AsyncIterableIteratorBase>& aObject, const nsCOMPtr<nsIGlobalObject>& aGlobalObject)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { return NextSteps(aCx, aObject, aGlobalObject, aRv);
};
// 3. Set object’s is finished to true.
aObject->mIsFinished = true;
// 4. Return the result of running the asynchronous iterator return algorithm // for interface, given object’s target, object, and value.
ErrorResult error;
RefPtr<Promise> returnPromise = GetReturnPromise(aCx, aValue, error);
error.WouldReportJSException(); if (error.Failed()) { return Promise::Reject(aGlobalObject, std::move(error), aRv);
}
// 3.7.10.2. Asynchronous iterator prototype object // …
RefPtr<Promise> returnStepsPromise; // 11. If ongoingPromise is not null, then: if (aObject->mOngoingPromise) { // 1. Let afterOngoingPromiseCapability be // ! NewPromiseCapability(%Promise%). // 2. Let onSettled be CreateBuiltinFunction(returnSteps, « »).
// aObject is the same object as 'this', so it's fine to capture 'this' // without taking a strong reference, because we already take a strong // reference to it through aObject. auto onSettled =
[this](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, const RefPtr<AsyncIterableIteratorBase>& aObject, const nsCOMPtr<nsIGlobalObject>& aGlobalObject,
JS::Handle<JS::Value> aVal) MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION { return ReturnSteps(aCx, aObject, aGlobalObject, aVal, aRv);
};
// 4. Set returnStepsPromise to afterOngoingPromiseCapability.[[Promise]].
returnStepsPromise = afterOngoingPromise.unwrap().forget();
} else { // 12. Otherwise: // 1. Set returnStepsPromise to the result of running returnSteps.
returnStepsPromise = ReturnSteps(aCx, aObject, globalObject, aValue, aRv);
}
// 13. Let fulfillSteps be the following steps: auto onFullFilled = [](JSContext* aCx, JS::Handle<JS::Value>,
ErrorResult& aRv, const nsCOMPtr<nsIGlobalObject>& aGlobalObject,
JS::Handle<JS::Value> aVal) { // 1. Return CreateIterResultObject(value, true).
JS::Rooted<JS::Value> dict(aCx);
iterator_utils::DictReturn(aCx, &dict, true, aVal, aRv); return Promise::Resolve(aGlobalObject, aCx, dict, aRv);
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.