diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index edf9f9434cf5..269ded07f4ed 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -236,8 +236,11 @@ nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const } } - if (nsContentUtils::HasDistributedChildren(parent) && - nsContentUtils::IsInSameAnonymousTree(parent, this)) { + if (IsRootOfAnonymousSubtree()) { + return parent; + } + + if (nsContentUtils::HasDistributedChildren(parent)) { // This node is distributed to insertion points, thus we // need to consult the destination insertion points list to // figure out where this node was inserted in the flattened tree. @@ -245,20 +248,25 @@ nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const // but the child does not match any insertion points, thus // the flattened tree parent is nullptr. nsTArray* destInsertionPoints = GetExistingDestInsertionPoints(); - parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ? - destInsertionPoints->LastElement()->GetParent() : nullptr; + if (!destInsertionPoints || destInsertionPoints->IsEmpty()) { + return nullptr; + } + parent = destInsertionPoints->LastElement()->GetParent(); + MOZ_ASSERT(parent); } else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { if (nsIContent* insertionPoint = GetXBLInsertionPoint()) { parent = insertionPoint->GetParent(); MOZ_ASSERT(parent); } + } else if (parent->OwnerDoc()->BindingManager()->GetBindingWithContent(parent)) { + // This is fallback content not assigned to any insertion point. + return nullptr; } // Shadow roots never shows up in the flattened tree. Return the host // instead. - if (parent && parent->IsInShadowTree()) { - ShadowRoot* parentShadowRoot = ShadowRoot::FromNode(parent); - if (parentShadowRoot) { + if (parent->IsInShadowTree()) { + if (ShadowRoot* parentShadowRoot = ShadowRoot::FromNode(parent)) { return parentShadowRoot->GetHost(); } } diff --git a/dom/base/nsIContentInlines.h b/dom/base/nsIContentInlines.h index 36bb705f4c1d..006a83216d47 100644 --- a/dom/base/nsIContentInlines.h +++ b/dom/base/nsIContentInlines.h @@ -75,17 +75,21 @@ static inline bool FlattenedTreeParentIsParent(const nsINode* aNode) } // Check if we want the flattened parent for style, and the node is the root - // of a native anonymous content subtree parented to the document's root element. - if (Type == nsIContent::eForStyle && aNode->HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) && + // of a native anonymous content subtree parented to the document's root + // element. + if (Type == nsIContent::eForStyle && + aNode->HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) && aNode->OwnerDoc()->GetRootElement() == aNode->GetParentNode()) { return false; } - // Check if the node is an explicit child of an element with a shadow root, - // re-bound to an insertion point. + // Check if the node is an explicit child of an element with a shadow root or + // an element with an XBL binding, which may be re-bound to an insertion + // point, or not be bound to any, and thus won't appear on the flattened tree + // at all. nsIContent* parent = aNode->GetParent(); - if (parent && parent->GetShadowRoot()) { + if (parent && (parent->GetShadowRoot() || parent->GetXBLBinding())) { return false; } diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 28edf19dec3d..b8774c35b058 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7491,6 +7491,20 @@ nsCSSFrameConstructor::LazilyStyleNewChildRange(nsIContent* aStartChild, } } +static bool +IsFlattenedTreeChild(nsIContent* aParent, nsIContent* aChild) +{ + FlattenedChildIterator iter(aParent); + for (nsIContent* node = iter.GetNextChild(); + node; + node = iter.GetNextChild()) { + if (node == aChild) { + return true; + } + } + return false; +} + void nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild) @@ -7504,6 +7518,8 @@ nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild, // NB: Parent may be null if the content is appended to a shadow root, and // isn't assigned to any insertion point. if (MOZ_LIKELY(parent) && parent->HasServoData()) { + MOZ_ASSERT(IsFlattenedTreeChild(parent, child), + "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"); styleSet->StyleNewSubtree(child->AsElement()); } }