Bug 1310040 - Make nsSupportsArray implement nsIArray. r=froydnj
authorEric Rahm <erahm@mozilla.com>
Tue, 18 Oct 2016 11:52:08 -0700
changeset 318536 ad002143ba47b08d4c65ab58ad4e063f296050d5
parent 318535 a1f6ee2b22395a54b4b7624e2e4a189fa3ec459d
child 318537 d0155687dae8b38cf72488e163e50b198924a94a
push id20725
push userphilringnalda@gmail.com
push dateThu, 20 Oct 2016 01:36:01 +0000
treeherderfx-team@998ad5a74da8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1310040
milestone52.0a1
Bug 1310040 - Make nsSupportsArray implement nsIArray. r=froydnj This makes nsSupportsArray implement the |nsIArray| interface. This will allow us to replace references to nsISupportsArray as a param in our gecko interfaces with nsIArray instead. The goal is to remove this adapter (and nsISupportsArray) after a full release cycle. MozReview-Commit-ID: If7RiO5muIk
xpcom/ds/nsICollection.idl
xpcom/ds/nsSupportsArray.cpp
xpcom/ds/nsSupportsArray.h
xpcom/tests/unit/test_nsIMutableArray.js
--- a/xpcom/ds/nsICollection.idl
+++ b/xpcom/ds/nsICollection.idl
@@ -14,16 +14,22 @@ interface nsICollection : nsISerializabl
   uint32_t Count();
   nsISupports GetElementAt(in uint32_t index);
   void QueryElementAt(in uint32_t index, in nsIIDRef uuid, 
                       [iid_is(uuid),retval] out nsQIResult result);
   void SetElementAt(in uint32_t index, in nsISupports item);
   void AppendElement(in nsISupports item);
   void RemoveElement(in nsISupports item);
 
+  /**
+   * This clashes with |nsISimpleEnumerator nsIArray.enumerate()| (only on the
+   * binary side), so it is renamed with a 'Deprecated' prefix in favor of the
+   * non-deprecated |nsIArray.enumerate|.
+   */
+  [binaryname(DeprecatedEnumerate)]
   nsIEnumerator Enumerate();
 
   void Clear();
 
 };
 
 %{C++
 
--- a/xpcom/ds/nsSupportsArray.cpp
+++ b/xpcom/ds/nsSupportsArray.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdint.h>
 #include <string.h>
 
+#include "nsArrayEnumerator.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsSupportsArray.h"
 #include "nsSupportsArrayEnumerator.h"
 
 nsresult
 nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const
 {
@@ -42,17 +43,17 @@ nsSupportsArray::Create(nsISupports* aOu
     return NS_ERROR_NO_AGGREGATION;
   }
 
   nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
 
   return it->QueryInterface(aIID, aResult);
 }
 
-NS_IMPL_ISUPPORTS(nsSupportsArray, nsISupportsArray, nsICollection,
+NS_IMPL_ISUPPORTS(nsSupportsArray, nsIArray, nsISupportsArray, nsICollection,
                   nsISerializable)
 
 NS_IMETHODIMP
 nsSupportsArray::Read(nsIObjectInputStream* aStream)
 {
   nsresult rv;
 
   uint32_t newArraySize;
@@ -167,17 +168,17 @@ nsSupportsArray::RemoveElement(nsISuppor
 NS_IMETHODIMP
 nsSupportsArray::Clear(void)
 {
   mArray.Clear();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSupportsArray::Enumerate(nsIEnumerator** aResult)
+nsSupportsArray::DeprecatedEnumerate(nsIEnumerator** aResult)
 {
   RefPtr<nsSupportsArrayEnumerator> e = new nsSupportsArrayEnumerator(this);
   e.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSupportsArray::Clone(nsISupportsArray** aResult)
@@ -203,8 +204,44 @@ nsSupportsArray::Clone(nsISupportsArray*
 nsresult
 NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
 {
   nsresult rv;
   rv = nsSupportsArray::Create(nullptr, NS_GET_IID(nsISupportsArray),
                                (void**)aInstancePtrResult);
   return rv;
 }
+
+/**
+ * nsIArray adapters.
+ */
+NS_IMETHODIMP
+nsSupportsArray::GetLength(uint32_t* aLength) {
+  return Count(aLength);
+}
+
+NS_IMETHODIMP
+nsSupportsArray::QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult)
+{
+  nsISupports* element = mArray.SafeElementAt(aIndex);
+  if (element) {
+    return element->QueryInterface(aIID, aResult);
+  }
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::IndexOf(uint32_t aStartIndex, nsISupports* aElement, uint32_t* aResult)
+{
+  int32_t idx = mArray.IndexOf(aElement, aStartIndex);
+  if (idx < 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  *aResult = static_cast<uint32_t>(idx);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Enumerate(nsISimpleEnumerator** aResult)
+{
+  return NS_NewArrayEnumerator(aResult, this);
+}
--- a/xpcom/ds/nsSupportsArray.h
+++ b/xpcom/ds/nsSupportsArray.h
@@ -6,17 +6,18 @@
 
 #ifndef nsSupportsArray_h__
 #define nsSupportsArray_h__
 
 #include "nsISupportsArray.h"
 #include "nsCOMArray.h"
 #include "mozilla/Attributes.h"
 
-class nsSupportsArray final : public nsISupportsArray
+class nsSupportsArray final : public nsISupportsArray,
+                              public nsIArray
 {
   ~nsSupportsArray(void); // nonvirtual since we're not subclassed
 
 public:
   nsSupportsArray(void);
 
   static MOZ_MUST_USE nsresult
   Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
@@ -28,37 +29,28 @@ public:
   // nsICollection methods:
   NS_IMETHOD Count(uint32_t* aResult) override
   {
     *aResult = mArray.Length();
     return NS_OK;
   }
   NS_IMETHOD GetElementAt(uint32_t aIndex, nsISupports** aResult) override;
   MOZ_MUST_USE NS_IMETHOD
-  QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult) override
-  {
-    nsISupports* element = mArray.SafeElementAt(aIndex);
-    if (element) {
-      return element->QueryInterface(aIID, aResult);
-    }
-    return NS_ERROR_FAILURE;
-  }
-  MOZ_MUST_USE NS_IMETHOD
   SetElementAt(uint32_t aIndex, nsISupports* aValue) override
   {
     return ReplaceElementAt(aValue, aIndex) ? NS_OK : NS_ERROR_FAILURE;
   }
   MOZ_MUST_USE NS_IMETHOD AppendElement(nsISupports* aElement) override
   {
     // XXX Invalid cast of bool to nsresult (bug 778110)
     return (nsresult)InsertElementAt(aElement, mArray.Length())/* ? NS_OK : NS_ERROR_FAILURE*/;
   }
   // XXX this is badly named - should be RemoveFirstElement
   MOZ_MUST_USE NS_IMETHOD RemoveElement(nsISupports* aElement) override;
-  NS_IMETHOD Enumerate(nsIEnumerator** aResult) override;
+  NS_IMETHOD DeprecatedEnumerate(nsIEnumerator** aResult) override;
   NS_IMETHOD Clear(void) override;
 
   // nsISupportsArray methods:
   NS_IMETHOD_(int32_t) IndexOf(const nsISupports* aPossibleElement) override;
 
   NS_IMETHOD GetIndexOf(nsISupports* aPossibleElement, int32_t* aResult) override
   {
     *aResult = IndexOf(aPossibleElement);
@@ -76,16 +68,21 @@ public:
 
   MOZ_MUST_USE NS_IMETHOD DeleteElementAt(uint32_t aIndex) override
   {
     return (RemoveElementAt(aIndex) ? NS_OK : NS_ERROR_FAILURE);
   }
 
   MOZ_MUST_USE NS_IMETHOD Clone(nsISupportsArray** aResult) override;
 
+  /**
+   * nsIArray adapters.
+   */
+  NS_DECL_NSIARRAY
+
 private:
   // Copy constructors are not allowed
   explicit nsSupportsArray(const nsISupportsArray& aOther);
 
   nsCOMArray<nsISupports> mArray;
 };
 
 #endif // nsSupportsArray_h__
--- a/xpcom/tests/unit/test_nsIMutableArray.js
+++ b/xpcom/tests/unit/test_nsIMutableArray.js
@@ -102,21 +102,62 @@ function test_enumerate()
     let str = en.getNext();
     do_check_true(str instanceof Ci.nsISupportsString);
     do_check_eq(str.data, "element " + i);
     i++;
   }
   do_check_eq(arr.length, i);
 }
 
+function test_nssupportsarray_interop() {
+  // Tests to check that an nsSupportsArray instance can behave like an
+  // nsIArray.
+  let test = Components.classes["@mozilla.org/supports-array;1"]
+             .createInstance(Ci.nsISupportsArray);
+
+  let str = new SupportsString();
+  str.data = "element";
+  test.AppendElement(str);
+
+  // Now query to an nsIArray.
+  let iarray = test.QueryInterface(Ci.nsIArray);
+  do_check_neq(iarray, null);
+
+  // Make sure |nsIArray.length| works.
+  do_check_eq(iarray.length, 1);
+
+  // Make sure |nsIArray.queryElementAt| works.
+  let elm = iarray.queryElementAt(0, Ci.nsISupportsString);
+  do_check_eq(elm.data, "element");
+
+  // Make sure |nsIArray.indexOf| works.
+  let idx = iarray.indexOf(0, str);
+  do_check_eq(idx, 0);
+
+  // Make sure |nsIArray.enumerate| works.
+  let en = iarray.enumerate();
+  do_check_neq(en, null);
+  let i = 0;
+  while (en.hasMoreElements()) {
+    let str = en.getNext();
+    do_check_true(str instanceof Ci.nsISupportsString);
+    do_check_eq(str.data, "element");
+    i++;
+  }
+
+  do_check_eq(iarray.length, i);
+}
+
+
 var tests = [
   test_appending_null_actually_inserts,
   test_object_gets_appended,
   test_insert_at_beginning,
   test_replace_element,
   test_clear,
   test_enumerate,
+  test_nssupportsarray_interop,
 ];
 
 function run_test() {
   for (var i = 0; i < tests.length; i++)
     tests[i]();
 }