Bug 1182197 investigation patch. Log the stack at promise fulfillment on a CCed promise into the crash reporter data. r=dmajor,nsm
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 08 Sep 2015 21:23:55 -0400
changeset 294067 947d0307ed7730e95171822033f6eb46cf3c2cd5
parent 294066 d7edc758649a9a5a43fbe038b2e190dca4072f25
child 294068 a1e45a92a3765862860a0a255f5fcc4ba0b3b552
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmajor, nsm
bugs1182197
milestone43.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 1182197 investigation patch. Log the stack at promise fulfillment on a CCed promise into the crash reporter data. r=dmajor,nsm
dom/promise/Promise.cpp
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -31,16 +31,19 @@
 #include "nsPIDOMWindow.h"
 #include "PromiseCallback.h"
 #include "PromiseDebugging.h"
 #include "PromiseNativeHandler.h"
 #include "PromiseWorkerProxy.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "xpcpublic.h"
+#ifdef MOZ_CRASHREPORTER
+#include "nsExceptionHandler.h"
+#endif
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 // Generator used by Promise::GetID.
 Atomic<uintptr_t> gIDGenerator(0);
 } // namespace
@@ -531,20 +534,20 @@ Promise::JSCallback(JSContext* aCx, unsi
   if (NS_FAILED(UNWRAP_OBJECT(Promise, &v.toObject(), promise))) {
     return Throw(aCx, NS_ERROR_UNEXPECTED);
   }
 
   v = js::GetFunctionNativeReserved(&args.callee(), SLOT_DATA);
   PromiseCallback::Task task = static_cast<PromiseCallback::Task>(v.toInt32());
 
   if (task == PromiseCallback::Resolve) {
-    promise->MaybeResolveInternal(aCx, args.get(0));
     if (!promise->CaptureStack(aCx, promise->mFullfillmentStack)) {
       return false;
     }
+    promise->MaybeResolveInternal(aCx, args.get(0));
   } else {
     promise->MaybeRejectInternal(aCx, args.get(0));
     if (!promise->CaptureStack(aCx, promise->mRejectionStack)) {
       return false;
     }
   }
 
   args.rval().setUndefined();
@@ -1337,16 +1340,39 @@ Promise::RejectInternal(JSContext* aCx,
   mResolvePending = true;
 
   MaybeSettle(aValue, Rejected);
 }
 
 void
 Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
 {
+#ifdef MOZ_CRASHREPORTER
+  if (!mGlobal && mFullfillmentStack) {
+    AutoJSAPI jsapi;
+    jsapi.Init();
+    JSContext* cx = jsapi.cx();
+    JS::RootedObject stack(cx, mFullfillmentStack);
+    JSAutoCompartment ac(cx, stack);
+    JS::RootedString stackJSString(cx);
+    if (JS::BuildStackString(cx, stack, &stackJSString)) {
+      nsAutoJSString stackString;
+      if (stackString.init(cx, stackJSString)) {
+        // Put the string in the crash report here, since we're about to crash
+        CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("cced_promise_stack"),
+                                           NS_ConvertUTF16toUTF8(stackString));
+      } else {
+        JS_ClearPendingException(cx);
+      }
+    } else {
+      JS_ClearPendingException(cx);
+    }
+  }
+#endif
+
   if (mGlobal->IsDying()) {
     return;
   }
 
   mSettlementTimestamp = TimeStamp::Now();
 
   SetResult(aValue);
   SetState(aState);