зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1617822 - Implement FetchEvent.handled r=dom-workers-and-storage-reviewers,asuth
Differential Revision: https://phabricator.services.mozilla.com/D93483
This commit is contained in:
Родитель
6e4797dff2
Коммит
5def06e77f
|
@ -153,6 +153,14 @@ already_AddRefed<FetchEvent> FetchEvent::Constructor(
|
|||
e->mRequest = aOptions.mRequest;
|
||||
e->mClientId = aOptions.mClientId;
|
||||
e->mResultingClientId = aOptions.mResultingClientId;
|
||||
RefPtr<nsIGlobalObject> global = do_QueryObject(aGlobal.GetAsSupports());
|
||||
MOZ_ASSERT(global);
|
||||
ErrorResult rv;
|
||||
e->mHandled = Promise::Create(global, rv);
|
||||
if (rv.Failed()) {
|
||||
rv.SuppressException();
|
||||
return nullptr;
|
||||
}
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ class FetchEvent final : public ExtendableEvent {
|
|||
nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
RefPtr<Request> mRequest;
|
||||
RefPtr<Promise> mHandled;
|
||||
nsCString mScriptSpec;
|
||||
nsCString mPreventDefaultScriptSpec;
|
||||
nsString mClientId;
|
||||
|
@ -184,6 +185,8 @@ class FetchEvent final : public ExtendableEvent {
|
|||
aResultingClientId = mResultingClientId;
|
||||
}
|
||||
|
||||
Promise* Handled() const { return mHandled; }
|
||||
|
||||
void RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv);
|
||||
|
||||
// Pull in the Event version of PreventDefault so we don't get
|
||||
|
|
|
@ -131,6 +131,7 @@ class ExtendableEventKeepAliveHandler final
|
|||
|
||||
if (mCallback) {
|
||||
mCallback->FinishedWithResult(mRejected ? Rejected : Resolved);
|
||||
mCallback = nullptr;
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
|
@ -167,6 +168,10 @@ class ExtendableEventKeepAliveHandler final
|
|||
void Cleanup() {
|
||||
MOZ_ASSERT(IsCurrentThreadRunningWorker());
|
||||
|
||||
if (mCallback) {
|
||||
mCallback->FinishedWithResult(Rejected);
|
||||
}
|
||||
|
||||
mSelfRef = nullptr;
|
||||
mWorkerRef = nullptr;
|
||||
mCallback = nullptr;
|
||||
|
@ -1059,6 +1064,7 @@ class MOZ_STACK_CLASS FetchEventOp::AutoCancel {
|
|||
}
|
||||
|
||||
MOZ_ASSERT(!mOwner->mRespondWithPromiseHolder.IsEmpty());
|
||||
mOwner->mHandled->MaybeRejectWithNetworkError("AutoCancel"_ns);
|
||||
mOwner->mRespondWithPromiseHolder.Reject(NS_ERROR_INTERCEPTION_FAILED,
|
||||
__func__);
|
||||
}
|
||||
|
@ -1230,9 +1236,10 @@ void FetchEventOp::MaybeFinished() {
|
|||
MOZ_ASSERT(!mPromiseHolder.IsEmpty());
|
||||
|
||||
if (mResult) {
|
||||
// mRespondWithPromiseHolder should have been settled in
|
||||
// {Resolve,Reject}Callback by now.
|
||||
MOZ_DIAGNOSTIC_ASSERT(mRespondWithPromiseHolder.IsEmpty());
|
||||
// It's possible that mRespondWithPromiseHolder wasn't settled. That happens
|
||||
// if the worker was terminated before the respondWith promise settled.
|
||||
|
||||
mHandled = nullptr;
|
||||
|
||||
ServiceWorkerFetchEventOpResult result(
|
||||
mResult.value() == Resolved ? NS_OK : NS_ERROR_FAILURE);
|
||||
|
@ -1468,6 +1475,14 @@ void FetchEventOp::ResolvedCallback(JSContext* aCx,
|
|||
|
||||
autoCancel.Reset();
|
||||
|
||||
// https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm Step 26: If
|
||||
// eventHandled is not null, then resolve eventHandled.
|
||||
//
|
||||
// mRespondWithPromiseHolder will resolve a MozPromise that will resolve on
|
||||
// the worker owner's thread, so it's fine to resolve the mHandled promise now
|
||||
// because content will not interfere with respondWith getting the Response to
|
||||
// where it's going.
|
||||
mHandled->MaybeResolveWithUndefined();
|
||||
mRespondWithPromiseHolder.Resolve(
|
||||
FetchEventRespondWithResult(
|
||||
SynthesizeResponseArgs(ir, mRespondWithClosure.ref())),
|
||||
|
@ -1497,6 +1512,11 @@ void FetchEventOp::RejectedCallback(JSContext* aCx,
|
|||
AsyncLog(sourceSpec, line, column, "InterceptionRejectedResponseWithURL"_ns,
|
||||
{std::move(requestURL), valueString});
|
||||
|
||||
// https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm Step 25.1:
|
||||
// If eventHandled is not null, then reject eventHandled with a "NetworkError"
|
||||
// DOMException in workerRealm.
|
||||
mHandled->MaybeRejectWithNetworkError(
|
||||
"FetchEvent.respondWith() Promise rejected"_ns);
|
||||
mRespondWithPromiseHolder.Resolve(
|
||||
FetchEventRespondWithResult(
|
||||
CancelInterceptionArgs(NS_ERROR_INTERCEPTION_FAILED)),
|
||||
|
@ -1581,6 +1601,7 @@ nsresult FetchEventOp::DispatchFetchEvent(JSContext* aCx,
|
|||
FetchEvent::Constructor(globalObject, u"fetch"_ns, fetchEventInit);
|
||||
fetchEvent->SetTrusted(true);
|
||||
fetchEvent->PostInit(args.workerScriptSpec(), this);
|
||||
mHandled = fetchEvent->Handled();
|
||||
|
||||
/**
|
||||
* Step 5: Dispatch the FetchEvent to the worker's global object
|
||||
|
@ -1590,6 +1611,7 @@ nsresult FetchEventOp::DispatchFetchEvent(JSContext* aCx,
|
|||
bool dispatchFailed = NS_FAILED(rv) && rv != NS_ERROR_XPC_JS_THREW_EXCEPTION;
|
||||
|
||||
if (NS_WARN_IF(dispatchFailed)) {
|
||||
mHandled = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1629,11 +1651,19 @@ nsresult FetchEventOp::DispatchFetchEvent(JSContext* aCx,
|
|||
"We don't support system-principal serviceworkers");
|
||||
|
||||
if (fetchEvent->DefaultPrevented(CallerType::NonSystem)) {
|
||||
// https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm
|
||||
// Step 24.1.1: If eventHandled is not null, then reject eventHandled with
|
||||
// a "NetworkError" DOMException in workerRealm.
|
||||
mHandled->MaybeRejectWithNetworkError(
|
||||
"FetchEvent.preventDefault() called"_ns);
|
||||
mRespondWithPromiseHolder.Resolve(
|
||||
FetchEventRespondWithResult(
|
||||
CancelInterceptionArgs(NS_ERROR_INTERCEPTION_FAILED)),
|
||||
__func__);
|
||||
} else {
|
||||
// https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm
|
||||
// Step 24.2: If eventHandled is not null, then resolve eventHandled.
|
||||
mHandled->MaybeResolveWithUndefined();
|
||||
mRespondWithPromiseHolder.Resolve(
|
||||
FetchEventRespondWithResult(ResetInterceptionArgs()), __func__);
|
||||
}
|
||||
|
|
|
@ -168,6 +168,10 @@ class FetchEventOp final : public ExtendableEventOp,
|
|||
|
||||
// Worker thread only; set when `FetchEvent::RespondWith()` is called.
|
||||
Maybe<FetchEventRespondWithClosure> mRespondWithClosure;
|
||||
|
||||
// Must be set to `nullptr` on the worker thread because `Promise`'s
|
||||
// destructor must be called on the worker thread.
|
||||
RefPtr<Promise> mHandled;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -15,6 +15,7 @@ interface FetchEvent : ExtendableEvent {
|
|||
[SameObject, BinaryName="request_"] readonly attribute Request request;
|
||||
readonly attribute DOMString clientId;
|
||||
readonly attribute DOMString resultingClientId;
|
||||
readonly attribute Promise<void> handled;
|
||||
|
||||
[Throws]
|
||||
void respondWith(Promise<Response> r);
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
[fetch-event-handled.https.html]
|
||||
max-asserts: 2
|
||||
[FetchEvent.handled should reject when the promise provided to respondWith() is rejected]
|
||||
expected: FAIL
|
||||
|
||||
[FetchEvent.handled should resolve when the promise provided to respondWith() is resolved]
|
||||
expected: FAIL
|
||||
|
||||
[FetchEvent.handled should reject when the promise provided to respondWith() is resolved to an invalid response]
|
||||
expected: FAIL
|
||||
|
||||
[FetchEvent.handled should reject when respondWith() is not called and the event is canceled]
|
||||
expected: FAIL
|
||||
|
||||
[FetchEvent.handled should resolve when respondWith() is not called for a sub-resource request]
|
||||
expected: FAIL
|
||||
|
||||
[FetchEvent.handled should resolve when respondWith() is not called for a navigation request]
|
||||
expected: FAIL
|
||||
|
Загрузка…
Ссылка в новой задаче