зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1725941 - Add AbortSignal support for locks.request() r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D128000
This commit is contained in:
Родитель
4839800b46
Коммит
f6b5ef8ffa
|
@ -50,7 +50,7 @@ Promise& Lock::GetWaitingPromise() {
|
|||
|
||||
void Lock::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) {
|
||||
if (mLockRequestChild) {
|
||||
locks::PLockRequestChild::Send__delete__(mLockRequestChild);
|
||||
locks::PLockRequestChild::Send__delete__(mLockRequestChild, false);
|
||||
mLockRequestChild = nullptr;
|
||||
}
|
||||
mReleasedPromise->MaybeResolve(aValue);
|
||||
|
@ -58,7 +58,7 @@ void Lock::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) {
|
|||
|
||||
void Lock::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) {
|
||||
if (mLockRequestChild) {
|
||||
locks::PLockRequestChild::Send__delete__(mLockRequestChild);
|
||||
locks::PLockRequestChild::Send__delete__(mLockRequestChild, false);
|
||||
mLockRequestChild = nullptr;
|
||||
}
|
||||
mReleasedPromise->MaybeReject(aValue);
|
||||
|
|
|
@ -125,12 +125,6 @@ already_AddRefed<Promise> LockManager::Request(const nsAString& aName,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (aOptions.mSignal.WasPassed()) {
|
||||
// TODO(krosylight): Bug 1725941
|
||||
aRv.ThrowNotSupportedError("AbortSignal support is not implemented yet");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mActor) {
|
||||
// TODO: https://github.com/WICG/web-locks/issues/78
|
||||
aRv.ThrowInvalidStateError(
|
||||
|
|
|
@ -15,7 +15,7 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(LockManagerChild, Release)
|
|||
|
||||
void LockManagerChild::RequestLock(const LockRequest& aRequest,
|
||||
const LockOptions& aOptions) {
|
||||
auto requestActor = MakeRefPtr<LockRequestChild>(aRequest);
|
||||
auto requestActor = MakeRefPtr<LockRequestChild>(aRequest, aOptions.mSignal);
|
||||
SendPLockRequestConstructor(
|
||||
requestActor, IPCLockRequest(nsString(aRequest.mName), aOptions.mMode,
|
||||
aOptions.mIfAvailable, aOptions.mSteal));
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace mozilla::dom::locks {
|
|||
|
||||
using IPCResult = mozilla::ipc::IPCResult;
|
||||
|
||||
NS_IMPL_ISUPPORTS(LockRequestChild, nsISupports)
|
||||
|
||||
// XXX: should be MOZ_CAN_RUN_SCRIPT, but not sure how to call it from closures
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY static void RunCallbackAndSettlePromise(
|
||||
LockGrantedCallback& aCallback, mozilla::dom::Lock* lock,
|
||||
|
@ -37,8 +39,13 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY static void RunCallbackAndSettlePromise(
|
|||
MOZ_ASSERT(!rv.Failed());
|
||||
}
|
||||
|
||||
LockRequestChild::LockRequestChild(const LockRequest& aRequest)
|
||||
LockRequestChild::LockRequestChild(
|
||||
const LockRequest& aRequest,
|
||||
const Optional<OwningNonNull<AbortSignal>>& aSignal)
|
||||
: mRequest(aRequest) {
|
||||
if (aSignal.WasPassed()) {
|
||||
Follow(&aSignal.Value());
|
||||
}
|
||||
if (!NS_IsMainThread()) {
|
||||
mWorkerRef = StrongWorkerRef::Create(
|
||||
GetCurrentThreadWorkerPrivate(), "LockManager",
|
||||
|
@ -48,6 +55,8 @@ LockRequestChild::LockRequestChild(const LockRequest& aRequest)
|
|||
|
||||
IPCResult LockRequestChild::RecvResolve(const LockMode& aLockMode,
|
||||
bool aIsAvailable) {
|
||||
Unfollow();
|
||||
|
||||
RefPtr<Lock> lock;
|
||||
RefPtr<Promise> promise;
|
||||
if (aIsAvailable) {
|
||||
|
@ -75,8 +84,14 @@ IPCResult LockRequestChild::RecvResolve(const LockMode& aLockMode,
|
|||
}
|
||||
|
||||
IPCResult LockRequestChild::RecvAbort() {
|
||||
Unfollow();
|
||||
mRequest.mPromise->MaybeRejectWithAbortError("The lock request is aborted");
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void LockRequestChild::RunAbortAlgorithm() {
|
||||
RecvAbort();
|
||||
Send__delete__(this, true);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::locks
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/dom/locks/PLockRequestChild.h"
|
||||
#include "mozilla/dom/Lock.h"
|
||||
#include "mozilla/dom/WorkerRef.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla::dom::locks {
|
||||
|
||||
|
@ -20,17 +21,22 @@ struct LockRequest {
|
|||
};
|
||||
|
||||
class LockRequestChild final : public PLockRequestChild,
|
||||
public AbortFollower,
|
||||
public SupportsWeakPtr {
|
||||
using IPCResult = mozilla::ipc::IPCResult;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(LockRequestChild)
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
public:
|
||||
explicit LockRequestChild(const LockRequest& aRequest);
|
||||
explicit LockRequestChild(
|
||||
const LockRequest& aRequest,
|
||||
const Optional<OwningNonNull<AbortSignal>>& aSignal);
|
||||
|
||||
IPCResult RecvResolve(const LockMode& aLockMode, bool aIsAvailable);
|
||||
IPCResult RecvAbort();
|
||||
|
||||
void RunAbortAlgorithm() final;
|
||||
|
||||
private:
|
||||
~LockRequestChild() = default;
|
||||
|
||||
|
|
|
@ -11,15 +11,19 @@
|
|||
|
||||
namespace mozilla::dom::locks {
|
||||
|
||||
mozilla::ipc::IPCResult LockRequestParent::Recv__delete__() {
|
||||
mozilla::ipc::IPCResult LockRequestParent::Recv__delete__(bool aAborted) {
|
||||
RefPtr<LockManagerParent> manager =
|
||||
static_cast<LockManagerParent*>(Manager());
|
||||
ManagedLocks& managed = manager->Locks();
|
||||
|
||||
DebugOnly<bool> unheld = managed.mHeldLocks.RemoveElement(this);
|
||||
MOZ_ASSERT(unheld, "No held lock?");
|
||||
MOZ_ASSERT_IF(!aAborted, unheld);
|
||||
|
||||
if (auto queue = managed.mQueueMap.Lookup(mRequest.name())) {
|
||||
if (aAborted) {
|
||||
DebugOnly<bool> dequeued = queue.Data().RemoveElement(this);
|
||||
MOZ_ASSERT_IF(!unheld, dequeued);
|
||||
}
|
||||
manager->ProcessRequestQueue(queue.Data());
|
||||
if (queue.Data().IsEmpty()) {
|
||||
// Remove if empty, to prevent the queue map from growing forever
|
||||
|
|
|
@ -22,7 +22,7 @@ class LockRequestParent final : public PLockRequestParent {
|
|||
|
||||
const IPCLockRequest& Data() { return mRequest; }
|
||||
|
||||
mozilla::ipc::IPCResult Recv__delete__() final;
|
||||
mozilla::ipc::IPCResult Recv__delete__(bool aAborted);
|
||||
|
||||
private:
|
||||
~LockRequestParent() = default;
|
||||
|
|
|
@ -21,7 +21,7 @@ protocol PLockRequest {
|
|||
async Abort();
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
async __delete__(bool aAborted);
|
||||
};
|
||||
|
||||
} // namespace cache
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
[signal.tentative.https.any.html]
|
||||
expected: ERROR
|
||||
[Abort after a timeout]
|
||||
expected: FAIL
|
||||
|
||||
[Synchronously signaled abort]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock released]
|
||||
expected: NOTRUN
|
||||
|
||||
[Signal that is not aborted]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock granted]
|
||||
expected: TIMEOUT
|
||||
|
||||
[An aborted request results in AbortError]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[signal.tentative.https.any.worker.html]
|
||||
expected: TIMEOUT
|
||||
[Abort after a timeout]
|
||||
expected: FAIL
|
||||
|
||||
[Synchronously signaled abort]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock released]
|
||||
expected: NOTRUN
|
||||
|
||||
[Signal that is not aborted]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock granted]
|
||||
expected: TIMEOUT
|
||||
|
||||
[An aborted request results in AbortError]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[signal.tentative.https.any.serviceworker.html]
|
||||
expected: TIMEOUT
|
||||
[Abort after a timeout]
|
||||
expected: FAIL
|
||||
|
||||
[Synchronously signaled abort]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock released]
|
||||
expected: NOTRUN
|
||||
|
||||
[Signal that is not aborted]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock granted]
|
||||
expected: TIMEOUT
|
||||
|
||||
[An aborted request results in AbortError]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[signal.tentative.https.any.sharedworker.html]
|
||||
expected: TIMEOUT
|
||||
[Abort after a timeout]
|
||||
expected: FAIL
|
||||
|
||||
[Synchronously signaled abort]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock released]
|
||||
expected: NOTRUN
|
||||
|
||||
[Signal that is not aborted]
|
||||
expected: FAIL
|
||||
|
||||
[Abort signaled after lock granted]
|
||||
expected: TIMEOUT
|
||||
|
||||
[An aborted request results in AbortError]
|
||||
expected: FAIL
|
||||
|
|
@ -190,3 +190,19 @@ promise_test(async t => {
|
|||
'Lock released promise should not reject');
|
||||
|
||||
}, 'Abort signaled after lock released');
|
||||
|
||||
promise_test(async t => {
|
||||
const res = uniqueName(t);
|
||||
|
||||
const controller = new AbortController();
|
||||
const first = requestLockAndHold(t, res, { signal: controller.signal });
|
||||
const next = navigator.locks.request(res, () => "resolved");
|
||||
controller.abort();
|
||||
|
||||
await promise_rejects_dom(t, "AbortError", first, "Request should abort");
|
||||
assert_equals(
|
||||
await next,
|
||||
"resolved",
|
||||
"The next request is processed after abort"
|
||||
);
|
||||
}, "Abort should process the next pending lock request");
|
||||
|
|
Загрузка…
Ссылка в новой задаче