Bug 1484496: Part 4b - Add intrinsic type information to most nsSimpleEnumerators. r=froydnj
authorKris Maglione <maglione.k@gmail.com>
Sat, 18 Aug 2018 21:06:32 -0700
changeset 490973 e8c65dc566057853a19c477e0b30cd9e81d6326b
parent 490972 8ca4845423179d1f0a2e929a827014b393564b76
child 490974 6d6c4d5d3097c603e01e366129efccdb667c6254
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1484496
milestone63.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 1484496: Part 4b - Add intrinsic type information to most nsSimpleEnumerators. r=froydnj This allows JS callers to automatically get the correct types during interation, without having to explicitly specify them. Differential Revision: https://phabricator.services.mozilla.com/D3728
browser/components/dirprovider/DirectoryProvider.cpp
browser/components/migration/nsIEHistoryEnumerator.h
docshell/base/nsDocShellEnumerator.h
dom/base/nsJSEnvironment.cpp
dom/commandhandler/nsCommandGroup.cpp
dom/payments/PaymentRequestService.cpp
dom/plugins/base/nsPluginDirServiceProvider.cpp
dom/workers/WorkerDebuggerManager.cpp
extensions/cookie/nsPermissionManager.cpp
intl/strres/nsStringBundle.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
netwerk/base/nsLoadGroup.cpp
netwerk/cookie/nsCookieService.cpp
security/manager/ssl/PKCS11ModuleDB.cpp
security/manager/ssl/nsNSSCertificate.h
security/manager/ssl/nsPKCS11Slot.cpp
security/manager/ssl/nsSiteSecurityService.cpp
toolkit/profile/nsToolkitProfileService.cpp
toolkit/xre/nsXREDirProvider.cpp
uriloader/exthandler/HandlerService.js
uriloader/exthandler/win/nsMIMEInfoWin.cpp
widget/gtk/nsFilePicker.cpp
widget/nsBaseFilePicker.cpp
widget/windows/nsFilePicker.cpp
xpcom/components/nsCategoryManager.cpp
xpcom/ds/nsArray.cpp
xpcom/ds/nsArrayEnumerator.cpp
xpcom/ds/nsArrayEnumerator.h
xpcom/ds/nsHashPropertyBag.cpp
xpcom/ds/nsIArray.idl
xpcom/ds/nsIArrayExtensions.idl
xpcom/ds/nsIMutableArray.idl
xpcom/ds/nsISimpleEnumerator.idl
xpcom/ds/nsObserverList.h
xpcom/ds/nsPersistentProperties.cpp
xpcom/ds/nsSimpleEnumerator.cpp
xpcom/ds/nsSimpleEnumerator.h
xpcom/ds/nsStringEnumerator.cpp
xpcom/io/nsAppFileLocationProvider.cpp
xpcom/io/nsLocalFileUnix.cpp
xpcom/io/nsLocalFileWin.cpp
xpfe/appshell/nsAppShellWindowEnumerator.h
--- a/browser/components/dirprovider/DirectoryProvider.cpp
+++ b/browser/components/dirprovider/DirectoryProvider.cpp
@@ -135,17 +135,17 @@ DirectoryProvider::GetFiles(const char *
     nsCOMPtr<nsIProperties> dirSvc
       (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
     if (!dirSvc)
       return NS_ERROR_FAILURE;
 
     nsCOMArray<nsIFile> distroFiles;
     AppendDistroSearchDirs(dirSvc, distroFiles);
 
-    return NS_NewArrayEnumerator(aResult, distroFiles);
+    return NS_NewArrayEnumerator(aResult, distroFiles, NS_GET_IID(nsIFile));
   }
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult)
 {
--- a/browser/components/migration/nsIEHistoryEnumerator.h
+++ b/browser/components/migration/nsIEHistoryEnumerator.h
@@ -14,16 +14,21 @@
 
 class nsIEHistoryEnumerator final : public nsSimpleEnumerator
 {
 public:
   NS_DECL_NSISIMPLEENUMERATOR
 
   nsIEHistoryEnumerator();
 
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsIWritablePropertyBag2);
+  }
+
 private:
   ~nsIEHistoryEnumerator() override;
 
   /**
    * Initializes the history reader, if needed.
    */
   void EnsureInitialized();
 
--- a/docshell/base/nsDocShellEnumerator.h
+++ b/docshell/base/nsDocShellEnumerator.h
@@ -41,16 +41,18 @@ protected:
   virtual ~nsDocShellEnumerator();
 
 public:
   explicit nsDocShellEnumerator(int32_t aEnumerationDirection);
 
   // nsISimpleEnumerator
   NS_DECL_NSISIMPLEENUMERATOR
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIDocShell); }
+
 public:
   nsresult GetEnumerationRootItem(nsIDocShellTreeItem** aEnumerationRootItem);
   nsresult SetEnumerationRootItem(nsIDocShellTreeItem* aEnumerationRootItem);
 
   nsresult GetEnumDocShellType(int32_t* aEnumerationItemType);
   nsresult SetEnumDocShellType(int32_t aEnumerationItemType);
 
   nsresult First();
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2933,17 +2933,23 @@ NS_IMETHODIMP nsJSArgArray::QueryElement
   return NS_ERROR_NO_INTERFACE;
 }
 
 NS_IMETHODIMP nsJSArgArray::IndexOf(uint32_t startIndex, nsISupports *element, uint32_t *_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP nsJSArgArray::Enumerate(nsISimpleEnumerator **_retval)
+NS_IMETHODIMP nsJSArgArray::ScriptedEnumerate(nsIJSIID* aElemIID, uint8_t aArgc,
+                                              nsISimpleEnumerator** aResult)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsJSArgArray::EnumerateImpl(const nsID& aEntryIID, nsISimpleEnumerator **_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 // The factory function
 nsresult NS_CreateJSArgv(JSContext *aContext, uint32_t argc,
                          const JS::Value* argv, nsIJSArgArray **aArray)
 {
--- a/dom/commandhandler/nsCommandGroup.cpp
+++ b/dom/commandhandler/nsCommandGroup.cpp
@@ -18,16 +18,21 @@
 class nsGroupsEnumerator : public nsSimpleEnumerator
 {
 public:
   explicit nsGroupsEnumerator(
     nsControllerCommandGroup::GroupsHashtable& aInHashTable);
 
   NS_DECL_NSISIMPLEENUMERATOR
 
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsISupportsCString);
+  }
+
 protected:
   ~nsGroupsEnumerator() override;
 
   nsresult Initialize();
 
 protected:
   nsControllerCommandGroup::GroupsHashtable& mHashTable;
   int32_t mIndex;
@@ -123,16 +128,21 @@ nsGroupsEnumerator::Initialize()
 
 class nsNamedGroupEnumerator : public nsSimpleEnumerator
 {
 public:
   explicit nsNamedGroupEnumerator(nsTArray<nsCString>* aInArray);
 
   NS_DECL_NSISIMPLEENUMERATOR
 
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsISupportsCString);
+  }
+
 protected:
   ~nsNamedGroupEnumerator() override;
 
   nsTArray<nsCString>* mGroupArray;
   int32_t mIndex;
 };
 
 nsNamedGroupEnumerator::nsNamedGroupEnumerator(nsTArray<nsCString>* aInArray)
--- a/dom/payments/PaymentRequestService.cpp
+++ b/dom/payments/PaymentRequestService.cpp
@@ -20,16 +20,22 @@ namespace {
 class PaymentRequestEnumerator final : public nsSimpleEnumerator
 {
 public:
   NS_DECL_NSISIMPLEENUMERATOR
 
   PaymentRequestEnumerator()
     : mIndex(0)
   {}
+
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsIPaymentRequest);
+  }
+
 private:
   ~PaymentRequestEnumerator() override = default;
   uint32_t mIndex;
 };
 
 NS_IMETHODIMP
 PaymentRequestEnumerator::HasMoreElements(bool* aReturn)
 {
--- a/dom/plugins/base/nsPluginDirServiceProvider.cpp
+++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp
@@ -57,17 +57,17 @@ nsPluginDirServiceProvider::GetPLIDDirec
   NS_ENSURE_ARG_POINTER(aEnumerator);
   *aEnumerator = nullptr;
 
   nsCOMArray<nsIFile> dirs;
 
   GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs);
   GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs);
 
-  return NS_NewArrayEnumerator(aEnumerator, dirs);
+  return NS_NewArrayEnumerator(aEnumerator, dirs, NS_GET_IID(nsIFile));
 }
 
 nsresult
 nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs)
 {
   nsCOMPtr<nsIWindowsRegKey> regKey =
     do_CreateInstance("@mozilla.org/windows-registry-key;1");
   NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
--- a/dom/workers/WorkerDebuggerManager.cpp
+++ b/dom/workers/WorkerDebuggerManager.cpp
@@ -85,16 +85,21 @@ public:
   explicit WorkerDebuggerEnumerator(
                              const nsTArray<RefPtr<WorkerDebugger>>& aDebuggers)
   : mDebuggers(aDebuggers), mIndex(0)
   {
   }
 
   NS_DECL_NSISIMPLEENUMERATOR
 
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsIWorkerDebugger);
+  }
+
 private:
   ~WorkerDebuggerEnumerator() override = default;
 };
 
 NS_IMETHODIMP
 WorkerDebuggerEnumerator::HasMoreElements(bool* aResult)
 {
   *aResult = mIndex < mDebuggers.Length();
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -2606,17 +2606,17 @@ NS_IMETHODIMP nsPermissionManager::GetEn
                              permEntry.mExpireTime);
       if (NS_WARN_IF(!permission)) {
         continue;
       }
       array.AppendObject(permission);
     }
   }
 
-  return NS_NewArrayEnumerator(aEnum, array);
+  return NS_NewArrayEnumerator(aEnum, array, NS_GET_IID(nsIPermission));
 }
 
 NS_IMETHODIMP nsPermissionManager::GetAllForURI(nsIURI* aURI, nsISimpleEnumerator **aEnum)
 {
   nsCOMPtr<nsIPrincipal> principal;
   nsresult rv = GetPrincipal(aURI, getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2655,17 +2655,17 @@ nsPermissionManager::GetAllForPrincipal(
                              permEntry.mExpireTime);
       if (NS_WARN_IF(!permission)) {
         continue;
       }
       array.AppendObject(permission);
     }
   }
 
-  return NS_NewArrayEnumerator(aEnum, array);
+  return NS_NewArrayEnumerator(aEnum, array, NS_GET_IID(nsIPermission));
 }
 
 NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
 {
   ENSURE_NOT_CHILD_PROCESS;
 
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     // The profile is about to change,
--- a/intl/strres/nsStringBundle.cpp
+++ b/intl/strres/nsStringBundle.cpp
@@ -266,16 +266,21 @@ class StringMapEnumerator final : public
 {
 public:
   NS_DECL_NSISIMPLEENUMERATOR
 
   explicit StringMapEnumerator(SharedStringMap* aStringMap)
     : mStringMap(aStringMap)
   {}
 
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsIPropertyElement);
+  }
+
 protected:
   virtual ~StringMapEnumerator() = default;
 
 private:
   RefPtr<SharedStringMap> mStringMap;
 
   uint32_t mIndex = 0;
 };
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1508,28 +1508,28 @@ XPCShellDirProvider::GetFiles(const char
         file->AppendNative(NS_LITERAL_CSTRING("chrome"));
         dirs.AppendObject(file);
 
         nsresult rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
                                              getter_AddRefs(file));
         if (NS_SUCCEEDED(rv))
             dirs.AppendObject(file);
 
-        return NS_NewArrayEnumerator(result, dirs);
+        return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile));
     } else if (!strcmp(prop, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
         nsCOMArray<nsIFile> dirs;
         nsCOMPtr<nsIFile> appDir;
         bool exists;
         if (mAppDir &&
             NS_SUCCEEDED(mAppDir->Clone(getter_AddRefs(appDir))) &&
             NS_SUCCEEDED(appDir->AppendNative(NS_LITERAL_CSTRING("defaults"))) &&
             NS_SUCCEEDED(appDir->AppendNative(NS_LITERAL_CSTRING("preferences"))) &&
             NS_SUCCEEDED(appDir->Exists(&exists)) && exists) {
             dirs.AppendObject(appDir);
-            return NS_NewArrayEnumerator(result, dirs);
+            return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile));
         }
         return NS_ERROR_FAILURE;
     } else if (!strcmp(prop, NS_APP_PLUGINS_DIR_LIST)) {
         nsCOMArray<nsIFile> dirs;
         // Add the test plugin location passed in by the caller or through
         // runxpcshelltests.
         if (mPluginDir) {
             dirs.AppendObject(mPluginDir);
@@ -1544,12 +1544,12 @@ XPCShellDirProvider::GetFiles(const char
                 if (NS_SUCCEEDED(mGREDir->Clone(getter_AddRefs(file)))) {
                     file->AppendNative(NS_LITERAL_CSTRING("plugins"));
                     if (NS_SUCCEEDED(file->Exists(&exists)) && exists) {
                         dirs.AppendObject(file);
                     }
                 }
             }
         }
-        return NS_NewArrayEnumerator(result, dirs);
+        return NS_NewArrayEnumerator(result, dirs, NS_GET_IID(nsIFile));
     }
     return NS_ERROR_FAILURE;
 }
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -393,17 +393,17 @@ nsXPCWrappedJSClass::BuildPropertyEnumer
 
         nsCOMPtr<nsIProperty> property =
             new xpcProperty(autoStr.get(), (uint32_t)autoStr.Length(), value);
 
         if (!propertyArray.AppendObject(property))
             return NS_ERROR_FAILURE;
     }
 
-    return NS_NewArrayEnumerator(aEnumerate, propertyArray);
+    return NS_NewArrayEnumerator(aEnumerate, propertyArray, NS_GET_IID(nsIProperty));
 }
 
 /***************************************************************************/
 
 NS_IMPL_ISUPPORTS(xpcProperty, nsIProperty)
 
 xpcProperty::xpcProperty(const char16_t* aName, uint32_t aNameLen,
                          nsIVariant* aValue)
--- a/netwerk/base/nsLoadGroup.cpp
+++ b/netwerk/base/nsLoadGroup.cpp
@@ -649,17 +649,17 @@ nsLoadGroup::GetRequests(nsISimpleEnumer
     nsCOMArray<nsIRequest> requests;
     requests.SetCapacity(mRequests.EntryCount());
 
     for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
       auto e = static_cast<RequestMapEntry*>(iter.Get());
       requests.AppendObject(e->mKey);
     }
 
-    return NS_NewArrayEnumerator(aRequests, requests);
+    return NS_NewArrayEnumerator(aRequests, requests, NS_GET_IID(nsIRequest));
 }
 
 NS_IMETHODIMP
 nsLoadGroup::SetGroupObserver(nsIRequestObserver* aObserver)
 {
     mObserver = do_GetWeakReference(aObserver);
     return NS_OK;
 }
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -2488,17 +2488,17 @@ nsCookieService::GetEnumerator(nsISimple
   nsCOMArray<nsICookie> cookieList(mDBState->cookieCount);
   for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
     const nsCookieEntry::ArrayType& cookies = iter.Get()->GetCookies();
     for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
       cookieList.AppendObject(cookies[i]);
     }
   }
 
-  return NS_NewArrayEnumerator(aEnumerator, cookieList);
+  return NS_NewArrayEnumerator(aEnumerator, cookieList, NS_GET_IID(nsICookie2));
 }
 
 NS_IMETHODIMP
 nsCookieService::GetSessionEnumerator(nsISimpleEnumerator **aEnumerator)
 {
   if (!mDBState) {
     NS_WARNING("No DBState! Profile already closed?");
     return NS_ERROR_NOT_AVAILABLE;
@@ -2513,17 +2513,17 @@ nsCookieService::GetSessionEnumerator(ns
       nsCookie* cookie = cookies[i];
       // Filter out non-session cookies.
       if (cookie->IsSession()) {
         cookieList.AppendObject(cookie);
       }
     }
   }
 
-  return NS_NewArrayEnumerator(aEnumerator, cookieList);
+  return NS_NewArrayEnumerator(aEnumerator, cookieList, NS_GET_IID(nsICookie2));
 }
 
 static nsresult
 InitializeOriginAttributes(OriginAttributes* aAttrs,
                            JS::HandleValue aOriginAttributes,
                            JSContext* aCx,
                            uint8_t aArgc,
                            const char16_t* aAPI,
@@ -4923,17 +4923,17 @@ nsCookieService::GetCookiesFromHost(cons
     return NS_NewEmptyEnumerator(aEnumerator);
 
   nsCOMArray<nsICookie> cookieList(mMaxCookiesPerHost);
   const nsCookieEntry::ArrayType &cookies = entry->GetCookies();
   for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
     cookieList.AppendObject(cookies[i]);
   }
 
-  return NS_NewArrayEnumerator(aEnumerator, cookieList);
+  return NS_NewArrayEnumerator(aEnumerator, cookieList, NS_GET_IID(nsICookie2));
 }
 
 NS_IMETHODIMP
 nsCookieService::GetCookiesWithOriginAttributes(const nsAString&    aPattern,
                                                 const nsACString&   aHost,
                                                 nsISimpleEnumerator **aEnumerator)
 {
   mozilla::OriginAttributesPattern pattern;
@@ -4982,17 +4982,17 @@ nsCookieService::GetCookiesWithOriginAtt
 
     const nsCookieEntry::ArrayType& entryCookies = entry->GetCookies();
 
     for (nsCookieEntry::IndexType i = 0; i < entryCookies.Length(); ++i) {
       cookies.AppendObject(entryCookies[i]);
     }
   }
 
-  return NS_NewArrayEnumerator(aEnumerator, cookies);
+  return NS_NewArrayEnumerator(aEnumerator, cookies, NS_GET_IID(nsICookie2));
 }
 
 NS_IMETHODIMP
 nsCookieService::RemoveCookiesWithOriginAttributes(const nsAString& aPattern,
                                                    const nsACString& aHost)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
 
--- a/security/manager/ssl/PKCS11ModuleDB.cpp
+++ b/security/manager/ssl/PKCS11ModuleDB.cpp
@@ -187,17 +187,17 @@ PKCS11ModuleDB::ListModules(nsISimpleEnu
        list = list->next) {
     nsCOMPtr<nsIPKCS11Module> module = new nsPKCS11Module(list->module);
     nsresult rv = array->AppendElement(module);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
-  return array->Enumerate(_retval);
+  return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Module));
 }
 
 NS_IMETHODIMP
 PKCS11ModuleDB::GetCanToggleFIPS(bool* aCanToggleFIPS)
 {
   NS_ENSURE_ARG_POINTER(aCanToggleFIPS);
 
   *aCanToggleFIPS = SECMOD_CanDeleteInternalModule();
--- a/security/manager/ssl/nsNSSCertificate.h
+++ b/security/manager/ssl/nsNSSCertificate.h
@@ -123,16 +123,18 @@ private:
    void operator=(const nsNSSCertList&) = delete;
 };
 
 class nsNSSCertListEnumerator : public nsSimpleEnumerator
 {
 public:
    NS_DECL_NSISIMPLEENUMERATOR
 
+   const nsID& DefaultInterface() override { return NS_GET_IID(nsIX509Cert); }
+
    explicit nsNSSCertListEnumerator(const mozilla::UniqueCERTCertList& certList);
 private:
    virtual ~nsNSSCertListEnumerator() {}
 
    mozilla::UniqueCERTCertList mCertList;
 
    nsNSSCertListEnumerator(const nsNSSCertListEnumerator&) = delete;
    void operator=(const nsNSSCertListEnumerator&) = delete;
--- a/security/manager/ssl/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/nsPKCS11Slot.cpp
@@ -285,10 +285,10 @@ nsPKCS11Module::ListSlots(nsISimpleEnume
       nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(mModule->slots[i]);
       rv = array->AppendElement(slot);
       if (NS_FAILED(rv)) {
         return rv;
       }
     }
   }
 
-  return array->Enumerate(_retval);
+  return array->Enumerate(_retval, NS_GET_IID(nsIPKCS11Slot));
 }
--- a/security/manager/ssl/nsSiteSecurityService.cpp
+++ b/security/manager/ssl/nsSiteSecurityService.cpp
@@ -468,17 +468,17 @@ SiteHPKPState::GetSha256Keys(nsISimpleEn
     nsresult rv = variant->SetAsAUTF8String(key);
     if (NS_FAILED(rv)) {
       return rv;
     }
     if (!keys.AppendObject(variant)) {
       return NS_ERROR_FAILURE;
     }
   }
-  return NS_NewArrayEnumerator(aSha256Keys, keys);
+  return NS_NewArrayEnumerator(aSha256Keys, keys, NS_GET_IID(nsIVariant));
 }
 
 NS_IMETHODIMP
 SiteHPKPState::GetOriginAttributes(JSContext* aCx,
   JS::MutableHandle<JS::Value> aOriginAttributes)
 {
   if (!ToJSValue(aCx, mOriginAttributes, aOriginAttributes)) {
     return NS_ERROR_FAILURE;
@@ -1890,17 +1890,17 @@ nsSiteSecurityService::Enumerate(uint32_
         break;
       default:
         MOZ_ASSERT_UNREACHABLE("SSS:Enumerate got invalid type");
     }
 
     states.AppendObject(state);
   }
 
-  NS_NewArrayEnumerator(aEnumerator, states);
+  NS_NewArrayEnumerator(aEnumerator, states, NS_GET_IID(nsISiteSecurityState));
   return NS_OK;
 }
 
 //------------------------------------------------------------
 // nsSiteSecurityService::nsIObserver
 //------------------------------------------------------------
 
 NS_IMETHODIMP
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -144,16 +144,21 @@ private:
 
     static nsToolkitProfileService *gService;
 
     class ProfileEnumerator final : public nsSimpleEnumerator
     {
     public:
         NS_DECL_NSISIMPLEENUMERATOR
 
+        const nsID& DefaultInterface() override
+        {
+          return NS_GET_IID(nsIToolkitProfile);
+        }
+
         explicit ProfileEnumerator(nsToolkitProfile *first)
           { mCurrent = first; }
     private:
         RefPtr<nsToolkitProfile> mCurrent;
     };
 };
 
 nsToolkitProfile::nsToolkitProfile(const nsACString& aName,
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -849,41 +849,41 @@ nsXREDirProvider::GetFilesInternal(const
   if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
     nsCOMArray<nsIFile> directories;
 
     static const char *const kAppendNothing[] = { nullptr };
 
     LoadDirsIntoArray(mAppBundleDirectories,
                       kAppendNothing, directories);
 
-    rv = NS_NewArrayEnumerator(aResult, directories);
+    rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
   }
   else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
     nsCOMArray<nsIFile> directories;
 
     LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
     LoadDirsIntoArray(mAppBundleDirectories,
                       kAppendPrefDir, directories);
 
-    rv = NS_NewArrayEnumerator(aResult, directories);
+    rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
   }
   else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
     // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
     // for OS window decoration.
 
     static const char *const kAppendChromeDir[] = { "chrome", nullptr };
     nsCOMArray<nsIFile> directories;
     LoadDirIntoArray(mXULAppDir,
                      kAppendChromeDir,
                      directories);
     LoadDirsIntoArray(mAppBundleDirectories,
                       kAppendChromeDir,
                       directories);
 
-    rv = NS_NewArrayEnumerator(aResult, directories);
+    rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
   }
   else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
     nsCOMArray<nsIFile> directories;
 
     if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
       nsCOMPtr<nsIFile> appdir;
       rv = XRE_GetBinaryPath(getter_AddRefs(appdir));
       if (NS_SUCCEEDED(rv)) {
@@ -903,17 +903,17 @@ nsXREDirProvider::GetFilesInternal(const
     if (mProfileDir) {
       nsCOMArray<nsIFile> profileDir;
       profileDir.AppendObject(mProfileDir);
       LoadDirsIntoArray(profileDir,
                         kAppendPlugins,
                         directories);
     }
 
-    rv = NS_NewArrayEnumerator(aResult, directories);
+    rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = NS_SUCCESS_AGGREGATE_RESULT;
   }
   else
     rv = NS_ERROR_FAILURE;
 
   return rv;
--- a/uriloader/exthandler/HandlerService.js
+++ b/uriloader/exthandler/HandlerService.js
@@ -212,17 +212,17 @@ HandlerService.prototype = {
         {
           get: function(target, name) {
             return target[name] || target._handlerInfo[name];
           },
         },
       );
       handlers.appendElement(handler);
     }
-    return handlers.enumerate();
+    return handlers.enumerate(Ci.nsIHandlerInfo);
   },
 
   // nsIHandlerService
   store(handlerInfo) {
     let handlerList = this._getHandlerListByHandlerInfoType(handlerInfo);
 
     // Retrieve an existing entry if present, instead of creating a new one, so
     // that we preserve unknown properties for forward compatibility.
--- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp
@@ -162,17 +162,17 @@ nsMIMEInfoWin::GetEnumerator(nsISimpleEn
   GetProperty(NS_LITERAL_STRING("defaultApplicationIconURL"), getter_AddRefs(variant));
   if (variant)
     properties.AppendObject(variant);
 
   GetProperty(NS_LITERAL_STRING("customApplicationIconURL"), getter_AddRefs(variant));
   if (variant)
     properties.AppendObject(variant);
 
-  return NS_NewArrayEnumerator(_retval, properties);
+  return NS_NewArrayEnumerator(_retval, properties, NS_GET_IID(nsIVariant));
 }
 
 static nsresult GetIconURLVariant(nsIFile* aApplication, nsIVariant* *_retval)
 {
   nsAutoCString fileURLSpec;
   NS_GetURLSpecFromFile(aApplication, fileURLSpec);
   nsAutoCString iconURLSpec; iconURLSpec.AssignLiteral("moz-icon://");
   iconURLSpec += fileURLSpec;
--- a/widget/gtk/nsFilePicker.cpp
+++ b/widget/gtk/nsFilePicker.cpp
@@ -341,17 +341,17 @@ nsFilePicker::GetFileURL(nsIURI **aFileU
 }
 
 NS_IMETHODIMP
 nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
 {
   NS_ENSURE_ARG_POINTER(aFiles);
 
   if (mMode == nsIFilePicker::modeOpenMultiple) {
-    return NS_NewArrayEnumerator(aFiles, mFiles);
+    return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile));
   }
 
   return NS_ERROR_FAILURE;
 }
 
 nsresult
 nsFilePicker::Show(int16_t *aReturn)
 {
--- a/widget/nsBaseFilePicker.cpp
+++ b/widget/nsBaseFilePicker.cpp
@@ -107,16 +107,18 @@ public:
   nsBaseFilePickerEnumerator(nsPIDOMWindowOuter* aParent,
                              nsISimpleEnumerator* iterator,
                              int16_t aMode)
     : mIterator(iterator)
     , mParent(aParent->GetCurrentInnerWindow())
     , mMode(aMode)
   {}
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
+
   NS_IMETHOD
   GetNext(nsISupports** aResult) override
   {
     nsCOMPtr<nsISupports> tmp;
     nsresult rv = mIterator->GetNext(getter_AddRefs(tmp));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!tmp) {
@@ -278,17 +280,17 @@ NS_IMETHODIMP nsBaseFilePicker::GetFiles
   // doesn't implement GetFiles() yet.
   // so we fake it.
   nsCOMPtr <nsIFile> file;
   rv = GetFile(getter_AddRefs(file));
   NS_ENSURE_SUCCESS(rv,rv);
 
   files.AppendObject(file);
 
-  return NS_NewArrayEnumerator(aFiles, files);
+  return NS_NewArrayEnumerator(aFiles, files, NS_GET_IID(nsIFile));
 }
 
 // Set the display directory
 NS_IMETHODIMP nsBaseFilePicker::SetDisplayDirectory(nsIFile *aDirectory)
 {
   // if displaySpecialDirectory has been previously called, let's abort this
   // operation.
   if (!mDisplaySpecialDirectory.IsEmpty()) {
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -683,17 +683,17 @@ nsFilePicker::GetFileURL(nsIURI **aFileU
 
   return NS_NewFileURI(aFileURL, file);
 }
 
 NS_IMETHODIMP
 nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
 {
   NS_ENSURE_ARG_POINTER(aFiles);
-  return NS_NewArrayEnumerator(aFiles, mFiles);
+  return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile));
 }
 
 // Get the file + path
 NS_IMETHODIMP
 nsBaseWinFilePicker::SetDefaultString(const nsAString& aString)
 {
   mDefaultFilePath = aString;
 
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -54,16 +54,21 @@ class BaseStringEnumerator
   : public nsSimpleEnumerator
   , private nsIUTF8StringEnumerator
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSISIMPLEENUMERATOR
   NS_DECL_NSIUTF8STRINGENUMERATOR
 
+  const nsID& DefaultInterface() override
+  {
+    return NS_GET_IID(nsISupportsCString);
+  }
+
 protected:
   // Callback function for NS_QuickSort to sort mArray
   static int SortCallback(const void*, const void*, void*);
 
   BaseStringEnumerator()
     : mArray(nullptr)
     , mCount(0)
     , mSimpleCurItem(0)
--- a/xpcom/ds/nsArray.cpp
+++ b/xpcom/ds/nsArray.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 "nsArray.h"
 #include "nsArrayEnumerator.h"
 #include "nsThreadUtils.h"
+#include "xpcjsid.h"
 
 NS_INTERFACE_MAP_BEGIN(nsArray)
   NS_INTERFACE_MAP_ENTRY(nsIArray)
   NS_INTERFACE_MAP_ENTRY(nsIArrayExtensions)
   NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
 NS_INTERFACE_MAP_END
 
@@ -74,21 +75,32 @@ nsArrayBase::IndexOf(uint32_t aStartInde
     return NS_ERROR_FAILURE;
   }
 
   *aResult = static_cast<uint32_t>(idx);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsArrayBase::Enumerate(nsISimpleEnumerator** aResult)
+nsArrayBase::ScriptedEnumerate(nsIJSIID* aElemIID, uint8_t aArgc,
+                               nsISimpleEnumerator** aResult)
 {
+  if (aArgc > 0 && aElemIID) {
+    return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this), *aElemIID->GetID());
+  }
   return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this));
 }
 
+
+NS_IMETHODIMP
+nsArrayBase::EnumerateImpl(const nsID& aElemIID, nsISimpleEnumerator** aResult)
+{
+  return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this), aElemIID);
+}
+
 // nsIMutableArray implementation
 
 NS_IMETHODIMP
 nsArrayBase::AppendElement(nsISupports* aElement)
 {
   bool result = mArray.AppendObject(aElement);
   return result ? NS_OK : NS_ERROR_FAILURE;
 }
--- a/xpcom/ds/nsArrayEnumerator.cpp
+++ b/xpcom/ds/nsArrayEnumerator.cpp
@@ -18,27 +18,31 @@
 
 class nsSimpleArrayEnumerator final : public nsSimpleEnumerator
 {
 public:
   // nsISimpleEnumerator interface
   NS_DECL_NSISIMPLEENUMERATOR
 
   // nsSimpleArrayEnumerator methods
-  explicit nsSimpleArrayEnumerator(nsIArray* aValueArray)
+  explicit nsSimpleArrayEnumerator(nsIArray* aValueArray, const nsID& aEntryIID)
     : mValueArray(aValueArray)
+    , mEntryIID(aEntryIID)
     , mIndex(0)
   {
   }
 
+  const nsID& DefaultInterface() override { return mEntryIID; }
+
 private:
   ~nsSimpleArrayEnumerator() override = default;
 
 protected:
   nsCOMPtr<nsIArray> mValueArray;
+  const nsID mEntryIID;
   uint32_t mIndex;
 };
 
 NS_IMETHODIMP
 nsSimpleArrayEnumerator::HasMoreElements(bool* aResult)
 {
   MOZ_ASSERT(aResult != 0, "null ptr");
   if (!aResult) {
@@ -81,19 +85,20 @@ nsSimpleArrayEnumerator::GetNext(nsISupp
     return NS_ERROR_UNEXPECTED;
   }
 
   return mValueArray->QueryElementAt(mIndex++, NS_GET_IID(nsISupports),
                                      (void**)aResult);
 }
 
 nsresult
-NS_NewArrayEnumerator(nsISimpleEnumerator** aResult, nsIArray* aArray)
+NS_NewArrayEnumerator(nsISimpleEnumerator** aResult, nsIArray* aArray,
+                      const nsID& aEntryIID)
 {
-  RefPtr<nsSimpleArrayEnumerator> enumer = new nsSimpleArrayEnumerator(aArray);
+  RefPtr<nsSimpleArrayEnumerator> enumer = new nsSimpleArrayEnumerator(aArray, aEntryIID);
   enumer.forget(aResult);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 // enumerator implementation for nsCOMArray
 // creates a snapshot of the array in question
@@ -101,36 +106,41 @@ NS_NewArrayEnumerator(nsISimpleEnumerato
 // allocation is done correctly
 class nsCOMArrayEnumerator final : public nsSimpleEnumerator
 {
 public:
   // nsISimpleEnumerator interface
   NS_DECL_NSISIMPLEENUMERATOR
 
   // Use this instead of `new`.
-  static nsCOMArrayEnumerator* Allocate(const nsCOMArray_base& aArray);
+  static nsCOMArrayEnumerator* Allocate(const nsCOMArray_base& aArray, const nsID& aEntryIID);
 
   // specialized operator to make sure we make room for mValues
   void operator delete(void* aPtr) { free(aPtr); }
 
+  const nsID& DefaultInterface() override { return mEntryIID; }
+
 private:
   // nsSimpleArrayEnumerator methods
-  nsCOMArrayEnumerator()
+  explicit nsCOMArrayEnumerator(const nsID& aEntryIID)
     : mIndex(0)
     , mArraySize(0)
+    , mEntryIID(aEntryIID)
   {
     mValueArray[0] = nullptr;
   }
 
   ~nsCOMArrayEnumerator(void) override;
 
 protected:
   uint32_t mIndex;            // current position
   uint32_t mArraySize;        // size of the array
 
+  const nsID& mEntryIID;
+
   // this is actually bigger
   nsISupports* mValueArray[1];
 };
 
 nsCOMArrayEnumerator::~nsCOMArrayEnumerator()
 {
   // only release the entries that we haven't visited yet
   for (; mIndex < mArraySize; ++mIndex) {
@@ -170,33 +180,33 @@ nsCOMArrayEnumerator::GetNext(nsISupport
   // this really isn't necessary. just pretend this happens, since
   // we'll never visit this value again!
   // mValueArray[(mIndex-1)] = nullptr;
 
   return NS_OK;
 }
 
 nsCOMArrayEnumerator*
-nsCOMArrayEnumerator::Allocate(const nsCOMArray_base& aArray)
+nsCOMArrayEnumerator::Allocate(const nsCOMArray_base& aArray, const nsID& aEntryIID)
 {
   // create enough space such that mValueArray points to a large
   // enough value. Note that the initial value of aSize gives us
   // space for mValueArray[0], so we must subtract
   size_t size = sizeof(nsCOMArrayEnumerator);
   uint32_t count;
   if (aArray.Count() > 0) {
     count = static_cast<uint32_t>(aArray.Count());
     size += (count - 1) * sizeof(aArray[0]);
   } else {
     count = 0;
   }
 
   // Allocate a buffer large enough to contain our object and its array.
   void* mem = moz_xmalloc(size);
-  auto result = new (mozilla::KnownNotNull, mem) nsCOMArrayEnumerator();
+  auto result = new (mozilla::KnownNotNull, mem) nsCOMArrayEnumerator(aEntryIID);
 
   result->mArraySize = count;
 
   // now need to copy over the values, and addref each one
   // now this might seem like a lot of work, but we're actually just
   // doing all our AddRef's ahead of time since GetNext() doesn't
   // need to AddRef() on the way out
   for (uint32_t i = 0; i < count; ++i) {
@@ -204,14 +214,15 @@ nsCOMArrayEnumerator::Allocate(const nsC
     NS_IF_ADDREF(result->mValueArray[i]);
   }
 
   return result;
 }
 
 nsresult
 NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
-                      const nsCOMArray_base& aArray)
+                      const nsCOMArray_base& aArray,
+                      const nsID& aEntryIID)
 {
-  RefPtr<nsCOMArrayEnumerator> enumerator = nsCOMArrayEnumerator::Allocate(aArray);
+  RefPtr<nsCOMArrayEnumerator> enumerator = nsCOMArrayEnumerator::Allocate(aArray, aEntryIID);
   enumerator.forget(aResult);
   return NS_OK;
 }
--- a/xpcom/ds/nsArrayEnumerator.h
+++ b/xpcom/ds/nsArrayEnumerator.h
@@ -4,29 +4,31 @@
  * 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/. */
 
 #ifndef nsArrayEnumerator_h__
 #define nsArrayEnumerator_h__
 
 // enumerator implementation for nsIArray
 
-#include "nscore.h"
+#include "nsISupports.h"
 
 class nsISimpleEnumerator;
 class nsIArray;
 class nsCOMArray_base;
 
 // Create an enumerator for an existing nsIArray implementation
 // The enumerator holds an owning reference to the array.
 nsresult
 NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
-                      nsIArray* aArray);
+                      nsIArray* aArray,
+                      const nsID& aEntryIID = NS_GET_IID(nsISupports));
 
 // create an enumerator for an existing nsCOMArray<T> implementation
 // The enumerator will hold an owning reference to each ELEMENT in
 // the array. This means that the nsCOMArray<T> can safely go away
 // without its objects going away.
 nsresult
 NS_NewArrayEnumerator(nsISimpleEnumerator** aResult,
-                      const nsCOMArray_base& aArray);
+                      const nsCOMArray_base& aArray,
+                      const nsID& aEntryIID = NS_GET_IID(nsISupports));
 
 #endif
--- a/xpcom/ds/nsHashPropertyBag.cpp
+++ b/xpcom/ds/nsHashPropertyBag.cpp
@@ -115,17 +115,18 @@ nsHashPropertyBagBase::GetEnumerator(nsI
 
   for (auto iter = mPropertyHash.Iter(); !iter.Done(); iter.Next()) {
     const nsAString& key = iter.Key();
     nsIVariant* data = iter.UserData();
     nsSimpleProperty* sprop = new nsSimpleProperty(key, data);
     propertyArray->AppendElement(sprop);
   }
 
-  return NS_NewArrayEnumerator(aResult, propertyArray);
+  return NS_NewArrayEnumerator(aResult, propertyArray,
+                               NS_GET_IID(nsIProperty));
 }
 
 #define IMPL_GETSETPROPERTY_AS(Name, Type) \
 NS_IMETHODIMP \
 nsHashPropertyBagBase::GetPropertyAs ## Name (const nsAString & prop, Type *_retval) \
 { \
     nsIVariant* v = mPropertyHash.GetWeak(prop); \
     if (!v) \
--- a/xpcom/ds/nsIArray.idl
+++ b/xpcom/ds/nsIArray.idl
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "nsISupports.idl"
 
+interface nsIJSIID;
 interface nsISimpleEnumerator;
 
 /**
  * nsIArray
  *
  * An indexed collection of elements. Provides basic functionality for
  * retrieving elements at a specific position, searching for
  * elements. Indexes are zero-based, such that the last element in the
@@ -26,17 +27,17 @@ interface nsISimpleEnumerator;
  * nsIArray, that the array should not be QueryInterfaced to an
  * nsIMutableArray for modification. If the interface in question had
  * intended the array to be modified, it would have returned an
  * nsIMutableArray!
  *
  * null is a valid entry in the array, and as such any nsISupports
  * parameters may be null, except where noted.
  */
-[scriptable, uuid(114744d9-c369-456e-b55a-52fe52880d2d)]
+[scriptable, builtinclass, uuid(114744d9-c369-456e-b55a-52fe52880d2d)]
 interface nsIArray : nsISupports
 {
     /**
      * length
      *
      * number of elements in the array.
      */
     readonly attribute unsigned long length;
@@ -82,10 +83,22 @@ interface nsIArray : nsISupports
 
     /**
      * enumerate the array
      *
      * @returns a new enumerator positioned at the start of the array
      * @throws NS_ERROR_FAILURE if the array is empty (to make it easy
      *         to detect errors), or NS_ERROR_OUT_OF_MEMORY if out of memory.
      */
-    nsISimpleEnumerator enumerate();
+    [binaryname(ScriptedEnumerate), optional_argc]
+    nsISimpleEnumerator enumerate([optional] in nsIJSIID aElemIID);
+
+    [noscript]
+    nsISimpleEnumerator enumerateImpl(in nsIDRef aElemIID);
+
+    %{C++
+    nsresult
+    Enumerate(nsISimpleEnumerator** aRetVal, const nsID& aElemIID = NS_GET_IID(nsISupports))
+    {
+      return EnumerateImpl(aElemIID, aRetVal);
+    }
+    %}
 };
--- a/xpcom/ds/nsIArrayExtensions.idl
+++ b/xpcom/ds/nsIArrayExtensions.idl
@@ -19,17 +19,17 @@
  * but doing the same with nsIArray is somewhat less convenient, since
  * queryElementAt is not nearly so nice to use from JavaScript.  So we provide
  * this extension interface so interfaces that currently return
  * nsISupportsArray can start returning nsIArrayExtensions and all JavaScript
  * should Just Work. Eventually we'll roll this interface into nsIArray
  * itself, possibly getting rid of the Count() method, as it duplicates
  * nsIArray functionality.
  */
-[scriptable, uuid(261d442e-050c-453d-8aaa-b3f23bcc528b)]
+[scriptable, builtinclass, uuid(261d442e-050c-453d-8aaa-b3f23bcc528b)]
 interface nsIArrayExtensions : nsIArray
 {
   /**
    * Count()
    *
    * Retrieves the length of the array. This is an alias for the
    * |nsIArray.length| attribute.
    */
--- a/xpcom/ds/nsIMutableArray.idl
+++ b/xpcom/ds/nsIMutableArray.idl
@@ -15,17 +15,17 @@
  * that null elements can be created as a side effect of
  * insertElementAt(). Conversely, if insertElementAt() is never used,
  * and null elements are never explicitly added to the array, then it
  * is guaranteed that queryElementAt() will never return a null value.
  *
  * Any of these methods may throw NS_ERROR_OUT_OF_MEMORY when the
  * array must grow to complete the call, but the allocation fails.
  */
-[scriptable, uuid(af059da0-c85b-40ec-af07-ae4bfdc192cc)]
+[scriptable, builtinclass, uuid(af059da0-c85b-40ec-af07-ae4bfdc192cc)]
 interface nsIMutableArray : nsIArrayExtensions
 {
     /**
      * appendElement()
      * 
      * Append an element at the end of the array.
      *
      * @param element The element to append.
--- a/xpcom/ds/nsISimpleEnumerator.idl
+++ b/xpcom/ds/nsISimpleEnumerator.idl
@@ -26,17 +26,18 @@ interface nsIJSEnumerator : nsISupports 
   [implicit_jscontext]
   jsval next();
 };
 
 [scriptable, uuid(796f340d-0a2a-490b-9c60-640765e99782)]
 interface nsISimpleEnumeratorBase : nsISupports {
   /**
    * Returns a JavaScript iterator for all remaining entries in the enumerator.
-   * Each entry is queried only to nsISupports.
+   * Each entry is typically queried to the appropriate interface for the
+   * enumerator.
    */
   [symbol]
   nsIJSEnumerator iterator();
 
   /**
    * Returns JavaScript iterator for all remaining entries in the enumerator.
    * Each entry is queried only to the supplied interface. If any element
    * fails to query to that interface, the error is propagated to the caller.
--- a/xpcom/ds/nsObserverList.h
+++ b/xpcom/ds/nsObserverList.h
@@ -77,16 +77,18 @@ private:
 
 class nsObserverEnumerator final : public nsSimpleEnumerator
 {
 public:
   NS_DECL_NSISIMPLEENUMERATOR
 
   explicit nsObserverEnumerator(nsObserverList* aObserverList);
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIObserver); }
+
 private:
   ~nsObserverEnumerator() override = default;
 
   int32_t mIndex; // Counts up from 0
   nsCOMArray<nsIObserver> mObservers;
 };
 
 #endif /* nsObserverList_h___ */
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -565,17 +565,17 @@ nsPersistentProperties::Enumerate(nsISim
       new nsPropertyElement(nsDependentCString(entry->mKey),
                             nsDependentString(entry->mValue));
 
     if (!props.AppendObject(element)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
-  return NS_NewArrayEnumerator(aResult, props);
+  return NS_NewArrayEnumerator(aResult, props, NS_GET_IID(nsIPropertyElement));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XXX Some day we'll unify the nsIPersistentProperties interface with
 // nsIProperties, but until now...
 
 NS_IMETHODIMP
 nsPersistentProperties::Get(const char* aProp, const nsIID& aUUID,
--- a/xpcom/ds/nsSimpleEnumerator.cpp
+++ b/xpcom/ds/nsSimpleEnumerator.cpp
@@ -66,17 +66,17 @@ JSEnumerator::Next(JSContext* aCx, JS::M
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(JSEnumerator, nsIJSEnumerator)
 
 nsresult
 nsSimpleEnumerator::Iterator(nsIJSEnumerator **aResult)
 {
-  auto result = MakeRefPtr<JSEnumerator>(this, NS_GET_IID(nsISupports));
+  auto result = MakeRefPtr<JSEnumerator>(this, DefaultInterface());
   result.forget(aResult);
   return NS_OK;
 }
 
 nsresult
 nsSimpleEnumerator::Entries(const nsIID& aIface, nsIJSEnumerator **aResult)
 {
   auto result = MakeRefPtr<JSEnumerator>(this, aIface);
--- a/xpcom/ds/nsSimpleEnumerator.h
+++ b/xpcom/ds/nsSimpleEnumerator.h
@@ -9,13 +9,15 @@
 
 #include "nsISimpleEnumerator.h"
 
 class nsSimpleEnumerator : public nsISimpleEnumerator
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSISIMPLEENUMERATORBASE
 
+  virtual const nsID& DefaultInterface() { return NS_GET_IID(nsISupports); }
+
 protected:
   virtual ~nsSimpleEnumerator() = default;
 };
 
 #endif
--- a/xpcom/ds/nsStringEnumerator.cpp
+++ b/xpcom/ds/nsStringEnumerator.cpp
@@ -54,16 +54,24 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIUTF8STRINGENUMERATOR
 
   // have to declare nsIStringEnumerator manually, because of
   // overlapping method names
   NS_IMETHOD GetNext(nsAString& aResult) override;
   NS_DECL_NSISIMPLEENUMERATOR
 
+  const nsID& DefaultInterface() override
+  {
+    if (mIsUnicode) {
+      return NS_GET_IID(nsISupportsString);
+    }
+    return NS_GET_IID(nsISupportsCString);
+  }
+
 private:
   ~nsStringEnumerator()
   {
     if (mOwnsArray) {
       // const-casting is safe here, because the NS_New*
       // constructors make sure mOwnsArray is consistent with
       // the constness of the objects
       if (mIsUnicode) {
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -385,16 +385,18 @@ public:
    */
   nsAppDirectoryEnumerator(nsIDirectoryServiceProvider* aProvider,
                            const char* aKeyList[]) :
     mProvider(aProvider),
     mCurrentKey(aKeyList)
   {
   }
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
+
   NS_IMETHOD HasMoreElements(bool* aResult) override
   {
     while (!mNext && *mCurrentKey) {
       bool dontCare;
       nsCOMPtr<nsIFile> testFile;
       (void)mProvider->GetFile(*mCurrentKey++, &dontCare, getter_AddRefs(testFile));
       // Don't return a file which does not exist.
       bool exists;
--- a/xpcom/io/nsLocalFileUnix.cpp
+++ b/xpcom/io/nsLocalFileUnix.cpp
@@ -105,16 +105,18 @@ public:
 
   // nsIDirectoryEnumerator interface
   NS_DECL_NSIDIRECTORYENUMERATOR
 
   NS_IMETHOD Init(nsLocalFile* aParent, bool aIgnored);
 
   NS_FORWARD_NSISIMPLEENUMERATORBASE(nsSimpleEnumerator::)
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
+
 private:
   ~nsDirEnumeratorUnix() override;
 
 protected:
   NS_IMETHOD GetNextEntry();
 
   DIR*           mDir;
   struct dirent* mEntry;
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -236,16 +236,18 @@ class nsDriveEnumerator : public nsSimpl
 {
 public:
   nsDriveEnumerator();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSISIMPLEENUMERATOR
   NS_FORWARD_NSISIMPLEENUMERATORBASE(nsSimpleEnumerator::)
   nsresult Init();
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
+
   NS_IMETHOD GetNextFile(nsIFile** aResult) override
   {
     bool hasMore = false;
     nsresult rv = HasMoreElements(&hasMore);
     if (NS_FAILED(rv) || !hasMore) {
       return rv;
     }
     nsCOMPtr<nsISupports> next;
@@ -696,16 +698,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_FORWARD_NSISIMPLEENUMERATORBASE(nsSimpleEnumerator::)
 
   nsDirEnumerator() : mDir(nullptr)
   {
   }
 
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
+
   nsresult Init(nsIFile* aParent)
   {
     nsAutoString filepath;
     aParent->GetTarget(filepath);
 
     if (filepath.IsEmpty()) {
       aParent->GetPath(filepath);
     }
--- a/xpfe/appshell/nsAppShellWindowEnumerator.h
+++ b/xpfe/appshell/nsAppShellWindowEnumerator.h
@@ -78,16 +78,18 @@ public:
 
 class nsASXULWindowEnumerator : public nsAppShellWindowEnumerator {
 
 public:
   nsASXULWindowEnumerator(const char16_t* aTypeString,
                           nsWindowMediator& inMediator);
   virtual ~nsASXULWindowEnumerator();
   NS_IMETHOD GetNext(nsISupports **retval) override;
+
+  const nsID& DefaultInterface() override { return NS_GET_IID(nsIXULWindow); }
 };
 
 //
 // concrete enumerators
 //
 
 class nsASDOMWindowEarlyToLateEnumerator : public nsASDOMWindowEnumerator {