Bug 792169 - introduce better, safer constructors for nsArray; r=bsmedberg
authorNathan Froyd <froydnj@mozilla.com>
Fri, 21 Sep 2012 12:12:32 -0400
changeset 107851 711db2ce69f083b080a3a7dbca817eb966c4059c
parent 107850 fe13372ae794eb178fdb2e7a7276eb2918cf7000
child 107852 ed139b2239303d251a3e2469e68cb68ea6ab5558
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersbsmedberg
bugs792169
milestone18.0a1
Bug 792169 - introduce better, safer constructors for nsArray; r=bsmedberg
xpcom/build/XPCOMModule.inc
xpcom/ds/Makefile.in
xpcom/ds/nsArray.cpp
xpcom/ds/nsArray.h
xpcom/ds/nsHashPropertyBag.cpp
--- a/xpcom/build/XPCOMModule.inc
+++ b/xpcom/build/XPCOMModule.inc
@@ -13,17 +13,17 @@
     COMPONENT(SCRIPTABLEBASE64ENCODER, nsScriptableBase64EncoderConstructor)
     COMPONENT(PIPE, nsPipeConstructor)
 
     COMPONENT(PROPERTIES, nsPropertiesConstructor)
 
     COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create)
 
     COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create)
-    COMPONENT(ARRAY, nsArrayConstructor)
+    COMPONENT(ARRAY, nsArray::XPCOMConstructor)
     COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor)
     COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor)
     COMPONENT(ATOMSERVICE, nsAtomServiceConstructor)
     COMPONENT(OBSERVERSERVICE, nsObserverService::Create)
 
     COMPONENT(TIMER, nsTimerImplConstructor)
 
 #define COMPONENT_SUPPORTS(TYPE, Type)                                         \
--- a/xpcom/ds/Makefile.in
+++ b/xpcom/ds/Makefile.in
@@ -54,16 +54,17 @@ EXPORTS_NAMESPACES = mozilla
 
 EXPORTS_mozilla = \
   CharTokenizer.h \
   TimeStamp.h \
   StringBuilder.h \
   $(NULL)
 
 EXPORTS		= \
+		nsArray.h \
 		nsAtomService.h \
 		nsCheapSets.h \
 		nsCppSharedAllocator.h \
 		nsCRT.h \
 		nsExpirationTracker.h \
 		nsFixedSizeAllocator.h \
 		nsHashtable.h \
 		nsIByteBuffer.h \
--- a/xpcom/ds/nsArray.cpp
+++ b/xpcom/ds/nsArray.cpp
@@ -190,19 +190,23 @@ FindElementCallback(void *aElement, void
         return false;    // stop! We found it
     }
     closure->resultIndex++;
 
     return true;
 }
 
 nsresult
-nsArrayConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult)
+nsArray::XPCOMConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult)
 {
     if (aOuter)
         return NS_ERROR_NO_AGGREGATION;
 
-    nsCOMPtr<nsIArray> inst = NS_IsMainThread() ? new nsArrayCC : new nsArray;
-    if (!inst)
-        return NS_ERROR_OUT_OF_MEMORY;
-
+    nsCOMPtr<nsIMutableArray> inst = Create();
     return inst->QueryInterface(aIID, aResult); 
 }
+
+already_AddRefed<nsIMutableArray>
+nsArray::Create()
+{
+    nsCOMPtr<nsIMutableArray> inst = NS_IsMainThread() ? new nsArrayCC : new nsArray;
+    return inst.forget();
+}
--- a/xpcom/ds/nsArray.h
+++ b/xpcom/ds/nsArray.h
@@ -15,44 +15,50 @@
 #define NS_ARRAY_CLASSNAME \
   "nsIArray implementation"
 
 // {35C66FD1-95E9-4e0a-80C5-C3BD2B375481}
 #define NS_ARRAY_CID \
 { 0x35c66fd1, 0x95e9, 0x4e0a, \
   { 0x80, 0xc5, 0xc3, 0xbd, 0x2b, 0x37, 0x54, 0x81 } }
 
-
-// adapter class to map nsIArray->nsCOMArray
-// do NOT declare this as a stack or member variable, use
-// nsCOMArray instead!
-// if you need to convert a nsCOMArray->nsIArray, see NS_NewArray above
 class nsArray : public nsIMutableArray
 {
 public:
-    nsArray() { }
-    nsArray(const nsCOMArray_base& aBaseArray) : mArray(aBaseArray)
-    { }
-    
     NS_DECL_ISUPPORTS
     NS_DECL_NSIARRAY
     NS_DECL_NSIMUTABLEARRAY
 
+    /* Both of these factory functions create a cycle-collectable array
+       on the main thread and a non-cycle-collectable array on other
+       threads.  */
+    static already_AddRefed<nsIMutableArray> Create();
+    /* Only for the benefit of the XPCOM module system, use Create()
+       instead.  */
+    static nsresult XPCOMConstructor(nsISupports* aOuter, const nsIID& aIID,
+                                     void** aResult);
 protected:
+    nsArray() { }
+    nsArray(const nsArray& other);
+    nsArray(const nsCOMArray_base& aBaseArray) : mArray(aBaseArray)
+    { }
+    
     virtual ~nsArray(); // nsArrayCC inherits from this
 
     nsCOMArray_base mArray;
 };
 
 class nsArrayCC MOZ_FINAL : public nsArray
 {
+    friend class nsArray;
+
 public:
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(nsArrayCC)
+
+private:
     nsArrayCC() : nsArray() { }
+    nsArrayCC(const nsArrayCC& other);
     nsArrayCC(const nsCOMArray_base& aBaseArray) : nsArray(aBaseArray)
     { }
-    
-    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_CLASS(nsArrayCC)
 };
 
-nsresult nsArrayConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult);
-
 #endif
--- a/xpcom/ds/nsHashPropertyBag.cpp
+++ b/xpcom/ds/nsHashPropertyBag.cpp
@@ -154,17 +154,17 @@ PropertyHashToArrayFunc (const nsAString
     propertyArray->AppendElement(sprop, false);
     return PL_DHASH_NEXT;
 }
 
 
 NS_IMETHODIMP
 nsHashPropertyBag::GetEnumerator(nsISimpleEnumerator* *_retval)
 {
-    nsCOMPtr<nsIMutableArray> propertyArray = new nsArray();
+    nsCOMPtr<nsIMutableArray> propertyArray = nsArray::Create();
     if (!propertyArray)
         return NS_ERROR_OUT_OF_MEMORY;
 
     mPropertyHash.EnumerateRead(PropertyHashToArrayFunc, propertyArray.get());
 
     return NS_NewArrayEnumerator(_retval, propertyArray);
 }