Bug 1765018 - part 4: Make EditorBase::InsertTextWithTransaction treat only EditorDOMPoint r=m_kato
In theory, methods which touch the DOM tree should take `EditorDOMPoint` rather than `EditorRawDOMPoint`. And now, we can return meaningful value if it succeeded, with `Result`. Therefore, this patch makes it return `Result<EditorDOMPoint, nsresult>` instead of taking an out argument, and take only `EditorDOMPoint` rather than taking any type of `EditorDOMPointBase` since it's always converted to `EditorDOMPoint`. Differential Revision: https://phabricator.services.mozilla.com/D143881
This commit is contained in:
@@ -2779,33 +2779,28 @@ EditorDOMPointType EditorBase::FindBetterInsertionPoint(
|
||||
return aPoint;
|
||||
}
|
||||
|
||||
nsresult EditorBase::InsertTextWithTransaction(
|
||||
Result<EditorDOMPoint, nsresult> EditorBase::InsertTextWithTransaction(
|
||||
Document& aDocument, const nsAString& aStringToInsert,
|
||||
const EditorRawDOMPoint& aPointToInsert,
|
||||
EditorRawDOMPoint* aPointAfterInsertedString) {
|
||||
const EditorDOMPoint& aPointToInsert) {
|
||||
MOZ_ASSERT(
|
||||
ShouldHandleIMEComposition() || !AllowsTransactionsToChangeSelection(),
|
||||
"caller must have already used AutoTransactionsConserveSelection "
|
||||
"if this is not for updating composition string");
|
||||
|
||||
if (NS_WARN_IF(!aPointToInsert.IsSet())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return Err(NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aPointToInsert.IsSetAndValid());
|
||||
|
||||
if (!ShouldHandleIMEComposition() && aStringToInsert.IsEmpty()) {
|
||||
if (aPointAfterInsertedString) {
|
||||
*aPointAfterInsertedString = aPointToInsert;
|
||||
}
|
||||
return NS_OK;
|
||||
return aPointToInsert;
|
||||
}
|
||||
|
||||
// In some cases, the node may be the anonymous div element or a padding
|
||||
// <br> element for empty last line. Let's try to look for better insertion
|
||||
// point in the nearest text node if there is.
|
||||
EditorDOMPoint pointToInsert =
|
||||
FindBetterInsertionPoint(aPointToInsert.To<EditorDOMPoint>());
|
||||
EditorDOMPoint pointToInsert = FindBetterInsertionPoint(aPointToInsert);
|
||||
|
||||
// If a neighboring text node already exists, use that
|
||||
if (!pointToInsert.IsInTextNode()) {
|
||||
@@ -2825,84 +2820,83 @@ nsresult EditorBase::InsertTextWithTransaction(
|
||||
if (!pointToInsert.IsInTextNode()) {
|
||||
// create a text node
|
||||
RefPtr<nsTextNode> newNode = CreateTextNode(u""_ns);
|
||||
if (NS_WARN_IF(!newNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!newNode))) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
// then we insert it into the dom tree
|
||||
nsresult rv = InsertNodeWithTransaction(*newNode, pointToInsert);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
|
||||
return rv;
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
|
||||
return Err(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
pointToInsert.Set(newNode, 0);
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
|
||||
return Err(rv);
|
||||
}
|
||||
pointToInsert.Set(newNode, 0u);
|
||||
newOffset = aStringToInsert.Length();
|
||||
} else {
|
||||
newOffset = aStringToInsert.Length();
|
||||
newOffset += pointToInsert.Offset();
|
||||
if (NS_WARN_IF(!newOffset.isValid())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!newOffset.isValid()))) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
nsresult rv = InsertTextIntoTextNodeWithTransaction(
|
||||
aStringToInsert, EditorDOMPointInText(pointToInsert.ContainerAsText(),
|
||||
pointToInsert.Offset()));
|
||||
if (NS_FAILED(rv)) {
|
||||
aStringToInsert, pointToInsert.AsInText());
|
||||
if (MOZ_UNLIKELY(Destroyed())) {
|
||||
NS_WARNING(
|
||||
"EditorBase::InsertTextIntoTextNodeWithTransaction() caused "
|
||||
"destroying the editor");
|
||||
return Err(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
NS_WARNING("EditorBase::InsertTextIntoTextNodeWithTransaction() failed");
|
||||
return rv;
|
||||
return Err(rv);
|
||||
}
|
||||
if (aPointAfterInsertedString) {
|
||||
aPointAfterInsertedString->Set(pointToInsert.GetContainer(),
|
||||
newOffset.value());
|
||||
NS_WARNING_ASSERTION(
|
||||
aPointAfterInsertedString->IsSetAndValid(),
|
||||
"Failed to set aPointAfterInsertedString, but ignored");
|
||||
}
|
||||
return NS_OK;
|
||||
return EditorDOMPoint(pointToInsert.GetContainer(), newOffset.value());
|
||||
}
|
||||
|
||||
if (pointToInsert.IsInTextNode()) {
|
||||
CheckedUint32 newOffset = aStringToInsert.Length();
|
||||
newOffset += pointToInsert.Offset();
|
||||
if (NS_WARN_IF(!newOffset.isValid())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!newOffset.isValid()))) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
// we are inserting text into an existing text node.
|
||||
nsresult rv = InsertTextIntoTextNodeWithTransaction(
|
||||
aStringToInsert, EditorDOMPointInText(pointToInsert.ContainerAsText(),
|
||||
pointToInsert.Offset()));
|
||||
if (NS_FAILED(rv)) {
|
||||
if (MOZ_UNLIKELY(Destroyed())) {
|
||||
NS_WARNING(
|
||||
"EditorBase::InsertTextIntoTextNodeWithTransaction() caused "
|
||||
"destroying the editor");
|
||||
return Err(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
NS_WARNING("EditorBase::InsertTextIntoTextNodeWithTransaction() failed");
|
||||
return rv;
|
||||
return Err(rv);
|
||||
}
|
||||
if (aPointAfterInsertedString) {
|
||||
aPointAfterInsertedString->Set(pointToInsert.GetContainer(),
|
||||
newOffset.value());
|
||||
NS_WARNING_ASSERTION(
|
||||
aPointAfterInsertedString->IsSetAndValid(),
|
||||
"Failed to set aPointAfterInsertedString, but ignored");
|
||||
}
|
||||
return NS_OK;
|
||||
return EditorDOMPoint(pointToInsert.GetContainer(), newOffset.value());
|
||||
}
|
||||
|
||||
// we are inserting text into a non-text node. first we have to create a
|
||||
// textnode (this also populates it with the text)
|
||||
RefPtr<nsTextNode> newNode = CreateTextNode(aStringToInsert);
|
||||
if (NS_WARN_IF(!newNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!newNode))) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
// then we insert it into the dom tree
|
||||
nsresult rv = InsertNodeWithTransaction(*newNode, pointToInsert);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (MOZ_UNLIKELY(Destroyed())) {
|
||||
NS_WARNING(
|
||||
"EditorBase::InsertNodeWithTransaction() caused destroying the editor");
|
||||
return Err(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
|
||||
return rv;
|
||||
return Err(rv);
|
||||
}
|
||||
if (aPointAfterInsertedString) {
|
||||
aPointAfterInsertedString->Set(newNode, aStringToInsert.Length());
|
||||
NS_WARNING_ASSERTION(
|
||||
aPointAfterInsertedString->IsSetAndValid(),
|
||||
"Failed to set aPointAfterInsertedString, but ignored");
|
||||
}
|
||||
return NS_OK;
|
||||
return EditorDOMPoint(newNode, aStringToInsert.Length());
|
||||
}
|
||||
|
||||
static bool TextFragmentBeginsWithStringAtOffset(
|
||||
|
||||
@@ -1642,21 +1642,17 @@ class EditorBase : public nsIEditor,
|
||||
*
|
||||
* @param aDocument The document of this editor.
|
||||
* @param aStringToInsert The string to insert.
|
||||
* @param aPointToInser The point to insert aStringToInsert.
|
||||
* @param aPointToInsert The point to insert aStringToInsert.
|
||||
* Must be valid DOM point.
|
||||
* @param aPointAfterInsertedString
|
||||
* The point after inserted aStringToInsert.
|
||||
* So, when this method actually inserts string,
|
||||
* this is set to a point in the text node.
|
||||
* Otherwise, this may be set to aPointToInsert.
|
||||
* @return When this succeeds to insert the string or
|
||||
* does nothing during composition, returns NS_OK.
|
||||
* Otherwise, an error code.
|
||||
* @return If succeeded, returns the point after inserted
|
||||
* aStringToInsert. So, when this method actually
|
||||
* inserts string, returns a point in the text node.
|
||||
* Otherwise, returns aPointToInsert.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT virtual nsresult InsertTextWithTransaction(
|
||||
Document& aDocument, const nsAString& aStringToInsert,
|
||||
const EditorRawDOMPoint& aPointToInsert,
|
||||
EditorRawDOMPoint* aPointAfterInsertedString = nullptr);
|
||||
[[nodiscard]] MOZ_CAN_RUN_SCRIPT virtual Result<EditorDOMPoint, nsresult>
|
||||
InsertTextWithTransaction(Document& aDocument,
|
||||
const nsAString& aStringToInsert,
|
||||
const EditorDOMPoint& aPointToInsert);
|
||||
|
||||
/**
|
||||
* InsertTextIntoTextNodeWithTransaction() inserts aStringToInsert into
|
||||
|
||||
@@ -1132,26 +1132,26 @@ EditActionResult HTMLEditor::HandleInsertText(
|
||||
|
||||
if (aEditSubAction == EditSubAction::eInsertTextComingFromIME) {
|
||||
auto compositionStartPoint =
|
||||
GetFirstIMESelectionStartPoint<EditorRawDOMPoint>();
|
||||
GetFirstIMESelectionStartPoint<EditorDOMPoint>();
|
||||
if (!compositionStartPoint.IsSet()) {
|
||||
compositionStartPoint = pointToInsert.To<EditorRawDOMPoint>();
|
||||
compositionStartPoint = pointToInsert;
|
||||
}
|
||||
|
||||
if (aInsertionString.IsEmpty()) {
|
||||
// Right now the WhiteSpaceVisibilityKeeper code bails on empty strings,
|
||||
// but IME needs the InsertTextWithTransaction() call to still happen
|
||||
// since empty strings are meaningful there.
|
||||
nsresult rv = InsertTextWithTransaction(*document, aInsertionString,
|
||||
compositionStartPoint);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, aInsertionString,
|
||||
compositionStartPoint);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("HTMLEditor::InsertTextWithTransaction() failed");
|
||||
return EditActionResult(insertTextResult.unwrapErr());
|
||||
}
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"HTMLEditor::InsertTextWithTransaction() failed");
|
||||
return EditActionHandled(rv);
|
||||
return EditActionHandled();
|
||||
}
|
||||
|
||||
auto compositionEndPoint = GetLastIMESelectionEndPoint<EditorRawDOMPoint>();
|
||||
auto compositionEndPoint = GetLastIMESelectionEndPoint<EditorDOMPoint>();
|
||||
if (!compositionEndPoint.IsSet()) {
|
||||
compositionEndPoint = compositionStartPoint;
|
||||
}
|
||||
@@ -1163,8 +1163,8 @@ EditActionResult HTMLEditor::HandleInsertText(
|
||||
return EditActionHandled(rv);
|
||||
}
|
||||
|
||||
compositionStartPoint = GetFirstIMESelectionStartPoint<EditorRawDOMPoint>();
|
||||
compositionEndPoint = GetLastIMESelectionEndPoint<EditorRawDOMPoint>();
|
||||
compositionStartPoint = GetFirstIMESelectionStartPoint<EditorDOMPoint>();
|
||||
compositionEndPoint = GetLastIMESelectionEndPoint<EditorDOMPoint>();
|
||||
if (NS_WARN_IF(!compositionStartPoint.IsSet()) ||
|
||||
NS_WARN_IF(!compositionEndPoint.IsSet())) {
|
||||
// Mutation event listener has changed the DOM tree...
|
||||
@@ -1256,19 +1256,14 @@ EditActionResult HTMLEditor::HandleInsertText(
|
||||
"to different point "
|
||||
"by mutation observer");
|
||||
} else {
|
||||
EditorRawDOMPoint pointAfterInsertedString;
|
||||
nsresult rv = InsertTextWithTransaction(
|
||||
*document, subStr, currentPoint.To<EditorRawDOMPoint>(),
|
||||
&pointAfterInsertedString);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, subStr, currentPoint);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("HTMLEditor::InsertTextWithTransaction() failed");
|
||||
return EditActionHandled(rv);
|
||||
return EditActionHandled(insertTextResult.unwrapErr());
|
||||
}
|
||||
currentPoint = pointAfterInsertedString.To<EditorDOMPoint>();
|
||||
pointToInsert = pointAfterInsertedString.To<EditorDOMPoint>();
|
||||
currentPoint = insertTextResult.inspect();
|
||||
pointToInsert = insertTextResult.unwrap();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -2097,13 +2092,13 @@ nsresult HTMLEditor::HandleInsertLinefeed(const EditorDOMPoint& aPointToBreak,
|
||||
{
|
||||
AutoTrackDOMPoint trackingInsertingPosition(RangeUpdaterRef(),
|
||||
&pointToInsert);
|
||||
nsresult rv = InsertTextWithTransaction(
|
||||
*document, u"\n"_ns, pointToInsert.To<EditorRawDOMPoint>(),
|
||||
&caretAfterInsert);
|
||||
if (NS_FAILED(rv)) {
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, u"\n"_ns, pointToInsert);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("HTMLEditor::InsertTextWithTransaction() failed");
|
||||
return rv;
|
||||
return insertTextResult.unwrapErr();
|
||||
}
|
||||
caretAfterInsert = insertTextResult.unwrap().To<EditorRawDOMPoint>();
|
||||
}
|
||||
|
||||
// Insert a padding <br> element at the end of the block element if there is
|
||||
|
||||
@@ -3492,14 +3492,14 @@ nsresult HTMLEditor::ReplaceTextWithTransaction(
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsresult rv = InsertTextWithTransaction(
|
||||
*document, aStringToInsert, EditorRawDOMPoint(&aTextNode, aOffset));
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, aStringToInsert,
|
||||
EditorDOMPoint(&aTextNode, aOffset));
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("HTMLEditor::InsertTextWithTransaction() failed");
|
||||
return insertTextResult.unwrapErr();
|
||||
}
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"HTMLEditor::InsertTextWithTransaction() failed");
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(aTextNode))) {
|
||||
@@ -3590,25 +3590,21 @@ nsresult HTMLEditor::ReplaceTextWithTransaction(
|
||||
return NS_WARN_IF(Destroyed()) ? NS_ERROR_EDITOR_DESTROYED : rv;
|
||||
}
|
||||
|
||||
nsresult HTMLEditor::InsertTextWithTransaction(
|
||||
Result<EditorDOMPoint, nsresult> HTMLEditor::InsertTextWithTransaction(
|
||||
Document& aDocument, const nsAString& aStringToInsert,
|
||||
const EditorRawDOMPoint& aPointToInsert,
|
||||
EditorRawDOMPoint* aPointAfterInsertedString) {
|
||||
const EditorDOMPoint& aPointToInsert) {
|
||||
if (NS_WARN_IF(!aPointToInsert.IsSet())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
return Err(NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
// Do nothing if the node is read-only
|
||||
if (NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(
|
||||
*aPointToInsert.GetContainer()))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(
|
||||
*aPointToInsert.GetContainer())))) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
nsresult rv = EditorBase::InsertTextWithTransaction(
|
||||
aDocument, aStringToInsert, aPointToInsert, aPointAfterInsertedString);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"EditorBase::InsertTextWithTransaction() failed");
|
||||
return rv;
|
||||
return EditorBase::InsertTextWithTransaction(aDocument, aStringToInsert,
|
||||
aPointToInsert);
|
||||
}
|
||||
|
||||
Result<EditorDOMPoint, nsresult> HTMLEditor::PrepareToInsertBRElement(
|
||||
|
||||
@@ -784,10 +784,10 @@ class HTMLEditor final : public EditorBase,
|
||||
/**
|
||||
* InsertTextWithTransaction() inserts aStringToInsert at aPointToInsert.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT nsresult InsertTextWithTransaction(
|
||||
Document& aDocument, const nsAString& aStringToInsert,
|
||||
const EditorRawDOMPoint& aPointToInsert,
|
||||
EditorRawDOMPoint* aPointAfterInsertedString = nullptr) final;
|
||||
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditorDOMPoint, nsresult>
|
||||
InsertTextWithTransaction(Document& aDocument,
|
||||
const nsAString& aStringToInsert,
|
||||
const EditorDOMPoint& aPointToInsert) final;
|
||||
|
||||
/**
|
||||
* CopyLastEditableChildStyles() clones inline container elements into
|
||||
|
||||
@@ -199,58 +199,50 @@ EditActionResult TextEditor::InsertLineFeedCharacterAtSelection() {
|
||||
}
|
||||
}
|
||||
|
||||
// get the (collapsed) selection location
|
||||
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return EditActionIgnored(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
EditorRawDOMPoint pointToInsert(firstRange->StartRef());
|
||||
if (NS_WARN_IF(!pointToInsert.IsSet())) {
|
||||
return EditActionIgnored(NS_ERROR_FAILURE);
|
||||
const auto pointToInsert = GetFirstSelectionStartPoint<EditorDOMPoint>();
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!pointToInsert.IsSet()))) {
|
||||
return EditActionResult(NS_ERROR_FAILURE);
|
||||
}
|
||||
MOZ_ASSERT(pointToInsert.IsSetAndValid());
|
||||
MOZ_ASSERT(!pointToInsert.IsContainerHTMLElement(nsGkAtoms::br));
|
||||
|
||||
RefPtr<Document> document = GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return EditActionIgnored(NS_ERROR_NOT_INITIALIZED);
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!document))) {
|
||||
return EditActionResult(NS_ERROR_NOT_INITIALIZED);
|
||||
}
|
||||
|
||||
// Don't change my selection in sub-transactions.
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// Insert a linefeed character.
|
||||
EditorRawDOMPoint pointAfterInsertedLineFeed;
|
||||
nsresult rv = InsertTextWithTransaction(*document, u"\n"_ns, pointToInsert,
|
||||
&pointAfterInsertedLineFeed);
|
||||
if (!pointAfterInsertedLineFeed.IsSet()) {
|
||||
NS_WARNING(
|
||||
"EditorBase::InsertTextWithTransaction(\\n) didn't return position of "
|
||||
"inserted linefeed");
|
||||
return EditActionIgnored(NS_ERROR_FAILURE);
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, u"\n"_ns, pointToInsert);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("TextEditor::InsertTextWithTransaction(\"\\n\") failed");
|
||||
return EditActionResult(insertTextResult.unwrapErr());
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("TextEditor::InsertTextWithTransaction(\\n) failed");
|
||||
return EditActionIgnored(rv);
|
||||
if (MOZ_UNLIKELY(!insertTextResult.inspect().IsSet())) {
|
||||
NS_WARNING(
|
||||
"EditorBase::InsertTextWithTransaction(\"\\n\") didn't return position "
|
||||
"of inserted linefeed");
|
||||
return EditActionHandled(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// set the selection to the correct location
|
||||
MOZ_ASSERT(
|
||||
!pointAfterInsertedLineFeed.GetChild(),
|
||||
"After inserting text into a text node, pointAfterInsertedLineFeed."
|
||||
"GetChild() should be nullptr");
|
||||
rv = CollapseSelectionTo(pointAfterInsertedLineFeed);
|
||||
MOZ_ASSERT(insertTextResult.inspect().IsInTextNode(),
|
||||
"After inserting text into a text node, insertTextResult should "
|
||||
"return a point in a text node");
|
||||
nsresult rv = CollapseSelectionTo(insertTextResult.inspect());
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
NS_WARNING("EditorBase::CollapseSelectionTo() failed");
|
||||
return EditActionIgnored(rv);
|
||||
return EditActionHandled(rv);
|
||||
}
|
||||
|
||||
// XXX I don't think we still need this. This must have been required when
|
||||
// `<textarea>` was implemented with text nodes and `<br>` elements.
|
||||
// see if we're at the end of the editor range
|
||||
const auto endPoint = GetFirstSelectionEndPoint<EditorRawDOMPoint>();
|
||||
if (endPoint == pointAfterInsertedLineFeed) {
|
||||
if (endPoint == insertTextResult.inspect()) {
|
||||
// SetInterlinePosition(true) means we want the caret to stick to the
|
||||
// content on the "right". We want the caret to stick to whatever is
|
||||
// past the break. This is because the break is on the same line we
|
||||
@@ -454,13 +446,8 @@ EditActionResult TextEditor::HandleInsertText(
|
||||
HandleNewLinesInStringForSingleLineEditor(insertionString);
|
||||
}
|
||||
|
||||
// get the (collapsed) selection location
|
||||
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return EditActionHandled(NS_ERROR_FAILURE);
|
||||
}
|
||||
EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
|
||||
if (NS_WARN_IF(!atStartOfSelection.IsSetAndValid())) {
|
||||
const auto atStartOfSelection = GetFirstSelectionStartPoint<EditorDOMPoint>();
|
||||
if (MOZ_UNLIKELY(NS_WARN_IF(!atStartOfSelection.IsSetAndValid()))) {
|
||||
return EditActionHandled(NS_ERROR_FAILURE);
|
||||
}
|
||||
MOZ_ASSERT(!atStartOfSelection.IsContainerHTMLElement(nsGkAtoms::br));
|
||||
@@ -471,22 +458,20 @@ EditActionResult TextEditor::HandleInsertText(
|
||||
}
|
||||
|
||||
if (aEditSubAction == EditSubAction::eInsertTextComingFromIME) {
|
||||
EditorRawDOMPoint compositionStartPoint =
|
||||
GetFirstIMESelectionStartPoint<EditorRawDOMPoint>();
|
||||
EditorDOMPoint compositionStartPoint =
|
||||
GetFirstIMESelectionStartPoint<EditorDOMPoint>();
|
||||
if (!compositionStartPoint.IsSet()) {
|
||||
compositionStartPoint = FindBetterInsertionPoint(atStartOfSelection);
|
||||
NS_WARNING_ASSERTION(
|
||||
compositionStartPoint.IsSet(),
|
||||
"EditorBase::FindBetterInsertionPoint() failed, but ignored");
|
||||
}
|
||||
nsresult rv = InsertTextWithTransaction(*document, insertionString,
|
||||
compositionStartPoint);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, insertionString,
|
||||
compositionStartPoint);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("EditorBase::InsertTextWithTransaction() failed");
|
||||
return EditActionHandled(rv);
|
||||
return EditActionResult(insertTextResult.unwrapErr());
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(aEditSubAction == EditSubAction::eInsertText);
|
||||
@@ -494,32 +479,30 @@ EditActionResult TextEditor::HandleInsertText(
|
||||
// don't change my selection in subtransactions
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
EditorRawDOMPoint pointAfterStringInserted;
|
||||
nsresult rv = InsertTextWithTransaction(*document, insertionString,
|
||||
atStartOfSelection,
|
||||
&pointAfterStringInserted);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
InsertTextWithTransaction(*document, insertionString,
|
||||
atStartOfSelection);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr())) {
|
||||
NS_WARNING("EditorBase::InsertTextWithTransaction() failed");
|
||||
return EditActionHandled(rv);
|
||||
return EditActionResult(insertTextResult.unwrapErr());
|
||||
}
|
||||
|
||||
if (pointAfterStringInserted.IsSet()) {
|
||||
if (insertTextResult.inspect().IsSet()) {
|
||||
// Make the caret attach to the inserted text, unless this text ends with
|
||||
// a LF, in which case make the caret attach to the next line.
|
||||
const bool endsWithLF =
|
||||
!insertionString.IsEmpty() && insertionString.Last() == nsCRT::LF;
|
||||
pointAfterStringInserted.SetInterlinePosition(
|
||||
EditorDOMPoint pointToPutCaret = insertTextResult.unwrap();
|
||||
pointToPutCaret.SetInterlinePosition(
|
||||
endsWithLF ? InterlinePosition::StartOfNextLine
|
||||
: InterlinePosition::EndOfLine);
|
||||
MOZ_ASSERT(
|
||||
!pointAfterStringInserted.GetChild(),
|
||||
"After inserting text into a text node, pointAfterStringInserted."
|
||||
"GetChild() should be nullptr");
|
||||
nsresult rv = CollapseSelectionTo(pointAfterStringInserted);
|
||||
MOZ_ASSERT(pointToPutCaret.IsInTextNode(),
|
||||
"After inserting text into a text node, insertTextResult "
|
||||
"should return a point in a text node");
|
||||
nsresult rv = CollapseSelectionTo(pointToPutCaret);
|
||||
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
|
||||
NS_WARNING(
|
||||
"EditorBase::CollapseSelectionTo() caused destroying the editor");
|
||||
return EditActionHandled(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
NS_WARNING_ASSERTION(
|
||||
|
||||
@@ -1203,13 +1203,19 @@ nsresult WhiteSpaceVisibilityKeeper::ReplaceText(
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
OwningNonNull<Document> document = *aHTMLEditor.GetDocument();
|
||||
nsresult rv = aHTMLEditor.InsertTextWithTransaction(
|
||||
document, theString, pointToInsert.To<EditorRawDOMPoint>(),
|
||||
aPointAfterInsertedString);
|
||||
if (NS_WARN_IF(aHTMLEditor.Destroyed())) {
|
||||
Result<EditorDOMPoint, nsresult> insertTextResult =
|
||||
aHTMLEditor.InsertTextWithTransaction(document, theString, pointToInsert);
|
||||
if (MOZ_UNLIKELY(insertTextResult.isErr() && insertTextResult.inspectErr() ==
|
||||
NS_ERROR_EDITOR_DESTROYED)) {
|
||||
NS_WARNING(
|
||||
"HTMLEditor::InsertTextWithTransaction() caused destroying the editor");
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (insertTextResult.isOk()) {
|
||||
if (aPointAfterInsertedString) {
|
||||
*aPointAfterInsertedString =
|
||||
insertTextResult.unwrap().To<EditorRawDOMPoint>();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user