Bug 1859245 - part 3: Make `JoinNodesTransaction` and `SplitNodeTransaction` handle only the new direction mode r=m_kato

Depends on D191606

Differential Revision: https://phabricator.services.mozilla.com/D191607
This commit is contained in:
Masayuki Nakano 2023-10-27 01:57:29 +00:00
Родитель 22a3483011
Коммит 982ddb7a9a
10 изменённых файлов: 41 добавлений и 148 удалений

Просмотреть файл

@ -6751,8 +6751,8 @@ void EditorBase::TopLevelEditSubActionData::WillDeleteContent(
}
void EditorBase::TopLevelEditSubActionData::DidSplitContent(
EditorBase& aEditorBase, nsIContent& aSplitContent, nsIContent& aNewContent,
SplitNodeDirection aSplitNodeDirection) {
EditorBase& aEditorBase, nsIContent& aSplitContent,
nsIContent& aNewContent) {
MOZ_ASSERT(aEditorBase.AsHTMLEditor());
if (!aEditorBase.mInitSucceeded || aEditorBase.Destroyed()) {
@ -6763,14 +6763,9 @@ void EditorBase::TopLevelEditSubActionData::DidSplitContent(
return; // Temporarily disabled by edit sub-action handler.
}
DebugOnly<nsresult> rvIgnored =
aSplitNodeDirection == SplitNodeDirection::LeftNodeIsNewOne
? AddRangeToChangedRange(*aEditorBase.AsHTMLEditor(),
EditorRawDOMPoint(&aNewContent, 0),
EditorRawDOMPoint(&aSplitContent, 0))
: AddRangeToChangedRange(*aEditorBase.AsHTMLEditor(),
EditorRawDOMPoint::AtEndOf(aSplitContent),
EditorRawDOMPoint::AtEndOf(aNewContent));
DebugOnly<nsresult> rvIgnored = AddRangeToChangedRange(
*aEditorBase.AsHTMLEditor(), EditorRawDOMPoint::AtEndOf(aSplitContent),
EditorRawDOMPoint::AtEndOf(aNewContent));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"TopLevelEditSubActionData::AddRangeToChangedRange() "
"failed, but ignored");

Просмотреть файл

@ -849,8 +849,7 @@ class EditorBase : public nsIEditor,
void WillDeleteContent(EditorBase& aEditorBase,
nsIContent& aRemovingContent);
void DidSplitContent(EditorBase& aEditorBase, nsIContent& aSplitContent,
nsIContent& aNewContent,
SplitNodeDirection aSplitNodeDirection);
nsIContent& aNewContent);
void DidJoinContents(EditorBase& aEditorBase,
const EditorRawDOMPoint& aJoinedPoint);
void DidInsertText(EditorBase& aEditorBase,

Просмотреть файл

@ -5109,8 +5109,8 @@ Result<SplitNodeResult, nsresult> HTMLEditor::SplitNodeWithTransaction(
if (NS_WARN_IF(!newContent) || NS_WARN_IF(!splitContent)) {
return Err(NS_ERROR_FAILURE);
}
TopLevelEditSubActionDataRef().DidSplitContent(
*this, *splitContent, *newContent, transaction->GetSplitNodeDirection());
TopLevelEditSubActionDataRef().DidSplitContent(*this, *splitContent,
*newContent);
if (NS_WARN_IF(!newContent->IsInComposedDoc()) ||
NS_WARN_IF(!splitContent->IsInComposedDoc())) {
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
@ -5554,8 +5554,7 @@ void HTMLEditor::DidJoinNodesTransaction(
mTextServicesDocument) {
textServicesDocument->DidJoinContents(
aTransaction.CreateJoinedPoint<EditorRawDOMPoint>(),
*aTransaction.GetRemovedContent(),
aTransaction.GetJoinNodesDirection());
*aTransaction.GetRemovedContent());
}
}
@ -5563,9 +5562,7 @@ void HTMLEditor::DidJoinNodesTransaction(
for (auto& listener : mActionListeners.Clone()) {
DebugOnly<nsresult> rvIgnored = listener->DidJoinContents(
aTransaction.CreateJoinedPoint<EditorRawDOMPoint>(),
aTransaction.GetRemovedContent(),
aTransaction.GetJoinNodesDirection() ==
JoinNodesDirection::LeftNodeIntoRightNode);
aTransaction.GetRemovedContent());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidJoinContents() failed, but ignored");

Просмотреть файл

@ -5,10 +5,9 @@
#include "JoinNodesTransaction.h"
#include "EditorDOMPoint.h" // for EditorDOMPoint, etc.
#include "HTMLEditHelpers.h" // for SplitNodeResult
#include "JoinSplitNodeDirection.h" // JoinNodesDirection
#include "HTMLEditor.h" // for HTMLEditor
#include "EditorDOMPoint.h" // for EditorDOMPoint, etc.
#include "HTMLEditHelpers.h" // for SplitNodeResult
#include "HTMLEditor.h" // for HTMLEditor
#include "HTMLEditorInlines.h"
#include "HTMLEditUtils.h"
@ -42,14 +41,8 @@ JoinNodesTransaction::JoinNodesTransaction(HTMLEditor& aHTMLEditor,
nsIContent& aLeftContent,
nsIContent& aRightContent)
: mHTMLEditor(&aHTMLEditor),
mRemovedContent(aHTMLEditor.GetJoinNodesDirection() ==
JoinNodesDirection::LeftNodeIntoRightNode
? &aLeftContent
: &aRightContent),
mKeepingContent(aHTMLEditor.GetJoinNodesDirection() ==
JoinNodesDirection::LeftNodeIntoRightNode
? &aRightContent
: &aLeftContent) {
mRemovedContent(&aRightContent),
mKeepingContent(&aLeftContent) {
// printf("JoinNodesTransaction size: %zu\n", sizeof(JoinNodesTransaction));
static_assert(sizeof(JoinNodesTransaction) <= 64,
"Transaction classes may be created a lot and may be alive "
@ -71,9 +64,7 @@ std::ostream& operator<<(std::ostream& aStream,
aStream << " (" << *aTransaction.mKeepingContent << ")";
}
aStream << ", mJoinedOffset=" << aTransaction.mJoinedOffset
<< ", mHTMLEditor=" << aTransaction.mHTMLEditor.get()
<< ", GetJoinNodesDirection()="
<< aTransaction.GetJoinNodesDirection() << " }";
<< ", mHTMLEditor=" << aTransaction.mHTMLEditor.get() << " }";
return aStream;
}
@ -84,16 +75,6 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodesTransaction, EditTransactionBase,
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinNodesTransaction)
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
SplitNodeDirection JoinNodesTransaction::GetSplitNodeDirection() const {
return MOZ_LIKELY(mHTMLEditor) ? mHTMLEditor->GetSplitNodeDirection()
: SplitNodeDirection::LeftNodeIsNewOne;
}
JoinNodesDirection JoinNodesTransaction::GetJoinNodesDirection() const {
return MOZ_LIKELY(mHTMLEditor) ? mHTMLEditor->GetJoinNodesDirection()
: JoinNodesDirection::LeftNodeIntoRightNode;
}
bool JoinNodesTransaction::CanDoIt() const {
if (NS_WARN_IF(!mKeepingContent) || NS_WARN_IF(!mRemovedContent) ||
NS_WARN_IF(!mHTMLEditor) ||
@ -140,22 +121,16 @@ nsresult JoinNodesTransaction::DoTransactionInternal(
// For now, setting mJoinedOffset to removed content length so that
// CreateJoinedPoint returns a point in mKeepingContent whose offset is
// the result if all content in mRemovedContent are moved to start or end of
// mKeepingContent without any intervation. The offset will be adjusted
// mKeepingContent without any intervention. The offset will be adjusted
// below.
mJoinedOffset =
GetJoinNodesDirection() == JoinNodesDirection::LeftNodeIntoRightNode
? mRemovedContent->Length()
: mKeepingContent->Length();
mJoinedOffset = mKeepingContent->Length();
const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
const OwningNonNull<nsIContent> removingContent = *mRemovedContent;
const OwningNonNull<nsIContent> keepingContent = *mKeepingContent;
nsresult rv;
// Let's try to get actual joined point with the tacker.
EditorDOMPoint joinNodesPoint =
GetJoinNodesDirection() == JoinNodesDirection::LeftNodeIntoRightNode
? EditorDOMPoint(keepingContent, 0u)
: EditorDOMPoint::AtEndOf(keepingContent);
auto joinNodesPoint = EditorDOMPoint::AtEndOf(keepingContent);
{
AutoTrackDOMPoint trackJoinNodePoint(htmlEditor->RangeUpdaterRef(),
&joinNodesPoint);

Просмотреть файл

@ -60,11 +60,6 @@ class JoinNodesTransaction final : public EditTransactionBase {
MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override;
// Note that we don't support join/split node direction switching per
// transaction.
[[nodiscard]] SplitNodeDirection GetSplitNodeDirection() const;
[[nodiscard]] JoinNodesDirection GetJoinNodesDirection() const;
/**
* GetExistingContent() and GetRemovedContent() never returns nullptr
* unless the cycle collector clears them out.

Просмотреть файл

@ -10,8 +10,7 @@
#include "HTMLEditor.h" // for HTMLEditor
#include "HTMLEditorInlines.h"
#include "HTMLEditUtils.h"
#include "JoinSplitNodeDirection.h" // for SplitNodeDirection
#include "SelectionState.h" // for AutoTrackDOMPoint and RangeUpdater
#include "SelectionState.h" // for AutoTrackDOMPoint and RangeUpdater
#include "mozilla/Logging.h"
#include "mozilla/Maybe.h"
@ -71,9 +70,7 @@ std::ostream& operator<<(std::ostream& aStream,
aStream << " (" << *aTransaction.mSplitContent << ")";
}
aStream << ", mSplitOffset=" << aTransaction.mSplitOffset
<< ", mHTMLEditor=" << aTransaction.mHTMLEditor.get()
<< ", GetSplitNodeDirection()="
<< aTransaction.GetSplitNodeDirection() << " }";
<< ", mHTMLEditor=" << aTransaction.mHTMLEditor.get() << " }";
return aStream;
}
@ -86,16 +83,6 @@ NS_IMPL_RELEASE_INHERITED(SplitNodeTransaction, EditTransactionBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SplitNodeTransaction)
NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
SplitNodeDirection SplitNodeTransaction::GetSplitNodeDirection() const {
return MOZ_LIKELY(mHTMLEditor) ? mHTMLEditor->GetSplitNodeDirection()
: SplitNodeDirection::LeftNodeIsNewOne;
}
JoinNodesDirection SplitNodeTransaction::GetJoinNodesDirection() const {
return MOZ_LIKELY(mHTMLEditor) ? mHTMLEditor->GetJoinNodesDirection()
: JoinNodesDirection::LeftNodeIntoRightNode;
}
NS_IMETHODIMP SplitNodeTransaction::DoTransaction() {
MOZ_LOG(GetLogModule(), LogLevel::Info,
("%p SplitNodeTransaction::%s this=%s", this, __FUNCTION__,
@ -183,20 +170,12 @@ NS_IMETHODIMP SplitNodeTransaction::UndoTransaction() {
const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
const OwningNonNull<nsIContent> keepingContent = *mSplitContent;
const OwningNonNull<nsIContent> removingContent = *mNewContent;
nsresult rv;
EditorDOMPoint joinedPoint;
{
// Unfortunately, we cannot track joining point if moving right node content
// into left node since it cannot track changes from web apps and HTMLEditor
// never removes the content of the left node. So it should be true that
// we don't need to track the point in the direction.
Maybe<AutoTrackDOMPoint> trackJoinedPoint;
if (GetJoinNodesDirection() == JoinNodesDirection::LeftNodeIntoRightNode) {
joinedPoint.Set(keepingContent, 0u);
trackJoinedPoint.emplace(htmlEditor->RangeUpdaterRef(), &joinedPoint);
}
rv = htmlEditor->DoJoinNodes(keepingContent, removingContent);
}
// Unfortunately, we cannot track joining point if moving right node content
// into left node since it cannot track changes from web apps and HTMLEditor
// never removes the content of the left node. So it should be true that
// we don't need to track the point in this case.
nsresult rv = htmlEditor->DoJoinNodes(keepingContent, removingContent);
if (NS_SUCCEEDED(rv)) {
// Adjust split offset for redo here
if (joinedPoint.IsSet()) {

Просмотреть файл

@ -53,11 +53,6 @@ class SplitNodeTransaction final : public EditTransactionBase {
MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override;
// Note that we don't support join/split node direction switching per
// transaction.
[[nodiscard]] SplitNodeDirection GetSplitNodeDirection() const;
[[nodiscard]] JoinNodesDirection GetJoinNodesDirection() const;
nsIContent* GetSplitContent() const { return mSplitContent; }
nsIContent* GetNewContent() const { return mNewContent; }
nsINode* GetParentNode() const { return mParentNode; }

Просмотреть файл

@ -50,16 +50,10 @@ interface nsIEditActionListener : nsISupports
* right node. Otherwise, it points start of inserted
* right node content in the left node.
* @param aRemovedNode The removed node.
* @param aLeftNodeWasRemoved
* true if left node is removed and its contents were
* moved into start of the right node.
* false if right node is removed and its contents were
* moved into end of the left node.
*/
[noscript]
void DidJoinContents([const] in EditorRawDOMPointRef aJoinedPoint,
[const] in Node aRemovedNode,
in bool aLeftNodeWasRemoved);
[const] in Node aRemovedNode);
/**
* Called after the editor inserts text.

Просмотреть файл

@ -10,7 +10,6 @@
#include "FilteredContentIterator.h" // for FilteredContentIterator
#include "HTMLEditHelpers.h" // for BlockInlineCheck
#include "HTMLEditUtils.h" // for HTMLEditUtils
#include "JoinSplitNodeDirection.h" // for JoinNodesDirection
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/IntegerRange.h" // for IntegerRange
@ -1338,8 +1337,7 @@ void TextServicesDocument::DidDeleteContent(const nsIContent& aChildContent) {
}
void TextServicesDocument::DidJoinContents(
const EditorRawDOMPoint& aJoinedPoint, const nsIContent& aRemovedContent,
JoinNodesDirection aJoinNodesDirection) {
const EditorRawDOMPoint& aJoinedPoint, const nsIContent& aRemovedContent) {
// Make sure that both nodes are text nodes -- otherwise we don't care.
if (!aJoinedPoint.IsInTextNode() || !aRemovedContent.IsText()) {
return;
@ -1367,30 +1365,19 @@ void TextServicesDocument::DidJoinContents(
const size_t removedIndex = *maybeRemovedIndex;
const size_t joinedIndex = *maybeJoinedIndex;
if (aJoinNodesDirection == JoinNodesDirection::LeftNodeIntoRightNode) {
if (MOZ_UNLIKELY(removedIndex > joinedIndex)) {
NS_ASSERTION(removedIndex < joinedIndex, "Indexes out of order.");
return;
}
NS_ASSERTION(mOffsetTable[joinedIndex]->mOffsetInTextNode == 0,
"Unexpected offset value for joinedIndex.");
} else {
if (MOZ_UNLIKELY(joinedIndex > removedIndex)) {
NS_ASSERTION(joinedIndex < removedIndex, "Indexes out of order.");
return;
}
NS_ASSERTION(mOffsetTable[removedIndex]->mOffsetInTextNode == 0,
"Unexpected offset value for rightIndex.");
if (MOZ_UNLIKELY(joinedIndex > removedIndex)) {
NS_ASSERTION(joinedIndex < removedIndex, "Indexes out of order.");
return;
}
NS_ASSERTION(mOffsetTable[removedIndex]->mOffsetInTextNode == 0,
"Unexpected offset value for rightIndex.");
// Run through the table and change all entries referring to
// the removed node so that they now refer to the joined node,
// and adjust offsets if necessary.
const uint32_t movedTextDataLength =
aJoinNodesDirection == JoinNodesDirection::LeftNodeIntoRightNode
? aJoinedPoint.Offset()
: aJoinedPoint.ContainerAs<Text>()->TextDataLength() -
aJoinedPoint.Offset();
aJoinedPoint.ContainerAs<Text>()->TextDataLength() -
aJoinedPoint.Offset();
for (uint32_t i = removedIndex; i < mOffsetTable.Length(); i++) {
const UniquePtr<OffsetEntry>& entry = mOffsetTable[i];
LockOffsetEntryArrayLengthInDebugBuild(observer, mOffsetTable);
@ -1399,26 +1386,9 @@ void TextServicesDocument::DidJoinContents(
}
if (entry->mIsValid) {
entry->mTextNode = aJoinedPoint.ContainerAs<Text>();
if (aJoinNodesDirection == JoinNodesDirection::RightNodeIntoLeftNode) {
// The text was moved from aRemovedContent to end of the container of
// aJoinedPoint.
entry->mOffsetInTextNode += movedTextDataLength;
}
}
}
if (aJoinNodesDirection == JoinNodesDirection::LeftNodeIntoRightNode) {
// The text was moved from aRemovedContent to start of the container of
// aJoinedPoint.
for (uint32_t i = joinedIndex; i < mOffsetTable.Length(); i++) {
const UniquePtr<OffsetEntry>& entry = mOffsetTable[i];
LockOffsetEntryArrayLengthInDebugBuild(observer, mOffsetTable);
if (entry->mTextNode != aJoinedPoint.ContainerAs<Text>()) {
break;
}
if (entry->mIsValid) {
entry->mOffsetInTextNode += movedTextDataLength;
}
// The text was moved from aRemovedContent to end of the container of
// aJoinedPoint.
entry->mOffsetInTextNode += movedTextDataLength;
}
}
@ -2784,16 +2754,12 @@ TextServicesDocument::DidDeleteNode(nsINode* aChild, nsresult aResult) {
}
NS_IMETHODIMP TextServicesDocument::DidJoinContents(
const EditorRawDOMPoint& aJoinedPoint, const nsINode* aRemovedNode,
bool aLeftNodeWasRemoved) {
const EditorRawDOMPoint& aJoinedPoint, const nsINode* aRemovedNode) {
if (MOZ_UNLIKELY(NS_WARN_IF(!aJoinedPoint.IsSetAndValid()) ||
NS_WARN_IF(!aRemovedNode->IsContent()))) {
return NS_OK;
}
DidJoinContents(aJoinedPoint, *aRemovedNode->AsContent(),
aLeftNodeWasRemoved
? JoinNodesDirection::LeftNodeIntoRightNode
: JoinNodesDirection::RightNodeIntoLeftNode);
DidJoinContents(aJoinedPoint, *aRemovedNode->AsContent());
return NS_OK;
}

Просмотреть файл

@ -27,7 +27,6 @@ namespace mozilla {
class EditorBase;
class FilteredContentIterator;
class OffsetEntry;
enum class JoinNodesDirection; // Declared in HTMLEditHelpers.h
namespace dom {
class AbstractRange;
@ -374,8 +373,7 @@ class TextServicesDocument final : public nsIEditActionListener {
*/
void DidDeleteContent(const nsIContent& aChildContent);
void DidJoinContents(const EditorRawDOMPoint& aJoinedPoint,
const nsIContent& aRemovedContent,
JoinNodesDirection aJoinNodesDirection);
const nsIContent& aRemovedContent);
private:
// TODO: We should get rid of this method since `aAbstractRange` has