commit ea28b263ac2b83315a92b2af5111ab1edadd3193
parent 8c541f7253c0a4f15225401920e02a7822483120
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Mon, 10 Nov 2025 23:37:31 +0000
Bug 1998440 - Deal with having the same frame tree position in different frames. r=layout-reviewers,dholbert
Table cols are in a separate frame list and as the comment already said
CompareTreePosition doesn't deal with it (could be hard too).
Differential Revision: https://phabricator.services.mozilla.com/D271926
Diffstat:
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -11549,8 +11549,8 @@ const nsIFrame* PresShell::GetAnchorPosAnchor(
return nullptr;
}
-template <bool AreWeMerging>
-void PresShell::AddAnchorPosAnchorImpl(const nsAtom* aName, nsIFrame* aFrame) {
+void PresShell::AddAnchorPosAnchorImpl(const nsAtom* aName, nsIFrame* aFrame,
+ bool aForMerge) {
MOZ_ASSERT(aName);
auto& entry = mAnchorPosAnchors.LookupOrInsertWith(
@@ -11577,7 +11577,7 @@ void PresShell::AddAnchorPosAnchorImpl(const nsAtom* aName, nsIFrame* aFrame) {
if (BinarySearchIf(entry, 0, entry.Length(), cmp, &matchOrInsertionIdx)) {
if (entry.ElementAt(matchOrInsertionIdx) == aFrame) {
// nsLayoutUtils::CompareTreePosition() returns 0 when the frames are
- // in different documents or child lists. This indicates that
+ // in different documents or child lists. This could indicate that
// the tree is being restructured and we can defer anchor insertion
// to a MergeAnchorPosAnchors call after the restructuring is complete.
MOZ_ASSERT_UNREACHABLE("Attempt to insert a frame twice was made");
@@ -11585,27 +11585,23 @@ void PresShell::AddAnchorPosAnchorImpl(const nsAtom* aName, nsIFrame* aFrame) {
}
MOZ_ASSERT(!entry.Contains(aFrame));
- if constexpr (AreWeMerging) {
- MOZ_ASSERT_UNREACHABLE(
- "A frame may not be in a different child list at merge time");
- } else {
+ if (!aForMerge) {
// nsLayoutUtils::CompareTreePosition() returns 0 when the frames are
- // in different documents or child lists. This indicates that
+ // in different documents or child lists. This could indicate that
// the tree is being restructured and we can defer anchor insertion
// to a MergeAnchorPosAnchors call after the restructuring is complete.
mLazyAnchorPosAnchorChanges.AppendElement(
AnchorPosAnchorChange{RefPtr<const nsAtom>(aName), aFrame});
+ return;
}
-
- return;
}
MOZ_ASSERT(!entry.Contains(aFrame));
- *entry.InsertElementAt(matchOrInsertionIdx) = aFrame;
+ entry.InsertElementAt(matchOrInsertionIdx, aFrame);
}
void PresShell::AddAnchorPosAnchor(const nsAtom* aName, nsIFrame* aFrame) {
- AddAnchorPosAnchorImpl</* AreWeMerging */ false>(aName, aFrame);
+ AddAnchorPosAnchorImpl(aName, aFrame, /* aForMerge = */ false);
}
void PresShell::RemoveAnchorPosAnchor(const nsAtom* aName, nsIFrame* aFrame) {
@@ -11643,7 +11639,7 @@ void PresShell::RemoveAnchorPosAnchor(const nsAtom* aName, nsIFrame* aFrame) {
void PresShell::MergeAnchorPosAnchorChanges() {
for (const auto& [name, frame] : mLazyAnchorPosAnchorChanges) {
- AddAnchorPosAnchorImpl</* AreWeMerging */ true>(name, frame);
+ AddAnchorPosAnchorImpl(name, frame, /* aForMerge = */ true);
}
mLazyAnchorPosAnchorChanges.Clear();
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
@@ -1854,8 +1854,8 @@ class PresShell final : public nsStubDocumentObserver,
private:
~PresShell();
- template <bool AreWeMerging>
- void AddAnchorPosAnchorImpl(const nsAtom* aName, nsIFrame* aFrame);
+ void AddAnchorPosAnchorImpl(const nsAtom* aName, nsIFrame* aFrame,
+ bool aForMerge);
void SetIsActive(bool aIsActive);
bool ComputeActiveness() const;
diff --git a/testing/web-platform/tests/css/css-anchor-position/anchor-name-table-col-crash.html b/testing/web-platform/tests/css/css-anchor-position/anchor-name-table-col-crash.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugzil.la/1998440">
+<style>
+ * {
+ contain-intrinsic-size: auto none !important;
+ anchor-name: --anchor-name_0;
+ }
+</style>
+<script>
+ window.addEventListener("load", async () => {
+ const body = document.getElementById("id_3")
+ const table = document.createElement("table")
+ const tr = document.createElement("tr")
+ table.appendChild(tr)
+ const col = document.createElement("col")
+ table.appendChild(col)
+ body.appendChild(table)
+ })
+</script>
+<body id="id_3">
+<ol></ol>
+</body>