Bug 1964407 - Implement TaskSignal.any for the web task scheduling API r=jjaschke,dom-core,webidl,smaug
Spec: https://wicg.github.io/scheduling-apis/#dom-tasksignal-any Differential Revision: https://phabricator.services.mozilla.com/D248346
This commit is contained in:
committed by
sefeng@mozilla.com
parent
2dbaa8bc5c
commit
3d9727c887
@@ -55,7 +55,8 @@ nsIGlobalObject* AbortController::GetParentObject() const { return mGlobal; }
|
||||
AbortSignal* AbortController::Signal() {
|
||||
if (!mSignal) {
|
||||
JS::Rooted<JS::Value> reason(RootingCx(), mReason);
|
||||
mSignal = new AbortSignal(mGlobal, mAborted, reason);
|
||||
mSignal = AbortSignal::Create(
|
||||
mGlobal, mAborted ? SignalAborted::Yes : SignalAborted::No, reason);
|
||||
}
|
||||
|
||||
return mSignal;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
enum class SignalAborted { No, Yes };
|
||||
|
||||
class AbortSignal;
|
||||
class AbortSignalImpl;
|
||||
|
||||
@@ -54,7 +56,8 @@ class AbortFollower : public nsISupports {
|
||||
*/
|
||||
class AbortSignalImpl : public nsISupports, public SupportsWeakPtr {
|
||||
public:
|
||||
explicit AbortSignalImpl(bool aAborted, JS::Handle<JS::Value> aReason);
|
||||
explicit AbortSignalImpl(SignalAborted aAborted,
|
||||
JS::Handle<JS::Value> aReason);
|
||||
|
||||
bool Aborted() const;
|
||||
|
||||
@@ -99,7 +102,7 @@ class AbortSignalImpl : public nsISupports, public SupportsWeakPtr {
|
||||
// abort algorithms) empty this and make all contained followers |Unfollow()|.
|
||||
nsTObserverArray<RefPtr<AbortFollower>> mFollowers;
|
||||
|
||||
bool mAborted;
|
||||
SignalAborted mAborted;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -23,16 +23,17 @@ namespace mozilla::dom {
|
||||
// AbortSignalImpl
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
AbortSignalImpl::AbortSignalImpl(bool aAborted, JS::Handle<JS::Value> aReason)
|
||||
AbortSignalImpl::AbortSignalImpl(SignalAborted aAborted,
|
||||
JS::Handle<JS::Value> aReason)
|
||||
: mReason(aReason), mAborted(aAborted) {
|
||||
MOZ_ASSERT_IF(!mReason.isUndefined(), mAborted);
|
||||
MOZ_ASSERT_IF(!mReason.isUndefined(), Aborted());
|
||||
}
|
||||
|
||||
bool AbortSignalImpl::Aborted() const { return mAborted; }
|
||||
bool AbortSignalImpl::Aborted() const { return mAborted == SignalAborted::Yes; }
|
||||
|
||||
void AbortSignalImpl::GetReason(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aReason) {
|
||||
if (!mAborted) {
|
||||
if (!Aborted()) {
|
||||
return;
|
||||
}
|
||||
MaybeAssignAbortError(aCx);
|
||||
@@ -44,7 +45,7 @@ JS::Value AbortSignalImpl::RawReason() const { return mReason.get(); }
|
||||
// https://dom.spec.whatwg.org/#abortsignal-signal-abort
|
||||
void AbortSignalImpl::SignalAbort(JS::Handle<JS::Value> aReason) {
|
||||
// Step 1: If signal is aborted, then return.
|
||||
if (mAborted) {
|
||||
if (Aborted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,7 +85,7 @@ void AbortSignalImpl::RunAbortSteps() {
|
||||
}
|
||||
|
||||
void AbortSignalImpl::SetAborted(JS::Handle<JS::Value> aReason) {
|
||||
mAborted = true;
|
||||
mAborted = SignalAborted::Yes;
|
||||
mReason = aReason;
|
||||
}
|
||||
|
||||
@@ -99,7 +100,7 @@ void AbortSignalImpl::Unlink(AbortSignalImpl* aSignal) {
|
||||
}
|
||||
|
||||
void AbortSignalImpl::MaybeAssignAbortError(JSContext* aCx) {
|
||||
MOZ_ASSERT(mAborted);
|
||||
MOZ_ASSERT(Aborted());
|
||||
if (!mReason.isUndefined()) {
|
||||
return;
|
||||
}
|
||||
@@ -151,13 +152,31 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
NS_IMPL_ADDREF_INHERITED(AbortSignal, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(AbortSignal, DOMEventTargetHelper)
|
||||
|
||||
AbortSignal::AbortSignal(nsIGlobalObject* aGlobalObject, bool aAborted,
|
||||
already_AddRefed<AbortSignal> AbortSignal::Create(
|
||||
nsIGlobalObject* aGlobalObject, SignalAborted aAborted,
|
||||
JS::Handle<JS::Value> aReason) {
|
||||
RefPtr<AbortSignal> signal =
|
||||
new AbortSignal(aGlobalObject, aAborted, aReason);
|
||||
signal->Init();
|
||||
return signal.forget();
|
||||
}
|
||||
|
||||
void AbortSignal::Init() {
|
||||
// Init is use to separate this HoldJSObjects call to avoid calling
|
||||
// it in the constructor.
|
||||
//
|
||||
// We can't call HoldJSObjects in the constructor because it'll
|
||||
// addref `this` before the vtable is set up properly, so the parent
|
||||
// type gets stored in the CC participant table. This is problematic
|
||||
// for classes that inherit AbortSignal.
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
AbortSignal::AbortSignal(nsIGlobalObject* aGlobalObject, SignalAborted aAborted,
|
||||
JS::Handle<JS::Value> aReason)
|
||||
: DOMEventTargetHelper(aGlobalObject),
|
||||
AbortSignalImpl(aAborted, aReason),
|
||||
mDependent(false) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
mDependent(false) {}
|
||||
|
||||
JSObject* AbortSignal::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
@@ -168,7 +187,8 @@ already_AddRefed<AbortSignal> AbortSignal::Abort(
|
||||
GlobalObject& aGlobal, JS::Handle<JS::Value> aReason) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
RefPtr<AbortSignal> abortSignal = new AbortSignal(global, true, aReason);
|
||||
RefPtr<AbortSignal> abortSignal =
|
||||
AbortSignal::Create(global, SignalAborted::Yes, aReason);
|
||||
return abortSignal.forget();
|
||||
}
|
||||
|
||||
@@ -256,7 +276,7 @@ already_AddRefed<AbortSignal> AbortSignal::Timeout(GlobalObject& aGlobal,
|
||||
|
||||
// Step 1. Let signal be a new AbortSignal object.
|
||||
RefPtr<AbortSignal> signal =
|
||||
new AbortSignal(global, false, JS::UndefinedHandleValue);
|
||||
AbortSignal::Create(global, SignalAborted::No, JS::UndefinedHandleValue);
|
||||
|
||||
// Step 3. Run steps after a timeout given global, "AbortSignal-timeout",
|
||||
// milliseconds, and the following step: ...
|
||||
@@ -283,17 +303,20 @@ already_AddRefed<AbortSignal> AbortSignal::Any(
|
||||
GlobalObject& aGlobal,
|
||||
const Sequence<OwningNonNull<AbortSignal>>& aSignals) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
mozilla::Span span{aSignals.Elements(), aSignals.Length()};
|
||||
return Any(global, span);
|
||||
return Any(global, aSignals, [](nsIGlobalObject* aGlobal) {
|
||||
return AbortSignal::Create(aGlobal, SignalAborted::No,
|
||||
JS::UndefinedHandleValue);
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<AbortSignal> AbortSignal::Any(
|
||||
nsIGlobalObject* aGlobal,
|
||||
const Span<const OwningNonNull<AbortSignal>>& aSignals) {
|
||||
const Span<const OwningNonNull<AbortSignal>>& aSignals,
|
||||
FunctionRef<already_AddRefed<AbortSignal>(nsIGlobalObject* aGlobal)>
|
||||
aCreateResultSignal) {
|
||||
// Step 1. Let resultSignal be a new object implementing AbortSignal using
|
||||
// realm
|
||||
RefPtr<AbortSignal> resultSignal =
|
||||
new AbortSignal(aGlobal, false, JS::UndefinedHandleValue);
|
||||
RefPtr<AbortSignal> resultSignal = aCreateResultSignal(aGlobal);
|
||||
|
||||
if (!aSignals.IsEmpty()) {
|
||||
// (Prepare for step 2 which uses the reason of this. Cannot use
|
||||
@@ -441,7 +464,7 @@ AbortFollower::~AbortFollower() { Unfollow(); }
|
||||
// https://dom.spec.whatwg.org/#abortsignal-add
|
||||
void AbortFollower::Follow(AbortSignalImpl* aSignal) {
|
||||
// Step 1.
|
||||
if (aSignal->mAborted) {
|
||||
if (aSignal->Aborted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,11 +31,12 @@ class AbortSignal : public DOMEventTargetHelper, public AbortSignalImpl {
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(AbortSignal,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
AbortSignal(nsIGlobalObject* aGlobalObject, bool aAborted,
|
||||
JS::Handle<JS::Value> aReason);
|
||||
static already_AddRefed<AbortSignal> Create(nsIGlobalObject* aGlobalObject,
|
||||
SignalAborted aAborted,
|
||||
JS::Handle<JS::Value> aReason);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
IMPL_EVENT_HANDLER(abort);
|
||||
|
||||
@@ -51,7 +52,9 @@ class AbortSignal : public DOMEventTargetHelper, public AbortSignalImpl {
|
||||
const Sequence<OwningNonNull<AbortSignal>>& aSignals);
|
||||
static already_AddRefed<AbortSignal> Any(
|
||||
nsIGlobalObject* aGlobal,
|
||||
const Span<const OwningNonNull<AbortSignal>>& aSignals);
|
||||
const Span<const OwningNonNull<AbortSignal>>& aSignals,
|
||||
FunctionRef<already_AddRefed<AbortSignal>(nsIGlobalObject* aGlobal)>
|
||||
aCreateResultSignal);
|
||||
|
||||
void ThrowIfAborted(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
@@ -60,7 +63,12 @@ class AbortSignal : public DOMEventTargetHelper, public AbortSignalImpl {
|
||||
bool Dependent() const;
|
||||
|
||||
protected:
|
||||
~AbortSignal();
|
||||
AbortSignal(nsIGlobalObject* aGlobalObject, SignalAborted aAborted,
|
||||
JS::Handle<JS::Value> aReason);
|
||||
|
||||
void Init();
|
||||
|
||||
virtual ~AbortSignal();
|
||||
|
||||
void MakeDependentOn(AbortSignal* aSignal);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ void IdleRequest::IdleRun(nsPIDOMWindowInner* aWindow,
|
||||
// Set state’s priority source to the result of creating a fixed priority
|
||||
// unabortable task signal given "background" and realm.
|
||||
newState->SetPrioritySource(
|
||||
new TaskSignal(aWindow->AsGlobal(), TaskPriority::Background));
|
||||
TaskSignal::Create(aWindow->AsGlobal(), TaskPriority::Background));
|
||||
// Set event loop’s current scheduling state to state.
|
||||
innerWindow->SetWebTaskSchedulingState(newState);
|
||||
callback->Call(*deadline, "requestIdleCallback handler");
|
||||
|
||||
@@ -90,7 +90,7 @@ class AbortSignalMainThread final : public AbortSignalImpl {
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbortSignalMainThread)
|
||||
|
||||
explicit AbortSignalMainThread(bool aAborted)
|
||||
explicit AbortSignalMainThread(SignalAborted aAborted)
|
||||
: AbortSignalImpl(aAborted, JS::UndefinedHandleValue) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
@@ -147,7 +147,7 @@ class AbortSignalProxy final : public AbortFollower {
|
||||
// thread, to create it in already-aborted state if necessary. It does *not*
|
||||
// reflect the instantaneous is-aborted status of the worker thread's
|
||||
// AbortSignal.
|
||||
const bool mAborted;
|
||||
const SignalAborted mAborted;
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
@@ -155,7 +155,8 @@ class AbortSignalProxy final : public AbortFollower {
|
||||
AbortSignalProxy(AbortSignalImpl* aSignalImpl,
|
||||
nsIEventTarget* aMainThreadEventTarget)
|
||||
: mMainThreadEventTarget(aMainThreadEventTarget),
|
||||
mAborted(aSignalImpl->Aborted()) {
|
||||
mAborted(aSignalImpl->Aborted() ? SignalAborted::Yes
|
||||
: SignalAborted::No) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(mMainThreadEventTarget);
|
||||
Follow(aSignalImpl);
|
||||
|
||||
@@ -63,7 +63,10 @@ Request::Request(nsIGlobalObject* aOwner, SafeRefPtr<InternalRequest> aRequest,
|
||||
// If we don't have a signal as argument, we will create it when required by
|
||||
// content, otherwise the Request's signal must follow what has been passed.
|
||||
AutoTArray<OwningNonNull<AbortSignal>, 1> array{OwningNonNull(*aSignal)};
|
||||
mSignal = AbortSignal::Any(aOwner, mozilla::Span{array});
|
||||
mSignal = AbortSignal::Any(aOwner, array, [](nsIGlobalObject* aGlobal) {
|
||||
return AbortSignal::Create(aGlobal, SignalAborted::No,
|
||||
JS::UndefinedHandleValue);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +510,8 @@ Headers* Request::Headers_() {
|
||||
|
||||
AbortSignal* Request::GetOrCreateSignal() {
|
||||
if (!mSignal) {
|
||||
mSignal = new AbortSignal(mOwner, false, JS::UndefinedHandleValue);
|
||||
mSignal = AbortSignal::Create(mOwner, SignalAborted::No,
|
||||
JS::UndefinedHandleValue);
|
||||
}
|
||||
|
||||
return mSignal;
|
||||
|
||||
@@ -149,8 +149,10 @@ void SetUpWritableStreamDefaultController(
|
||||
ResetQueue(aController);
|
||||
|
||||
// Step 6. Set controller.[[signal]] to a new AbortSignal.
|
||||
RefPtr<AbortSignal> signal = new AbortSignal(aController->GetParentObject(),
|
||||
false, JS::UndefinedHandleValue);
|
||||
RefPtr<AbortSignal> signal =
|
||||
AbortSignal::Create(aController->GetParentObject(), SignalAborted::No,
|
||||
JS::UndefinedHandleValue);
|
||||
|
||||
aController->SetSignal(signal);
|
||||
|
||||
// Step 7. Set controller.[[started]] to false.
|
||||
|
||||
@@ -8,8 +8,14 @@ enum TaskPriority {
|
||||
"background"
|
||||
};
|
||||
|
||||
dictionary TaskSignalAnyInit {
|
||||
(TaskPriority or TaskSignal) priority = "user-visible";
|
||||
};
|
||||
|
||||
[Exposed=(Window, Worker), Pref="dom.enable_web_task_scheduling"]
|
||||
interface TaskSignal : AbortSignal {
|
||||
[NewObject] static TaskSignal _any(sequence<AbortSignal> signals, optional TaskSignalAnyInit init = {});
|
||||
|
||||
readonly attribute TaskPriority priority;
|
||||
|
||||
attribute EventHandler onprioritychange;
|
||||
|
||||
@@ -10,6 +10,16 @@
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(TaskSignal, AbortSignal,
|
||||
mDependentTaskSignals)
|
||||
|
||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(TaskSignal, AbortSignal)
|
||||
|
||||
already_AddRefed<TaskSignal> TaskSignal::Create(nsIGlobalObject* aGlobalObject,
|
||||
TaskPriority aPriority) {
|
||||
return do_AddRef(new TaskSignal(aGlobalObject, aPriority));
|
||||
}
|
||||
|
||||
void TaskSignal::RunPriorityChangeAlgorithms() {
|
||||
for (const WeakPtr<WebTaskScheduler>& scheduler : mSchedulers) {
|
||||
if (scheduler) {
|
||||
@@ -20,4 +30,62 @@ void TaskSignal::RunPriorityChangeAlgorithms() {
|
||||
void TaskSignal::SetWebTaskScheduler(WebTaskScheduler* aScheduler) {
|
||||
mSchedulers.AppendElement(aScheduler);
|
||||
}
|
||||
|
||||
// https://wicg.github.io/scheduling-apis/#create-a-dependent-task-signal
|
||||
/* static */
|
||||
already_AddRefed<TaskSignal> TaskSignal::Any(
|
||||
GlobalObject& aGlobal, const Sequence<OwningNonNull<AbortSignal>>& aSignals,
|
||||
const TaskSignalAnyInit& aInit) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
// 1. Let resultSignal be the result of creating a dependent signal from
|
||||
// signals using the TaskSignal interface and realm.
|
||||
RefPtr<AbortSignal> abortSignal =
|
||||
AbortSignal::Any(global, aSignals, [](nsIGlobalObject* aGlobal) {
|
||||
// Use User_visible as a temporary priority for now, it'll alwasy be set
|
||||
// again later.
|
||||
RefPtr<TaskSignal> signal =
|
||||
new TaskSignal(aGlobal, TaskPriority::User_visible);
|
||||
return signal.forget();
|
||||
});
|
||||
|
||||
if (!abortSignal) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<TaskSignal> resultSignal = static_cast<TaskSignal*>(abortSignal.get());
|
||||
|
||||
// 2. Set resultSignal’s dependent to true.
|
||||
resultSignal->mDependent = true;
|
||||
|
||||
// 3. If init["priority"] is a TaskPriority, then:
|
||||
if (aInit.mPriority.IsTaskPriority()) {
|
||||
// 3.1 Set resultSignal’s priority to init["priority"].
|
||||
resultSignal->SetPriority(aInit.mPriority.GetAsTaskPriority());
|
||||
return resultSignal.forget();
|
||||
}
|
||||
|
||||
// 4. Otherwise:
|
||||
// 4.1. Let sourceSignal be init["priority"].
|
||||
OwningNonNull<TaskSignal> sourceSignal = aInit.mPriority.GetAsTaskSignal();
|
||||
|
||||
// 4.2. Set resultSignal’s priority to sourceSignal’s priority.
|
||||
resultSignal->SetPriority(sourceSignal->Priority());
|
||||
|
||||
// 4.3 If sourceSignal does not have fixed priority, then:
|
||||
if (!sourceSignal->HasFixedPriority()) {
|
||||
// 4.3.1 If sourceSignal’s dependent is true, then set sourceSignal to
|
||||
// sourceSignal’s source signal
|
||||
if (sourceSignal->mDependent) {
|
||||
sourceSignal = sourceSignal->mSourceTaskSignal;
|
||||
}
|
||||
// 4.3.2. Assert: sourceSignal is not dependent.
|
||||
MOZ_ASSERT(!sourceSignal->mDependent);
|
||||
// 4.3.3. Set resultSignal’s source signal to a weak reference to
|
||||
// sourceSignal.
|
||||
resultSignal->mSourceTaskSignal = sourceSignal;
|
||||
// 4.3.4. Append resultSignal to sourceSignal’s dependent signals.
|
||||
sourceSignal->mDependentTaskSignals.AppendElement(resultSignal);
|
||||
}
|
||||
return resultSignal.forget();
|
||||
}
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -13,15 +13,21 @@
|
||||
#include "mozilla/dom/WebTaskSchedulingBinding.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
class TaskSignal : public AbortSignal {
|
||||
class TaskSignal final : public AbortSignal {
|
||||
public:
|
||||
TaskSignal(nsIGlobalObject* aGlobal, TaskPriority aPriority)
|
||||
: AbortSignal(aGlobal, false, JS::UndefinedHandleValue),
|
||||
mPriority(aPriority),
|
||||
mPriorityChanging(false) {}
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TaskSignal, AbortSignal)
|
||||
|
||||
IMPL_EVENT_HANDLER(prioritychange);
|
||||
|
||||
static already_AddRefed<TaskSignal> Create(nsIGlobalObject* aGlobalObject,
|
||||
TaskPriority aPriority);
|
||||
|
||||
static already_AddRefed<TaskSignal> Any(
|
||||
GlobalObject& aGlobal,
|
||||
const Sequence<OwningNonNull<AbortSignal>>& aSignals,
|
||||
const TaskSignalAnyInit& aInit);
|
||||
|
||||
TaskPriority Priority() const { return mPriority; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
@@ -43,13 +49,34 @@ class TaskSignal : public AbortSignal {
|
||||
|
||||
void SetWebTaskScheduler(WebTaskScheduler* aScheduler);
|
||||
|
||||
// https://wicg.github.io/scheduling-apis/#tasksignal-has-fixed-priority
|
||||
bool HasFixedPriority() const { return mDependent && !mSourceTaskSignal; }
|
||||
|
||||
nsTArray<RefPtr<TaskSignal>>& DependentTaskSignals() {
|
||||
return mDependentTaskSignals;
|
||||
}
|
||||
|
||||
private:
|
||||
TaskSignal(nsIGlobalObject* aGlobal, TaskPriority aPriority)
|
||||
: AbortSignal(aGlobal, SignalAborted::No, JS::UndefinedHandleValue),
|
||||
mPriority(aPriority),
|
||||
mPriorityChanging(false) {
|
||||
AbortSignal::Init();
|
||||
}
|
||||
|
||||
TaskPriority mPriority;
|
||||
|
||||
// https://wicg.github.io/scheduling-apis/#tasksignal-priority-changing
|
||||
bool mPriorityChanging;
|
||||
|
||||
nsTArray<WeakPtr<WebTaskScheduler>> mSchedulers;
|
||||
|
||||
// https://wicg.github.io/scheduling-apis/#tasksignal-source-signal
|
||||
WeakPtr<TaskSignal> mSourceTaskSignal;
|
||||
|
||||
// https://wicg.github.io/scheduling-apis/#tasksignal-dependent-signals
|
||||
nsTArray<RefPtr<TaskSignal>> mDependentTaskSignals;
|
||||
|
||||
~TaskSignal() = default;
|
||||
};
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -16,12 +16,14 @@ WebTaskController::WebTaskController(nsIGlobalObject* aGlobal,
|
||||
TaskPriority aPriority)
|
||||
: AbortController(aGlobal) {
|
||||
MOZ_ASSERT(!mSignal);
|
||||
mSignal = new TaskSignal(aGlobal, aPriority);
|
||||
mSignal = TaskSignal::Create(aGlobal, aPriority);
|
||||
}
|
||||
|
||||
void WebTaskController::SetPriority(TaskPriority aPriority, ErrorResult& aRv) {
|
||||
// https://wicg.github.io/scheduling-apis/#tasksignal-signal-priority-change
|
||||
RefPtr<TaskSignal> taskSignal = static_cast<TaskSignal*>(mSignal.get());
|
||||
void WebTaskController::SignalPriorityChange(TaskSignal* aTaskSignal,
|
||||
TaskPriority aPriority,
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<TaskSignal> taskSignal = aTaskSignal;
|
||||
|
||||
MOZ_ASSERT(taskSignal);
|
||||
if (taskSignal->PriorityChanging()) {
|
||||
aRv.ThrowNotAllowedError("Signal's priority changing is true");
|
||||
@@ -47,9 +49,21 @@ void WebTaskController::SetPriority(TaskPriority aPriority, ErrorResult& aRv) {
|
||||
event->SetTrusted(true);
|
||||
|
||||
taskSignal->DispatchEvent(*event);
|
||||
|
||||
for (const RefPtr<TaskSignal>& dependentSignal :
|
||||
taskSignal->DependentTaskSignals().Clone()) {
|
||||
SignalPriorityChange(dependentSignal, aPriority, aRv);
|
||||
}
|
||||
|
||||
taskSignal->SetPriorityChanging(false);
|
||||
}
|
||||
|
||||
void WebTaskController::SetPriority(TaskPriority aPriority, ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mSignal->IsTaskSignal());
|
||||
// mSignal for WebTaskController should always be a TaskSignal.
|
||||
SignalPriorityChange(static_cast<TaskSignal*>(mSignal.get()), aPriority, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<WebTaskController> WebTaskController::Constructor(
|
||||
const GlobalObject& aGlobal, const TaskControllerInit& aInit,
|
||||
ErrorResult& aRv) {
|
||||
|
||||
@@ -28,6 +28,10 @@ class WebTaskController : public AbortController {
|
||||
void SetPriority(TaskPriority aPriority, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
// https://wicg.github.io/scheduling-apis/#tasksignal-signal-priority-change
|
||||
void SignalPriorityChange(TaskSignal* aTaskSignal, TaskPriority aPriority,
|
||||
ErrorResult& aRv);
|
||||
|
||||
~WebTaskController() = default;
|
||||
};
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -322,11 +322,12 @@ already_AddRefed<Promise> WebTaskScheduler::PostTask(
|
||||
// result of creating a fixed priority unabortable task signal given
|
||||
// options["priority"]
|
||||
newState->SetPrioritySource(
|
||||
new TaskSignal(GetParentObject(), taskPriority.Value()));
|
||||
TaskSignal::Create(GetParentObject(), taskPriority.Value()));
|
||||
} else if (signalValue && signalValue->IsTaskSignal()) {
|
||||
// 7. Otherwise if signal is not null and implements the TaskSignal
|
||||
// interface, then set state’s priority source to signal.
|
||||
newState->SetPrioritySource(static_cast<TaskSignal*>(signalValue));
|
||||
newState->SetPrioritySource(
|
||||
do_AddRef(static_cast<TaskSignal*>(signalValue)));
|
||||
}
|
||||
|
||||
if (!newState->GetPrioritySource()) {
|
||||
@@ -334,7 +335,7 @@ already_AddRefed<Promise> WebTaskScheduler::PostTask(
|
||||
// source to the result of creating a fixed priority unabortable task
|
||||
// signal given "user-visible".
|
||||
newState->SetPrioritySource(
|
||||
new TaskSignal(GetParentObject(), TaskPriority::User_visible));
|
||||
TaskSignal::Create(GetParentObject(), TaskPriority::User_visible));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(newState->GetPrioritySource());
|
||||
@@ -420,7 +421,7 @@ already_AddRefed<Promise> WebTaskScheduler::YieldImpl() {
|
||||
// 6. If prioritySource is null, then set prioritySource to the result of
|
||||
// creating a fixed priority unabortable task signal given "user-visible".
|
||||
prioritySource =
|
||||
new TaskSignal(GetParentObject(), TaskPriority::User_visible);
|
||||
TaskSignal::Create(GetParentObject(), TaskPriority::User_visible);
|
||||
}
|
||||
|
||||
// 7. Let handle be the result of creating a task handle given result and
|
||||
|
||||
@@ -45,9 +45,9 @@ class WebTaskSchedulingState {
|
||||
AbortSignal* GetAbortSource() { return mAbortSource; }
|
||||
TaskSignal* GetPrioritySource() { return mPrioritySource; }
|
||||
|
||||
void SetPrioritySource(TaskSignal* aPrioritySource) {
|
||||
MOZ_ASSERT(aPrioritySource->IsTaskSignal());
|
||||
void SetPrioritySource(already_AddRefed<TaskSignal> aPrioritySource) {
|
||||
mPrioritySource = aPrioritySource;
|
||||
MOZ_ASSERT(mPrioritySource->IsTaskSignal());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
[task-signal-any-post-task-run-order.tentative.any.serviceworker.html]
|
||||
expected:
|
||||
if debug and (os == "win") and (processor == "x86_64"): [OK, ERROR, CRASH]
|
||||
if debug and (os == "win") and (processor == "x86"): [OK, ERROR]
|
||||
if debug and (os == "mac"): [ERROR, OK]
|
||||
if debug and (os == "linux"): [OK, ERROR, CRASH]
|
||||
if not debug and (os == "android"): [OK, ERROR]
|
||||
[scheduler.postTask() tasks run in priority order with a fixed priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a dynamic priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a composite signal whose source has fixed priority]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[task-signal-any-post-task-run-order.tentative.any.html]
|
||||
expected:
|
||||
if debug and (os == "win") and (processor == "x86_64"): [CRASH, OK, ERROR]
|
||||
if debug and (os == "linux") and not fission: [CRASH, OK, ERROR]
|
||||
if not debug and (os == "linux") and fission: OK
|
||||
if not debug and (os == "linux") and not fission: CRASH
|
||||
if debug and (os == "android"): CRASH
|
||||
if not debug and (os == "win"): OK
|
||||
if not debug and (os == "mac"): [OK, CRASH]
|
||||
if not debug and (os == "android"): [OK, CRASH]
|
||||
[OK, ERROR]
|
||||
[scheduler.postTask() tasks run in priority order with a fixed priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a dynamic priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a composite signal whose source has fixed priority]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[task-signal-any-post-task-run-order.tentative.any.worker.html]
|
||||
expected:
|
||||
if debug and (os == "android"): OK
|
||||
if not debug: OK
|
||||
[OK, ERROR]
|
||||
[scheduler.postTask() tasks run in priority order with a fixed priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a dynamic priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a composite signal whose source has fixed priority]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[task-signal-any-post-task-run-order.tentative.any.sharedworker.html]
|
||||
expected:
|
||||
if debug and (os == "android"): OK
|
||||
if not debug: OK
|
||||
[OK, ERROR]
|
||||
[scheduler.postTask() tasks run in priority order with a fixed priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a dynamic priority composite signal]
|
||||
expected: FAIL
|
||||
|
||||
[scheduler.postTask() tasks run in priority order with a composite signal whose source has fixed priority]
|
||||
expected: FAIL
|
||||
@@ -1,131 +0,0 @@
|
||||
[task-signal-any-priority.tentative.any.html]
|
||||
[TaskSignal.any() returns a user-visible TaskSignal when no priority is specified]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a string]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a TaskSignal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with dynamic priority]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals with intermediate sources]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change propagates to multiple dependent signals in the right order]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates abort and priority]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates priority after returning an aborted signal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() does not fire prioritychange for dependents added during prioritychange]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[task-signal-any-priority.tentative.any.sharedworker.html]
|
||||
expected:
|
||||
if (os == "linux") and debug: [OK, ERROR]
|
||||
if (os == "android") and not debug: [OK, CRASH]
|
||||
[TaskSignal.any() returns a user-visible TaskSignal when no priority is specified]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a string]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a TaskSignal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with dynamic priority]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals with intermediate sources]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change propagates to multiple dependent signals in the right order]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates abort and priority]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates priority after returning an aborted signal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() does not fire prioritychange for dependents added during prioritychange]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[task-signal-any-priority.tentative.any.worker.html]
|
||||
[TaskSignal.any() returns a user-visible TaskSignal when no priority is specified]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a string]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a TaskSignal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with dynamic priority]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals with intermediate sources]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change propagates to multiple dependent signals in the right order]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates abort and priority]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates priority after returning an aborted signal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() does not fire prioritychange for dependents added during prioritychange]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[task-signal-any-priority.tentative.any.serviceworker.html]
|
||||
expected:
|
||||
if (os == "android") and not debug: [OK, ERROR]
|
||||
[TaskSignal.any() returns a user-visible TaskSignal when no priority is specified]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a string]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with the correct priority when intialized with a TaskSignal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() returns a signal with dynamic priority]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change events fire for composite signals with intermediate sources]
|
||||
expected: FAIL
|
||||
|
||||
[Priority change propagates to multiple dependent signals in the right order]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates abort and priority]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() propagates priority after returning an aborted signal]
|
||||
expected: FAIL
|
||||
|
||||
[TaskSignal.any() does not fire prioritychange for dependents added during prioritychange]
|
||||
expected: FAIL
|
||||
Reference in New Issue
Block a user