Bug 1283712 - Part 6: Add xpc::ErrorBase, xpc::ErrorNote, and xpc::ErrorReport.mNotes. r=bholley
authorTooru Fujisawa <arai_a@mac.com>
Wed, 15 Feb 2017 23:53:06 +0900
changeset 343090 003d483f64e0bf69ff6e7d1e9b02a9b74dfa4cc4
parent 343089 00672a065d8c13e2399c55f0d86226f83afb9393
child 343091 de4875e04b7747d22377009d016feec433e666d1
push id31369
push userkwierso@gmail.com
push dateThu, 16 Feb 2017 00:18:40 +0000
treeherdermozilla-central@e9b926463f9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1283712
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1283712 - Part 6: Add xpc::ErrorBase, xpc::ErrorNote, and xpc::ErrorReport.mNotes. r=bholley
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcpublic.h
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -167,47 +167,71 @@ nsXPConnect::IsISupportsDescendant(nsIIn
 {
     bool found = false;
     if (info)
         info->HasAncestor(&NS_GET_IID(nsISupports), &found);
     return found;
 }
 
 void
+xpc::ErrorBase::Init(JSErrorBase* aReport)
+{
+    if (!aReport->filename)
+        mFileName.SetIsVoid(true);
+    else
+        mFileName.AssignWithConversion(aReport->filename);
+
+    mLineNumber = aReport->lineno;
+    mColumn = aReport->column;
+}
+
+void
+xpc::ErrorNote::Init(JSErrorNotes::Note* aNote)
+{
+    xpc::ErrorBase::Init(aNote);
+
+    ErrorNoteToMessageString(aNote, mErrorMsg);
+}
+
+void
 xpc::ErrorReport::Init(JSErrorReport* aReport, const char* aToStringResult,
                        bool aIsChrome, uint64_t aWindowID)
 {
+    xpc::ErrorBase::Init(aReport);
     mCategory = aIsChrome ? NS_LITERAL_CSTRING("chrome javascript")
                           : NS_LITERAL_CSTRING("content javascript");
     mWindowID = aWindowID;
 
     ErrorReportToMessageString(aReport, mErrorMsg);
     if (mErrorMsg.IsEmpty() && aToStringResult) {
         AppendUTF8toUTF16(aToStringResult, mErrorMsg);
     }
 
-    if (!aReport->filename) {
-        mFileName.SetIsVoid(true);
-    } else {
-        mFileName.AssignWithConversion(aReport->filename);
-    }
-
     mSourceLine.Assign(aReport->linebuf(), aReport->linebufLength());
     const JSErrorFormatString* efs = js::GetErrorMessage(nullptr, aReport->errorNumber);
 
     if (efs == nullptr) {
         mErrorMsgName.AssignASCII("");
     } else {
         mErrorMsgName.AssignASCII(efs->name);
     }
 
-    mLineNumber = aReport->lineno;
-    mColumn = aReport->column;
     mFlags = aReport->flags;
     mIsMuted = 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).Init(note.get());
+            i++;
+        }
+    }
 }
 
 void
 xpc::ErrorReport::Init(JSContext* aCx, mozilla::dom::Exception* aException,
                        bool aIsChrome, uint64_t aWindowID)
 {
     mCategory = aIsChrome ? NS_LITERAL_CSTRING("chrome javascript")
                           : NS_LITERAL_CSTRING("content javascript");
@@ -223,42 +247,73 @@ xpc::ErrorReport::Init(JSContext* aCx, m
     aException->GetColumnNumber(&mColumn);
 
     mFlags = JSREPORT_EXCEPTION;
 }
 
 static LazyLogModule gJSDiagnostics("JSDiagnostics");
 
 void
+xpc::ErrorBase::AppendErrorDetailsTo(nsCString& error)
+{
+    error.Append(NS_LossyConvertUTF16toASCII(mFileName));
+    error.AppendLiteral(", line ");
+    error.AppendInt(mLineNumber, 10);
+    error.AppendLiteral(": ");
+    error.Append(NS_LossyConvertUTF16toASCII(mErrorMsg));
+}
+
+void
+xpc::ErrorNote::LogToStderr()
+{
+    if (!nsContentUtils::DOMWindowDumpEnabled())
+        return;
+
+    nsAutoCString error;
+    error.AssignLiteral("JavaScript note: ");
+    AppendErrorDetailsTo(error);
+
+    fprintf(stderr, "%s\n", error.get());
+    fflush(stderr);
+}
+
+void
+xpc::ErrorReport::LogToStderr()
+{
+    if (!nsContentUtils::DOMWindowDumpEnabled())
+        return;
+
+    nsAutoCString error;
+    error.AssignLiteral("JavaScript ");
+    if (JSREPORT_IS_STRICT(mFlags))
+        error.AppendLiteral("strict ");
+    if (JSREPORT_IS_WARNING(mFlags))
+        error.AppendLiteral("warning: ");
+    else
+        error.AppendLiteral("error: ");
+    AppendErrorDetailsTo(error);
+
+    fprintf(stderr, "%s\n", error.get());
+    fflush(stderr);
+
+    for (size_t i = 0, len = mNotes.Length(); i < len; i++) {
+        ErrorNote& note = mNotes[i];
+        note.LogToStderr();
+    }
+}
+
+void
 xpc::ErrorReport::LogToConsole()
 {
   LogToConsoleWithStack(nullptr);
 }
 void
 xpc::ErrorReport::LogToConsoleWithStack(JS::HandleObject aStack)
 {
-    // Log to stdout.
-    if (nsContentUtils::DOMWindowDumpEnabled()) {
-        nsAutoCString error;
-        error.AssignLiteral("JavaScript ");
-        if (JSREPORT_IS_STRICT(mFlags))
-            error.AppendLiteral("strict ");
-        if (JSREPORT_IS_WARNING(mFlags))
-            error.AppendLiteral("warning: ");
-        else
-            error.AppendLiteral("error: ");
-        error.Append(NS_LossyConvertUTF16toASCII(mFileName));
-        error.AppendLiteral(", line ");
-        error.AppendInt(mLineNumber, 10);
-        error.AppendLiteral(": ");
-        error.Append(NS_LossyConvertUTF16toASCII(mErrorMsg));
-
-        fprintf(stderr, "%s\n", error.get());
-        fflush(stderr);
-    }
+    LogToStderr();
 
     MOZ_LOG(gJSDiagnostics,
             JSREPORT_IS_WARNING(mFlags) ? LogLevel::Warning : LogLevel::Error,
             ("file %s, line %u\n%s", NS_LossyConvertUTF16toASCII(mFileName).get(),
              mLineNumber, NS_LossyConvertUTF16toASCII(mErrorMsg).get()));
 
     // Log to the console. We do this last so that we can simply return if
     // there's no console service without affecting the other reporting
@@ -284,16 +339,26 @@ xpc::ErrorReport::LogToConsoleWithStack(
                                                 mCategory, mWindowID);
     NS_ENSURE_SUCCESS_VOID(rv);
     consoleService->LogMessage(errorObject);
 
 }
 
 /* static */
 void
+xpc::ErrorNote::ErrorNoteToMessageString(JSErrorNotes::Note* aNote,
+                                         nsAString& aString)
+{
+    aString.Truncate();
+    if (aNote->message())
+        aString.Append(NS_ConvertUTF8toUTF16(aNote->message().c_str()));
+}
+
+/* static */
+void
 xpc::ErrorReport::ErrorReportToMessageString(JSErrorReport* aReport,
                                              nsAString& aString)
 {
     aString.Truncate();
     if (aReport->message()) {
         JSFlatString* name = js::GetErrorTypeName(CycleCollectedJSContext::Get()->Context(), aReport->exnType);
         if (name) {
             AssignJSFlatString(aString, name);
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -527,57 +527,85 @@ bool
 SetAddonInterposition(const nsACString& addonId, nsIAddonInterposition* interposition);
 
 bool
 AllowCPOWsInAddon(const nsACString& addonId, bool allow);
 
 bool
 ExtraWarningsForSystemJS();
 
-class ErrorReport {
+class ErrorBase {
+  public:
+    nsString mErrorMsg;
+    nsString mFileName;
+    uint32_t mLineNumber;
+    uint32_t mColumn;
+
+    ErrorBase() : mLineNumber(0)
+                , mColumn(0)
+    {}
+
+    void Init(JSErrorBase* aReport);
+
+    void AppendErrorDetailsTo(nsCString& error);
+};
+
+class ErrorNote : public ErrorBase {
+  public:
+    void Init(JSErrorNotes::Note* aNote);
+
+    // Produce an error event message string from the given JSErrorNotes::Note.
+    // This may produce an empty string if aNote doesn't have a message
+    // attached.
+    static void ErrorNoteToMessageString(JSErrorNotes::Note* aNote,
+                                         nsAString& aString);
+
+    // Log the error note to the stderr.
+    void LogToStderr();
+};
+
+class ErrorReport : public ErrorBase {
   public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ErrorReport);
 
+    nsTArray<ErrorNote> mNotes;
+
+    nsCString mCategory;
+    nsString mSourceLine;
+    nsString mErrorMsgName;
+    uint64_t mWindowID;
+    uint32_t mFlags;
+    bool mIsMuted;
+
     ErrorReport() : mWindowID(0)
-                  , mLineNumber(0)
-                  , mColumn(0)
                   , mFlags(0)
                   , mIsMuted(false)
     {}
 
     void Init(JSErrorReport* aReport, const char* aToStringResult,
               bool aIsChrome, uint64_t aWindowID);
     void Init(JSContext* aCx, mozilla::dom::Exception* aException,
               bool aIsChrome, uint64_t aWindowID);
+
     // Log the error report to the console.  Which console will depend on the
     // window id it was initialized with.
     void LogToConsole();
     // Log to console, using the given stack object (which should be a stack of
     // the sort that JS::CaptureCurrentStack produces).  aStack is allowed to be
     // null.
     void LogToConsoleWithStack(JS::HandleObject aStack);
 
     // Produce an error event message string from the given JSErrorReport.  Note
     // that this may produce an empty string if aReport doesn't have a
     // message attached.
     static void ErrorReportToMessageString(JSErrorReport* aReport,
                                            nsAString& aString);
 
-  public:
-
-    nsCString mCategory;
-    nsString mErrorMsgName;
-    nsString mErrorMsg;
-    nsString mFileName;
-    nsString mSourceLine;
-    uint64_t mWindowID;
-    uint32_t mLineNumber;
-    uint32_t mColumn;
-    uint32_t mFlags;
-    bool mIsMuted;
+    // Log the error report to the stderr.
+    void LogToStderr();
 
   private:
     ~ErrorReport() {}
 };
 
 void
 DispatchScriptErrorEvent(nsPIDOMWindowInner* win, JS::RootingContext* rootingCx,
                          xpc::ErrorReport* xpcReport, JS::Handle<JS::Value> exception);