Backed out 5 changesets (bug 1519193) for build bustages in Document.cpp CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Sat, 12 Jan 2019 00:29:37 +0200
changeset 453574 487a0df75166
parent 453573 24243f13c895
child 453575 03f596ee1683
push id35360
push usernbeleuzu@mozilla.com
push dateSat, 12 Jan 2019 09:39:47 +0000
treeherdermozilla-central@cb35977ae7a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1519193
milestone66.0a1
backs oute118466df64d
12d89a7fe296
08b0f2b9a96a
1caa462e7f08
aae6e06aa88b
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 5 changesets (bug 1519193) for build bustages in Document.cpp CLOSED TREE Backed out changeset e118466df64d (bug 1519193) Backed out changeset 12d89a7fe296 (bug 1519193) Backed out changeset 08b0f2b9a96a (bug 1519193) Backed out changeset 1caa462e7f08 (bug 1519193) Backed out changeset aae6e06aa88b (bug 1519193)
dom/base/CustomElementRegistry.cpp
dom/base/Document.cpp
dom/base/ShadowIncludingTreeIterator.h
dom/base/moz.build
layout/base/PresShell.cpp
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/CustomElementRegistry.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/dom/CustomElementRegistryBinding.h"
 #include "mozilla/dom/HTMLElementBinding.h"
-#include "mozilla/dom/ShadowIncludingTreeIterator.h"
 #include "mozilla/dom/XULElementBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/WebComponentsBinding.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/CustomEvent.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "nsHTMLTags.h"
 #include "jsapi.h"
@@ -553,16 +552,18 @@ namespace {
 
 class CandidateFinder {
  public:
   CandidateFinder(nsTHashtable<nsRefPtrHashKey<nsIWeakReference>>& aCandidates,
                   Document* aDoc);
   nsTArray<nsCOMPtr<Element>> OrderedCandidates();
 
  private:
+  bool Traverse(Element* aRoot, nsTArray<nsCOMPtr<Element>>& aOrderedElements);
+
   nsCOMPtr<Document> mDoc;
   nsInterfaceHashtable<nsPtrHashKey<Element>, Element> mCandidates;
 };
 
 CandidateFinder::CandidateFinder(
     nsTHashtable<nsRefPtrHashKey<nsIWeakReference>>& aCandidates,
     Document* aDoc)
     : mDoc(aDoc), mCandidates(aCandidates.Count()) {
@@ -584,32 +585,55 @@ nsTArray<nsCOMPtr<Element>> CandidateFin
     for (auto iter = mCandidates.Iter(); !iter.Done(); iter.Next()) {
       nsTArray<nsCOMPtr<Element>> rval({std::move(iter.Data())});
       iter.Remove();
       return rval;
     }
   }
 
   nsTArray<nsCOMPtr<Element>> orderedElements(mCandidates.Count());
-  for (nsINode* node : ShadowIncludingTreeIterator(*mDoc)) {
-    Element* element = Element::FromNode(node);
-    if (!element) {
-      continue;
+  for (Element* child = mDoc->GetFirstElementChild(); child;
+       child = child->GetNextElementSibling()) {
+    if (!Traverse(child, orderedElements)) {
+      break;
     }
+  }
+
+  return orderedElements;
+}
 
-    nsCOMPtr<Element> elem;
-    if (mCandidates.Remove(element, getter_AddRefs(elem))) {
-      orderedElements.AppendElement(std::move(elem));
-      if (mCandidates.Count() == 0) {
-        break;
+bool CandidateFinder::Traverse(Element* aRoot,
+                               nsTArray<nsCOMPtr<Element>>& aOrderedElements) {
+  nsCOMPtr<Element> elem;
+  if (mCandidates.Remove(aRoot, getter_AddRefs(elem))) {
+    aOrderedElements.AppendElement(std::move(elem));
+    if (mCandidates.Count() == 0) {
+      return false;
+    }
+  }
+
+  if (ShadowRoot* root = aRoot->GetShadowRoot()) {
+    // First iterate the children of the shadow root if aRoot is a shadow host.
+    for (Element* child = root->GetFirstElementChild(); child;
+         child = child->GetNextElementSibling()) {
+      if (!Traverse(child, aOrderedElements)) {
+        return false;
       }
     }
   }
 
-  return orderedElements;
+  // Iterate the explicit children of aRoot.
+  for (Element* child = aRoot->GetFirstElementChild(); child;
+       child = child->GetNextElementSibling()) {
+    if (!Traverse(child, aOrderedElements)) {
+      return false;
+    }
+  }
+
+  return true;
 }
 
 }  // namespace
 
 void CustomElementRegistry::UpgradeCandidates(
     nsAtom* aKey, CustomElementDefinition* aDefinition, ErrorResult& aRv) {
   DocGroup* docGroup = mWindow->GetDocGroup();
   if (!docGroup) {
@@ -976,38 +1000,48 @@ void CustomElementRegistry::SetElementCr
     return;
   }
 
   RefPtr<CustomElementCreationCallback> callback = &aCallback;
   mElementCreationCallbacks.Put(nameAtom, callback.forget());
   return;
 }
 
-void CustomElementRegistry::Upgrade(nsINode& aRoot) {
-  for (nsINode* node : ShadowIncludingTreeIterator(aRoot)) {
-    Element* element = Element::FromNode(node);
-    if (!element) {
-      continue;
-    }
-
+static void TryUpgrade(nsINode& aNode) {
+  Element* element = aNode.IsElement() ? aNode.AsElement() : nullptr;
+  if (element) {
     CustomElementData* ceData = element->GetCustomElementData();
     if (ceData) {
       NodeInfo* nodeInfo = element->NodeInfo();
       nsAtom* typeAtom = ceData->GetCustomElementType();
       CustomElementDefinition* definition =
           nsContentUtils::LookupCustomElementDefinition(
               nodeInfo->GetDocument(), nodeInfo->NameAtom(),
               nodeInfo->NamespaceID(), typeAtom);
       if (definition) {
         nsContentUtils::EnqueueUpgradeReaction(element, definition);
       }
     }
+
+    if (ShadowRoot* root = element->GetShadowRoot()) {
+      for (Element* child = root->GetFirstElementChild(); child;
+           child = child->GetNextElementSibling()) {
+        TryUpgrade(*child);
+      }
+    }
+  }
+
+  for (Element* child = aNode.GetFirstElementChild(); child;
+       child = child->GetNextElementSibling()) {
+    TryUpgrade(*child);
   }
 }
 
+void CustomElementRegistry::Upgrade(nsINode& aRoot) { TryUpgrade(aRoot); }
+
 void CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
                                 JS::MutableHandle<JS::Value> aRetVal) {
   RefPtr<nsAtom> nameAtom(NS_Atomize(aName));
   CustomElementDefinition* data = mCustomDefinitions.GetWeak(nameAtom);
 
   if (!data) {
     aRetVal.setUndefined();
     return;
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -3542,31 +3542,31 @@ void Document::TryChannelCharset(nsIChan
         return;
       } else if (aExecutor && !charsetVal.IsEmpty()) {
         aExecutor->ComplainAboutBogusProtocolCharset(this);
       }
     }
   }
 }
 
-static inline void AssertNoStaleServoDataIn(nsINode& aSubtreeRoot) {
+static inline void AssertNoStaleServoDataIn(const nsINode& aSubtreeRoot) {
 #ifdef DEBUG
-  for (nsINode* node : ShadowIncludingTreeIterator(aSubtreeRoot)) {
+  for (const nsINode* node = &aSubtreeRoot; node;
+       node = node->GetNextNode(&aSubtreeRoot)) {
     const Element* element = Element::FromNode(node);
     if (!element) {
       continue;
     }
     MOZ_ASSERT(!element->HasServoData());
+    if (auto* shadow = element->GetShadowRoot()) {
+      AssertNoStaleServoDataIn(*shadow);
+    }
     if (nsXBLBinding* binding = element->GetXBLBinding()) {
       if (nsXBLBinding* bindingWithContent = binding->GetBindingWithContent()) {
         nsIContent* content = bindingWithContent->GetAnonymousContent();
-        // Need to do this instead of just AssertNoStaleServoDataIn(*content),
-        // because the parent of the children of the <content> element isn't the
-        // <content> element, but the bound element, and that confuses
-        // GetNextNode a lot.
         MOZ_ASSERT(!content->AsElement()->HasServoData());
         for (nsINode* child = content->GetFirstChild(); child;
              child = child->GetNextSibling()) {
           AssertNoStaleServoDataIn(*child);
         }
       }
     }
   }
@@ -3576,17 +3576,17 @@ static inline void AssertNoStaleServoDat
 already_AddRefed<nsIPresShell> Document::CreateShell(
     nsPresContext* aContext, nsViewManager* aViewManager,
     UniquePtr<ServoStyleSet> aStyleSet) {
   NS_ASSERTION(!mPresShell, "We have a presshell already!");
 
   NS_ENSURE_FALSE(GetBFCacheEntry(), nullptr);
 
   FillStyleSet(aStyleSet.get());
-  AssertNoStaleServoDataIn(*this);
+  AssertNoStaleServoDataIn(static_cast<nsINode&>(*this));
 
   RefPtr<PresShell> shell = new PresShell;
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   mPresShell = shell;
   shell->Init(this, aContext, aViewManager, std::move(aStyleSet));
 
   // Make sure to never paint if we belong to an invisible DocShell.
   nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
@@ -3699,17 +3699,17 @@ void Document::DeleteShell() {
   MarkUserFontSetDirty();
 
   nsIPresShell* oldShell = mPresShell;
   mPresShell = nullptr;
   UpdateFrameRequestCallbackSchedulingState(oldShell);
   mStyleSetFilled = false;
 
   ClearStaleServoData();
-  AssertNoStaleServoDataIn(*this);
+  AssertNoStaleServoDataIn(static_cast<nsINode&>(*this));
 }
 
 void Document::SetBFCacheEntry(nsIBFCacheEntry* aEntry) {
   MOZ_ASSERT(IsBFCachingAllowed() || !aEntry, "You should have checked!");
 
   if (mPresShell) {
     if (aEntry) {
       mPresShell->StopObservingRefreshDriver();
deleted file mode 100644
--- a/dom/base/ShadowIncludingTreeIterator.h
+++ /dev/null
@@ -1,113 +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/. */
-
-/**
- * Implementation of
- * https://dom.spec.whatwg.org/#concept-shadow-including-tree-order in iterator
- * form.  This can and should be used to avoid recursion on the stack and lots
- * of function calls during shadow-including tree iteration.
- */
-
-#ifndef mozilla_dom_ShadowIncludingTreeIterator_h
-#define mozilla_dom_ShadowIncludingTreeIterator_h
-
-#include "nsINode.h"
-#include "nsTArray.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/ShadowRoot.h"
-
-namespace mozilla {
-namespace dom {
-
-class ShadowIncludingTreeIterator {
- public:
-  /**
-   * Initialize an iterator with aRoot.  After that it can be iterated with a
-   * range-based for loop.  At the moment, that's the only supported form of use
-   * for this iterator.
-   */
-  explicit ShadowIncludingTreeIterator(nsINode& aRoot) : mCurrent(&aRoot) {
-    mRoots.AppendElement(&aRoot);
-  }
-
-#ifdef DEBUG
-  ~ShadowIncludingTreeIterator() {
-    MOZ_ASSERT(
-        !mMutationGuard.Mutated(0),
-        "Don't mutate the DOM while using a ShadowIncludingTreeIterator");
-  }
-#endif  // DEBUG
-
-  // Basic support for range-based for loops.  This will modify the iterator as
-  // it goes.
-  ShadowIncludingTreeIterator& begin() { return *this; }
-
-  ShadowIncludingTreeIterator end() { return ShadowIncludingTreeIterator(); }
-
-  bool operator!=(const ShadowIncludingTreeIterator& aOther) {
-    return mCurrent != aOther.mCurrent;
-  }
-
-  void operator++() { Next(); }
-
-  nsINode* operator*() { return mCurrent; }
-
- private:
-  // Constructor used only for end() to represent a drained iterator.
-  ShadowIncludingTreeIterator() : mCurrent(nullptr) {}
-
-  void Next() {
-    MOZ_ASSERT(mCurrent, "Don't call Next() after we have no current node");
-
-    // We walk shadow roots immediately after their shadow host.
-    if (Element* element = Element::FromNode(mCurrent)) {
-      if (ShadowRoot* shadowRoot = element->GetShadowRoot()) {
-        mCurrent = shadowRoot;
-        mRoots.AppendElement(shadowRoot);
-        return;
-      }
-    }
-
-    mCurrent = mCurrent->GetNextNode(mRoots.LastElement());
-    while (!mCurrent) {
-      // Nothing left under this root.  Keep trying to pop the stack until we
-      // find a node or run out of stack.
-      nsINode* root = mRoots.PopLastElement();
-      if (mRoots.IsEmpty()) {
-        // No more roots to step out of; we're done.  mCurrent is already set to
-        // null.
-        return;
-      }
-      mCurrent =
-          ShadowRoot::FromNode(root)->Host()->GetNextNode(mRoots.LastElement());
-    }
-  }
-
-  // The current node we're at.
-  nsINode* mCurrent;
-
-  // Stack of roots that we're inside of right now.  An empty stack can only
-  // happen when mCurrent is null (and hence we are done iterating).
-  //
-  // The default array size here is picked based on gut feeling.  We want at
-  // least 1, since we will always add something to it in our constructor.
-  // Having a few more entries probably makes sense, because this is commonly
-  // used in cases when we know we have custom elements, and hence likely have
-  // shadow DOMs.  But the exact value "4" was just picked because it sounded
-  // not too big, not too small.  Feel free to replace it with something else
-  // based on actual data.
-  AutoTArray<nsINode*, 4> mRoots;
-
-#ifdef DEBUG
-  // Make sure no one mutates the DOM while we're walking over it.
-  nsMutationGuard mMutationGuard;
-#endif  // DEBUG
-};
-
-}  // namespace dom
-}  // namespace mozilla
-
-#endif  // mozilla_dom_ShadowIncludingTreeIterator_h
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -215,17 +215,16 @@ EXPORTS.mozilla.dom += [
     'Pose.h',
     'PostMessageEvent.h',
     'ProcessMessageManager.h',
     'ResponsiveImageSelector.h',
     'SameProcessMessageQueue.h',
     'ScreenLuminance.h',
     'ScreenOrientation.h',
     'Selection.h',
-    'ShadowIncludingTreeIterator.h',
     'ShadowRoot.h',
     'StructuredCloneBlob.h',
     'StructuredCloneHolder.h',
     'StructuredCloneTags.h',
     'StructuredCloneTester.h',
     'StyleSheetList.h',
     'SubtleCrypto.h',
     'SyncMessageSender.h',
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -71,17 +71,16 @@
 #include "nsFrameManager.h"
 #include "nsXPCOM.h"
 #include "nsILayoutHistoryState.h"
 #include "nsILineIterator.h"  // for ScrollContentIntoView
 #include "PLDHashTable.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/dom/PointerEventBinding.h"
-#include "mozilla/dom/ShadowIncludingTreeIterator.h"
 #include "nsIObserverService.h"
 #include "nsDocShell.h"  // for reflow observation
 #include "nsIBaseWindow.h"
 #include "nsError.h"
 #include "nsLayoutUtils.h"
 #include "nsViewportInfo.h"
 #include "nsCSSRendering.h"
 // for |#ifdef DEBUG| code
@@ -2875,19 +2874,21 @@ void nsIPresShell::SlotAssignmentWillCha
       aNewSlot->SetHasDirtyDescendantsForServo();
       aNewSlot->NoteDirtySubtreeForServo();
     }
   }
 }
 
 #ifdef DEBUG
 static void AssertNoFramesInSubtree(nsIContent* aContent) {
-  for (nsINode* node : ShadowIncludingTreeIterator(*aContent)) {
-    nsIContent* c = nsIContent::FromNode(node);
+  for (nsIContent* c = aContent; c; c = c->GetNextNode(aContent)) {
     MOZ_ASSERT(!c->GetPrimaryFrame());
+    if (auto* shadowRoot = c->GetShadowRoot()) {
+      AssertNoFramesInSubtree(shadowRoot);
+    }
     if (auto* binding = c->GetXBLBinding()) {
       if (auto* bindingWithContent = binding->GetBindingWithContent()) {
         nsIContent* anonContent = bindingWithContent->GetAnonymousContent();
         MOZ_ASSERT(!anonContent->GetPrimaryFrame());
 
         // Need to do this instead of just AssertNoFramesInSubtree(anonContent),
         // because the parent of the children of the <content> element isn't the
         // <content> element, but the bound element, and that confuses