Bug 1887954 - Make nsIFrame::GetLastLeaf() never returns a frame in native anonymous subtrees under the given frame r=emilio

It does not check whether the child frame is in a native anonymous subtree
only when every first child at digging the frame tree.  This patch rewrites
the complicated loop with 2 for-loops and make it always check whether the
frame is for a native anonymous subtree root or not before updating the result.

Differential Revision: https://phabricator.services.mozilla.com/D206283
This commit is contained in:
Masayuki Nakano 2024-04-03 07:20:57 +00:00
parent 4818daad52
commit 9bfe998503
3 changed files with 47 additions and 15 deletions

View file

@ -10716,21 +10716,27 @@ ComputedStyle* nsIFrame::DoGetParentComputedStyle(
} }
void nsIFrame::GetLastLeaf(nsIFrame** aFrame) { void nsIFrame::GetLastLeaf(nsIFrame** aFrame) {
if (!aFrame || !*aFrame) return; if (!aFrame || !*aFrame) {
nsIFrame* child = *aFrame; return;
// if we are a block frame then go for the last line of 'this' }
while (1) { for (nsIFrame* maybeLastLeaf = (*aFrame)->PrincipalChildList().LastChild();
child = child->PrincipalChildList().FirstChild(); maybeLastLeaf;) {
if (!child) return; // nothing to do nsIFrame* lastChildNotInSubTree = nullptr;
nsIFrame* siblingFrame; for (nsIFrame* child = maybeLastLeaf; child;
nsIContent* content; child = child->GetPrevSibling()) {
// ignore anonymous elements, e.g. mozTableAdd* mozTableRemove* nsIContent* content = child->GetContent();
// see bug 278197 comment #12 #13 for details // ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
while ((siblingFrame = child->GetNextSibling()) && // see bug 278197 comment #12 #13 for details
(content = siblingFrame->GetContent()) && if (content && !content->IsRootOfNativeAnonymousSubtree()) {
!content->IsRootOfNativeAnonymousSubtree()) lastChildNotInSubTree = child;
child = siblingFrame; break;
*aFrame = child; }
}
if (!lastChildNotInSubTree) {
return;
}
*aFrame = lastChildNotInSubTree;
maybeLastLeaf = lastChildNotInSubTree->PrincipalChildList().LastChild();
} }
} }

View file

@ -3939,6 +3939,9 @@ class nsIFrame : public nsQueryFrame {
public: public:
// given a frame five me the first/last leaf available // given a frame five me the first/last leaf available
// XXX Robert O'Callahan wants to move these elsewhere // XXX Robert O'Callahan wants to move these elsewhere
// FIXME: Only GetLastLeaf() never returns a leaf frame in native anonymous
// subtrees under aFrame. However, GetFirstLeaf() may return a leaf frame
// in a native anonymous subtree.
static void GetLastLeaf(nsIFrame** aFrame); static void GetLastLeaf(nsIFrame** aFrame);
static void GetFirstLeaf(nsIFrame** aFrame); static void GetFirstLeaf(nsIFrame** aFrame);

View file

@ -0,0 +1,23 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script>
document.addEventListener("DOMContentLoaded", () => {
getSelection().addRange(document.createRange());
const range = document.createRange();
range.selectNode(document.querySelector("meter"));
getSelection().addRange(range);
getSelection().modify('move', 'left', 'line');
document.querySelector("input").style.display = "none";
getSelection().modify('move', 'left', 'lineboundary');
})
</script>
</head>
<body>
<input>
<div contenteditable>
<meter>
</div>
</body>
</html>