summaryrefslogtreecommitdiff
path: root/dom/workers
diff options
context:
space:
mode:
Diffstat (limited to 'dom/workers')
-rw-r--r--dom/workers/RuntimeService.cpp1
-rw-r--r--dom/workers/ScriptLoader.cpp14
-rw-r--r--dom/workers/ServiceWorkerEvents.cpp130
-rw-r--r--dom/workers/ServiceWorkerScriptCache.cpp10
-rw-r--r--dom/workers/WorkerHolder.cpp9
-rw-r--r--dom/workers/WorkerHolder.h11
-rw-r--r--dom/workers/WorkerPrefs.h1
-rw-r--r--dom/workers/WorkerPrivate.cpp15
-rw-r--r--dom/workers/WorkerPrivate.h1
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;