Bug 1118764 - Don't distribute anonymous root content in shadow DOM. r=bz
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -149,17 +149,18 @@ nsIContent::FindFirstNonChromeOnlyAccess
return nullptr;
}
nsIContent*
nsIContent::GetFlattenedTreeParent() const
{
nsIContent* parent = GetParent();
- if (nsContentUtils::HasDistributedChildren(parent)) {
+ if (parent && nsContentUtils::HasDistributedChildren(parent) &&
+ nsContentUtils::IsInSameAnonymousTree(parent, this)) {
// 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.
// It may be the case that |parent| distributes its children
// but the child does not match any insertion points, thus
// the flattened tree parent is nullptr.
nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ?
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -583,18 +583,22 @@ ShadowRoot::IsPooledNode(nsIContent* aCo
nsIContent* aHost)
{
if (nsContentUtils::IsContentInsertionPoint(aContent) ||
IsShadowInsertionPoint(aContent)) {
// Insertion points never end up in the pool.
return false;
}
- if (aContainer == aHost) {
- // Any other child nodes of the host will end up in the pool.
+ if (aContainer == aHost &&
+ nsContentUtils::IsInSameAnonymousTree(aContainer, aContent)) {
+ // Children of the host will end up in the pool. We check to ensure
+ // that the content is in the same anonymous tree as the container
+ // because anonymous content may report its container as the host
+ // but it may not be in the host's child list.
return true;
}
if (aContainer && aContainer->IsHTML(nsGkAtoms::content)) {
// Fallback content will end up in pool if its parent is a child of the host.
HTMLContentElement* content = static_cast<HTMLContentElement*>(aContainer);
return content->IsInsertionPoint() && content->MatchedNodes().IsEmpty() &&
aContainer->GetParentNode() == aHost;
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1118764.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<body>
+<style>
+#foo {
+ overflow: scroll;
+ height: 100px;
+}
+</style>
+<div id="foo">
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+Mozilla Firefox<br>
+<script>
+foo.createShadowRoot().innerHTML = "<content></content>";
+</script>
+</body>
+</html>
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -189,17 +189,17 @@ nsPlaceholderFrame::CanContinueTextRun()
return mOutOfFlowFrame->CanContinueTextRun();
}
nsStyleContext*
nsPlaceholderFrame::GetParentStyleContext(nsIFrame** aProviderFrame) const
{
NS_PRECONDITION(GetParent(), "How can we not have a parent here?");
- nsIContent* parentContent = mContent ? mContent->GetParent() : nullptr;
+ nsIContent* parentContent = mContent ? mContent->GetFlattenedTreeParent() : nullptr;
if (parentContent) {
nsStyleContext* sc =
PresContext()->FrameManager()->GetDisplayContentsStyleFor(parentContent);
if (sc) {
*aProviderFrame = nullptr;
return sc;
}
}