Bug 1818339 - Make AutoRangeArray set mAnchorFocusRange correctly r=m_kato

There are some paths which do not set `mAnchorFocusRange` correctly.
Therefore, even if its `RangeCount()` returns 1 or larger,
`GetAnchorFocusRange()` may return `nullptr`.

Differential Revision: https://phabricator.services.mozilla.com/D171045
This commit is contained in:
Masayuki Nakano 2023-02-28 00:46:17 +00:00
parent 3d617b7f9e
commit 31b7027bb9
2 changed files with 51 additions and 13 deletions

View file

@ -50,6 +50,7 @@ AutoRangeArray::AutoRangeArray(const AutoRangeArray& aOther)
RefPtr<nsRange> clonedRange = range->CloneRange(); RefPtr<nsRange> clonedRange = range->CloneRange();
mRanges.AppendElement(std::move(clonedRange)); mRanges.AppendElement(std::move(clonedRange));
} }
mAnchorFocusRange = aOther.mAnchorFocusRange;
} }
template <typename PointType> template <typename PointType>
@ -59,7 +60,8 @@ AutoRangeArray::AutoRangeArray(const EditorDOMRangeBase<PointType>& aRange) {
if (NS_WARN_IF(!range) || NS_WARN_IF(!range->IsPositioned())) { if (NS_WARN_IF(!range) || NS_WARN_IF(!range->IsPositioned())) {
return; return;
} }
mRanges.AppendElement(std::move(range)); mRanges.AppendElement(*range);
mAnchorFocusRange = std::move(range);
} }
template <typename PT, typename CT> template <typename PT, typename CT>
@ -69,7 +71,8 @@ AutoRangeArray::AutoRangeArray(const EditorDOMPointBase<PT, CT>& aPoint) {
if (NS_WARN_IF(!range) || NS_WARN_IF(!range->IsPositioned())) { if (NS_WARN_IF(!range) || NS_WARN_IF(!range->IsPositioned())) {
return; return;
} }
mRanges.AppendElement(std::move(range)); mRanges.AppendElement(*range);
mAnchorFocusRange = std::move(range);
} }
AutoRangeArray::~AutoRangeArray() { AutoRangeArray::~AutoRangeArray() {
@ -843,6 +846,13 @@ void AutoRangeArray::ExtendRangesToWrapLinesToHandleBlockLevelEditAction(
mRanges.RemoveElementAt(i); mRanges.RemoveElementAt(i);
} }
} }
if (!mAnchorFocusRange || !mAnchorFocusRange->IsPositioned()) {
if (mRanges.IsEmpty()) {
mAnchorFocusRange = nullptr;
} else {
mAnchorFocusRange = mRanges.LastElement();
}
}
} }
} }
@ -951,17 +961,22 @@ AutoRangeArray::SplitTextAtEndBoundariesAndInlineAncestorsAtBothBoundaries(
// FYI: The following code is originated in // FYI: The following code is originated in
// https://searchfox.org/mozilla-central/rev/c8e15e17bc6fd28f558c395c948a6251b38774ff/editor/libeditor/HTMLEditSubActionHandler.cpp#7023 // https://searchfox.org/mozilla-central/rev/c8e15e17bc6fd28f558c395c948a6251b38774ff/editor/libeditor/HTMLEditSubActionHandler.cpp#7023
nsTArray<OwningNonNull<RangeItem>> rangeItemArray; AutoTArray<OwningNonNull<RangeItem>, 8> rangeItemArray;
rangeItemArray.AppendElements(mRanges.Length()); rangeItemArray.AppendElements(mRanges.Length());
// First register ranges for special editor gravity // First register ranges for special editor gravity
for (OwningNonNull<RangeItem>& rangeItem : rangeItemArray) { Maybe<size_t> anchorFocusRangeIndex;
rangeItem = new RangeItem(); for (size_t index : IntegerRange(rangeItemArray.Length())) {
rangeItem->StoreRange(*mRanges[0]); rangeItemArray[index] = new RangeItem();
aHTMLEditor.RangeUpdaterRef().RegisterRangeItem(*rangeItem); rangeItemArray[index]->StoreRange(*mRanges[index]);
// TODO: We should keep the array, and just update the ranges. aHTMLEditor.RangeUpdaterRef().RegisterRangeItem(*rangeItemArray[index]);
mRanges.RemoveElementAt(0); if (mRanges[index] == mAnchorFocusRange) {
anchorFocusRangeIndex = Some(index);
}
} }
// TODO: We should keep the array, and just update the ranges.
mRanges.Clear();
mAnchorFocusRange = nullptr;
// Now bust up inlines. // Now bust up inlines.
nsresult rv = NS_OK; nsresult rv = NS_OK;
for (OwningNonNull<RangeItem>& item : Reversed(rangeItemArray)) { for (OwningNonNull<RangeItem>& item : Reversed(rangeItemArray)) {
@ -980,13 +995,19 @@ AutoRangeArray::SplitTextAtEndBoundariesAndInlineAncestorsAtBothBoundaries(
} }
} }
// Then unregister the ranges // Then unregister the ranges
for (OwningNonNull<RangeItem>& item : rangeItemArray) { for (size_t index : IntegerRange(rangeItemArray.Length())) {
aHTMLEditor.RangeUpdaterRef().DropRangeItem(item); aHTMLEditor.RangeUpdaterRef().DropRangeItem(rangeItemArray[index]);
RefPtr<nsRange> range = item->GetRange(); RefPtr<nsRange> range = rangeItemArray[index]->GetRange();
if (range) { if (range && range->IsPositioned()) {
if (anchorFocusRangeIndex.isSome() && index == *anchorFocusRangeIndex) {
mAnchorFocusRange = range;
}
mRanges.AppendElement(std::move(range)); mRanges.AppendElement(std::move(range));
} }
} }
if (!mAnchorFocusRange && !mRanges.IsEmpty()) {
mAnchorFocusRange = mRanges.LastElement();
}
// XXX Why do we ignore the other errors here?? // XXX Why do we ignore the other errors here??
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {

View file

@ -0,0 +1,17 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script>
addEventListener("load", () => {
const dialog = document.querySelector("dialog");
dialog.showModal();
dialog.close();
document.execCommand("justifyLeft");
document.execCommand("delete");
});
</script>
</head>
<body><dialog contenteditable>
</dialog></body>
</html>