Bug 1140435 - Part 1 - Add the asyncCause and asyncCaller properties to nsIStackFrame. r=bz
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Sat, 07 Mar 2015 13:30:34 +0000
changeset 232414 750120b03c83b692dc927b0ac3759724ab803cf2
parent 232413 4fb7b71b56d4c2bd85d39bb024329b0cb95cfd8f
child 232415 bdacb3e22b546a7879ba00c6700092da28901d8e
push id28379
push userphilringnalda@gmail.com
push dateSun, 08 Mar 2015 03:39:06 +0000
treeherdermozilla-central@fecf1afb0830 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1140435
milestone39.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 1140435 - Part 1 - Add the asyncCause and asyncCaller properties to nsIStackFrame. r=bz
dom/bindings/Exceptions.cpp
xpcom/base/nsIException.idl
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -251,18 +251,20 @@ protected:
 
   virtual nsresult GetColNo(int32_t* aColNo)
   {
     *aColNo = mColNo;
     return NS_OK;
   }
 
   nsCOMPtr<nsIStackFrame> mCaller;
+  nsCOMPtr<nsIStackFrame> mAsyncCaller;
   nsString mFilename;
   nsString mFunname;
+  nsString mAsyncCause;
   int32_t mLineno;
   int32_t mColNo;
   uint32_t mLanguage;
 };
 
 StackFrame::StackFrame(uint32_t aLanguage,
                        const char* aFilename,
                        const char* aFunctionName,
@@ -275,17 +277,17 @@ StackFrame::StackFrame(uint32_t aLanguag
   CopyUTF8toUTF16(aFilename, mFilename);
   CopyUTF8toUTF16(aFunctionName, mFunname);
 }
 
 StackFrame::~StackFrame()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION(StackFrame, mCaller)
+NS_IMPL_CYCLE_COLLECTION(StackFrame, mCaller, mAsyncCaller)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(StackFrame)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(StackFrame)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StackFrame)
   NS_INTERFACE_MAP_ENTRY(nsIStackFrame)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
@@ -300,16 +302,18 @@ public:
   explicit JSStackFrame(JS::Handle<JSObject*> aStack);
 
   static already_AddRefed<nsIStackFrame>
   CreateStack(JSContext* aCx, int32_t aMaxDepth = -1);
 
   NS_IMETHOD GetLanguageName(nsACString& aLanguageName) MOZ_OVERRIDE;
   NS_IMETHOD GetFilename(nsAString& aFilename) MOZ_OVERRIDE;
   NS_IMETHOD GetName(nsAString& aFunction) MOZ_OVERRIDE;
+  NS_IMETHOD GetAsyncCause(nsAString& aAsyncCause) MOZ_OVERRIDE;
+  NS_IMETHOD GetAsyncCaller(nsIStackFrame** aAsyncCaller) MOZ_OVERRIDE;
   NS_IMETHOD GetCaller(nsIStackFrame** aCaller) MOZ_OVERRIDE;
   NS_IMETHOD GetFormattedStack(nsAString& aStack) MOZ_OVERRIDE;
 
 protected:
   virtual bool IsJSFrame() const MOZ_OVERRIDE {
     return true;
   }
 
@@ -321,26 +325,30 @@ private:
 
   JS::Heap<JSObject*> mStack;
   nsString mFormattedStack;
 
   bool mFilenameInitialized;
   bool mFunnameInitialized;
   bool mLinenoInitialized;
   bool mColNoInitialized;
+  bool mAsyncCauseInitialized;
+  bool mAsyncCallerInitialized;
   bool mCallerInitialized;
   bool mFormattedStackInitialized;
 };
 
 JSStackFrame::JSStackFrame(JS::Handle<JSObject*> aStack)
   : mStack(aStack)
   , mFilenameInitialized(false)
   , mFunnameInitialized(false)
   , mLinenoInitialized(false)
   , mColNoInitialized(false)
+  , mAsyncCauseInitialized(false)
+  , mAsyncCallerInitialized(false)
   , mCallerInitialized(false)
   , mFormattedStackInitialized(false)
 {
   MOZ_ASSERT(mStack);
 
   mozilla::HoldJSObjects(this);
   mLineno = 0;
   mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
@@ -573,16 +581,94 @@ NS_IMETHODIMP StackFrame::GetColumnNumbe
 
 /* readonly attribute AUTF8String sourceLine; */
 NS_IMETHODIMP StackFrame::GetSourceLine(nsACString& aSourceLine)
 {
   aSourceLine.Truncate();
   return NS_OK;
 }
 
+/* readonly attribute AString asyncCause; */
+NS_IMETHODIMP JSStackFrame::GetAsyncCause(nsAString& aAsyncCause)
+{
+  NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
+  ThreadsafeAutoJSContext cx;
+  JS::Rooted<JSString*> asyncCause(cx);
+  bool canCache = false, useCachedValue = false;
+  GetValueIfNotCached(cx, mStack, JS::GetSavedFrameAsyncCause,
+                      mAsyncCauseInitialized, &canCache, &useCachedValue,
+                      &asyncCause);
+
+  if (useCachedValue) {
+    return StackFrame::GetAsyncCause(aAsyncCause);
+  }
+
+  if (asyncCause) {
+    nsAutoJSString str;
+    if (!str.init(cx, asyncCause)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    aAsyncCause = str;
+  } else {
+    aAsyncCause.SetIsVoid(true);
+  }
+
+  if (canCache) {
+    mAsyncCause = aAsyncCause;
+    mAsyncCauseInitialized = true;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP StackFrame::GetAsyncCause(nsAString& aAsyncCause)
+{
+  // The async cause must be set to null if empty.
+  if (mAsyncCause.IsEmpty()) {
+    aAsyncCause.SetIsVoid(true);
+  } else {
+    aAsyncCause.Assign(mAsyncCause);
+  }
+
+  return NS_OK;
+}
+
+/* readonly attribute nsIStackFrame asyncCaller; */
+NS_IMETHODIMP JSStackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller)
+{
+  NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
+  ThreadsafeAutoJSContext cx;
+  JS::Rooted<JSObject*> asyncCallerObj(cx);
+  bool canCache = false, useCachedValue = false;
+  GetValueIfNotCached(cx, mStack, JS::GetSavedFrameAsyncParent,
+                      mAsyncCallerInitialized, &canCache, &useCachedValue,
+                      &asyncCallerObj);
+
+  if (useCachedValue) {
+    return StackFrame::GetAsyncCaller(aAsyncCaller);
+  }
+
+  nsCOMPtr<nsIStackFrame> asyncCaller =
+    asyncCallerObj ? new JSStackFrame(asyncCallerObj) : nullptr;
+  asyncCaller.forget(aAsyncCaller);
+
+  if (canCache) {
+    mAsyncCaller = *aAsyncCaller;
+    mAsyncCallerInitialized = true;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP StackFrame::GetAsyncCaller(nsIStackFrame** aAsyncCaller)
+{
+  NS_IF_ADDREF(*aAsyncCaller = mAsyncCaller);
+  return NS_OK;
+}
+
 /* readonly attribute nsIStackFrame caller; */
 NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
 {
   NS_ENSURE_TRUE(mStack, NS_ERROR_NOT_AVAILABLE);
   ThreadsafeAutoJSContext cx;
   JS::Rooted<JSObject*> callerObj(cx);
   bool canCache = false, useCachedValue = false;
   GetValueIfNotCached(cx, mStack, JS::GetSavedFrameParent, mCallerInitialized,
--- a/xpcom/base/nsIException.idl
+++ b/xpcom/base/nsIException.idl
@@ -5,28 +5,30 @@
 
 /*
  * Interfaces for representing cross-language exceptions and stack traces.
  */
 
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(8272a3d5-2a94-40c0-8ab6-be76583a0221)]
+[scriptable, uuid(9787bc41-1ec9-4fe0-8b31-ffee5db6a893)]
 interface nsIStackFrame : nsISupports
 {
     // see nsIProgrammingLanguage for list of language consts
     readonly attribute uint32_t                language;
     readonly attribute AUTF8String             languageName;
     readonly attribute AString                 filename;
     readonly attribute AString                 name;
     // Valid line numbers begin at '1'. '0' indicates unknown.
     readonly attribute int32_t                 lineNumber;
     readonly attribute int32_t                 columnNumber;
     readonly attribute AUTF8String             sourceLine;
+    readonly attribute AString                 asyncCause;
+    readonly attribute nsIStackFrame           asyncCaller;
     readonly attribute nsIStackFrame           caller;
 
     // Returns a formatted stack string that looks like the sort of
     // string that would be returned by .stack on JS Error objects.
     // Only works on JS-language stack frames.
     readonly attribute AString                 formattedStack;
 
     AUTF8String toString();