/* -*- 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/. */
void WebTask::RunAbortAlgorithm() { // no-op if WebTask::Run has been called already if (mPromise->State() == Promise::PromiseState::Pending) { // There are two things that can keep a WebTask alive, either the abort // signal or WebTaskQueue. // It's possible that this task get cleared out from the WebTaskQueue first, // and then the abort signal get aborted. For example, the callback function // was async and there's a signal.abort() call in the callback. if (isInList()) {
remove();
}
mOwnerQueue->RemoveEntryFromTaskQueueMapIfNeeded();
mOwnerQueue = nullptr; // At this point mOwnerQueue is destructed and this is fine. // The caller of WebTask::Run keeps it alive.
ErrorResult error;
nsIGlobalObject* global = mPromise->GetGlobalObject(); if (!global || global->IsDying()) { returnfalse;
}
AutoJSAPI jsapi; if (!jsapi.Init(global)) { returnfalse;
}
// If the state is Rejected, it means the above Call triggers the // RunAbortAlgorithm method and rejected the promise
MOZ_ASSERT_IF(promiseState != Promise::PromiseState::Pending,
promiseState == Promise::PromiseState::Rejected); #endif
if (error.Failed()) { if (!error.IsUncatchableException()) {
mPromise->MaybeReject(std::move(error));
} else {
error.SuppressException();
}
} else {
mPromise->MaybeResolve(returnVal);
}
ErrorResult rv; // Instead of making WebTaskScheduler::PostTask throws, we always // create the promise and return it. This is because we need to // create the promise explicitly to be able to reject it with // signal's reason.
RefPtr<Promise> promise = Promise::Create(mParent, rv); if (rv.Failed()) { return nullptr;
}
nsIGlobalObject* global = GetParentObject(); if (!global || global->IsDying()) {
promise->MaybeRejectWithNotSupportedError("Current window is detached"); return promise.forget();
}
if (taskSignal.WasPassed()) {
AbortSignal& signalValue = taskSignal.Value();
if (signalValue.Aborted()) {
AutoJSAPI jsapi; if (!jsapi.Init(global)) {
promise->MaybeReject(NS_ERROR_UNEXPECTED); return promise.forget();
}
// Let queue be the result of selecting the scheduler task queue for scheduler // given signal and priority.
WebTaskQueue& taskQueue = SelectTaskQueue(taskSignal, taskPriority);
uint64_t delay = aOptions.mDelay;
RefPtr<WebTask> task = CreateTask(taskQueue, taskSignal, aCallback, promise); if (delay > 0) {
nsresult rv = SetTimeoutForDelayedTask(task, delay); if (NS_FAILED(rv)) {
promise->MaybeRejectWithUnknownError( "Failed to setup timeout for delayed task");
} return promise.forget();
}
if (!QueueTask(task)) {
MOZ_ASSERT(task->isInList());
task->remove();
promise->MaybeRejectWithNotSupportedError("Unable to queue the task"); return promise.forget();
}
WebTask* WebTaskScheduler::GetNextTask() const { // We first combine queues from both mStaticPriorityTaskQueues and // mDynamicPriorityTaskQueues into a single hash map which the // keys are the priorities and the values are all the queues that // belong to this priority. // // Then From the queues which // 1. Have scheduled tasks // 2. Its priority is not less than any other queues' priority // We pick the task which has the smallest enqueue order.
nsTHashMap<nsUint32HashKey, nsTArray<WebTaskQueue*>> allQueues;
for (auto iter = mStaticPriorityTaskQueues.ConstIter(); !iter.Done();
iter.Next()) { constauto& queue = iter.Data(); if (!queue->Tasks().isEmpty() && queue->GetFirstScheduledTask()) {
nsTArray<WebTaskQueue*>& queuesForThisPriority =
allQueues.LookupOrInsert(static_cast<uint32_t>(iter.Key()));
queuesForThisPriority.AppendElement(queue.get());
}
}
for (auto iter = mDynamicPriorityTaskQueues.ConstIter(); !iter.Done();
iter.Next()) { constauto& queue = iter.Data(); if (!queue->Tasks().isEmpty() && queue->GetFirstScheduledTask()) {
nsTArray<WebTaskQueue*>& queuesForThisPriority = allQueues.LookupOrInsert( static_cast<uint32_t>(iter.Key()->Priority()));
queuesForThisPriority.AppendElement(queue.get());
}
}
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.