diff options
Diffstat (limited to 'dom/workers')
-rw-r--r-- | dom/workers/RuntimeService.cpp | 4 | ||||
-rw-r--r-- | dom/workers/WorkerPrivate.cpp | 133 | ||||
-rw-r--r-- | dom/workers/WorkerPrivate.h | 3 | ||||
-rw-r--r-- | dom/workers/test/test_404.html | 1 | ||||
-rw-r--r-- | dom/workers/test/test_bug1036484.html | 1 | ||||
-rw-r--r-- | dom/workers/test/test_loadError.html | 8 |
6 files changed, 121 insertions, 29 deletions
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 1f5616873..1739f3d31 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -301,7 +301,9 @@ 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"))) - .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict"))); + .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict"))) + .setArrayProtoValues(GetWorkerPref<bool>( + NS_LITERAL_CSTRING("array_prototype_values"))); RuntimeService::SetDefaultContextOptions(contextOptions); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index c2ab4aca3..bd8a33032 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 8008f30e5..465c0f9a3 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(); diff --git a/dom/workers/test/test_404.html b/dom/workers/test/test_404.html index e2e83a35e..15e5ded68 100644 --- a/dom/workers/test/test_404.html +++ b/dom/workers/test/test_404.html @@ -25,7 +25,6 @@ Tests of DOM Worker Threads worker.onerror = function(event) { is(event.target, worker); - is(event.message, 'NetworkError: Failed to load worker script at "nonexistent_worker.js"'); event.preventDefault(); SimpleTest.finish(); }; diff --git a/dom/workers/test/test_bug1036484.html b/dom/workers/test/test_bug1036484.html index 17b9d490f..49c31bbc9 100644 --- a/dom/workers/test/test_bug1036484.html +++ b/dom/workers/test/test_bug1036484.html @@ -25,7 +25,6 @@ function test(script) { worker.onerror = function(event) { is(event.target, worker); - ok(event.message.startsWith("NetworkError: Failed to load worker script")) event.preventDefault(); runTests(); }; diff --git a/dom/workers/test/test_loadError.html b/dom/workers/test/test_loadError.html index dc109b796..b9a215d11 100644 --- a/dom/workers/test/test_loadError.html +++ b/dom/workers/test/test_loadError.html @@ -13,15 +13,13 @@ <script class="testbody" type="text/javascript"> "use strict"; -var loadErrorMessage = 'SecurityError: Failed to load worker script at "about:blank"'; - function nextTest() { (function(){ function workerfunc() { var subworker = new Worker("about:blank"); subworker.onerror = function(e) { e.preventDefault(); - postMessage(e.message); + postMessage("ERROR"); } } var b = new Blob([workerfunc+'workerfunc();']); @@ -37,7 +35,7 @@ function nextTest() { return; } w.onmessage = function(e) { - is(e.data, loadErrorMessage, + is(e.data, "ERROR", "Should catch the error when loading inner script"); if (++i < 2) callworker(i); else SimpleTest.finish(); @@ -54,8 +52,6 @@ try { var worker = new Worker("about:blank"); worker.onerror = function(e) { e.preventDefault(); - is(e.message, loadErrorMessage, - "Should get the right error from the toplevel script"); nextTest(); } |