summaryrefslogtreecommitdiffstats
path: root/dom/workers/WorkerPrivate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/workers/WorkerPrivate.cpp')
-rw-r--r--dom/workers/WorkerPrivate.cpp147
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.