summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/workers/WorkerPrivate.cpp226
-rw-r--r--dom/workers/WorkerPrivate.h46
-rw-r--r--dom/workers/moz.build1
-rw-r--r--dom/workers/test/test_sharedWorker.html2
4 files changed, 158 insertions, 117 deletions
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index 6bc5c4f96..27eb570e9 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -87,6 +87,7 @@
#include "nsProxyRelease.h"
#include "nsQueryObject.h"
#include "nsSandboxFlags.h"
+#include "nsScriptError.h"
#include "nsUTF8Utils.h"
#include "prthread.h"
#include "xpcpublic.h"
@@ -281,27 +282,34 @@ struct WindowAction
};
void
-LogErrorToConsole(const nsAString& aMessage,
- const nsAString& aFilename,
- const nsAString& aLine,
- uint32_t aLineNumber,
- uint32_t aColumnNumber,
- uint32_t aFlags,
- uint64_t aInnerWindowId)
+LogErrorToConsole(const WorkerErrorReport& aReport, uint64_t aInnerWindowId)
{
AssertIsOnMainThread();
- nsCOMPtr<nsIScriptError> scriptError =
- do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
+ RefPtr<nsScriptErrorBase> scriptError = new nsScriptError();
NS_WARNING_ASSERTION(scriptError, "Failed to create script error!");
if (scriptError) {
- if (NS_FAILED(scriptError->InitWithWindowID(aMessage, aFilename, aLine,
- aLineNumber, aColumnNumber,
- aFlags, "Web Worker",
+ nsAutoCString category("Web Worker");
+ if (NS_FAILED(scriptError->InitWithWindowID(aReport.mMessage,
+ aReport.mFilename,
+ aReport.mLine,
+ aReport.mLineNumber,
+ aReport.mColumnNumber,
+ aReport.mFlags,
+ category,
aInnerWindowId))) {
NS_WARNING("Failed to init script error!");
scriptError = nullptr;
+
+ for (size_t i = 0, len = aReport.mNotes.Length(); i < len; i++) {
+ const WorkerErrorNote& note = aReport.mNotes.ElementAt(i);
+
+ nsScriptErrorNote* noteObject = new nsScriptErrorNote();
+ noteObject->Init(note.mMessage, note.mFilename,
+ note.mLineNumber, note.mColumnNumber);
+ scriptError->AddNote(noteObject);
+ }
}
}
@@ -316,23 +324,23 @@ LogErrorToConsole(const nsAString& aMessage,
}
NS_WARNING("LogMessage failed!");
} else if (NS_SUCCEEDED(consoleService->LogStringMessage(
- aMessage.BeginReading()))) {
+ aReport.mMessage.BeginReading()))) {
return;
}
NS_WARNING("LogStringMessage failed!");
}
- NS_ConvertUTF16toUTF8 msg(aMessage);
- NS_ConvertUTF16toUTF8 filename(aFilename);
+ NS_ConvertUTF16toUTF8 msg(aReport.mMessage);
+ NS_ConvertUTF16toUTF8 filename(aReport.mFilename);
static const char kErrorString[] = "JS error in Web Worker: %s [%s:%u]";
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", kErrorString, msg.get(),
- filename.get(), aLineNumber);
+ filename.get(), aReport.mLineNumber);
#endif
- fprintf(stderr, kErrorString, msg.get(), filename.get(), aLineNumber);
+ fprintf(stderr, kErrorString, msg.get(), filename.get(), aReport.mLineNumber);
fflush(stderr);
}
@@ -536,10 +544,7 @@ private:
}
if (aWorkerPrivate->IsSharedWorker()) {
- aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
- EmptyString(),
- EmptyString(), 0, 0,
- JSREPORT_ERROR,
+ aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, nullptr,
/* isErrorEvent */ false);
return true;
}
@@ -1060,15 +1065,7 @@ private:
class ReportErrorRunnable final : public WorkerRunnable
{
- nsString mMessage;
- nsString mFilename;
- nsString mLine;
- uint32_t mLineNumber;
- uint32_t mColumnNumber;
- uint32_t mFlags;
- uint32_t mErrorNumber;
- JSExnType mExnType;
- bool mMutedError;
+ WorkerErrorReport mReport;
public:
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
@@ -1077,11 +1074,7 @@ public:
static void
ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aFireAtScope, WorkerPrivate* aTarget,
- const nsString& aMessage, const nsString& aFilename,
- const nsString& aLine, uint32_t aLineNumber,
- uint32_t aColumnNumber, uint32_t aFlags,
- uint32_t aErrorNumber, JSExnType aExnType,
- bool aMutedError, uint64_t aInnerWindowId,
+ const WorkerErrorReport& aReport, uint64_t aInnerWindowId,
JS::Handle<JS::Value> aException = JS::NullHandleValue)
{
if (aWorkerPrivate) {
@@ -1092,16 +1085,16 @@ public:
// We should not fire error events for warnings but instead make sure that
// they show up in the error console.
- if (!JSREPORT_IS_WARNING(aFlags)) {
+ if (!JSREPORT_IS_WARNING(aReport.mFlags)) {
// First fire an ErrorEvent at the worker.
RootedDictionary<ErrorEventInit> init(aCx);
- if (aMutedError) {
+ if (aReport.mMutedError) {
init.mMessage.AssignLiteral("Script error.");
} else {
- init.mMessage = aMessage;
- init.mFilename = aFilename;
- init.mLineno = aLineNumber;
+ init.mMessage = aReport.mMessage;
+ init.mFilename = aReport.mFilename;
+ init.mLineno = aReport.mLineNumber;
init.mError = aException;
}
@@ -1128,7 +1121,8 @@ public:
// into an error event on our parent worker!
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
// better.
- if (aFireAtScope && (aTarget || aErrorNumber != JSMSG_OVER_RECURSED)) {
+ if (aFireAtScope &&
+ (aTarget || aReport.mErrorNumber != JSMSG_OVER_RECURSED)) {
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
NS_ASSERTION(global, "This should never be null!");
@@ -1145,8 +1139,8 @@ public:
MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
if (globalScope || IsDebuggerSandbox(global)) {
- aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
- aMessage);
+ aWorkerPrivate->ReportErrorToDebugger(aReport.mFilename, aReport.mLineNumber,
+ aReport.mMessage);
return;
}
@@ -1193,28 +1187,20 @@ public:
// Now fire a runnable to do the same on the parent's thread if we can.
if (aWorkerPrivate) {
RefPtr<ReportErrorRunnable> runnable =
- new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
- aLineNumber, aColumnNumber, aFlags,
- aErrorNumber, aExnType, aMutedError);
+ new ReportErrorRunnable(aWorkerPrivate, aReport);
runnable->Dispatch();
return;
}
// Otherwise log an error to the error console.
- LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
- aFlags, aInnerWindowId);
+ LogErrorToConsole(aReport, aInnerWindowId);
}
private:
- ReportErrorRunnable(WorkerPrivate* aWorkerPrivate, const nsString& aMessage,
- const nsString& aFilename, const nsString& aLine,
- uint32_t aLineNumber, uint32_t aColumnNumber,
- uint32_t aFlags, uint32_t aErrorNumber,
- JSExnType aExnType, bool aMutedError)
+ ReportErrorRunnable(WorkerPrivate* aWorkerPrivate,
+ const WorkerErrorReport& aReport)
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
- mMessage(aMessage), mFilename(aFilename), mLine(aLine),
- mLineNumber(aLineNumber), mColumnNumber(aColumnNumber), mFlags(aFlags),
- mErrorNumber(aErrorNumber), mExnType(aExnType), mMutedError(aMutedError)
+ mReport(aReport)
{ }
virtual void
@@ -1251,9 +1237,7 @@ private:
}
if (aWorkerPrivate->IsSharedWorker()) {
- aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
- mLine, mLineNumber,
- mColumnNumber, mFlags,
+ aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, &mReport,
/* isErrorEvent */ true);
return true;
}
@@ -1267,9 +1251,10 @@ private:
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
aWorkerPrivate->WorkerName(),
aWorkerPrivate->ScriptURL(),
- mMessage,
- mFilename, mLine, mLineNumber,
- mColumnNumber, mFlags, mExnType);
+ mReport.mMessage,
+ mReport.mFilename, mReport.mLine, mReport.mLineNumber,
+ mReport.mColumnNumber, mReport.mFlags,
+ mReport.mExnType);
}
return true;
}
@@ -1289,9 +1274,8 @@ private:
return true;
}
- ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mMessage,
- mFilename, mLine, mLineNumber, mColumnNumber, mFlags,
- mErrorNumber, mExnType, mMutedError, innerWindowId);
+ ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mReport,
+ innerWindowId);
return true;
}
};
@@ -3314,21 +3298,16 @@ template <class Derived>
void
WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
JSContext* aCx,
- const nsAString& aMessage,
- const nsAString& aFilename,
- const nsAString& aLine,
- uint32_t aLineNumber,
- uint32_t aColumnNumber,
- uint32_t aFlags,
+ const WorkerErrorReport* aReport,
bool aIsErrorEvent)
{
AssertIsOnMainThread();
- if (JSREPORT_IS_WARNING(aFlags)) {
+ if (aIsErrorEvent && JSREPORT_IS_WARNING(aReport->mFlags)) {
// Don't fire any events anywhere. Just log to console.
// XXXbz should we log to all the consoles of all the relevant windows?
- LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
- aFlags, 0);
+ MOZ_ASSERT(aReport);
+ LogErrorToConsole(*aReport, 0);
return;
}
@@ -3357,10 +3336,10 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
RootedDictionary<ErrorEventInit> errorInit(aCx);
errorInit.mBubbles = false;
errorInit.mCancelable = true;
- errorInit.mMessage = aMessage;
- errorInit.mFilename = aFilename;
- errorInit.mLineno = aLineNumber;
- errorInit.mColno = aColumnNumber;
+ errorInit.mMessage = aReport->mMessage;
+ errorInit.mFilename = aReport->mFilename;
+ errorInit.mLineno = aReport->mLineNumber;
+ errorInit.mColno = aReport->mColumnNumber;
event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
errorInit);
@@ -3426,9 +3405,9 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
MOZ_ASSERT(NS_IsMainThread());
RootedDictionary<ErrorEventInit> init(aCx);
- init.mLineno = aLineNumber;
- init.mFilename = aFilename;
- init.mMessage = aMessage;
+ init.mLineno = aReport->mLineNumber;
+ init.mFilename = aReport->mFilename;
+ init.mMessage = aReport->mMessage;
init.mCancelable = true;
init.mBubbles = true;
@@ -3446,8 +3425,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
// Finally log a warning in the console if no window tried to prevent it.
if (shouldLogErrorToConsole) {
- LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
- aFlags, 0);
+ MOZ_ASSERT(aReport);
+ LogErrorToConsole(*aReport, 0);
}
}
@@ -4120,7 +4099,10 @@ WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
listeners[index]->OnError(aFilename, aLineno, aMessage);
}
- LogErrorToConsole(aMessage, aFilename, nsString(), aLineno, 0, 0, 0);
+ WorkerErrorReport report;
+ report.mMessage = aMessage;
+ report.mFilename = aFilename;
+ LogErrorToConsole(report, 0);
}
WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
@@ -5926,6 +5908,47 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
}
void
+WorkerErrorBase::AssignErrorBase(JSErrorBase* aReport)
+{
+ mFilename = NS_ConvertUTF8toUTF16(aReport->filename);
+ mLineNumber = aReport->lineno;
+ mColumnNumber = aReport->column;
+ mErrorNumber = aReport->errorNumber;
+}
+
+void
+WorkerErrorNote::AssignErrorNote(JSErrorNotes::Note* aNote)
+{
+ WorkerErrorBase::AssignErrorBase(aNote);
+ xpc::ErrorNote::ErrorNoteToMessageString(aNote, mMessage);
+}
+
+void
+WorkerErrorReport::AssignErrorReport(JSErrorReport* aReport)
+{
+ WorkerErrorBase::AssignErrorBase(aReport);
+ xpc::ErrorReport::ErrorReportToMessageString(aReport, mMessage);
+
+ mLine.Assign(aReport->linebuf(), aReport->linebufLength());
+ mFlags = aReport->flags;
+ MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
+ mExnType = JSExnType(aReport->exnType);
+ mMutedError = aReport->isMuted;
+
+ if (aReport->notes) {
+ if (!mNotes.SetLength(aReport->notes->length(), fallible)) {
+ return;
+ }
+
+ size_t i = 0;
+ for (auto&& note : *aReport->notes) {
+ mNotes.ElementAt(i).AssignErrorNote(note.get());
+ i++;
+ }
+ }
+}
+
+void
WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
JSErrorReport* aReport)
{
@@ -5947,32 +5970,17 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
}
JS_ClearPendingException(aCx);
- nsString message, filename, line;
- uint32_t lineNumber, columnNumber, flags, errorNumber;
- JSExnType exnType = JSEXN_ERR;
- bool mutedError = aReport && aReport->isMuted;
-
+ WorkerErrorReport report;
if (aReport) {
- // We want the same behavior here as xpc::ErrorReport::init here.
- xpc::ErrorReport::ErrorReportToMessageString(aReport, message);
-
- filename = NS_ConvertUTF8toUTF16(aReport->filename);
- line.Assign(aReport->linebuf(), aReport->linebufLength());
- lineNumber = aReport->lineno;
- columnNumber = aReport->tokenOffset();
- flags = aReport->flags;
- errorNumber = aReport->errorNumber;
- MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
- exnType = JSExnType(aReport->exnType);
+ report.AssignErrorReport(aReport);
}
else {
- lineNumber = columnNumber = errorNumber = 0;
- flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
+ report.mFlags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
}
- if (message.IsEmpty() && aToStringResult) {
+ if (report.mMessage.IsEmpty() && aToStringResult) {
nsDependentCString toStringResult(aToStringResult.c_str());
- if (!AppendUTF8toUTF16(toStringResult, message, mozilla::fallible)) {
+ if (!AppendUTF8toUTF16(toStringResult, report.mMessage, mozilla::fallible)) {
// Try again, with only a 1 KB string. Do this infallibly this time.
// If the user doesn't have 1 KB to spare we're done anyways.
uint32_t index = std::min(uint32_t(1024), toStringResult.Length());
@@ -5982,7 +5990,7 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
nsDependentCString truncatedToStringResult(aToStringResult.c_str(),
index);
- AppendUTF8toUTF16(truncatedToStringResult, message);
+ AppendUTF8toUTF16(truncatedToStringResult, report.mMessage);
}
}
@@ -5991,13 +5999,11 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
// Don't want to run the scope's error handler if this is a recursive error or
// if we ran out of memory.
bool fireAtScope = mErrorHandlerRecursionCount == 1 &&
- errorNumber != JSMSG_OUT_OF_MEMORY &&
+ report.mErrorNumber != JSMSG_OUT_OF_MEMORY &&
JS::CurrentGlobalOrNull(aCx);
- ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
- filename, line, lineNumber,
- columnNumber, flags, errorNumber, exnType,
- mutedError, 0, exn);
+ ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, report, 0,
+ exn);
mErrorHandlerRecursionCount--;
}
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index 20a530205..885abccd5 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -140,6 +140,45 @@ public:
}
};
+class WorkerErrorBase {
+public:
+ nsString mMessage;
+ nsString mFilename;
+ uint32_t mLineNumber;
+ uint32_t mColumnNumber;
+ uint32_t mErrorNumber;
+
+ WorkerErrorBase()
+ : mLineNumber(0),
+ mColumnNumber(0),
+ mErrorNumber(0)
+ { }
+
+ void AssignErrorBase(JSErrorBase* aReport);
+};
+
+class WorkerErrorNote : public WorkerErrorBase {
+public:
+ void AssignErrorNote(JSErrorNotes::Note* aNote);
+};
+
+class WorkerErrorReport : public WorkerErrorBase {
+public:
+ nsString mLine;
+ uint32_t mFlags;
+ JSExnType mExnType;
+ bool mMutedError;
+ nsTArray<WorkerErrorNote> mNotes;
+
+ WorkerErrorReport()
+ : mFlags(0),
+ mExnType(JSEXN_ERR),
+ mMutedError(false)
+ { }
+
+ void AssignErrorReport(JSErrorReport* aReport);
+};
+
template <class Derived>
class WorkerPrivateParent : public DOMEventTargetHelper
{
@@ -401,12 +440,7 @@ public:
void
BroadcastErrorToSharedWorkers(JSContext* aCx,
- const nsAString& aMessage,
- const nsAString& aFilename,
- const nsAString& aLine,
- uint32_t aLineNumber,
- uint32_t aColumnNumber,
- uint32_t aFlags,
+ const WorkerErrorReport* aReport,
bool aIsErrorEvent);
void
diff --git a/dom/workers/moz.build b/dom/workers/moz.build
index 4f4b52e4a..9fea84193 100644
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -94,6 +94,7 @@ LOCAL_INCLUDES += [
'../base',
'../system',
'/dom/base',
+ '/dom/bindings',
'/xpcom/build',
'/xpcom/threads',
]
diff --git a/dom/workers/test/test_sharedWorker.html b/dom/workers/test/test_sharedWorker.html
index 3d3d4e2c6..c00c4e586 100644
--- a/dom/workers/test/test_sharedWorker.html
+++ b/dom/workers/test/test_sharedWorker.html
@@ -23,7 +23,7 @@
const errorFilename = href.substring(0, href.lastIndexOf("/") + 1) +
filename;
const errorLine = 91;
- const errorColumn = 0;
+ const errorColumn = 11;
var worker = new SharedWorker(filename);