зеркало из https://github.com/mozilla/gecko-dev.git
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)
This commit is contained in:
Родитель
fe50d1eef4
Коммит
f53cd6172e
|
@ -10,7 +10,6 @@
|
|||
#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"
|
||||
|
@ -558,6 +557,8 @@ class CandidateFinder {
|
|||
nsTArray<nsCOMPtr<Element>> OrderedCandidates();
|
||||
|
||||
private:
|
||||
bool Traverse(Element* aRoot, nsTArray<nsCOMPtr<Element>>& aOrderedElements);
|
||||
|
||||
nsCOMPtr<Document> mDoc;
|
||||
nsInterfaceHashtable<nsPtrHashKey<Element>, Element> mCandidates;
|
||||
};
|
||||
|
@ -589,24 +590,47 @@ nsTArray<nsCOMPtr<Element>> CandidateFinder::OrderedCandidates() {
|
|||
}
|
||||
|
||||
nsTArray<nsCOMPtr<Element>> orderedElements(mCandidates.Count());
|
||||
for (nsINode* node : ShadowIncludingTreeIterator(*mDoc)) {
|
||||
Element* element = Element::FromNode(node);
|
||||
if (!element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<Element> elem;
|
||||
if (mCandidates.Remove(element, getter_AddRefs(elem))) {
|
||||
orderedElements.AppendElement(std::move(elem));
|
||||
if (mCandidates.Count() == 0) {
|
||||
break;
|
||||
}
|
||||
for (Element* child = mDoc->GetFirstElementChild(); child;
|
||||
child = child->GetNextElementSibling()) {
|
||||
if (!Traverse(child, orderedElements)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return orderedElements;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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(
|
||||
|
@ -981,13 +1005,9 @@ void CustomElementRegistry::SetElementCreationCallback(
|
|||
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();
|
||||
|
@ -1000,9 +1020,23 @@ void CustomElementRegistry::Upgrade(nsINode& aRoot) {
|
|||
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));
|
||||
|
|
|
@ -3547,21 +3547,21 @@ void Document::TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
|
|||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
|
@ -3581,7 +3581,7 @@ already_AddRefed<nsIPresShell> Document::CreateShell(
|
|||
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)
|
||||
|
@ -3704,7 +3704,7 @@ void Document::DeleteShell() {
|
|||
mStyleSetFilled = false;
|
||||
|
||||
ClearStaleServoData();
|
||||
AssertNoStaleServoDataIn(*this);
|
||||
AssertNoStaleServoDataIn(static_cast<nsINode&>(*this));
|
||||
}
|
||||
|
||||
void Document::SetBFCacheEntry(nsIBFCacheEntry* aEntry) {
|
||||
|
|
|
@ -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
|
|
@ -220,7 +220,6 @@ EXPORTS.mozilla.dom += [
|
|||
'ScreenLuminance.h',
|
||||
'ScreenOrientation.h',
|
||||
'Selection.h',
|
||||
'ShadowIncludingTreeIterator.h',
|
||||
'ShadowRoot.h',
|
||||
'StructuredCloneBlob.h',
|
||||
'StructuredCloneHolder.h',
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
#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"
|
||||
|
@ -2880,9 +2879,11 @@ void nsIPresShell::SlotAssignmentWillChange(Element& aElement,
|
|||
|
||||
#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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче