Bug 1924195: Support multiple anchors with the same name. r=layout-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D247785
This commit is contained in:
Jari Jalkanen
2025-05-14 10:33:06 +00:00
committed by jjalkanen@mozilla.com
parent 93dad181f3
commit 03056ee940
2 changed files with 44 additions and 8 deletions

View File

@@ -11508,23 +11508,59 @@ nsIFrame* PresShell::GetAbsoluteContainingBlock(nsIFrame* aFrame) {
nsIFrame* PresShell::GetAnchorPosAnchor(const nsAtom* aName) const {
MOZ_ASSERT(aName);
if (auto entry = mAnchorPosAnchors.Lookup(aName)) {
return entry.Data();
if (const auto& entry = mAnchorPosAnchors.Lookup(aName)) {
return entry->SafeLastElement(nullptr);
}
return nullptr;
}
void PresShell::AddAnchorPosAnchor(const nsAtom* aName, nsIFrame* aFrame) {
MOZ_ASSERT(aName);
mAnchorPosAnchors.InsertOrUpdate(aName, aFrame);
auto& entry = mAnchorPosAnchors.LookupOrInsertWith(
aName, []() { return nsTArray<nsIFrame*>(); });
if (entry.IsEmpty()) {
entry.AppendElement(aFrame);
return;
}
struct FrameTreeComparator {
nsIFrame* mFrame;
constexpr int32_t operator()(nsIFrame* aOther) const {
return nsLayoutUtils::CompareTreePosition(aOther, mFrame, nullptr);
}
};
FrameTreeComparator cmp{aFrame};
size_t matchOrInsertionIdx = entry.Length();
// If the same element is already in the array,
// someone forgot to call RemoveAnchorPosAnchor.
if (BinarySearchIf(entry, 0, entry.Length(), cmp, &matchOrInsertionIdx)) {
MOZ_ASSERT_UNREACHABLE("Anchor added already");
return;
}
*entry.InsertElementAt(matchOrInsertionIdx) = aFrame;
}
void PresShell::RemoveAnchorPosAnchor(const nsAtom* aName, nsIFrame* aFrame) {
MOZ_ASSERT(aName);
if (auto entry = mAnchorPosAnchors.Lookup(aName)) {
if (entry.Data() == aFrame) {
entry.Remove();
}
auto entry = mAnchorPosAnchors.Lookup(aName);
if (!entry) {
return; // Nothing to remove.
}
auto& anchorArray = entry.Data();
MOZ_ASSERT(!anchorArray.IsEmpty());
MOZ_ASSERT(anchorArray.Contains(aFrame));
anchorArray.RemoveElement(aFrame);
if (anchorArray.IsEmpty()) {
entry.Remove();
}
}

View File

@@ -3029,7 +3029,7 @@ class PresShell final : public nsStubDocumentObserver,
// A hash table of heap allocated weak frames.
nsTHashSet<WeakFrame*> mWeakFrames;
nsTHashMap<RefPtr<const nsAtom>, nsIFrame*> mAnchorPosAnchors;
nsTHashMap<RefPtr<const nsAtom>, nsTArray<nsIFrame*>> mAnchorPosAnchors;
// Reflow roots that need to be reflowed.
DepthOrderedFrameList mDirtyRoots;