diff options
-rwxr-xr-x | dom/events/Event.cpp | 15 | ||||
-rwxr-xr-x | dom/events/Event.h | 4 | ||||
-rw-r--r-- | dom/workers/WorkerPrivate.cpp | 133 | ||||
-rw-r--r-- | dom/workers/WorkerPrivate.h | 3 | ||||
-rw-r--r-- | testing/web-platform/meta/fetch/nosniff/worker.html.ini | 3 |
5 files changed, 132 insertions, 26 deletions
diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp index 2af34136e..2546a81ad 100755 --- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -412,8 +412,17 @@ Event::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) { nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr<Event> e = new Event(t, nullptr, nullptr); - bool trusted = e->Init(t); + return Constructor(t, aType, aParam); +} + +// static +already_AddRefed<Event> +Event::Constructor(EventTarget* aEventTarget, + const nsAString& aType, + const EventInit& aParam) +{ + RefPtr<Event> e = new Event(aEventTarget, nullptr, nullptr); + bool trusted = e->Init(aEventTarget); e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable); e->SetTrusted(trusted); e->SetComposed(aParam.mComposed); @@ -1209,7 +1218,7 @@ Event::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter) } NS_IMETHODIMP_(void) -Event::SetOwner(mozilla::dom::EventTarget* aOwner) +Event::SetOwner(EventTarget* aOwner) { mOwner = nullptr; diff --git a/dom/events/Event.h b/dom/events/Event.h index c28226e8a..0817aa809 100755 --- a/dom/events/Event.h +++ b/dom/events/Event.h @@ -142,6 +142,10 @@ public: LayoutDeviceIntPoint aPoint, CSSIntPoint aDefaultPoint); + static already_AddRefed<Event> Constructor(EventTarget* aEventTarget, + const nsAString& aType, + const EventInit& aParam); + static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal, const nsAString& aType, const EventInit& aParam, 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/testing/web-platform/meta/fetch/nosniff/worker.html.ini b/testing/web-platform/meta/fetch/nosniff/worker.html.ini deleted file mode 100644 index 011ad15b8..000000000 --- a/testing/web-platform/meta/fetch/nosniff/worker.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[worker.html] - type: testharness - expected: ERROR |