summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2023-03-26 00:15:45 +0100
committerMoonchild <moonchild@palemoon.org>2023-03-26 00:15:45 +0100
commitecda3426e690bfb7734b1ca7c23cda9249a0472b (patch)
treec13b8d1aa2b7c25f1acd251b9eb717c40ef18c45 /layout
parent434379eb34335131bb44dfd229c06db42fcb208e (diff)
downloaduxp-ecda3426e690bfb7734b1ca7c23cda9249a0472b.tar.gz
Issue #2176 - Don't reconstruct the parent when tearing down
display:contents nodes with pseudo-elements. We need to use StyleChildrenIterator which iterates over them, instead. This is a bit of a hack but we can't always have our cake. We need to be a bit careful though, since ::before and ::after are owned by their own frame, and thus could be unbound from the tree or even dead after removing the frame. This basically ports bugs 1435566 and 1438467
Diffstat (limited to 'layout')
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp46
1 files changed, 16 insertions, 30 deletions
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index 8293e5198c..6a512891f9 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8137,26 +8137,10 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
"display:contents nodes shouldn't have a frame");
if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
- nsIContent* ancestor = aChild->GetFlattenedTreeParent();
- MOZ_ASSERT(ancestor, "display: contents on the root?");
- while (!ancestor->GetPrimaryFrame()) {
- ancestor = ancestor->GetFlattenedTreeParent();
- MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
- }
-
- nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
- if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) {
- *aDidReconstruct = true;
-
- // XXXmats Can we recreate frames only for the ::after/::before content?
- // XXX Perhaps even only those that belong to the aChild sub-tree?
- LAYOUT_PHASE_TEMP_EXIT();
- RecreateFramesForContent(ancestor, insertionKind, aFlags);
- LAYOUT_PHASE_TEMP_REENTER();
- return;
- }
-
- FlattenedChildIterator iter(aChild);
+ // NOTE(emilio): We may iterate through ::before and ::after here and they
+ // may be gone after the respective ContentRemoved call. Right now
+ // StyleChildrenIterator handles that properly, so it's not an issue.
+ StyleChildrenIterator iter(aChild);
for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) {
LAYOUT_PHASE_TEMP_EXIT();
@@ -8333,8 +8317,13 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.");
parentFrame = childFrame->GetParent();
}
+
RemoveFrame(nsLayoutUtils::GetChildListNameFor(childFrame), childFrame);
+ // NOTE(emilio): aChild could be dead here already if it is a ::before or
+ // ::after pseudo-element (since in that case it was owned by childFrame,
+ // which we just destroyed).
+
if (isRoot) {
mRootElementFrame = nullptr;
mRootElementStyleFrame = nullptr;
@@ -8354,8 +8343,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
// to do this if the table parent type of our parent type is not
// eTypeBlock, though, because in that case the whitespace isn't
// being suppressed due to us anyway.
- if (aContainer && !aChild->IsRootOfAnonymousSubtree() &&
- aFlags == REMOVE_CONTENT &&
+ if (aContainer && aOldNextSibling && aFlags == REMOVE_CONTENT &&
GetParentType(parentType) == eTypeBlock) {
// Adjacent whitespace-only text nodes might have been suppressed if
// this node does not have inline ends. Create frames for them now
@@ -8370,17 +8358,15 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
//
// FIXME(emilio): This should probably use the lazy frame construction
// bits if possible instead of reframing it in place.
- if (aOldNextSibling) {
- nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
- if (prevSibling && prevSibling->GetPreviousSibling()) {
- LAYOUT_PHASE_TEMP_EXIT();
- ReframeTextIfNeeded(aContainer, prevSibling);
- LAYOUT_PHASE_TEMP_REENTER();
- }
+ nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
+ if (prevSibling && prevSibling->GetPreviousSibling()) {
+ LAYOUT_PHASE_TEMP_EXIT();
+ ReframeTextIfNeeded(aContainer, prevSibling);
+ LAYOUT_PHASE_TEMP_REENTER();
}
// Reframe any text node just after the node being removed, if there is
// one, and if it's not the last child or the first child.
- if (aOldNextSibling && aOldNextSibling->GetNextSibling() &&
+ if (aOldNextSibling->GetNextSibling() &&
aOldNextSibling->GetPreviousSibling()) {
LAYOUT_PHASE_TEMP_EXIT();
ReframeTextIfNeeded(aContainer, aOldNextSibling);