diff options
Diffstat (limited to 'dom/workers/WorkerPrivate.cpp')
-rw-r--r-- | dom/workers/WorkerPrivate.cpp | 147 |
1 files changed, 114 insertions, 33 deletions
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index c2ab4aca3..8848e881a 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; } @@ -2336,8 +2419,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent( MOZ_ASSERT_IF(mIsChromeWorker, mIsSecureContext); MOZ_ASSERT(IsDedicatedWorker()); - mNowBaseTimeStamp = aParent->NowBaseTimeStamp(); - mNowBaseTimeHighRes = aParent->NowBaseTime(); if (aParent->mParentFrozen) { Freeze(nullptr); @@ -2368,18 +2449,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent( .creationOptions().setSecureContext(true); } - if (IsDedicatedWorker() && mLoadInfo.mWindow && - mLoadInfo.mWindow->GetPerformance()) { - mNowBaseTimeStamp = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()-> - GetNavigationStartTimeStamp(); - mNowBaseTimeHighRes = - mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()-> - GetNavigationStartHighRes(); - } else { - mNowBaseTimeStamp = CreationTimeStamp(); - mNowBaseTimeHighRes = CreationTime(); - } - // Our parent can get suspended after it initiates the async creation // of a new worker thread. In this case suspend the new worker as well. if (mLoadInfo.mWindow && mLoadInfo.mWindow->IsSuspended()) { @@ -3250,7 +3319,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers( const nsAString& aLine, uint32_t aLineNumber, uint32_t aColumnNumber, - uint32_t aFlags) + uint32_t aFlags, + bool aIsErrorEvent) { AssertIsOnMainThread(); @@ -3281,31 +3351,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. |