diff options
Diffstat (limited to 'dom/workers')
-rw-r--r-- | dom/workers/RuntimeService.cpp | 1 | ||||
-rw-r--r-- | dom/workers/ScriptLoader.cpp | 14 | ||||
-rw-r--r-- | dom/workers/ServiceWorkerEvents.cpp | 130 | ||||
-rw-r--r-- | dom/workers/ServiceWorkerScriptCache.cpp | 10 | ||||
-rw-r--r-- | dom/workers/WorkerHolder.cpp | 9 | ||||
-rw-r--r-- | dom/workers/WorkerHolder.h | 11 | ||||
-rw-r--r-- | dom/workers/WorkerPrefs.h | 1 | ||||
-rw-r--r-- | dom/workers/WorkerPrivate.cpp | 15 | ||||
-rw-r--r-- | dom/workers/WorkerPrivate.h | 1 |
9 files changed, 103 insertions, 89 deletions
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 239207efc9..6138a3c6de 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -299,6 +299,7 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */) .setNativeRegExp(GetWorkerPref<bool>(NS_LITERAL_CSTRING("native_regexp"))) .setAsyncStack(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asyncstack"))) .setWerror(GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror"))) + .setStreams(GetWorkerPref<bool>(NS_LITERAL_CSTRING("streams"))) .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict"))) .setArrayProtoValues(GetWorkerPref<bool>( NS_LITERAL_CSTRING("array_prototype_values"))); diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index 5aaac7cfae..bedf966ef1 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -700,9 +700,14 @@ private: request.SetAsUSVString().Rebind(loadInfo.mFullURL.Data(), loadInfo.mFullURL.Length()); + // This JSContext will not end up executing JS code because here there are + // no ReadableStreams involved. + AutoJSAPI jsapi; + jsapi.Init(); + ErrorResult error; RefPtr<Promise> cachePromise = - mCacheCreator->Cache_()->Put(request, *response, error); + mCacheCreator->Cache_()->Put(jsapi.cx(), request, *response, error); if (NS_WARN_IF(error.Failed())) { nsresult rv = error.StealNSResult(); channel->Cancel(rv); @@ -1667,8 +1672,13 @@ CacheScriptLoader::Load(Cache* aCache) mozilla::dom::CacheQueryOptions params; + // This JSContext will not end up executing JS code because here there are + // no ReadableStreams involved. + AutoJSAPI jsapi; + jsapi.Init(); + ErrorResult error; - RefPtr<Promise> promise = aCache->Match(request, params, error); + RefPtr<Promise> promise = aCache->Match(jsapi.cx(), request, params, error); if (NS_WARN_IF(error.Failed())) { Fail(error.StealNSResult()); return; diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp index ce2e5e7aae..569422da25 100644 --- a/dom/workers/ServiceWorkerEvents.cpp +++ b/dom/workers/ServiceWorkerEvents.cpp @@ -6,6 +6,7 @@ #include "ServiceWorkerEvents.h" #include "nsAutoPtr.h" +#include "nsContentUtils.h" #include "nsIConsoleReportCollector.h" #include "nsIHttpChannelInternal.h" #include "nsINetworkInterceptController.h" @@ -30,8 +31,6 @@ #include "mozilla/Move.h" #include "mozilla/Preferences.h" #include "mozilla/dom/BodyUtil.h" -#include "mozilla/dom/DOMException.h" -#include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/EncodingUtils.h" #include "mozilla/dom/FetchEventBinding.h" #include "mozilla/dom/MessagePort.h" @@ -404,76 +403,6 @@ void RespondWithCopyComplete(void* aClosure, nsresult aStatus) MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event)); } -namespace { - -void -ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue, - nsACString& aSourceSpecOut, uint32_t *aLineOut, - uint32_t *aColumnOut, nsString& aMessageOut) -{ - MOZ_ASSERT(aLineOut); - MOZ_ASSERT(aColumnOut); - - if (aValue.isObject()) { - JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); - RefPtr<DOMException> domException; - - // Try to process as an Error object. Use the file/line/column values - // from the Error as they will be more specific to the root cause of - // the problem. - JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr; - if (err) { - // Use xpc to extract the error message only. We don't actually send - // this report anywhere. - RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport(); - report->Init(err, - "<unknown>", // toString result - false, // chrome - 0); // window ID - - if (!report->mFileName.IsEmpty()) { - CopyUTF16toUTF8(report->mFileName, aSourceSpecOut); - *aLineOut = report->mLineNumber; - *aColumnOut = report->mColumn; - } - aMessageOut.Assign(report->mErrorMsg); - } - - // Next, try to unwrap the rejection value as a DOMException. - else if(NS_SUCCEEDED(UNWRAP_OBJECT(DOMException, obj, domException))) { - - nsAutoString filename; - domException->GetFilename(aCx, filename); - if (!filename.IsEmpty()) { - CopyUTF16toUTF8(filename, aSourceSpecOut); - *aLineOut = domException->LineNumber(aCx); - *aColumnOut = domException->ColumnNumber(); - } - - domException->GetName(aMessageOut); - aMessageOut.AppendLiteral(": "); - - nsAutoString message; - domException->GetMessageMoz(message); - aMessageOut.Append(message); - } - } - - // If we could not unwrap a specific error type, then perform default safe - // string conversions on primitives. Objects will result in "[Object]" - // unfortunately. - if (aMessageOut.IsEmpty()) { - nsAutoJSString jsString; - if (jsString.init(aCx, aValue)) { - aMessageOut = jsString; - } else { - JS_ClearPendingException(aCx); - } - } -} - -} // anonymous namespace - class MOZ_STACK_CLASS AutoCancel { RefPtr<RespondWithHandler> mOwner; @@ -505,6 +434,44 @@ public: } } + // This function steals the error message from a ErrorResult. + void + SetCancelErrorResult(JSContext* aCx, ErrorResult& aRv) + { + MOZ_DIAGNOSTIC_ASSERT(aRv.Failed()); + MOZ_DIAGNOSTIC_ASSERT(!JS_IsExceptionPending(aCx)); + + // Storing the error as exception in the JSContext. + if (!aRv.MaybeSetPendingException(aCx)) { + return; + } + + MOZ_ASSERT(!aRv.Failed()); + + // Let's take the pending exception. + JS::Rooted<JS::Value> exn(aCx); + if (!JS_GetPendingException(aCx, &exn)) { + return; + } + + JS_ClearPendingException(aCx); + + // Converting the exception in a js::ErrorReport. + js::ErrorReport report(aCx); + if (!report.init(aCx, exn, js::ErrorReport::WithSideEffects)) { + JS_ClearPendingException(aCx); + return; + } + + MOZ_ASSERT(mOwner); + MOZ_ASSERT(mMessageName.EqualsLiteral("InterceptionFailedWithURL")); + MOZ_ASSERT(mParams.Length() == 1); + + // Let's store the error message here. + mMessageName.Assign(report.toStringResult().c_str()); + mParams.Clear(); + } + template<typename... Params> void SetCancelMessage(const nsACString& aMessageName, Params&&... aParams) { @@ -557,7 +524,8 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu uint32_t line = 0; uint32_t column = 0; nsString valueString; - ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString); + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, + valueString); autoCancel.SetCancelMessageAndLocation(sourceSpec, line, column, NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"), @@ -572,7 +540,8 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu uint32_t line = 0; uint32_t column = 0; nsString valueString; - ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString); + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, + valueString); autoCancel.SetCancelMessageAndLocation(sourceSpec, line, column, NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"), @@ -659,7 +628,12 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu ir->GetUnfilteredBody(getter_AddRefs(body)); // Errors and redirects may not have a body. if (body) { - response->SetBodyUsed(); + IgnoredErrorResult error; + response->SetBodyUsed(aCx, error); + if (NS_WARN_IF(error.Failed())) { + autoCancel.SetCancelErrorResult(aCx, error); + return; + } nsCOMPtr<nsIOutputStream> responseBody; rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody)); @@ -715,7 +689,8 @@ RespondWithHandler::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu uint32_t column = mRespondWithColumnNumber; nsString valueString; - ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString); + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, + valueString); ::AsyncLog(mInterceptedChannel, sourceSpec, line, column, NS_LITERAL_CSTRING("InterceptionRejectedResponseWithURL"), @@ -853,7 +828,8 @@ public: nsCString spec; uint32_t line = 0; uint32_t column = 0; - ExtractErrorValues(aCx, aValue, spec, &line, &column, mRejectValue); + nsContentUtils::ExtractErrorValues(aCx, aValue, spec, &line, &column, + mRejectValue); // only use the extracted location if we found one if (!spec.IsEmpty()) { diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index 05be250da8..f343c35586 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -395,7 +395,7 @@ public: return; } - WriteToCache(cache); + WriteToCache(aCx, cache); return; } @@ -528,7 +528,7 @@ private: } void - WriteToCache(Cache* aCache) + WriteToCache(JSContext* aCx, Cache* aCache) { AssertIsOnMainThread(); MOZ_ASSERT(aCache); @@ -561,8 +561,10 @@ private: // For now we have to wait until the Put Promise is fulfilled before we can // continue since Cache does not yet support starting a read that is being // written to. - RefPtr<Promise> cachePromise = aCache->Put(request, *response, result); + RefPtr<Promise> cachePromise = aCache->Put(aCx, request, *response, result); if (NS_WARN_IF(result.Failed())) { + // No exception here because there are no ReadableStreams involved here. + MOZ_ASSERT(!result.IsJSException()); MOZ_ASSERT(!result.IsErrorWithMessage()); Fail(result.StealNSResult()); return; @@ -903,7 +905,7 @@ CompareCache::ManageCacheResult(JSContext* aCx, JS::Handle<JS::Value> aValue) request.SetAsUSVString().Rebind(mURL.Data(), mURL.Length()); ErrorResult error; CacheQueryOptions params; - RefPtr<Promise> promise = cache->Match(request, params, error); + RefPtr<Promise> promise = cache->Match(aCx, request, params, error); if (NS_WARN_IF(error.Failed())) { mManager->CacheFinished(error.StealNSResult(), false); return; diff --git a/dom/workers/WorkerHolder.cpp b/dom/workers/WorkerHolder.cpp index 5a8c5c4d8f..dcdcd29fa3 100644 --- a/dom/workers/WorkerHolder.cpp +++ b/dom/workers/WorkerHolder.cpp @@ -8,8 +8,9 @@ BEGIN_WORKERS_NAMESPACE -WorkerHolder::WorkerHolder() +WorkerHolder::WorkerHolder(Behavior aBehavior) : mWorkerPrivate(nullptr) + , mBehavior(aBehavior) { } @@ -44,6 +45,12 @@ WorkerHolder::ReleaseWorker() ReleaseWorkerInternal(); } +WorkerHolder::Behavior +WorkerHolder::GetBehavior() const +{ + return mBehavior; +} + void WorkerHolder::ReleaseWorkerInternal() { diff --git a/dom/workers/WorkerHolder.h b/dom/workers/WorkerHolder.h index 050c6f8e20..d8f3927af7 100644 --- a/dom/workers/WorkerHolder.h +++ b/dom/workers/WorkerHolder.h @@ -73,7 +73,12 @@ class WorkerHolder public: NS_DECL_OWNINGTHREAD - WorkerHolder(); + enum Behavior { + AllowIdleShutdownStart, + PreventIdleShutdownStart, + }; + + explicit WorkerHolder(Behavior aBehavior = PreventIdleShutdownStart); virtual ~WorkerHolder(); bool HoldWorker(WorkerPrivate* aWorkerPrivate, Status aFailStatus); @@ -81,6 +86,8 @@ public: virtual bool Notify(Status aStatus) = 0; + Behavior GetBehavior() const; + protected: void ReleaseWorkerInternal(); @@ -88,6 +95,8 @@ protected: private: void AssertIsOwningThread() const; + + const Behavior mBehavior; }; END_WORKERS_NAMESPACE diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h index 215b375ddb..415435cf06 100644 --- a/dom/workers/WorkerPrefs.h +++ b/dom/workers/WorkerPrefs.h @@ -35,6 +35,7 @@ WORKER_SIMPLE_PREF("dom.serviceWorkers.testing.enabled", ServiceWorkersTestingEn WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, OPEN_WINDOW_ENABLED) WORKER_SIMPLE_PREF("dom.storageManager.enabled", StorageManagerEnabled, STORAGEMANAGER_ENABLED) WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED) +WORKER_SIMPLE_PREF("dom.streams.enabled", StreamsEnabled, STREAMS_ENABLED) WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED) WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED) WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 622a882a65..3b3de7e3b5 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -4154,6 +4154,7 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent, , mDebugger(nullptr) , mJSContext(nullptr) , mPRThread(nullptr) + , mNumHoldersPreventingShutdownStart(0) , mDebuggerEventLoopLevel(0) , mMainThreadEventTarget(do_GetMainThread()) , mErrorHandlerRecursionCount(0) @@ -5382,8 +5383,11 @@ WorkerPrivate::AddHolder(WorkerHolder* aHolder, Status aFailStatus) MOZ_ASSERT(!mHolders.Contains(aHolder), "Already know about this one!"); - if (mHolders.IsEmpty() && !ModifyBusyCountFromWorker(true)) { - return false; + if (aHolder->GetBehavior() == WorkerHolder::PreventIdleShutdownStart) { + if (!mNumHoldersPreventingShutdownStart && !ModifyBusyCountFromWorker(true)) { + return false; + } + mNumHoldersPreventingShutdownStart += 1; } mHolders.AppendElement(aHolder); @@ -5398,8 +5402,11 @@ WorkerPrivate::RemoveHolder(WorkerHolder* aHolder) MOZ_ASSERT(mHolders.Contains(aHolder), "Didn't know about this one!"); mHolders.RemoveElement(aHolder); - if (mHolders.IsEmpty() && !ModifyBusyCountFromWorker(false)) { - NS_WARNING("Failed to modify busy count!"); + if (aHolder->GetBehavior() == WorkerHolder::PreventIdleShutdownStart) { + mNumHoldersPreventingShutdownStart -= 1; + if (!mNumHoldersPreventingShutdownStart && !ModifyBusyCountFromWorker(false)) { + NS_WARNING("Failed to modify busy count!"); + } } } diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 9effdccc9a..26afecb69b 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -980,6 +980,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate> RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope; nsTArray<ParentType*> mChildWorkers; nsTObserverArray<WorkerHolder*> mHolders; + uint32_t mNumHoldersPreventingShutdownStart; nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts; uint32_t mDebuggerEventLoopLevel; RefPtr<ThrottledEventQueue> mMainThreadThrottledEventQueue; |