Backed out 6 changesets (bug 1342303) for build bustage a=backout
authorWes Kocher <wkocher@mozilla.com>
Thu, 02 Mar 2017 16:35:43 -0800
changeset 392326 b0b40ce3dfe576bd23aba0e0de79c221564b8f13
parent 392325 89137679a68cce70e8307b58e91cc9ade3f56b2c
child 392327 8a2b1bdb15491e41508b8959e3fe2bc24a26d790
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1342303
milestone54.0a1
backs out89137679a68cce70e8307b58e91cc9ade3f56b2c
20a1bcb47c33f96691fabd451bc54db13d3c7e26
bc3b2e7a383b6b0ee08363d642ead4188ecc8a2d
bdc491b9ebde3a05e8f7f4fd834f0354b4a99570
5c6042dee665597e1e21697e0a1de7a2aab60d55
b5de1dfff82f40c9cfdba333b7380861f1f373ce
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
Backed out 6 changesets (bug 1342303) for build bustage a=backout Backed out changeset 89137679a68c (bug 1342303) Backed out changeset 20a1bcb47c33 (bug 1342303) Backed out changeset bc3b2e7a383b (bug 1342303) Backed out changeset bdc491b9ebde (bug 1342303) Backed out changeset 5c6042dee665 (bug 1342303) Backed out changeset b5de1dfff82f (bug 1342303) MozReview-Commit-ID: BjlVAX480jI
docshell/shistory/nsSHEntry.cpp
layout/style/CSSStyleSheet.cpp
layout/style/CSSStyleSheet.h
layout/style/GroupRule.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRules.cpp
xpcom/ds/ArrayIterator.h
xpcom/ds/moz.build
xpcom/ds/nsCOMArray.h
xpcom/ds/nsTArray.h
xpfe/appshell/nsWindowMediator.cpp
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -54,24 +54,29 @@ nsSHEntry::nsSHEntry(const nsSHEntry& aO
   , mStateData(aOther.mStateData)
   , mIsSrcdocEntry(aOther.mIsSrcdocEntry)
   , mScrollRestorationIsManual(false)
   , mSrcdocData(aOther.mSrcdocData)
   , mBaseURI(aOther.mBaseURI)
 {
 }
 
+static bool
+ClearParentPtr(nsISHEntry* aEntry, void* /* aData */)
+{
+  if (aEntry) {
+    aEntry->SetParent(nullptr);
+  }
+  return true;
+}
+
 nsSHEntry::~nsSHEntry()
 {
   // Null out the mParent pointers on all our kids.
-  for (nsISHEntry* entry : mChildren) {
-    if (entry) {
-      entry->SetParent(nullptr);
-    }
-  }
+  mChildren.EnumerateForwards(ClearParentPtr, nullptr);
 }
 
 NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
 
 NS_IMETHODIMP
 nsSHEntry::SetScrollPosition(int32_t aX, int32_t aY)
 {
   mScrollPositionX = aX;
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -160,49 +160,51 @@ struct ChildSheetListBuilder {
       child->mParent = aPrimarySheet;
       child->SetAssociatedDocument(aPrimarySheet->mDocument,
                                    aPrimarySheet->mDocumentAssociationMode);
     }
   }
 };
 
 bool
-CSSStyleSheet::RebuildChildList(css::Rule* aRule,
-                                ChildSheetListBuilder* aBuilder)
+CSSStyleSheet::RebuildChildList(css::Rule* aRule, void* aBuilder)
 {
   int32_t type = aRule->GetType();
   if (type < css::Rule::IMPORT_RULE) {
     // Keep going till we get to the import rules.
     return true;
   }
 
   if (type != css::Rule::IMPORT_RULE) {
     // We're past all the import rules; stop the enumeration.
     return false;
   }
 
+  ChildSheetListBuilder* builder =
+    static_cast<ChildSheetListBuilder*>(aBuilder);
+
   // XXXbz We really need to decomtaminate all this stuff.  Is there a reason
   // that I can't just QI to ImportRule and get a CSSStyleSheet
   // directly from it?
   nsCOMPtr<nsIDOMCSSImportRule> importRule(do_QueryInterface(aRule));
   NS_ASSERTION(importRule, "GetType lied");
 
   nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
   importRule->GetStyleSheet(getter_AddRefs(childSheet));
 
   // Have to do this QI to be safe, since XPConnect can fake
   // nsIDOMCSSStyleSheets
   RefPtr<CSSStyleSheet> sheet = do_QueryObject(childSheet);
   if (!sheet) {
     return true;
   }
 
-  (*aBuilder->sheetSlot) = sheet;
-  aBuilder->SetParentLinks(*aBuilder->sheetSlot);
-  aBuilder->sheetSlot = &(*aBuilder->sheetSlot)->mNext;
+  (*builder->sheetSlot) = sheet;
+  builder->SetParentLinks(*builder->sheetSlot);
+  builder->sheetSlot = &(*builder->sheetSlot)->mNext;
   return true;
 }
 
 size_t
 CSSStyleSheet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = StyleSheet::SizeOfIncludingThis(aMallocSizeOf);
   const CSSStyleSheet* s = this;
@@ -231,54 +233,42 @@ CSSStyleSheet::SizeOfIncludingThis(Mallo
   return n;
 }
 
 CSSStyleSheetInner::CSSStyleSheetInner(CSSStyleSheetInner& aCopy,
                                        CSSStyleSheet* aPrimarySheet)
   : StyleSheetInfo(aCopy, aPrimarySheet)
 {
   MOZ_COUNT_CTOR(CSSStyleSheetInner);
-  for (css::Rule* rule : aCopy.mOrderedRules) {
-    RefPtr<css::Rule> clone = rule->Clone();
-    mOrderedRules.AppendObject(clone);
-    clone->SetStyleSheet(aPrimarySheet);
-  }
+  aCopy.mOrderedRules.EnumerateForwards(css::GroupRule::CloneRuleInto, &mOrderedRules);
+  mOrderedRules.EnumerateForwards(SetStyleSheetReference, aPrimarySheet);
 
   ChildSheetListBuilder builder = { &mFirstChild, aPrimarySheet };
-  for (css::Rule* rule : mOrderedRules) {
-    if (!CSSStyleSheet::RebuildChildList(rule, &builder)) {
-      break;
-    }
-  }
+  mOrderedRules.EnumerateForwards(CSSStyleSheet::RebuildChildList, &builder);
 
   RebuildNameSpaces();
 }
 
 CSSStyleSheetInner::~CSSStyleSheetInner()
 {
   MOZ_COUNT_DTOR(CSSStyleSheetInner);
-  for (css::Rule* rule : mOrderedRules) {
-    rule->SetStyleSheet(nullptr);
-  }
+  mOrderedRules.EnumerateForwards(SetStyleSheetReference, nullptr);
 }
 
 CSSStyleSheetInner*
 CSSStyleSheetInner::CloneFor(CSSStyleSheet* aPrimarySheet)
 {
   return new CSSStyleSheetInner(*this, aPrimarySheet);
 }
 
 void
 CSSStyleSheetInner::RemoveSheet(StyleSheet* aSheet)
 {
-  if (aSheet == mSheets.ElementAt(0) && mSheets.Length() > 1) {
-    StyleSheet* sheet = mSheets[1];
-    for (css::Rule* rule : mOrderedRules) {
-      rule->SetStyleSheet(sheet);
-    }
+  if ((aSheet == mSheets.ElementAt(0)) && (mSheets.Length() > 1)) {
+    mOrderedRules.EnumerateForwards(SetStyleSheetReference, mSheets[1]);
 
     ChildSheetListBuilder::ReparentChildList(mSheets[1], mFirstChild);
   }
 
   // Don't do anything after this call, because superclass implementation
   // may delete this.
   StyleSheetInfo::RemoveSheet(aSheet);
 }
@@ -310,27 +300,17 @@ CreateNameSpace(css::Rule* aRule, void* 
   return (css::Rule::CHARSET_RULE == type || css::Rule::IMPORT_RULE == type);
 }
 
 void 
 CSSStyleSheetInner::RebuildNameSpaces()
 {
   // Just nuke our existing namespace map, if any
   if (NS_SUCCEEDED(CreateNamespaceMap())) {
-    for (css::Rule* rule : mOrderedRules) {
-      switch (rule->GetType()) {
-        case css::Rule::NAMESPACE_RULE:
-          AddNamespaceRuleToMap(rule, mNameSpaceMap);
-          continue;
-        case css::Rule::CHARSET_RULE:
-        case css::Rule::IMPORT_RULE:
-          continue;
-      }
-      break;
-    }
+    mOrderedRules.EnumerateForwards(CreateNameSpace, mNameSpaceMap);
   }
 }
 
 nsresult
 CSSStyleSheetInner::CreateNamespaceMap()
 {
   mNameSpaceMap = nsXMLNameSpaceMap::Create(false);
   NS_ENSURE_TRUE(mNameSpaceMap, NS_ERROR_OUT_OF_MEMORY);
@@ -452,19 +432,17 @@ void
 CSSStyleSheet::UnlinkInner()
 {
   // We can only have a cycle through our inner if we have a unique inner,
   // because otherwise there are no JS wrappers for anything in the inner.
   if (mInner->mSheets.Length() != 1) {
     return;
   }
 
-  for (css::Rule* rule : Inner()->mOrderedRules) {
-    rule->SetStyleSheet(nullptr);
-  }
+  Inner()->mOrderedRules.EnumerateForwards(SetStyleSheetReference, nullptr);
   Inner()->mOrderedRules.Clear();
 
   StyleSheet::UnlinkInner();
 }
 
 void
 CSSStyleSheet::TraverseInner(nsCycleCollectionTraversalCallback &cb)
 {
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -33,17 +33,16 @@ class nsCSSRuleProcessor;
 class nsIURI;
 class nsMediaQueryResultCacheKey;
 class nsStyleSet;
 class nsPresContext;
 class nsXMLNameSpaceMap;
 
 namespace mozilla {
 class CSSStyleSheet;
-struct ChildSheetListBuilder;
 
 namespace css {
 class GroupRule;
 } // namespace css
 namespace dom {
 class CSSRuleList;
 } // namespace dom
 
@@ -160,18 +159,17 @@ public:
                             nsMediaQueryResultCacheKey& aKey) const;
 
   nsresult ReparseSheet(const nsAString& aInput);
 
   void SetInRuleProcessorCache() { mInRuleProcessorCache = true; }
 
   // Function used as a callback to rebuild our inner's child sheet
   // list after we clone a unique inner for ourselves.
-  static bool RebuildChildList(css::Rule* aRule,
-                               ChildSheetListBuilder* aBuilder);
+  static bool RebuildChildList(css::Rule* aRule, void* aBuilder);
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
 
   dom::Element* GetScopeElement() const { return mScopeElement; }
   void SetScopeElement(dom::Element* aScopeElement)
   {
     mScopeElement = aScopeElement;
   }
--- a/layout/style/GroupRule.h
+++ b/layout/style/GroupRule.h
@@ -53,17 +53,17 @@ public:
   virtual void SetStyleSheet(StyleSheet* aSheet) override;
 
 public:
   void AppendStyleRule(Rule* aRule);
 
   int32_t StyleRuleCount() const { return mRules.Count(); }
   Rule* GetStyleRuleAt(int32_t aIndex) const;
 
-  typedef bool (*RuleEnumFunc)(Rule* aElement, void* aData);
+  typedef IncrementalClearCOMRuleArray::nsCOMArrayEnumFunc RuleEnumFunc;
   bool EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const;
 
   /*
    * The next three methods should never be called unless you have first
    * called WillDirty() on the parent stylesheet.  After they are
    * called, DidDirty() needs to be called on the sheet.
    */
   nsresult DeleteStyleRuleAt(uint32_t aIndex);
@@ -71,16 +71,24 @@ public:
 
   virtual bool UseForPresentation(nsPresContext* aPresContext,
                                     nsMediaQueryResultCacheKey& aKey) = 0;
 
   // non-virtual -- it is only called by subclasses
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override = 0;
 
+  static bool
+  CloneRuleInto(Rule* aRule, void* aArray)
+  {
+    RefPtr<Rule> clone = aRule->Clone();
+    static_cast<IncrementalClearCOMRuleArray*>(aArray)->AppendObject(clone);
+    return true;
+  }
+
   // WebIDL API
   dom::CSSRuleList* CssRules();
   uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
                       ErrorResult& aRv);
   void DeleteRule(uint32_t aIndex, ErrorResult& aRv);
 
 protected:
   // to help implement nsIDOMCSSRule
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -3668,21 +3668,19 @@ nsCSSRuleProcessor::CascadeSheet(CSSStyl
 
     StyleSheet* child = aSheet->GetFirstChild();
     while (child) {
       CascadeSheet(child->AsGecko(), aData);
 
       child = child->mNext;
     }
 
-    for (css::Rule* rule : aSheet->Inner()->mOrderedRules) {
-      if (!CascadeRuleEnumFunc(rule, aData)) {
-        return false;
-      }
-    }
+    if (!aSheet->Inner()->mOrderedRules.EnumerateForwards(CascadeRuleEnumFunc,
+                                                         aData))
+      return false;
   }
   return true;
 }
 
 static int CompareWeightData(const void* aArg1, const void* aArg2,
                              void* closure)
 {
   const PerWeightData* arg1 = static_cast<const PerWeightData*>(aArg1);
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -426,32 +426,35 @@ ImportRule::WrapObject(JSContext* aCx,
   return CSSImportRuleBinding::Wrap(aCx, this, aGivenProto);
 }
 
 GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
   : Rule(aLineNumber, aColumnNumber)
 {
 }
 
+static bool
+SetParentRuleReference(Rule* aRule, void* aParentRule)
+{
+  GroupRule* parentRule = static_cast<GroupRule*>(aParentRule);
+  aRule->SetParentRule(parentRule);
+  return true;
+}
+
 GroupRule::GroupRule(const GroupRule& aCopy)
   : Rule(aCopy)
 {
-  for (const Rule* rule : aCopy.mRules) {
-    RefPtr<Rule> clone = rule->Clone();
-    mRules.AppendObject(clone);
-    clone->SetParentRule(this);
-  }
+  const_cast<GroupRule&>(aCopy).mRules.EnumerateForwards(GroupRule::CloneRuleInto, &mRules);
+  mRules.EnumerateForwards(SetParentRuleReference, this);
 }
 
 GroupRule::~GroupRule()
 {
   MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
-  for (Rule* rule : mRules) {
-    rule->SetParentRule(nullptr);
-  }
+  mRules.EnumerateForwards(SetParentRuleReference, nullptr);
   if (mRuleCollection) {
     mRuleCollection->DropReference();
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(GroupRule, Rule)
 NS_IMPL_RELEASE_INHERITED(GroupRule, Rule)
 
@@ -460,32 +463,35 @@ NS_INTERFACE_MAP_END_INHERITING(Rule)
 
 bool
 GroupRule::IsCCLeaf() const
 {
   // Let's not worry for now about sorting out whether we're a leaf or not.
   return false;
 }
 
+static bool
+SetStyleSheetReference(Rule* aRule, void* aSheet)
+{
+  aRule->SetStyleSheet(reinterpret_cast<StyleSheet*>(aSheet));
+  return true;
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GroupRule, Rule)
-  for (Rule* rule : tmp->mRules) {
-    rule->SetParentRule(nullptr);
-  }
+  tmp->mRules.EnumerateForwards(SetParentRuleReference, nullptr);
   // If tmp does not have a stylesheet, neither do its descendants.  In that
   // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
   // depth of group rule nesting.  But if tmp _does_ have a stylesheet (which
   // can happen if it gets unlinked earlier than its owning stylesheet), then we
   // need to null out the stylesheet pointer on descendants now, before we clear
   // tmp->mRules.
   if (tmp->GetStyleSheet()) {
-    for (Rule* rule : tmp->mRules) {
-      rule->SetStyleSheet(nullptr);
-    }
+    tmp->mRules.EnumerateForwards(SetStyleSheetReference, nullptr);
   }
   tmp->mRules.Clear();
   if (tmp->mRuleCollection) {
     tmp->mRuleCollection->DropReference();
     tmp->mRuleCollection = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -503,19 +509,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 /* virtual */ void
 GroupRule::SetStyleSheet(StyleSheet* aSheet)
 {
   // Don't set the sheet on the kids if it's already the same as the sheet we
   // already have.  This is needed to avoid O(N^2) behavior in group nesting
   // depth when seting the sheet to null during unlink, if we happen to unlin in
   // order from most nested rule up to least nested rule.
   if (aSheet != GetStyleSheet()) {
-    for (Rule* rule : mRules) {
-      rule->SetStyleSheet(aSheet);
-    }
+    mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
     Rule::SetStyleSheet(aSheet);
   }
 }
 
 #ifdef DEBUG
 /* virtual */ void
 GroupRule::List(FILE* out, int32_t aIndent) const
 {
@@ -541,22 +545,18 @@ Rule*
 GroupRule::GetStyleRuleAt(int32_t aIndex) const
 {
   return mRules.SafeObjectAt(aIndex);
 }
 
 bool
 GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
 {
-  for (const Rule* rule : mRules) {
-    if (!aFunc(const_cast<Rule*>(rule), aData)) {
-      return false;
-    }
-  }
-  return true;
+  return
+    const_cast<GroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
 }
 
 /*
  * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt)
  * should never be called unless you have first called WillDirty() on
  * the parents stylesheet.  After they are called, DidDirty() needs to
  * be called on the sheet
  */
deleted file mode 100644
--- a/xpcom/ds/ArrayIterator.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-// Common iterator implementation for array classes e.g. nsTArray.
-
-#ifndef mozilla_ArrayIterator_h
-#define mozilla_ArrayIterator_h
-
-#include <iterator>
-
-#include "mozilla/TypeTraits.h"
-
-namespace mozilla {
-
-// We have implemented a custom iterator class for array rather than using
-// raw pointers into the backing storage to improve the safety of C++11-style
-// range based iteration in the presence of array mutation, or script execution
-// (bug 1299489).
-//
-// Mutating an array which is being iterated is still wrong, and will either
-// cause elements to be missed or firefox to crash, but will not trigger memory
-// safety problems due to the release-mode bounds checking found in ElementAt.
-//
-// Dereferencing this iterator returns type Element. When Element is a reference
-// type, this iterator implements the full standard random access iterator spec,
-// and can be treated in many ways as though it is a pointer. Otherwise, it is
-// just enough to be used in range-based for loop.
-template<class Element, class ArrayType>
-class ArrayIterator
-{
-public:
-  typedef ArrayType                               array_type;
-  typedef ArrayIterator<Element, ArrayType>       iterator_type;
-  typedef typename array_type::index_type         index_type;
-  typedef typename RemoveReference<Element>::Type value_type;
-  typedef ptrdiff_t                               difference_type;
-  typedef value_type*                             pointer;
-  typedef value_type&                             reference;
-  typedef std::random_access_iterator_tag         iterator_category;
-
-private:
-  const array_type* mArray;
-  index_type mIndex;
-
-public:
-  ArrayIterator() : mArray(nullptr), mIndex(0) {}
-  ArrayIterator(const iterator_type& aOther)
-    : mArray(aOther.mArray), mIndex(aOther.mIndex) {}
-  ArrayIterator(const array_type& aArray, index_type aIndex)
-    : mArray(&aArray), mIndex(aIndex) {}
-
-  iterator_type& operator=(const iterator_type& aOther) {
-    mArray = aOther.mArray;
-    mIndex = aOther.mIndex;
-    return *this;
-  }
-
-  bool operator==(const iterator_type& aRhs) const {
-    return mIndex == aRhs.mIndex;
-  }
-  bool operator!=(const iterator_type& aRhs) const {
-    return !(*this == aRhs);
-  }
-  bool operator<(const iterator_type& aRhs) const {
-    return mIndex < aRhs.mIndex;
-  }
-  bool operator>(const iterator_type& aRhs) const {
-    return mIndex > aRhs.mIndex;
-  }
-  bool operator<=(const iterator_type& aRhs) const {
-    return mIndex <= aRhs.mIndex;
-  }
-  bool operator>=(const iterator_type& aRhs) const {
-    return mIndex >= aRhs.mIndex;
-  }
-
-  // These operators depend on the release mode bounds checks in
-  // ArrayIterator::ElementAt for safety.
-  value_type* operator->() const {
-    return const_cast<value_type*>(&mArray->ElementAt(mIndex));
-  }
-  Element operator*() const {
-    return const_cast<Element>(mArray->ElementAt(mIndex));
-  }
-
-  iterator_type& operator++() {
-    ++mIndex;
-    return *this;
-  }
-  iterator_type operator++(int) {
-    iterator_type it = *this;
-    ++*this;
-    return it;
-  }
-  iterator_type& operator--() {
-    --mIndex;
-    return *this;
-  }
-  iterator_type operator--(int) {
-    iterator_type it = *this;
-    --*this;
-    return it;
-  }
-
-  iterator_type& operator+=(difference_type aDiff) {
-    mIndex += aDiff;
-    return *this;
-  }
-  iterator_type& operator-=(difference_type aDiff) {
-    mIndex -= aDiff;
-    return *this;
-  }
-
-  iterator_type operator+(difference_type aDiff) const {
-    iterator_type it = *this;
-    it += aDiff;
-    return it;
-  }
-  iterator_type operator-(difference_type aDiff) const {
-    iterator_type it = *this;
-    it -= aDiff;
-    return it;
-  }
-
-  difference_type operator-(const iterator_type& aOther) const {
-    return static_cast<difference_type>(mIndex) -
-      static_cast<difference_type>(aOther.mIndex);
-  }
-
-  Element operator[](difference_type aIndex) const {
-    return *this->operator+(aIndex);
-  }
-};
-
-} // namespace mozilla
-
-#endif // mozilla_ArrayIterator_h
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -78,17 +78,16 @@ EXPORTS += [
     'nsTObserverArray.h',
     'nsTPriorityQueue.h',
     'nsVariant.h',
     'nsWhitespaceTokenizer.h',
     'PLDHashTable.h',
 ]
 
 EXPORTS.mozilla += [
-    'ArrayIterator.h',
     'IncrementalTokenizer.h',
     'Observer.h',
     'StickyTimeDuration.h',
     'Tokenizer.h',
 ]
 
 UNIFIED_SOURCES += [
     'IncrementalTokenizer.cpp',
--- a/xpcom/ds/nsCOMArray.h
+++ b/xpcom/ds/nsCOMArray.h
@@ -3,19 +3,17 @@
 /* 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/. */
 
 #ifndef nsCOMArray_h__
 #define nsCOMArray_h__
 
 #include "mozilla/Attributes.h"
-#include "mozilla/ArrayIterator.h"
 #include "mozilla/MemoryReporting.h"
-#include "mozilla/ReverseIterator.h"
 
 #include "nsCycleCollectionNoteChild.h"
 #include "nsTArray.h"
 #include "nsISupports.h"
 
 // See below for the definition of nsCOMArray<T>
 
 // a class that's nsISupports-specific, so that we can contain the
@@ -228,22 +226,16 @@ ImplCycleCollectionTraverse(nsCycleColle
 //
 // This array will accept null as an argument for any object, and will store
 // null in the array. But that also means that methods like ObjectAt() may
 // return null when referring to an existing, but null entry in the array.
 template<class T>
 class nsCOMArray : public nsCOMArray_base
 {
 public:
-  typedef int32_t                                       index_type;
-  typedef mozilla::ArrayIterator<T*, nsCOMArray>        iterator;
-  typedef mozilla::ArrayIterator<const T*, nsCOMArray>  const_iterator;
-  typedef mozilla::ReverseIterator<iterator>            reverse_iterator;
-  typedef mozilla::ReverseIterator<const_iterator>      const_reverse_iterator;
-
   nsCOMArray() {}
   explicit nsCOMArray(int32_t aCount) : nsCOMArray_base(aCount) {}
   explicit nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) {}
   nsCOMArray(nsCOMArray<T>&& aOther) { SwapElements(aOther); }
   ~nsCOMArray() {}
 
   // We have a move assignment operator, but no copy assignment operator.
   nsCOMArray<T>& operator=(nsCOMArray<T> && aOther)
@@ -339,16 +331,34 @@ public:
     nsCOMArray_base::ReplaceObjectAt(aObject, aIndex);
   }
   // nsTArray-compatible version
   void ReplaceElementAt(uint32_t aIndex, T* aElement)
   {
     nsCOMArray_base::ReplaceElementAt(aIndex, aElement);
   }
 
+  // Enumerator callback function. Return false to stop
+  // Here's a more readable form:
+  // bool enumerate(T* aElement, void* aData)
+  typedef bool (*nsCOMArrayEnumFunc)(T* aElement, void* aData);
+
+  // enumerate through the array with a callback.
+  bool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData)
+  {
+    return nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc(aFunc),
+                                              aData);
+  }
+
+  bool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData)
+  {
+    return nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc(aFunc),
+                                               aData);
+  }
+
   typedef int (*nsCOMArrayComparatorFunc)(T* aElement1, T* aElement2,
                                           void* aData);
 
   void Sort(nsCOMArrayComparatorFunc aFunc, void* aData)
   {
     nsCOMArray_base::Sort(nsBaseArrayComparatorFunc(aFunc), aData);
   }
 
@@ -428,32 +438,16 @@ public:
    * nsCOMArray<nsISomeInterface> array;
    * *length = array.Forget(retval);
    */
   uint32_t Forget(T*** aElements)
   {
     return nsCOMArray_base::Forget(reinterpret_cast<nsISupports***>(aElements));
   }
 
-  // Methods for range-based for loops.
-  iterator begin() { return iterator(*this, 0); }
-  const_iterator begin() const { return const_iterator(*this, 0); }
-  const_iterator cbegin() const { return begin(); }
-  iterator end() { return iterator(*this, Length()); }
-  const_iterator end() const { return const_iterator(*this, Length()); }
-  const_iterator cend() const { return end(); }
-
-  // Methods for reverse iterating.
-  reverse_iterator rbegin() { return reverse_iterator(end()); }
-  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
-  const_reverse_iterator crbegin() const { return rbegin(); }
-  reverse_iterator rend() { return reverse_iterator(begin()); }
-  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
-  const_reverse_iterator crend() const { return rend(); }
-
 private:
 
   // don't implement these!
   nsCOMArray<T>& operator=(const nsCOMArray<T>& aOther) = delete;
 };
 
 template<typename T>
 inline void
--- a/xpcom/ds/nsTArray.h
+++ b/xpcom/ds/nsTArray.h
@@ -4,17 +4,16 @@
  * 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 nsTArray_h__
 #define nsTArray_h__
 
 #include "nsTArrayForwardDeclare.h"
 #include "mozilla/Alignment.h"
-#include "mozilla/ArrayIterator.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/BinarySearch.h"
 #include "mozilla/fallible.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/ReverseIterator.h"
@@ -27,16 +26,17 @@
 #include "nscore.h"
 #include "nsQuickSort.h"
 #include "nsDebug.h"
 #include "nsISupportsImpl.h"
 #include "nsRegionFwd.h"
 #include <functional>
 #include <initializer_list>
 #include <new>
+#include <iterator>
 
 namespace JS {
 template<class T>
 class Heap;
 } /* namespace JS */
 
 class nsRegion;
 namespace mozilla {
@@ -352,16 +352,134 @@ struct nsTArray_SafeElementAtHelper<mozi
   {
     if (aIndex < static_cast<const Derived*>(this)->Length()) {
       return static_cast<const Derived*>(this)->ElementAt(aIndex);
     }
     return nullptr;
   }
 };
 
+// We have implemented a custom iterator class for nsTArray rather than using
+// raw pointers into the backing storage to improve the safety of C++11-style
+// range based iteration in the presence of array mutation, or script execution
+// (bug 1299489).
+//
+// Mutating an array which is being iterated is still wrong, and will either
+// cause elements to be missed or firefox to crash, but will not trigger memory
+// safety problems due to the release-mode bounds checking found in ElementAt.
+//
+// This iterator implements the full standard random access iterator spec, and
+// can be treated in may ways as though it is a pointer.
+template<class Element>
+class nsTArrayIterator
+{
+public:
+  typedef nsTArray<typename mozilla::RemoveConst<Element>::Type> array_type;
+  typedef nsTArrayIterator<Element>       iterator_type;
+  typedef typename array_type::index_type index_type;
+  typedef Element                         value_type;
+  typedef ptrdiff_t                       difference_type;
+  typedef value_type*                     pointer;
+  typedef value_type&                     reference;
+  typedef std::random_access_iterator_tag iterator_category;
+
+private:
+  const array_type* mArray;
+  index_type mIndex;
+
+public:
+  nsTArrayIterator() : mArray(nullptr), mIndex(0) {}
+  nsTArrayIterator(const iterator_type& aOther)
+    : mArray(aOther.mArray), mIndex(aOther.mIndex) {}
+  nsTArrayIterator(const array_type& aArray, index_type aIndex)
+    : mArray(&aArray), mIndex(aIndex) {}
+
+  iterator_type& operator=(const iterator_type& aOther) {
+    mArray = aOther.mArray;
+    mIndex = aOther.mIndex;
+    return *this;
+  }
+
+  bool operator==(const iterator_type& aRhs) const {
+    return mIndex == aRhs.mIndex;
+  }
+  bool operator!=(const iterator_type& aRhs) const {
+    return !(*this == aRhs);
+  }
+  bool operator<(const iterator_type& aRhs) const {
+    return mIndex < aRhs.mIndex;
+  }
+  bool operator>(const iterator_type& aRhs) const {
+    return mIndex > aRhs.mIndex;
+  }
+  bool operator<=(const iterator_type& aRhs) const {
+    return mIndex <= aRhs.mIndex;
+  }
+  bool operator>=(const iterator_type& aRhs) const {
+    return mIndex >= aRhs.mIndex;
+  }
+
+  // These operators depend on the release mode bounds checks in
+  // nsTArray::ElementAt for safety.
+  value_type* operator->() const {
+    return const_cast<value_type*>(&(*mArray)[mIndex]);
+  }
+  value_type& operator*() const {
+    return const_cast<value_type&>((*mArray)[mIndex]);
+  }
+
+  iterator_type& operator++() {
+    ++mIndex;
+    return *this;
+  }
+  iterator_type operator++(int) {
+    iterator_type it = *this;
+    ++*this;
+    return it;
+  }
+  iterator_type& operator--() {
+    --mIndex;
+    return *this;
+  }
+  iterator_type operator--(int) {
+    iterator_type it = *this;
+    --*this;
+    return it;
+  }
+
+  iterator_type& operator+=(difference_type aDiff) {
+    mIndex += aDiff;
+    return *this;
+  }
+  iterator_type& operator-=(difference_type aDiff) {
+    mIndex -= aDiff;
+    return *this;
+  }
+
+  iterator_type operator+(difference_type aDiff) const {
+    iterator_type it = *this;
+    it += aDiff;
+    return it;
+  }
+  iterator_type operator-(difference_type aDiff) const {
+    iterator_type it = *this;
+    it -= aDiff;
+    return it;
+  }
+
+  difference_type operator-(const iterator_type& aOther) const {
+    return static_cast<difference_type>(mIndex) -
+      static_cast<difference_type>(aOther.mIndex);
+  }
+
+  value_type& operator[](difference_type aIndex) const {
+    return *this->operator+(aIndex);
+  }
+};
+
 // Servo bindings.
 extern "C" void Gecko_EnsureTArrayCapacity(void* aArray,
                                            size_t aCapacity,
                                            size_t aElementSize);
 extern "C" void Gecko_ClearPODTArray(void* aArray,
                                      size_t aElementSize,
                                      size_t aElementAlign);
 
@@ -855,18 +973,18 @@ public:
   typedef typename nsTArray_CopyChooser<E>::Type     copy_type;
   typedef nsTArray_base<Alloc, copy_type>            base_type;
   typedef typename base_type::size_type              size_type;
   typedef typename base_type::index_type             index_type;
   typedef E                                          elem_type;
   typedef nsTArray_Impl<E, Alloc>                    self_type;
   typedef nsTArrayElementTraits<E>                   elem_traits;
   typedef nsTArray_SafeElementAtHelper<E, self_type> safeelementat_helper_type;
-  typedef mozilla::ArrayIterator<elem_type&, nsTArray<E>>       iterator;
-  typedef mozilla::ArrayIterator<const elem_type&, nsTArray<E>> const_iterator;
+  typedef nsTArrayIterator<elem_type>                iterator;
+  typedef nsTArrayIterator<const elem_type>          const_iterator;
   typedef mozilla::ReverseIterator<iterator>         reverse_iterator;
   typedef mozilla::ReverseIterator<const_iterator>   const_reverse_iterator;
 
   using safeelementat_helper_type::SafeElementAt;
   using base_type::EmptyHdr;
 
   // A special value that is used to indicate an invalid or unknown index
   // into the array.
--- a/xpfe/appshell/nsWindowMediator.cpp
+++ b/xpfe/appshell/nsWindowMediator.cpp
@@ -22,16 +22,26 @@
 
 #include "nsIDocShell.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIXULWindow.h"
 
 using namespace mozilla;
 
+static bool notifyOpenWindow(nsIWindowMediatorListener *aElement, void* aData);
+static bool notifyCloseWindow(nsIWindowMediatorListener *aElement, void* aData);
+static bool notifyWindowTitleChange(nsIWindowMediatorListener *aElement, void* aData);
+
+// for notifyWindowTitleChange
+struct WindowTitleData {
+  nsIXULWindow* mWindow;
+  const char16_t *mTitle;
+};
+
 nsresult
 nsWindowMediator::GetDOMWindow(nsIXULWindow* inWindow,
                                nsCOMPtr<nsPIDOMWindowOuter>& outDOMWindow)
 {
   nsCOMPtr<nsIDocShell> docShell;
 
   outDOMWindow = nullptr;
   inWindow->GetDocShell(getter_AddRefs(docShell));
@@ -76,20 +86,19 @@ NS_IMETHODIMP nsWindowMediator::Register
     return NS_ERROR_FAILURE;
   }
 
   mTimeStamp++;
 
   // Create window info struct and add to list of windows
   nsWindowInfo* windowInfo = new nsWindowInfo(inWindow, mTimeStamp);
 
-  for (nsIWindowMediatorListener* listener : mListeners) {
-    listener->OnOpenWindow(inWindow);
-  }
-
+  WindowTitleData winData = { inWindow, nullptr };
+  mListeners.EnumerateForwards(notifyOpenWindow, &winData);
+  
   if (mOldestWindow)
     windowInfo->InsertAfter(mOldestWindow->mOlder, nullptr);
   else
     mOldestWindow = windowInfo;
 
   return NS_OK;
 }
 
@@ -109,19 +118,18 @@ nsWindowMediator::UnregisterWindow(nsWin
 {
   // Inform the iterators
   uint32_t index = 0;
   while (index < mEnumeratorList.Length()) {
     mEnumeratorList[index]->WindowRemoved(inInfo);
     index++;
   }
   
-  for (nsIWindowMediatorListener* listener : mListeners) {
-    listener->OnCloseWindow(inInfo->mWindow.get());
-  }
+  WindowTitleData winData = { inInfo->mWindow.get(), nullptr };
+  mListeners.EnumerateForwards(notifyCloseWindow, &winData);
 
   // Remove from the lists and free up 
   if (inInfo == mOldestWindow)
     mOldestWindow = inInfo->mYounger;
   if (inInfo == mTopmostWindow)
     mTopmostWindow = inInfo->mLower;
   inInfo->Unlink(true, true);
   if (inInfo == mOldestWindow)
@@ -394,19 +402,18 @@ nsWindowMediator::UpdateWindowTimeStamp(
 
 NS_IMETHODIMP
 nsWindowMediator::UpdateWindowTitle(nsIXULWindow* inWindow,
                                     const char16_t* inTitle)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   NS_ENSURE_STATE(mReady);
   if (GetInfoFor(inWindow)) {
-    for (nsIWindowMediatorListener* listener : mListeners) {
-      listener->OnWindowTitleChange(inWindow, inTitle);
-    }
+    WindowTitleData winData = { inWindow, inTitle };
+    mListeners.EnumerateForwards(notifyWindowTitleChange, &winData);
   }
 
   return NS_OK;
 }
 
 /* This method's plan is to intervene only when absolutely necessary.
    We will get requests to place our windows behind unknown windows.
    For the most part, we need to leave those alone (turning them into
@@ -805,8 +812,35 @@ nsWindowMediator::Observe(nsISupports* a
   if (!strcmp(aTopic, "xpcom-shutdown") && mReady) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     while (mOldestWindow)
       UnregisterWindow(mOldestWindow);
     mReady = false;
   }
   return NS_OK;
 }
+
+bool
+notifyOpenWindow(nsIWindowMediatorListener *aListener, void* aData)
+{
+  WindowTitleData* winData = static_cast<WindowTitleData*>(aData);
+  aListener->OnOpenWindow(winData->mWindow);
+
+  return true;
+}
+
+bool
+notifyCloseWindow(nsIWindowMediatorListener *aListener, void* aData)
+{
+  WindowTitleData* winData = static_cast<WindowTitleData*>(aData);
+  aListener->OnCloseWindow(winData->mWindow);
+
+  return true;
+}
+
+bool 
+notifyWindowTitleChange(nsIWindowMediatorListener *aListener, void* aData)
+{
+  WindowTitleData* titleData = reinterpret_cast<WindowTitleData*>(aData);
+  aListener->OnWindowTitleChange(titleData->mWindow, titleData->mTitle);
+
+  return true;
+}