Bug 859817 - Introduce already_AddRefed.downcast(); r=ehsan
authorAryeh Gregor <ayg@aryeh.name>
Sun, 21 Apr 2013 14:56:06 +0300
changeset 140996 321ab55f16ba348bc707982af8da854ae3447773
parent 140995 31823d95dca28a249c63f8eeb2c99a26c3714e21
child 140997 57a0302a88b77893c544e12d4d18b8086a79a449
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs859817
milestone23.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 859817 - Introduce already_AddRefed.downcast(); r=ehsan
content/base/src/Text.cpp
content/base/src/nsContentUtils.cpp
docshell/base/nsDocShell.cpp
dom/base/nsDOMWindowUtils.cpp
dom/bindings/CallbackObject.h
widget/gtk2/nsIdleServiceGTK.h
xpcom/glue/nsCOMPtr.h
--- a/content/base/src/Text.cpp
+++ b/content/base/src/Text.cpp
@@ -11,13 +11,13 @@ namespace dom {
 already_AddRefed<Text>
 Text::SplitText(uint32_t aOffset, ErrorResult& rv)
 {
   nsCOMPtr<nsIContent> newChild;
   rv = SplitData(aOffset, getter_AddRefs(newChild));
   if (rv.Failed()) {
     return nullptr;
   }
-  return static_cast<Text*>(newChild.forget().get());
+  return newChild.forget().downcast<Text>();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -4228,17 +4228,17 @@ nsContentUtils::CreateContextualFragment
     }
 
     content = content->GetParent();
   }
 
   nsCOMPtr<nsIDOMDocumentFragment> frag;
   aRv = ParseFragmentXML(aFragment, document, tagStack,
                          aPreventScriptExecution, getter_AddRefs(frag));
-  return static_cast<DocumentFragment*>(frag.forget().get());
+  return frag.forget().downcast<DocumentFragment>();
 }
 
 /* static */
 void
 nsContentUtils::DropFragmentParsers()
 {
   NS_IF_RELEASE(sHTMLFragmentParser);
   NS_IF_RELEASE(sXMLFragmentParser);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2755,17 +2755,17 @@ nsDocShell::GetParent(nsIDocShellTreeIte
     // don't want to throw; we just want to return null.
     return NS_OK;
 }
 
 already_AddRefed<nsDocShell>
 nsDocShell::GetParentDocshell()
 {
     nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
-    return static_cast<nsDocShell*>(docshell.forget().get());
+    return docshell.forget().downcast<nsDocShell>();
 }
 
 nsresult
 nsDocShell::SetDocLoaderParent(nsDocLoader * aParent)
 {
     nsDocLoader::SetDocLoaderParent(aParent);
 
     // Curse ambiguous nsISupports inheritance!
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1288,17 +1288,17 @@ CanvasToImageSurface(nsIDOMHTMLCanvasEle
   }
 
   NS_ABORT_IF_FALSE(node->IsElement(),
                     "An nsINode that implements nsIDOMHTMLCanvasElement should "
                     "be an element.");
   nsLayoutUtils::SurfaceFromElementResult result =
     nsLayoutUtils::SurfaceFromElement(node->AsElement(),
                                       nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
-  return static_cast<gfxImageSurface*>(result.mSurface.forget().get());
+  return result.mSurface.forget().downcast<gfxImageSurface>();
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
                                   nsIDOMHTMLCanvasElement *aCanvas2,
                                   uint32_t* aMaxDifference,
                                   uint32_t* retVal)
 {
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -315,17 +315,17 @@ public:
       nsRefPtr<XPCOMCallbackT> callback = GetXPCOMCallback();
       return callback.forget();
     }
 
     nsCOMPtr<nsISupports> supp =
       CallbackObjectHolderBase::ToXPCOMCallback(GetWebIDLCallback(),
                                                 NS_GET_TEMPLATE_IID(XPCOMCallbackT));
     // ToXPCOMCallback already did the right QI for us.
-    return static_cast<XPCOMCallbackT*>(supp.forget().get());
+    return supp.forget().downcast<XPCOMCallbackT>();
   }
 
   // Try to return a WebIDLCallbackT version of this object.
   already_AddRefed<WebIDLCallbackT> ToWebIDLCallback() const
   {
     if (HasWebIDLCallback()) {
       nsRefPtr<WebIDLCallbackT> callback = GetWebIDLCallback();
       return callback.forget();
--- a/widget/gtk2/nsIdleServiceGTK.h
+++ b/widget/gtk2/nsIdleServiceGTK.h
@@ -26,24 +26,23 @@ class nsIdleServiceGTK : public nsIdleSe
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
 
     bool PollIdleTime(uint32_t* aIdleTime);
 
     static already_AddRefed<nsIdleServiceGTK> GetInstance()
     {
-        nsIdleServiceGTK* idleService =
-            static_cast<nsIdleServiceGTK*>(nsIdleService::GetInstance().get());
+        nsRefPtr<nsIdleServiceGTK> idleService =
+            nsIdleService::GetInstance().downcast<nsIdleServiceGTK>();
         if (!idleService) {
             idleService = new nsIdleServiceGTK();
-            NS_ADDREF(idleService);
         }
 
-        return idleService;
+        return idleService.forget();
     }
 
 private:
     ~nsIdleServiceGTK();
     XScreenSaverInfo* mXssInfo;
 
 protected:
     nsIdleServiceGTK();
--- a/xpcom/glue/nsCOMPtr.h
+++ b/xpcom/glue/nsCOMPtr.h
@@ -171,16 +171,42 @@ struct already_AddRefed
     template<class U>
     operator already_AddRefed<U>()
     {
       U* tmp = mRawPtr;
       mRawPtr = NULL;
       return tmp;
     }
 
+    /**
+     * This helper provides a static_cast replacement for already_AddRefed, so
+     * if you have
+     *
+     *   already_AddRefed<Parent> F();
+     *
+     * you can write
+     *
+     *   already_AddRefed<Child>
+     *   G()
+     *   {
+     *     return F().downcast<Child>();
+     *   }
+     *
+     * instead of
+     *
+     *     return dont_AddRef(static_cast<Child*>(F().get()));
+     */
+    template<class U>
+    already_AddRefed<U> downcast()
+    {
+      U* tmp = static_cast<U*>(mRawPtr);
+      mRawPtr = nullptr;
+      return already_AddRefed<U>(tmp);
+    }
+
     T* mRawPtr;
   };
 
 template <class T>
 inline
 const already_AddRefed<T>
 getter_AddRefs( T* aRawPtr )
     /*