summaryrefslogtreecommitdiff
path: root/dom/workers
diff options
context:
space:
mode:
authorjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-04-04 21:36:19 +0200
committerjanekptacijarabaci <janekptacijarabaci@seznam.cz>2018-04-04 21:36:19 +0200
commitaea1fd640e01b5e36fb5e9f435681d8d4501d6f5 (patch)
treeb60e6c7937103afdd7cd158292c07ae2c7abbb95 /dom/workers
parent3968897fb4b227b1a634700cbeaea715e58ac543 (diff)
downloaduxp-aea1fd640e01b5e36fb5e9f435681d8d4501d6f5.tar.gz
Bug 1288768 - Better error reporting for network errors in workers
Diffstat (limited to 'dom/workers')
-rw-r--r--dom/workers/WorkerPrivate.cpp133
-rw-r--r--dom/workers/WorkerPrivate.h3
2 files changed, 116 insertions, 20 deletions
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index c2ab4aca38..bd8a33032e 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -495,6 +495,82 @@ private:
}
};
+class ReportCompileErrorRunnable final : public WorkerRunnable
+{
+public:
+ static void
+ CreateAndDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
+ {
+ MOZ_ASSERT(aWorkerPrivate);
+ aWorkerPrivate->AssertIsOnWorkerThread();
+
+ RefPtr<ReportCompileErrorRunnable> runnable =
+ new ReportCompileErrorRunnable(aCx, aWorkerPrivate);
+ runnable->Dispatch();
+ }
+
+private:
+ ReportCompileErrorRunnable(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
+ : WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
+ {
+ aWorkerPrivate->AssertIsOnWorkerThread();
+ }
+
+ void
+ PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
+ {
+ aWorkerPrivate->AssertIsOnWorkerThread();
+
+ // Dispatch may fail if the worker was canceled, no need to report that as
+ // an error, so don't call base class PostDispatch.
+ }
+
+ bool
+ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+ {
+ if (aWorkerPrivate->IsFrozen() ||
+ aWorkerPrivate->IsParentWindowPaused()) {
+ MOZ_ASSERT(!IsDebuggerRunnable());
+ aWorkerPrivate->QueueRunnable(this);
+ return true;
+ }
+
+ if (aWorkerPrivate->IsSharedWorker()) {
+ aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
+ EmptyString(),
+ EmptyString(), 0, 0,
+ JSREPORT_ERROR,
+ /* isErrorEvent */ false);
+ return true;
+ }
+
+ if (aWorkerPrivate->IsServiceWorker()) {
+ RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+ if (swm) {
+ swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
+ aWorkerPrivate->WorkerName(),
+ aWorkerPrivate->ScriptURL(),
+ EmptyString(), EmptyString(), EmptyString(),
+ 0, 0, JSREPORT_ERROR, JSEXN_ERR);
+ }
+ return true;
+ }
+
+ if (!aWorkerPrivate->IsAcceptingEvents()) {
+ return true;
+ }
+
+ RefPtr<Event> event =
+ Event::Constructor(aWorkerPrivate, NS_LITERAL_STRING("error"),
+ EventInit());
+ event->SetTrusted(true);
+
+ nsEventStatus status = nsEventStatus_eIgnore;
+ aWorkerPrivate->DispatchDOMEvent(nullptr, event, nullptr, &status);
+ return true;
+ }
+};
+
class CompileScriptRunnable final : public WorkerRunnable
{
nsString mScriptURL;
@@ -538,9 +614,15 @@ private:
}
// Make sure to propagate exceptions from rv onto aCx, so that they will get
- // reported after we return. We do this for all failures on rv, because now
- // we're using rv to track all the state we care about.
- //
+ // reported after we return. We want to propagate just JS exceptions,
+ // because all the other errors are handled when the script is loaded.
+ // See: https://dom.spec.whatwg.org/#concept-event-fire
+ if (rv.Failed() && !rv.IsJSException()) {
+ ReportCompileErrorRunnable::CreateAndDispatch(aCx, aWorkerPrivate);
+ rv.SuppressException();
+ return false;
+ }
+
// This is a little dumb, but aCx is in the null compartment here because we
// set it up that way in our Run(), since we had not created the global at
// that point yet. So we need to enter the compartment of our global,
@@ -1171,7 +1253,8 @@ private:
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
mLine, mLineNumber,
- mColumnNumber, mFlags);
+ mColumnNumber, mFlags,
+ /* isErrorEvent */ true);
return true;
}
@@ -3250,7 +3333,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
- uint32_t aFlags)
+ uint32_t aFlags,
+ bool aIsErrorEvent)
{
AssertIsOnMainThread();
@@ -3281,31 +3365,42 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
// May be null.
nsPIDOMWindowInner* window = sharedWorker->GetOwner();
- RootedDictionary<ErrorEventInit> errorInit(aCx);
- errorInit.mBubbles = false;
- errorInit.mCancelable = true;
- errorInit.mMessage = aMessage;
- errorInit.mFilename = aFilename;
- errorInit.mLineno = aLineNumber;
- errorInit.mColno = aColumnNumber;
-
- RefPtr<ErrorEvent> errorEvent =
- ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
- errorInit);
- if (!errorEvent) {
+ RefPtr<Event> event;
+
+ if (aIsErrorEvent) {
+ RootedDictionary<ErrorEventInit> errorInit(aCx);
+ errorInit.mBubbles = false;
+ errorInit.mCancelable = true;
+ errorInit.mMessage = aMessage;
+ errorInit.mFilename = aFilename;
+ errorInit.mLineno = aLineNumber;
+ errorInit.mColno = aColumnNumber;
+
+ event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
+ errorInit);
+ } else {
+ event = Event::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
+ EventInit());
+ }
+
+ if (!event) {
ThrowAndReport(window, NS_ERROR_UNEXPECTED);
continue;
}
- errorEvent->SetTrusted(true);
+ event->SetTrusted(true);
bool defaultActionEnabled;
- nsresult rv = sharedWorker->DispatchEvent(errorEvent, &defaultActionEnabled);
+ nsresult rv = sharedWorker->DispatchEvent(event, &defaultActionEnabled);
if (NS_FAILED(rv)) {
ThrowAndReport(window, rv);
continue;
}
+ if (!aIsErrorEvent) {
+ continue;
+ }
+
if (defaultActionEnabled) {
// Add the owning window to our list so that we will fire an error event
// at it later.
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index 8008f30e54..465c0f9a33 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -408,7 +408,8 @@ public:
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
- uint32_t aFlags);
+ uint32_t aFlags,
+ bool aIsErrorEvent);
void
WorkerScriptLoaded();