Bug 1791224 - Use CreateNodeResultBase as the ok type of mozilla::Result r=m_kato

Similar to the previous patch, this changes a lot of lines.  However, I think
that it's not so hard to investigate regression point in this patch because
`CreateNodeResultBase` is not used so many times at handling on edit action.

Differential Revision: https://phabricator.services.mozilla.com/D157575
This commit is contained in:
Masayuki Nakano 2022-09-27 05:12:05 +00:00
parent 4e978b56b5
commit 6513faf43f
13 changed files with 1125 additions and 953 deletions

View file

@ -149,12 +149,15 @@ template EditorRawDOMPoint EditorBase::GetFirstIMESelectionStartPoint() const;
template EditorDOMPoint EditorBase::GetLastIMESelectionEndPoint() const; template EditorDOMPoint EditorBase::GetLastIMESelectionEndPoint() const;
template EditorRawDOMPoint EditorBase::GetLastIMESelectionEndPoint() const; template EditorRawDOMPoint EditorBase::GetLastIMESelectionEndPoint() const;
template CreateContentResult EditorBase::InsertNodeWithTransaction( template Result<CreateContentResult, nsresult>
nsIContent& aContentToInsert, const EditorDOMPoint& aPointToInsert); EditorBase::InsertNodeWithTransaction(nsIContent& aContentToInsert,
template CreateElementResult EditorBase::InsertNodeWithTransaction( const EditorDOMPoint& aPointToInsert);
Element& aContentToInsert, const EditorDOMPoint& aPointToInsert); template Result<CreateElementResult, nsresult>
template CreateTextResult EditorBase::InsertNodeWithTransaction( EditorBase::InsertNodeWithTransaction(Element& aContentToInsert,
Text& aContentToInsert, const EditorDOMPoint& aPointToInsert); const EditorDOMPoint& aPointToInsert);
template Result<CreateTextResult, nsresult>
EditorBase::InsertNodeWithTransaction(Text& aContentToInsert,
const EditorDOMPoint& aPointToInsert);
template EditorDOMPoint EditorBase::GetFirstSelectionStartPoint() const; template EditorDOMPoint EditorBase::GetFirstSelectionStartPoint() const;
template EditorRawDOMPoint EditorBase::GetFirstSelectionStartPoint() const; template EditorRawDOMPoint EditorBase::GetFirstSelectionStartPoint() const;
@ -1964,13 +1967,14 @@ NS_IMETHODIMP EditorBase::InsertNode(nsINode* aNodeToInsert,
} }
const uint32_t offset = std::min(aOffset, aContainer->Length()); const uint32_t offset = std::min(aOffset, aContainer->Length());
CreateContentResult insertContentResult = InsertNodeWithTransaction( Result<CreateContentResult, nsresult> insertContentResult =
*contentToInsert, EditorDOMPoint(aContainer, offset)); InsertNodeWithTransaction(*contentToInsert,
if (insertContentResult.isErr()) { EditorDOMPoint(aContainer, offset));
if (MOZ_UNLIKELY(insertContentResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return EditorBase::ToGenericNSResult(insertContentResult.unwrapErr()); return EditorBase::ToGenericNSResult(insertContentResult.unwrapErr());
} }
rv = insertContentResult.SuggestCaretPointTo( rv = insertContentResult.inspect().SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion, *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});
@ -1985,15 +1989,14 @@ NS_IMETHODIMP EditorBase::InsertNode(nsINode* aNodeToInsert,
} }
template <typename ContentNodeType> template <typename ContentNodeType>
CreateNodeResultBase<ContentNodeType> EditorBase::InsertNodeWithTransaction( Result<CreateNodeResultBase<ContentNodeType>, nsresult>
ContentNodeType& aContentToInsert, const EditorDOMPoint& aPointToInsert) { EditorBase::InsertNodeWithTransaction(ContentNodeType& aContentToInsert,
const EditorDOMPoint& aPointToInsert) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT_IF(IsTextEditor(), !aContentToInsert.IsText()); MOZ_ASSERT_IF(IsTextEditor(), !aContentToInsert.IsText());
using ResultType = CreateNodeResultBase<ContentNodeType>;
if (NS_WARN_IF(!aPointToInsert.IsSet())) { if (NS_WARN_IF(!aPointToInsert.IsSet())) {
return ResultType(NS_ERROR_INVALID_ARG); return Err(NS_ERROR_INVALID_ARG);
} }
MOZ_ASSERT(aPointToInsert.IsSetAndValid()); MOZ_ASSERT(aPointToInsert.IsSetAndValid());
@ -2001,7 +2004,7 @@ CreateNodeResultBase<ContentNodeType> EditorBase::InsertNodeWithTransaction(
AutoEditSubActionNotifier startToHandleEditSubAction( AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eInsertNode, nsIEditor::eNext, ignoredError); *this, EditSubAction::eInsertNode, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) { if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ResultType(ignoredError.StealNSResult()); return Err(ignoredError.StealNSResult());
} }
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
!ignoredError.Failed(), !ignoredError.Failed(),
@ -2023,24 +2026,24 @@ CreateNodeResultBase<ContentNodeType> EditorBase::InsertNodeWithTransaction(
} }
if (NS_WARN_IF(Destroyed())) { if (NS_WARN_IF(Destroyed())) {
return ResultType(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return ResultType(rv); return Err(rv);
} }
return ResultType(&aContentToInsert, return CreateNodeResultBase<ContentNodeType>(
transaction->SuggestPointToPutCaret<EditorDOMPoint>()); &aContentToInsert, transaction->SuggestPointToPutCaret<EditorDOMPoint>());
} }
CreateElementResult Result<CreateElementResult, nsresult>
EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction( EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(
const EditorDOMPoint& aPointToInsert) { const EditorDOMPoint& aPointToInsert) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(IsHTMLEditor() || !aPointToInsert.IsInTextNode()); MOZ_ASSERT(IsHTMLEditor() || !aPointToInsert.IsInTextNode());
if (MOZ_UNLIKELY(!aPointToInsert.IsSet())) { if (MOZ_UNLIKELY(!aPointToInsert.IsSet())) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
EditorDOMPoint pointToInsert; EditorDOMPoint pointToInsert;
@ -2050,7 +2053,7 @@ EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(
Result<EditorDOMPoint, nsresult> maybePointToInsert = Result<EditorDOMPoint, nsresult> maybePointToInsert =
MOZ_KnownLive(AsHTMLEditor())->PrepareToInsertBRElement(aPointToInsert); MOZ_KnownLive(AsHTMLEditor())->PrepareToInsertBRElement(aPointToInsert);
if (maybePointToInsert.isErr()) { if (maybePointToInsert.isErr()) {
return CreateElementResult(maybePointToInsert.unwrapErr()); return maybePointToInsert.propagateErr();
} }
MOZ_ASSERT(maybePointToInsert.inspect().IsSetAndValid()); MOZ_ASSERT(maybePointToInsert.inspect().IsSetAndValid());
pointToInsert = maybePointToInsert.unwrap(); pointToInsert = maybePointToInsert.unwrap();
@ -2058,11 +2061,11 @@ EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(
RefPtr<Element> newBRElement = CreateHTMLContent(nsGkAtoms::br); RefPtr<Element> newBRElement = CreateHTMLContent(nsGkAtoms::br);
if (NS_WARN_IF(!newBRElement)) { if (NS_WARN_IF(!newBRElement)) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
newBRElement->SetFlags(NS_PADDING_FOR_EMPTY_LAST_LINE); newBRElement->SetFlags(NS_PADDING_FOR_EMPTY_LAST_LINE);
CreateElementResult insertBRElementResult = Result<CreateElementResult, nsresult> insertBRElementResult =
InsertNodeWithTransaction<Element>(*newBRElement, pointToInsert); InsertNodeWithTransaction<Element>(*newBRElement, pointToInsert);
NS_WARNING_ASSERTION(insertBRElementResult.isOk(), NS_WARNING_ASSERTION(insertBRElementResult.isOk(),
"EditorBase::InsertNodeWithTransaction() failed"); "EditorBase::InsertNodeWithTransaction() failed");
@ -2779,13 +2782,13 @@ Result<EditorDOMPoint, nsresult> EditorBase::InsertTextWithTransaction(
return Err(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
// then we insert it into the dom tree // then we insert it into the dom tree
CreateTextResult insertTextNodeResult = Result<CreateTextResult, nsresult> insertTextNodeResult =
InsertNodeWithTransaction<Text>(*newTextNode, pointToInsert); InsertNodeWithTransaction<Text>(*newTextNode, pointToInsert);
if (insertTextNodeResult.isErr()) { if (MOZ_UNLIKELY(insertTextNodeResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return Err(insertTextNodeResult.unwrapErr()); return insertTextNodeResult.propagateErr();
} }
nsresult rv = insertTextNodeResult.SuggestCaretPointTo( nsresult rv = insertTextNodeResult.inspect().SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion, *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});
@ -2850,13 +2853,13 @@ Result<EditorDOMPoint, nsresult> EditorBase::InsertTextWithTransaction(
return Err(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
// then we insert it into the dom tree // then we insert it into the dom tree
CreateTextResult insertTextNodeResult = Result<CreateTextResult, nsresult> insertTextNodeResult =
InsertNodeWithTransaction<Text>(*newTextNode, pointToInsert); InsertNodeWithTransaction<Text>(*newTextNode, pointToInsert);
if (insertTextNodeResult.isErr()) { if (MOZ_UNLIKELY(insertTextNodeResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return Err(insertTextNodeResult.unwrapErr()); return Err(insertTextNodeResult.unwrapErr());
} }
nsresult rv = insertTextNodeResult.SuggestCaretPointTo( nsresult rv = insertTextNodeResult.inspect().SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion, *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});
@ -2867,7 +2870,7 @@ Result<EditorDOMPoint, nsresult> EditorBase::InsertTextWithTransaction(
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR, rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"CreateTextResult::SuggestCaretPointTo() failed, but ignored"); "CreateTextResult::SuggestCaretPointTo() failed, but ignored");
return EditorDOMPoint(insertTextNodeResult.UnwrapNewNode(), return EditorDOMPoint(insertTextNodeResult.inspect().GetNewNode(),
aStringToInsert.Length()); aStringToInsert.Length());
} }
@ -3358,16 +3361,16 @@ nsresult EditorBase::EnsurePaddingBRElementInMultilineEditor() {
AutoTransactionsConserveSelection dontChangeMySelection(*this); AutoTransactionsConserveSelection dontChangeMySelection(*this);
EditorDOMPoint endOfAnonymousDiv( EditorDOMPoint endOfAnonymousDiv(
EditorDOMPoint::AtEndOf(*anonymousDivOrBodyElement)); EditorDOMPoint::AtEndOf(*anonymousDivOrBodyElement));
CreateElementResult insertPaddingBRElementResult = Result<CreateElementResult, nsresult> insertPaddingBRElementResult =
InsertPaddingBRElementForEmptyLastLineWithTransaction( InsertPaddingBRElementForEmptyLastLineWithTransaction(
endOfAnonymousDiv); endOfAnonymousDiv);
if (insertPaddingBRElementResult.isErr()) { if (MOZ_UNLIKELY(insertPaddingBRElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction() " "EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction() "
"failed"); "failed");
return insertPaddingBRElementResult.unwrapErr(); return insertPaddingBRElementResult.unwrapErr();
} }
insertPaddingBRElementResult.IgnoreCaretPointSuggestion(); insertPaddingBRElementResult.inspect().IgnoreCaretPointSuggestion();
return NS_OK; return NS_OK;
} }

View file

@ -1718,9 +1718,10 @@ class EditorBase : public nsIEditor,
* point to put caret. * point to put caret.
*/ */
template <typename ContentNodeType> template <typename ContentNodeType>
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateNodeResultBase<ContentNodeType> [[nodiscard]] MOZ_CAN_RUN_SCRIPT
InsertNodeWithTransaction(ContentNodeType& aContentToInsert, Result<CreateNodeResultBase<ContentNodeType>, nsresult>
const EditorDOMPoint& aPointToInsert); InsertNodeWithTransaction(ContentNodeType& aContentToInsert,
const EditorDOMPoint& aPointToInsert);
/** /**
* InsertPaddingBRElementForEmptyLastLineWithTransaction() creates a padding * InsertPaddingBRElementForEmptyLastLineWithTransaction() creates a padding
@ -1732,7 +1733,7 @@ class EditorBase : public nsIEditor,
* @return If succeeded, returns the new <br> element and * @return If succeeded, returns the new <br> element and
* point to put caret around it. * point to put caret around it.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertPaddingBRElementForEmptyLastLineWithTransaction( InsertPaddingBRElementForEmptyLastLineWithTransaction(
const EditorDOMPoint& aPointToInsert); const EditorDOMPoint& aPointToInsert);

View file

@ -162,31 +162,12 @@ enum class SuggestCaret {
AndIgnoreTrivialError, AndIgnoreTrivialError,
}; };
// TODO: Perhaps, we can make this inherits mozilla::Result for guaranteeing
// same API. Then, changing to/from Result<*, nsresult> can be easier.
// For now, we should give same API name rather than same as
// mozilla::ErrorResult.
template <typename NodeType> template <typename NodeType>
class MOZ_STACK_CLASS CreateNodeResultBase final { class MOZ_STACK_CLASS CreateNodeResultBase final {
typedef CreateNodeResultBase<NodeType> SelfType; using SelfType = CreateNodeResultBase<NodeType>;
public: public:
// FYI: NS_SUCCEEDED and NS_FAILED contain MOZ_(UN)LIKELY so that isOk() and bool Handled() const { return mNode; }
// isErr() must not required to wrap with them.
bool isOk() const { return NS_SUCCEEDED(mRv); }
bool isErr() const { return NS_FAILED(mRv); }
bool Handled() const {
MOZ_ASSERT_IF(mRv == NS_SUCCESS_DOM_NO_OPERATION, !mNode);
return isOk() && mRv == NS_SUCCESS_DOM_NO_OPERATION;
}
constexpr nsresult inspectErr() const { return mRv; }
constexpr nsresult unwrapErr() const { return inspectErr(); }
constexpr bool EditorDestroyed() const {
return MOZ_UNLIKELY(mRv == NS_ERROR_EDITOR_DESTROYED);
}
constexpr bool GotUnexpectedDOMTree() const {
return MOZ_UNLIKELY(mRv == NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
NodeType* GetNewNode() const { return mNode; } NodeType* GetNewNode() const { return mNode; }
RefPtr<NodeType> UnwrapNewNode() { return std::move(mNode); } RefPtr<NodeType> UnwrapNewNode() { return std::move(mNode); }
@ -223,72 +204,56 @@ class MOZ_STACK_CLASS CreateNodeResultBase final {
const EditorBase& aEditorBase, const EditorBase& aEditorBase,
const SuggestCaretOptions& aOptions); const SuggestCaretOptions& aOptions);
explicit CreateNodeResultBase(nsresult aRv) : mRv(aRv) { explicit CreateNodeResultBase(NodeType& aNode) : mNode(&aNode) {}
MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(mRv)); explicit CreateNodeResultBase(NodeType& aNode,
}
explicit CreateNodeResultBase(NodeType* aNode)
: mNode(aNode), mRv(aNode ? NS_OK : NS_ERROR_FAILURE) {}
explicit CreateNodeResultBase(NodeType* aNode,
const EditorDOMPoint& aCandidateCaretPoint) const EditorDOMPoint& aCandidateCaretPoint)
: mNode(aNode), : mNode(&aNode), mCaretPoint(aCandidateCaretPoint) {}
mCaretPoint(aCandidateCaretPoint), explicit CreateNodeResultBase(NodeType& aNode,
mRv(aNode ? NS_OK : NS_ERROR_FAILURE) {}
explicit CreateNodeResultBase(NodeType* aNode,
EditorDOMPoint&& aCandidateCaretPoint) EditorDOMPoint&& aCandidateCaretPoint)
: mNode(aNode), : mNode(&aNode), mCaretPoint(std::move(aCandidateCaretPoint)) {}
mCaretPoint(std::move(aCandidateCaretPoint)),
mRv(aNode ? NS_OK : NS_ERROR_FAILURE) {}
explicit CreateNodeResultBase(RefPtr<NodeType>&& aNode) explicit CreateNodeResultBase(RefPtr<NodeType>&& aNode)
: mNode(std::move(aNode)), mRv(mNode.get() ? NS_OK : NS_ERROR_FAILURE) {} : mNode(std::move(aNode)) {}
explicit CreateNodeResultBase(RefPtr<NodeType>&& aNode, explicit CreateNodeResultBase(RefPtr<NodeType>&& aNode,
const EditorDOMPoint& aCandidateCaretPoint) const EditorDOMPoint& aCandidateCaretPoint)
: mNode(std::move(aNode)), : mNode(std::move(aNode)), mCaretPoint(aCandidateCaretPoint) {
mCaretPoint(aCandidateCaretPoint), MOZ_ASSERT(mNode);
mRv(mNode.get() ? NS_OK : NS_ERROR_FAILURE) {} }
explicit CreateNodeResultBase(RefPtr<NodeType>&& aNode, explicit CreateNodeResultBase(RefPtr<NodeType>&& aNode,
EditorDOMPoint&& aCandidateCaretPoint) EditorDOMPoint&& aCandidateCaretPoint)
: mNode(std::move(aNode)), : mNode(std::move(aNode)), mCaretPoint(std::move(aCandidateCaretPoint)) {
mCaretPoint(std::move(aCandidateCaretPoint)), MOZ_ASSERT(mNode);
mRv(mNode.get() ? NS_OK : NS_ERROR_FAILURE) {}
[[nodiscard]] static SelfType NotHandled() {
SelfType result;
result.mRv = NS_SUCCESS_DOM_NO_OPERATION;
return result;
} }
[[nodiscard]] static SelfType NotHandled() { return SelfType(); }
[[nodiscard]] static SelfType NotHandled( [[nodiscard]] static SelfType NotHandled(
const EditorDOMPoint& aPointToPutCaret) { const EditorDOMPoint& aPointToPutCaret) {
SelfType result; SelfType result;
result.mRv = NS_SUCCESS_DOM_NO_OPERATION;
result.mCaretPoint = aPointToPutCaret; result.mCaretPoint = aPointToPutCaret;
return result; return result;
} }
[[nodiscard]] static SelfType NotHandled(EditorDOMPoint&& aPointToPutCaret) { [[nodiscard]] static SelfType NotHandled(EditorDOMPoint&& aPointToPutCaret) {
SelfType result; SelfType result;
result.mRv = NS_SUCCESS_DOM_NO_OPERATION;
result.mCaretPoint = std::move(aPointToPutCaret); result.mCaretPoint = std::move(aPointToPutCaret);
return result; return result;
} }
#ifdef DEBUG #ifdef DEBUG
~CreateNodeResultBase() { ~CreateNodeResultBase() {
MOZ_ASSERT_IF(isOk(), !mCaretPoint.IsSet() || mHandledCaretPoint); MOZ_ASSERT(!mCaretPoint.IsSet() || mHandledCaretPoint);
} }
#endif #endif
CreateNodeResultBase(const SelfType& aOther) = delete; CreateNodeResultBase(const SelfType& aOther) = delete;
SelfType& operator=(const SelfType& aOther) = delete; SelfType& operator=(const SelfType& aOther) = delete;
CreateNodeResultBase(SelfType&& aOther) = default; CreateNodeResultBase(SelfType&& aOther) noexcept = default;
SelfType& operator=(SelfType&& aOther) = default; SelfType& operator=(SelfType&& aOther) noexcept = default;
private: private:
CreateNodeResultBase() = default; CreateNodeResultBase() = default;
RefPtr<NodeType> mNode; RefPtr<NodeType> mNode;
EditorDOMPoint mCaretPoint; EditorDOMPoint mCaretPoint;
nsresult mRv = NS_OK;
bool mutable mHandledCaretPoint = false; bool mutable mHandledCaretPoint = false;
}; };

View file

@ -698,19 +698,19 @@ nsresult HTMLEditor::SetPositionToAbsolute(Element& aElement) {
if (parentNode->GetChildCount() != 1) { if (parentNode->GetChildCount() != 1) {
return NS_OK; return NS_OK;
} }
CreateElementResult insertBRElementResult = Result<CreateElementResult, nsresult> insertBRElementResult =
InsertBRElement(WithTransaction::Yes, EditorDOMPoint(parentNode, 0u)); InsertBRElement(WithTransaction::Yes, EditorDOMPoint(parentNode, 0u));
if (insertBRElementResult.isErr()) { if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return insertBRElementResult.unwrapErr(); return insertBRElementResult.unwrapErr();
} }
// XXX Is this intentional selection change? // XXX Is this intentional selection change?
nsresult rv = insertBRElementResult.SuggestCaretPointTo( nsresult rv = insertBRElementResult.inspect().SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion, *this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt}); SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"CreateElementResult::SuggestCaretPointTo() failed"); "CreateElementResult::SuggestCaretPointTo() failed");
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(insertBRElementResult.inspect().GetNewNode());
return rv; return rv;
} }
@ -823,29 +823,33 @@ nsresult HTMLEditor::SetPositionToStatic(Element& aElement) {
{ {
// MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
// by the caller because of MOZ_CAN_RUN_SCRIPT method. // by the caller because of MOZ_CAN_RUN_SCRIPT method.
CreateElementResult maybeInsertBRElementBeforeFirstChildResult = Result<CreateElementResult, nsresult>
EnsureHardLineBeginsWithFirstChildOf(MOZ_KnownLive(*styledElement)); maybeInsertBRElementBeforeFirstChildResult =
if (maybeInsertBRElementBeforeFirstChildResult.isErr()) { EnsureHardLineBeginsWithFirstChildOf(MOZ_KnownLive(*styledElement));
if (MOZ_UNLIKELY(maybeInsertBRElementBeforeFirstChildResult.isErr())) {
NS_WARNING("HTMLEditor::EnsureHardLineBeginsWithFirstChildOf() failed"); NS_WARNING("HTMLEditor::EnsureHardLineBeginsWithFirstChildOf() failed");
return maybeInsertBRElementBeforeFirstChildResult.unwrapErr(); return maybeInsertBRElementBeforeFirstChildResult.unwrapErr();
} }
if (maybeInsertBRElementBeforeFirstChildResult.HasCaretPointSuggestion()) { CreateElementResult unwrappedResult =
pointToPutCaret = maybeInsertBRElementBeforeFirstChildResult.unwrap();
maybeInsertBRElementBeforeFirstChildResult.UnwrapCaretPoint(); if (unwrappedResult.HasCaretPointSuggestion()) {
pointToPutCaret = unwrappedResult.UnwrapCaretPoint();
} }
} }
{ {
// MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
// by the caller because of MOZ_CAN_RUN_SCRIPT method. // by the caller because of MOZ_CAN_RUN_SCRIPT method.
CreateElementResult maybeInsertBRElementAfterLastChildResult = Result<CreateElementResult, nsresult>
EnsureHardLineEndsWithLastChildOf(MOZ_KnownLive(*styledElement)); maybeInsertBRElementAfterLastChildResult =
if (maybeInsertBRElementAfterLastChildResult.isErr()) { EnsureHardLineEndsWithLastChildOf(MOZ_KnownLive(*styledElement));
if (MOZ_UNLIKELY(maybeInsertBRElementAfterLastChildResult.isErr())) {
NS_WARNING("HTMLEditor::EnsureHardLineEndsWithLastChildOf() failed"); NS_WARNING("HTMLEditor::EnsureHardLineEndsWithLastChildOf() failed");
return maybeInsertBRElementAfterLastChildResult.unwrapErr(); return maybeInsertBRElementAfterLastChildResult.unwrapErr();
} }
if (maybeInsertBRElementAfterLastChildResult.HasCaretPointSuggestion()) { CreateElementResult unwrappedResult =
pointToPutCaret = maybeInsertBRElementAfterLastChildResult.unwrap();
maybeInsertBRElementAfterLastChildResult.UnwrapCaretPoint(); if (unwrappedResult.HasCaretPointSuggestion()) {
pointToPutCaret = unwrappedResult.UnwrapCaretPoint();
} }
} }
{ {

File diff suppressed because it is too large Load diff

View file

@ -138,15 +138,15 @@ void HTMLEditor::AutoSelectionRestorer::Abort() {
* HTMLEditor * HTMLEditor
*****************************************************************************/ *****************************************************************************/
template CreateContentResult template Result<CreateContentResult, nsresult>
HTMLEditor::InsertNodeIntoProperAncestorWithTransaction( HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
nsIContent& aContentToInsert, const EditorDOMPoint& aPointToInsert, nsIContent& aContentToInsert, const EditorDOMPoint& aPointToInsert,
SplitAtEdges aSplitAtEdges); SplitAtEdges aSplitAtEdges);
template CreateElementResult template Result<CreateElementResult, nsresult>
HTMLEditor::InsertNodeIntoProperAncestorWithTransaction( HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
Element& aContentToInsert, const EditorDOMPoint& aPointToInsert, Element& aContentToInsert, const EditorDOMPoint& aPointToInsert,
SplitAtEdges aSplitAtEdges); SplitAtEdges aSplitAtEdges);
template CreateTextResult template Result<CreateTextResult, nsresult>
HTMLEditor::InsertNodeIntoProperAncestorWithTransaction( HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
Text& aContentToInsert, const EditorDOMPoint& aPointToInsert, Text& aContentToInsert, const EditorDOMPoint& aPointToInsert,
SplitAtEdges aSplitAtEdges); SplitAtEdges aSplitAtEdges);
@ -495,40 +495,43 @@ NS_IMETHODIMP HTMLEditor::SetDocumentCharacterSet(
} }
// Create a new meta charset tag // Create a new meta charset tag
CreateElementResult createNewMetaElementResult = CreateAndInsertElement( Result<CreateElementResult, nsresult> createNewMetaElementResult =
WithTransaction::Yes, *nsGkAtoms::meta, CreateAndInsertElement(
EditorDOMPoint(primaryHeadElement, 0), WithTransaction::Yes, *nsGkAtoms::meta,
[&aCharacterSet](HTMLEditor&, Element& aMetaElement, EditorDOMPoint(primaryHeadElement, 0),
const EditorDOMPoint&) { [&aCharacterSet](HTMLEditor&, Element& aMetaElement,
DebugOnly<nsresult> rvIgnored = aMetaElement.SetAttr( const EditorDOMPoint&) {
kNameSpaceID_None, nsGkAtoms::httpEquiv, u"Content-Type"_ns, DebugOnly<nsresult> rvIgnored = aMetaElement.SetAttr(
aMetaElement.IsInComposedDoc()); kNameSpaceID_None, nsGkAtoms::httpEquiv, u"Content-Type"_ns,
NS_WARNING_ASSERTION( aMetaElement.IsInComposedDoc());
NS_SUCCEEDED(rvIgnored), NS_WARNING_ASSERTION(
nsPrintfCString( NS_SUCCEEDED(rvIgnored),
"Element::SetAttr(nsGkAtoms::httpEquiv, \"Content-Type\", " nsPrintfCString(
"%s) failed, but ignored", "Element::SetAttr(nsGkAtoms::httpEquiv, \"Content-Type\", "
aMetaElement.IsInComposedDoc() ? "true" : "false") "%s) failed, but ignored",
.get()); aMetaElement.IsInComposedDoc() ? "true" : "false")
rvIgnored = aMetaElement.SetAttr( .get());
kNameSpaceID_None, nsGkAtoms::content, rvIgnored =
u"text/html;charset="_ns + NS_ConvertASCIItoUTF16(aCharacterSet), aMetaElement.SetAttr(kNameSpaceID_None, nsGkAtoms::content,
aMetaElement.IsInComposedDoc()); u"text/html;charset="_ns +
NS_WARNING_ASSERTION( NS_ConvertASCIItoUTF16(aCharacterSet),
NS_SUCCEEDED(rvIgnored), aMetaElement.IsInComposedDoc());
nsPrintfCString("Element::SetAttr(nsGkAtoms::content, " NS_WARNING_ASSERTION(
"\"text/html;charset=%s\", %s) failed, but ignored", NS_SUCCEEDED(rvIgnored),
nsPromiseFlatCString(aCharacterSet).get(), nsPrintfCString(
aMetaElement.IsInComposedDoc() ? "true" : "false") "Element::SetAttr(nsGkAtoms::content, "
.get()); "\"text/html;charset=%s\", %s) failed, but ignored",
return NS_OK; nsPromiseFlatCString(aCharacterSet).get(),
}); aMetaElement.IsInComposedDoc() ? "true" : "false")
.get());
return NS_OK;
});
NS_WARNING_ASSERTION(createNewMetaElementResult.isOk(), NS_WARNING_ASSERTION(createNewMetaElementResult.isOk(),
"HTMLEditor::CreateAndInsertElement(WithTransaction::" "HTMLEditor::CreateAndInsertElement(WithTransaction::"
"Yes, nsGkAtoms::meta) failed, but ignored"); "Yes, nsGkAtoms::meta) failed, but ignored");
// Probably, we don't need to update selection in this case since we should // Probably, we don't need to update selection in this case since we should
// not put selection into <head> element. // not put selection into <head> element.
createNewMetaElementResult.IgnoreCaretPointSuggestion(); createNewMetaElementResult.inspect().IgnoreCaretPointSuggestion();
return NS_OK; return NS_OK;
} }
@ -1604,15 +1607,16 @@ nsresult HTMLEditor::ReplaceHeadContentsWithSourceWithTransaction(
// Loop over the contents of the fragment and move into the document // Loop over the contents of the fragment and move into the document
while (nsCOMPtr<nsIContent> child = documentFragment->GetFirstChild()) { while (nsCOMPtr<nsIContent> child = documentFragment->GetFirstChild()) {
CreateContentResult insertChildContentResult = InsertNodeWithTransaction( Result<CreateContentResult, nsresult> insertChildContentResult =
*child, EditorDOMPoint(primaryHeadElement, offsetOfNewNode++)); InsertNodeWithTransaction(
if (insertChildContentResult.isErr()) { *child, EditorDOMPoint(primaryHeadElement, offsetOfNewNode++));
if (MOZ_UNLIKELY(insertChildContentResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertChildContentResult.unwrapErr(); return insertChildContentResult.unwrapErr();
} }
// We probably don't need to adjust selection here, although we've done it // We probably don't need to adjust selection here, although we've done it
// unless AutoTransactionsConserveSelection is created in a caller. // unless AutoTransactionsConserveSelection is created in a caller.
insertChildContentResult.IgnoreCaretPointSuggestion(); insertChildContentResult.inspect().IgnoreCaretPointSuggestion();
} }
return NS_OK; return NS_OK;
@ -1999,18 +2003,22 @@ nsresult HTMLEditor::InsertElementAtSelectionAsAction(
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
const CreateElementResult insertElementResult = {
InsertNodeIntoProperAncestorWithTransaction<Element>( Result<CreateElementResult, nsresult> insertElementResult =
*aElement, pointToInsert, SplitAtEdges::eAllowToCreateEmptyContainer); InsertNodeIntoProperAncestorWithTransaction<Element>(
if (insertElementResult.isErr()) { *aElement, pointToInsert,
NS_WARNING( SplitAtEdges::eAllowToCreateEmptyContainer);
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(SplitAtEdges::" if (MOZ_UNLIKELY(insertElementResult.isErr())) {
"eAllowToCreateEmptyContainer) failed"); NS_WARNING(
return EditorBase::ToGenericNSResult(insertElementResult.unwrapErr()); "HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
"SplitAtEdges::"
"eAllowToCreateEmptyContainer) failed");
return EditorBase::ToGenericNSResult(insertElementResult.unwrapErr());
}
insertElementResult.inspect().IgnoreCaretPointSuggestion();
} }
// Set caret after element, but check for special case // Set caret after element, but check for special case
// of inserting table-related elements: set in first cell instead // of inserting table-related elements: set in first cell instead
insertElementResult.IgnoreCaretPointSuggestion();
if (!SetCaretInTableCell(aElement)) { if (!SetCaretInTableCell(aElement)) {
if (NS_WARN_IF(Destroyed())) { if (NS_WARN_IF(Destroyed())) {
return EditorBase::ToGenericNSResult(NS_ERROR_EDITOR_DESTROYED); return EditorBase::ToGenericNSResult(NS_ERROR_EDITOR_DESTROYED);
@ -2032,29 +2040,27 @@ nsresult HTMLEditor::InsertElementAtSelectionAsAction(
const auto afterElement = EditorDOMPoint::After(*aElement); const auto afterElement = EditorDOMPoint::After(*aElement);
// Collapse selection to the new `<br>` element node after creating it. // Collapse selection to the new `<br>` element node after creating it.
const CreateElementResult insertBRElementResult = Result<CreateElementResult, nsresult> insertBRElementResult =
InsertBRElement(WithTransaction::Yes, afterElement, ePrevious); InsertBRElement(WithTransaction::Yes, afterElement, ePrevious);
if (insertBRElementResult.isErr()) { if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::Yes, ePrevious) failed"); "HTMLEditor::InsertBRElement(WithTransaction::Yes, ePrevious) failed");
return EditorBase::ToGenericNSResult(insertBRElementResult.unwrapErr()); return EditorBase::ToGenericNSResult(insertBRElementResult.unwrapErr());
} }
rv = insertBRElementResult.SuggestCaretPointTo(*this, {}); rv = insertBRElementResult.inspect().SuggestCaretPointTo(*this, {});
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed"); "EditorBase::CollapseSelectionTo() failed");
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(insertBRElementResult.inspect().GetNewNode());
return EditorBase::ToGenericNSResult(rv); return EditorBase::ToGenericNSResult(rv);
} }
template <typename NodeType> template <typename NodeType>
CreateNodeResultBase<NodeType> Result<CreateNodeResultBase<NodeType>, nsresult>
HTMLEditor::InsertNodeIntoProperAncestorWithTransaction( HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
NodeType& aContentToInsert, const EditorDOMPoint& aPointToInsert, NodeType& aContentToInsert, const EditorDOMPoint& aPointToInsert,
SplitAtEdges aSplitAtEdges) { SplitAtEdges aSplitAtEdges) {
using ResultType = CreateNodeResultBase<NodeType>;
if (NS_WARN_IF(!aPointToInsert.IsSet())) { if (NS_WARN_IF(!aPointToInsert.IsSet())) {
return ResultType(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
MOZ_ASSERT(aPointToInsert.IsSetAndValid()); MOZ_ASSERT(aPointToInsert.IsSetAndValid());
@ -2071,7 +2077,7 @@ HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
NS_WARNING( NS_WARNING(
"There was no proper container element to insert the content node in " "There was no proper container element to insert the content node in "
"the document"); "the document");
return ResultType(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
// Get the next point. // Get the next point.
@ -2084,7 +2090,7 @@ HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
NS_WARNING( NS_WARNING(
"There was no proper container element to insert the content node in " "There was no proper container element to insert the content node in "
"the editing host"); "the editing host");
return ResultType(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
} }
@ -2096,7 +2102,7 @@ HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
aPointToInsert, aSplitAtEdges); aPointToInsert, aSplitAtEdges);
if (splitNodeResult.isErr()) { if (splitNodeResult.isErr()) {
NS_WARNING("HTMLEditor::SplitNodeDeepWithTransaction() failed"); NS_WARNING("HTMLEditor::SplitNodeDeepWithTransaction() failed");
return ResultType(splitNodeResult.unwrapErr()); return Err(splitNodeResult.unwrapErr());
} }
pointToInsert = splitNodeResult.AtSplitPoint<EditorDOMPoint>(); pointToInsert = splitNodeResult.AtSplitPoint<EditorDOMPoint>();
MOZ_ASSERT(pointToInsert.IsSet()); MOZ_ASSERT(pointToInsert.IsSet());
@ -2106,7 +2112,7 @@ HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
} }
// Now we can insert the new node. // Now we can insert the new node.
ResultType insertContentNodeResult = Result<CreateNodeResultBase<NodeType>, nsresult> insertContentNodeResult =
InsertNodeWithTransaction<NodeType>(aContentToInsert, pointToInsert); InsertNodeWithTransaction<NodeType>(aContentToInsert, pointToInsert);
if (MOZ_LIKELY(insertContentNodeResult.isOk()) && if (MOZ_LIKELY(insertContentNodeResult.isOk()) &&
MOZ_UNLIKELY(NS_WARN_IF(!aContentToInsert.GetParentNode()) || MOZ_UNLIKELY(NS_WARN_IF(!aContentToInsert.GetParentNode()) ||
@ -2115,8 +2121,8 @@ HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(
NS_WARNING( NS_WARNING(
"EditorBase::InsertNodeWithTransaction() succeeded, but the inserted " "EditorBase::InsertNodeWithTransaction() succeeded, but the inserted "
"node was moved or removed by the web app"); "node was moved or removed by the web app");
insertContentNodeResult.IgnoreCaretPointSuggestion(); insertContentNodeResult.inspect().IgnoreCaretPointSuggestion();
return ResultType(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE); return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
} }
NS_WARNING_ASSERTION(insertContentNodeResult.isOk(), NS_WARNING_ASSERTION(insertContentNodeResult.isOk(),
"EditorBase::InsertNodeWithTransaction() failed"); "EditorBase::InsertNodeWithTransaction() failed");
@ -3170,7 +3176,7 @@ already_AddRefed<Element> HTMLEditor::GetSelectedElement(const nsAtom* aTagName,
return lastElementInRange.forget(); return lastElementInRange.forget();
} }
CreateElementResult HTMLEditor::CreateAndInsertElement( Result<CreateElementResult, nsresult> HTMLEditor::CreateAndInsertElement(
WithTransaction aWithTransaction, nsAtom& aTagName, WithTransaction aWithTransaction, nsAtom& aTagName,
const EditorDOMPoint& aPointToInsert, const EditorDOMPoint& aPointToInsert,
const InitializeInsertingElement& aInitializer) { const InitializeInsertingElement& aInitializer) {
@ -3186,7 +3192,7 @@ CreateElementResult HTMLEditor::CreateAndInsertElement(
AutoEditSubActionNotifier startToHandleEditSubAction( AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eCreateNode, nsIEditor::eNext, ignoredError); *this, EditSubAction::eCreateNode, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) { if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
!ignoredError.Failed(), !ignoredError.Failed(),
@ -3200,16 +3206,17 @@ CreateElementResult HTMLEditor::CreateAndInsertElement(
// CreatElementTransaction since we can use InsertNodeTransaction // CreatElementTransaction since we can use InsertNodeTransaction
// instead. // instead.
CreateElementResult createNewElementResult = [&]() MOZ_CAN_RUN_SCRIPT { auto createNewElementResult =
[&]() MOZ_CAN_RUN_SCRIPT -> Result<CreateElementResult, nsresult> {
RefPtr<Element> newElement = CreateHTMLContent(&aTagName); RefPtr<Element> newElement = CreateHTMLContent(&aTagName);
if (MOZ_UNLIKELY(!newElement)) { if (MOZ_UNLIKELY(!newElement)) {
NS_WARNING("EditorBase::CreateHTMLContent() failed"); NS_WARNING("EditorBase::CreateHTMLContent() failed");
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
nsresult rv = MarkElementDirty(*newElement); nsresult rv = MarkElementDirty(*newElement);
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) { if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING("EditorBase::MarkElementDirty() caused destroying the editor"); NS_WARNING("EditorBase::MarkElementDirty() caused destroying the editor");
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::MarkElementDirty() failed, but ignored"); "EditorBase::MarkElementDirty() failed, but ignored");
@ -3217,7 +3224,7 @@ CreateElementResult HTMLEditor::CreateAndInsertElement(
rv = aInitializer(*this, *newElement, aPointToInsert); rv = aInitializer(*this, *newElement, aPointToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed"); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed");
if (NS_WARN_IF(Destroyed())) { if (NS_WARN_IF(Destroyed())) {
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
} }
RefPtr<InsertNodeTransaction> transaction = RefPtr<InsertNodeTransaction> transaction =
@ -3230,30 +3237,30 @@ CreateElementResult HTMLEditor::CreateAndInsertElement(
NS_WARNING( NS_WARNING(
"InsertNodeTransaction::DoTransaction() caused destroying the " "InsertNodeTransaction::DoTransaction() caused destroying the "
"editor"); "editor");
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("InsertNodeTransaction::DoTransaction() failed"); NS_WARNING("InsertNodeTransaction::DoTransaction() failed");
return CreateElementResult(rv); return Err(rv);
} }
// Override the success code if new element was moved by the web apps. // Override the success code if new element was moved by the web apps.
if (newElement && if (newElement &&
newElement->GetParentNode() != aPointToInsert.GetContainer()) { newElement->GetParentNode() != aPointToInsert.GetContainer()) {
NS_WARNING("The new element was not inserted into the expected node"); NS_WARNING("The new element was not inserted into the expected node");
return CreateElementResult(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE); return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
} }
return CreateElementResult( return CreateElementResult(
std::move(newElement), std::move(newElement),
transaction->SuggestPointToPutCaret<EditorDOMPoint>()); transaction->SuggestPointToPutCaret<EditorDOMPoint>());
}(); }();
if (createNewElementResult.isErr()) { if (MOZ_UNLIKELY(createNewElementResult.isErr())) {
NS_WARNING("EditorBase::DoTransactionInternal() failed"); NS_WARNING("EditorBase::DoTransactionInternal() failed");
// XXX Why do we do this even when DoTransaction() returned error? // XXX Why do we do this even when DoTransaction() returned error?
DebugOnly<nsresult> rvIgnored = DebugOnly<nsresult> rvIgnored =
RangeUpdaterRef().SelAdjCreateNode(aPointToInsert); RangeUpdaterRef().SelAdjCreateNode(aPointToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Rangeupdater::SelAdjCreateNode() failed"); "RangeUpdater::SelAdjCreateNode() failed");
return createNewElementResult; return createNewElementResult;
} }
@ -3267,24 +3274,24 @@ CreateElementResult HTMLEditor::CreateAndInsertElement(
RangeUpdaterRef().SelAdjCreateNode(EditorRawDOMPoint( RangeUpdaterRef().SelAdjCreateNode(EditorRawDOMPoint(
aPointToInsert.GetContainer(), aPointToInsert.Offset())); aPointToInsert.GetContainer(), aPointToInsert.Offset()));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"Rangeupdater::SelAdjCreateNode() failed, but ignored"); "RangeUpdater::SelAdjCreateNode() failed, but ignored");
if (createNewElementResult.GetNewNode()) { if (MOZ_LIKELY(createNewElementResult.inspect().GetNewNode())) {
TopLevelEditSubActionDataRef().DidCreateElement( TopLevelEditSubActionDataRef().DidCreateElement(
*this, *createNewElementResult.GetNewNode()); *this, *createNewElementResult.inspect().GetNewNode());
} }
if (!StaticPrefs::editor_initialize_element_before_connect() && if (!StaticPrefs::editor_initialize_element_before_connect() &&
createNewElementResult.GetNewNode()) { MOZ_LIKELY(createNewElementResult.inspect().GetNewNode())) {
// MOZ_KnownLive(newElement) because it's grabbed by createNewElementResult. // MOZ_KnownLive because it's grabbed by createNewElementResult.
nsresult rv = nsresult rv = aInitializer(
aInitializer(*this, MOZ_KnownLive(*createNewElementResult.GetNewNode()), *this, MOZ_KnownLive(*createNewElementResult.inspect().GetNewNode()),
aPointToInsert); aPointToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed"); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed");
if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) { if (MOZ_UNLIKELY(NS_WARN_IF(Destroyed()))) {
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return CreateElementResult(rv); return Err(rv);
} }
} }
@ -3856,7 +3863,7 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::PrepareToInsertBRElement(
return atNextContent; return atNextContent;
} }
CreateElementResult HTMLEditor::InsertBRElement( Result<CreateElementResult, nsresult> HTMLEditor::InsertBRElement(
WithTransaction aWithTransaction, const EditorDOMPoint& aPointToInsert, WithTransaction aWithTransaction, const EditorDOMPoint& aPointToInsert,
EDirection aSelect /* = eNone */) { EDirection aSelect /* = eNone */) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
@ -3868,22 +3875,26 @@ CreateElementResult HTMLEditor::InsertBRElement(
nsPrintfCString("HTMLEditor::PrepareToInsertBRElement(%s) failed", nsPrintfCString("HTMLEditor::PrepareToInsertBRElement(%s) failed",
ToString(aWithTransaction).c_str()) ToString(aWithTransaction).c_str())
.get()); .get());
return CreateElementResult(maybePointToInsert.unwrapErr()); return maybePointToInsert.propagateErr();
} }
MOZ_ASSERT(maybePointToInsert.inspect().IsSetAndValid()); MOZ_ASSERT(maybePointToInsert.inspect().IsSetAndValid());
CreateElementResult createNewBRElementResult = CreateAndInsertElement( Result<CreateElementResult, nsresult> createNewBRElementResult =
aWithTransaction, *nsGkAtoms::br, maybePointToInsert.inspect()); CreateAndInsertElement(aWithTransaction, *nsGkAtoms::br,
if (createNewBRElementResult.isErr()) { maybePointToInsert.inspect());
if (MOZ_UNLIKELY(createNewBRElementResult.isErr())) {
NS_WARNING(nsPrintfCString("HTMLEditor::CreateAndInsertElement(%s) failed", NS_WARNING(nsPrintfCString("HTMLEditor::CreateAndInsertElement(%s) failed",
ToString(aWithTransaction).c_str()) ToString(aWithTransaction).c_str())
.get()); .get());
return CreateElementResult(createNewBRElementResult.unwrapErr()); return createNewBRElementResult.propagateErr();
} }
RefPtr<Element> newBRElement = createNewBRElementResult.UnwrapNewNode(); CreateElementResult unwrappedCreateNewBRElementResult =
createNewBRElementResult.unwrap();
RefPtr<Element> newBRElement =
unwrappedCreateNewBRElementResult.UnwrapNewNode();
MOZ_ASSERT(newBRElement); MOZ_ASSERT(newBRElement);
createNewBRElementResult.IgnoreCaretPointSuggestion(); unwrappedCreateNewBRElementResult.IgnoreCaretPointSuggestion();
switch (aSelect) { switch (aSelect) {
case eNext: { case eNext: {
const auto pointToPutCaret = EditorDOMPoint::After( const auto pointToPutCaret = EditorDOMPoint::After(
@ -3901,17 +3912,19 @@ CreateElementResult HTMLEditor::InsertBRElement(
"by itself"); "by itself");
[[fallthrough]]; [[fallthrough]];
case eNone: case eNone:
return CreateElementResult(std::move(newBRElement), return CreateElementResult(
createNewBRElementResult.UnwrapCaretPoint()); std::move(newBRElement),
unwrappedCreateNewBRElementResult.UnwrapCaretPoint());
} }
} }
CreateElementResult HTMLEditor::InsertContainerWithTransactionInternal( Result<CreateElementResult, nsresult>
HTMLEditor::InsertContainerWithTransactionInternal(
nsIContent& aContentToBeWrapped, nsAtom& aWrapperTagName, nsIContent& aContentToBeWrapped, nsAtom& aWrapperTagName,
nsAtom& aAttribute, const nsAString& aAttributeValue) { nsAtom& aAttribute, const nsAString& aAttributeValue) {
EditorDOMPoint pointToInsertNewContainer(&aContentToBeWrapped); EditorDOMPoint pointToInsertNewContainer(&aContentToBeWrapped);
if (NS_WARN_IF(!pointToInsertNewContainer.IsSet())) { if (NS_WARN_IF(!pointToInsertNewContainer.IsSet())) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
// aContentToBeWrapped will be moved to the new container before inserting the // aContentToBeWrapped will be moved to the new container before inserting the
// new container. So, when we insert the container, the insertion point is // new container. So, when we insert the container, the insertion point is
@ -3924,7 +3937,7 @@ CreateElementResult HTMLEditor::InsertContainerWithTransactionInternal(
// Create new container. // Create new container.
RefPtr<Element> newContainer = CreateHTMLContent(&aWrapperTagName); RefPtr<Element> newContainer = CreateHTMLContent(&aWrapperTagName);
if (NS_WARN_IF(!newContainer)) { if (NS_WARN_IF(!newContainer)) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
// Set attribute if needed. // Set attribute if needed.
@ -3932,11 +3945,11 @@ CreateElementResult HTMLEditor::InsertContainerWithTransactionInternal(
nsresult rv = newContainer->SetAttr(kNameSpaceID_None, &aAttribute, nsresult rv = newContainer->SetAttr(kNameSpaceID_None, &aAttribute,
aAttributeValue, true); aAttributeValue, true);
if (NS_WARN_IF(Destroyed())) { if (NS_WARN_IF(Destroyed())) {
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("Element::SetAttr() failed"); NS_WARNING("Element::SetAttr() failed");
return CreateElementResult(rv); return Err(rv);
} }
} }
@ -3948,7 +3961,7 @@ CreateElementResult HTMLEditor::InsertContainerWithTransactionInternal(
nsresult rv = DeleteNodeWithTransaction(aContentToBeWrapped); nsresult rv = DeleteNodeWithTransaction(aContentToBeWrapped);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed"); NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
return CreateElementResult(rv); return Err(rv);
} }
{ {
@ -3957,17 +3970,18 @@ CreateElementResult HTMLEditor::InsertContainerWithTransactionInternal(
// actions which may be caused by legacy mutation event listeners or // actions which may be caused by legacy mutation event listeners or
// chrome script. // chrome script.
AutoTransactionsConserveSelection conserveSelection(*this); AutoTransactionsConserveSelection conserveSelection(*this);
CreateContentResult insertContentNodeResult = InsertNodeWithTransaction( Result<CreateContentResult, nsresult> insertContentNodeResult =
aContentToBeWrapped, EditorDOMPoint(newContainer, 0u)); InsertNodeWithTransaction(aContentToBeWrapped,
if (insertContentNodeResult.isErr()) { EditorDOMPoint(newContainer, 0u));
if (MOZ_UNLIKELY(insertContentNodeResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return CreateElementResult(insertContentNodeResult.unwrapErr()); return insertContentNodeResult.propagateErr();
} }
insertContentNodeResult.IgnoreCaretPointSuggestion(); insertContentNodeResult.inspect().IgnoreCaretPointSuggestion();
} }
// Put the new container where aNode was. // Put the new container where aNode was.
CreateElementResult insertNewContainerElementResult = Result<CreateElementResult, nsresult> insertNewContainerElementResult =
InsertNodeWithTransaction<Element>(*newContainer, InsertNodeWithTransaction<Element>(*newContainer,
pointToInsertNewContainer); pointToInsertNewContainer);
NS_WARNING_ASSERTION(insertNewContainerElementResult.isOk(), NS_WARNING_ASSERTION(insertNewContainerElementResult.isOk(),
@ -3975,19 +3989,20 @@ CreateElementResult HTMLEditor::InsertContainerWithTransactionInternal(
return insertNewContainerElementResult; return insertNewContainerElementResult;
} }
CreateElementResult HTMLEditor::ReplaceContainerWithTransactionInternal( Result<CreateElementResult, nsresult>
HTMLEditor::ReplaceContainerWithTransactionInternal(
Element& aOldContainer, nsAtom& aTagName, nsAtom& aAttribute, Element& aOldContainer, nsAtom& aTagName, nsAtom& aAttribute,
const nsAString& aAttributeValue, bool aCloneAllAttributes) { const nsAString& aAttributeValue, bool aCloneAllAttributes) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!HTMLEditUtils::IsRemovableNode(aOldContainer)) || if (NS_WARN_IF(!HTMLEditUtils::IsRemovableNode(aOldContainer)) ||
NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(aOldContainer))) { NS_WARN_IF(!HTMLEditUtils::IsSimplyEditableNode(aOldContainer))) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
const RefPtr<Element> newContainer = CreateHTMLContent(&aTagName); const RefPtr<Element> newContainer = CreateHTMLContent(&aTagName);
if (NS_WARN_IF(!newContainer)) { if (NS_WARN_IF(!newContainer)) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
// Set or clone attribute if needed. // Set or clone attribute if needed.
@ -3999,7 +4014,7 @@ CreateElementResult HTMLEditor::ReplaceContainerWithTransactionInternal(
aAttributeValue, true); aAttributeValue, true);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("Element::SetAttr() failed"); NS_WARNING("Element::SetAttr() failed");
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
} }
@ -4028,7 +4043,7 @@ CreateElementResult HTMLEditor::ReplaceContainerWithTransactionInternal(
EditorDOMPoint(newContainer, 0u)); EditorDOMPoint(newContainer, 0u));
if (MOZ_UNLIKELY(moveChildResult.isErr())) { if (MOZ_UNLIKELY(moveChildResult.isErr())) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return CreateElementResult(moveChildResult.unwrapErr()); return moveChildResult.propagateErr();
} }
// We'll suggest new caret point which is suggested by new container // We'll suggest new caret point which is suggested by new container
// element insertion result. Therefore, we need to do nothing here. // element insertion result. Therefore, we need to do nothing here.
@ -4041,7 +4056,7 @@ CreateElementResult HTMLEditor::ReplaceContainerWithTransactionInternal(
nsresult rv = DeleteNodeWithTransaction(aOldContainer); nsresult rv = DeleteNodeWithTransaction(aOldContainer);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed"); NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
return CreateElementResult(rv); return Err(rv);
} }
if (referenceNode && (!referenceNode->GetParentNode() || if (referenceNode && (!referenceNode->GetParentNode() ||
@ -4049,18 +4064,19 @@ CreateElementResult HTMLEditor::ReplaceContainerWithTransactionInternal(
NS_WARNING( NS_WARNING(
"The reference node for insertion has been moved to different parent, " "The reference node for insertion has been moved to different parent, "
"so we got lost the insertion point"); "so we got lost the insertion point");
return CreateElementResult(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE); return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
} }
// Finally, insert the new node to where probably aOldContainer was. // Finally, insert the new node to where probably aOldContainer was.
CreateElementResult insertNewContainerElementResult = Result<CreateElementResult, nsresult> insertNewContainerElementResult =
InsertNodeWithTransaction<Element>( InsertNodeWithTransaction<Element>(
*newContainer, referenceNode ? EditorDOMPoint(referenceNode) *newContainer, referenceNode ? EditorDOMPoint(referenceNode)
: EditorDOMPoint::AtEndOf(*parentNode)); : EditorDOMPoint::AtEndOf(*parentNode));
NS_WARNING_ASSERTION(insertNewContainerElementResult.isOk(), NS_WARNING_ASSERTION(insertNewContainerElementResult.isOk(),
"EditorBase::InsertNodeWithTransaction() failed"); "EditorBase::InsertNodeWithTransaction() failed");
MOZ_ASSERT_IF(insertNewContainerElementResult.isOk(), MOZ_ASSERT_IF(
insertNewContainerElementResult.GetNewNode() == newContainer); insertNewContainerElementResult.isOk(),
insertNewContainerElementResult.inspect().GetNewNode() == newContainer);
return insertNewContainerElementResult; return insertNewContainerElementResult;
} }
@ -4547,16 +4563,19 @@ HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement) {
!previousSibling->IsHTMLElement(nsGkAtoms::br) && !previousSibling->IsHTMLElement(nsGkAtoms::br) &&
!HTMLEditUtils::IsBlockElement(*child)) { !HTMLEditUtils::IsBlockElement(*child)) {
// Insert br node // Insert br node
CreateElementResult insertBRElementResult = InsertBRElement( Result<CreateElementResult, nsresult> insertBRElementResult =
WithTransaction::Yes, EditorDOMPoint(&aElement, 0u)); InsertBRElement(WithTransaction::Yes,
if (insertBRElementResult.isErr()) { EditorDOMPoint(&aElement, 0u));
if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); "HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return Err(insertBRElementResult.unwrapErr()); return insertBRElementResult.propagateErr();
} }
insertBRElementResult.MoveCaretPointTo( CreateElementResult unwrappedInsertBRElementResult =
insertBRElementResult.unwrap();
unwrappedInsertBRElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(unwrappedInsertBRElementResult.GetNewNode());
} }
} }
@ -4573,16 +4592,19 @@ HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement) {
aElement, {WalkTreeOption::IgnoreNonEditableNode})) { aElement, {WalkTreeOption::IgnoreNonEditableNode})) {
if (!HTMLEditUtils::IsBlockElement(*lastChild) && if (!HTMLEditUtils::IsBlockElement(*lastChild) &&
!lastChild->IsHTMLElement(nsGkAtoms::br)) { !lastChild->IsHTMLElement(nsGkAtoms::br)) {
CreateElementResult insertBRElementResult = InsertBRElement( Result<CreateElementResult, nsresult> insertBRElementResult =
WithTransaction::Yes, EditorDOMPoint::AtEndOf(aElement)); InsertBRElement(WithTransaction::Yes,
if (insertBRElementResult.isErr()) { EditorDOMPoint::AtEndOf(aElement));
if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); "HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return Err(insertBRElementResult.unwrapErr()); return insertBRElementResult.propagateErr();
} }
insertBRElementResult.MoveCaretPointTo( CreateElementResult unwrappedInsertBRElementResult =
insertBRElementResult.unwrap();
unwrappedInsertBRElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(unwrappedInsertBRElementResult.GetNewNode());
} }
} }
} }
@ -4601,16 +4623,19 @@ HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement) {
aElement, {WalkTreeOption::IgnoreNonEditableNode})) { aElement, {WalkTreeOption::IgnoreNonEditableNode})) {
if (!HTMLEditUtils::IsBlockElement(*nextSibling) && if (!HTMLEditUtils::IsBlockElement(*nextSibling) &&
!nextSibling->IsHTMLElement(nsGkAtoms::br)) { !nextSibling->IsHTMLElement(nsGkAtoms::br)) {
CreateElementResult insertBRElementResult = InsertBRElement( Result<CreateElementResult, nsresult> insertBRElementResult =
WithTransaction::Yes, EditorDOMPoint(&aElement, 0u)); InsertBRElement(WithTransaction::Yes,
if (insertBRElementResult.isErr()) { EditorDOMPoint(&aElement, 0u));
if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); "HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return Err(insertBRElementResult.unwrapErr()); return insertBRElementResult.propagateErr();
} }
insertBRElementResult.MoveCaretPointTo( CreateElementResult unwrappedInsertBRElementResult =
insertBRElementResult.unwrap();
unwrappedInsertBRElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(unwrappedInsertBRElementResult.GetNewNode());
} }
} }
} }
@ -5410,24 +5435,25 @@ Result<RefPtr<Element>, nsresult> HTMLEditor::DeleteSelectionAndCreateElement(
if (!pointToInsert.IsSet()) { if (!pointToInsert.IsSet()) {
return Err(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
CreateElementResult createNewElementResult = CreateAndInsertElement( Result<CreateElementResult, nsresult> createNewElementResult =
WithTransaction::Yes, aTag, pointToInsert, aInitializer); CreateAndInsertElement(WithTransaction::Yes, aTag, pointToInsert,
if (createNewElementResult.isErr()) { aInitializer);
if (MOZ_UNLIKELY(createNewElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed"); "HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed");
return Err(createNewElementResult.unwrapErr()); return createNewElementResult.propagateErr();
} }
MOZ_ASSERT(createNewElementResult.GetNewNode()); MOZ_ASSERT(createNewElementResult.inspect().GetNewNode());
// We want the selection to be just after the new node // We want the selection to be just after the new node
createNewElementResult.IgnoreCaretPointSuggestion(); createNewElementResult.inspect().IgnoreCaretPointSuggestion();
rv = CollapseSelectionTo( rv = CollapseSelectionTo(
EditorRawDOMPoint::After(*createNewElementResult.GetNewNode())); EditorRawDOMPoint::After(*createNewElementResult.inspect().GetNewNode()));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("EditorBase::CollapseSelectionTo() failed"); NS_WARNING("EditorBase::CollapseSelectionTo() failed");
return Err(rv); return Err(rv);
} }
return createNewElementResult.UnwrapNewNode(); return createNewElementResult.unwrap().UnwrapNewNode();
} }
nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() { nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() {
@ -6076,12 +6102,13 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
// At first time, just create the most descendant inline container // At first time, just create the most descendant inline container
// element. // element.
if (!firstClonedElement) { if (!firstClonedElement) {
CreateElementResult createNewElementResult = CreateAndInsertElement( Result<CreateElementResult, nsresult> createNewElementResult =
WithTransaction::Yes, tagName, EditorDOMPoint(&aNewBlock, 0u), CreateAndInsertElement(
// MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 WithTransaction::Yes, tagName, EditorDOMPoint(&aNewBlock, 0u),
[&elementInPreviousBlock](HTMLEditor& aHTMLEditor, // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868
Element& aNewElement, const EditorDOMPoint&) [&elementInPreviousBlock](
MOZ_CAN_RUN_SCRIPT_BOUNDARY { HTMLEditor& aHTMLEditor, Element& aNewElement,
const EditorDOMPoint&) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
// Clone all attributes. Note that despite the method name, // Clone all attributes. Note that despite the method name,
// CloneAttributesWithTransaction does not create // CloneAttributesWithTransaction does not create
// transactions in this case because aNewElement has not // transactions in this case because aNewElement has not
@ -6091,32 +6118,36 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
aNewElement, *elementInPreviousBlock); aNewElement, *elementInPreviousBlock);
return NS_OK; return NS_OK;
}); });
if (createNewElementResult.isErr()) { if (MOZ_UNLIKELY(createNewElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed"); "HTMLEditor::CreateAndInsertElement(WithTransaction::Yes) failed");
return Err(createNewElementResult.unwrapErr()); return createNewElementResult.propagateErr();
} }
CreateElementResult unwrappedCreateNewElementResult =
createNewElementResult.unwrap();
// We'll return with a point suggesting new caret position and the // We'll return with a point suggesting new caret position and the
// following path does not require an update of selection here. // following path does not require an update of selection here.
// Therefore, we don't need to update selection here. // Therefore, we don't need to update selection here.
createNewElementResult.IgnoreCaretPointSuggestion(); unwrappedCreateNewElementResult.IgnoreCaretPointSuggestion();
firstClonedElement = lastClonedElement = firstClonedElement = lastClonedElement =
createNewElementResult.UnwrapNewNode(); unwrappedCreateNewElementResult.UnwrapNewNode();
continue; continue;
} }
// Otherwise, inserts new parent inline container to the previous inserted // Otherwise, inserts new parent inline container to the previous inserted
// inline container. // inline container.
CreateElementResult wrapClonedElementResult = Result<CreateElementResult, nsresult> wrapClonedElementResult =
InsertContainerWithTransaction(*lastClonedElement, tagName); InsertContainerWithTransaction(*lastClonedElement, tagName);
if (wrapClonedElementResult.isErr()) { if (MOZ_UNLIKELY(wrapClonedElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed"); NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed");
return Err(wrapClonedElementResult.unwrapErr()); return wrapClonedElementResult.propagateErr();
} }
CreateElementResult unwrappedWrapClonedElementResult =
wrapClonedElementResult.unwrap();
// We'll return with a point suggesting new caret so that we don't need to // We'll return with a point suggesting new caret so that we don't need to
// update selection here. // update selection here.
wrapClonedElementResult.IgnoreCaretPointSuggestion(); unwrappedWrapClonedElementResult.IgnoreCaretPointSuggestion();
MOZ_ASSERT(wrapClonedElementResult.GetNewNode()); MOZ_ASSERT(unwrappedWrapClonedElementResult.GetNewNode());
lastClonedElement = wrapClonedElementResult.UnwrapNewNode(); lastClonedElement = unwrappedWrapClonedElementResult.UnwrapNewNode();
CloneAttributesWithTransaction(*lastClonedElement, *elementInPreviousBlock); CloneAttributesWithTransaction(*lastClonedElement, *elementInPreviousBlock);
if (NS_WARN_IF(Destroyed())) { if (NS_WARN_IF(Destroyed())) {
return Err(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
@ -6129,15 +6160,15 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
return EditorDOMPoint(&aNewBlock, 0u); return EditorDOMPoint(&aNewBlock, 0u);
} }
CreateElementResult insertBRElementResult = InsertBRElement( Result<CreateElementResult, nsresult> insertBRElementResult = InsertBRElement(
WithTransaction::Yes, EditorDOMPoint(firstClonedElement, 0u)); WithTransaction::Yes, EditorDOMPoint(firstClonedElement, 0u));
if (insertBRElementResult.isErr()) { if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return Err(insertBRElementResult.unwrapErr()); return insertBRElementResult.propagateErr();
} }
insertBRElementResult.IgnoreCaretPointSuggestion(); insertBRElementResult.inspect().IgnoreCaretPointSuggestion();
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(insertBRElementResult.inspect().GetNewNode());
return EditorDOMPoint(insertBRElementResult.GetNewNode()); return EditorDOMPoint(insertBRElementResult.inspect().GetNewNode());
} }
nsresult HTMLEditor::GetElementOrigin(Element& aElement, int32_t& aX, nsresult HTMLEditor::GetElementOrigin(Element& aElement, int32_t& aX,

View file

@ -746,7 +746,7 @@ class HTMLEditor final : public EditorBase,
* @return The new <br> node and suggesting point to put * @return The new <br> node and suggesting point to put
* caret which respects aSelect. * caret which respects aSelect.
*/ */
MOZ_CAN_RUN_SCRIPT CreateElementResult InsertBRElement( MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult> InsertBRElement(
WithTransaction aWithTransaction, const EditorDOMPoint& aPointToInsert, WithTransaction aWithTransaction, const EditorDOMPoint& aPointToInsert,
EDirection aSelect = eNone); EDirection aSelect = eNone);
@ -877,7 +877,7 @@ class HTMLEditor final : public EditorBase,
* Helper routines for font size changing. * Helper routines for font size changing.
*/ */
enum class FontSize { incr, decr }; enum class FontSize { incr, decr };
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
SetFontSizeOnTextNode(Text& aTextNode, uint32_t aStartOffset, SetFontSizeOnTextNode(Text& aTextNode, uint32_t aStartOffset,
uint32_t aEndOffset, FontSize aIncrementOrDecrement); uint32_t aEndOffset, FontSize aIncrementOrDecrement);
@ -1156,8 +1156,9 @@ class HTMLEditor final : public EditorBase,
* @return If succeeded, returns new <br> element and * @return If succeeded, returns new <br> element and
* candidate caret point. * candidate caret point.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult HandleInsertBRElement( [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
const EditorDOMPoint& aPointToBreak, const Element& aEditingHost); HandleInsertBRElement(const EditorDOMPoint& aPointToBreak,
const Element& aEditingHost);
/** /**
* HandleInsertLinefeed() inserts a linefeed character into aInsertToBreak. * HandleInsertLinefeed() inserts a linefeed character into aInsertToBreak.
@ -1305,7 +1306,8 @@ class HTMLEditor final : public EditorBase,
* @return The created new element node and candidate caret * @return The created new element node and candidate caret
* position. * position.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult CreateAndInsertElement( [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
CreateAndInsertElement(
WithTransaction aWithTransaction, nsAtom& aTagName, WithTransaction aWithTransaction, nsAtom& aTagName,
const EditorDOMPoint& aPointToInsert, const EditorDOMPoint& aPointToInsert,
const InitializeInsertingElement& aInitializer = DoNothingForNewElement); const InitializeInsertingElement& aInitializer = DoNothingForNewElement);
@ -1356,7 +1358,7 @@ class HTMLEditor final : public EditorBase,
* suggesting point to put caret. * suggesting point to put caret.
*/ */
enum class BRElementNextToSplitPoint { Keep, Delete }; enum class BRElementNextToSplitPoint { Keep, Delete };
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertElementWithSplittingAncestorsWithTransaction( InsertElementWithSplittingAncestorsWithTransaction(
nsAtom& aTagName, const EditorDOMPoint& aPointToInsert, nsAtom& aTagName, const EditorDOMPoint& aPointToInsert,
BRElementNextToSplitPoint aBRElementNextToSplitPoint, BRElementNextToSplitPoint aBRElementNextToSplitPoint,
@ -1417,7 +1419,7 @@ class HTMLEditor final : public EditorBase,
* The caret suggestion may be unset if there is * The caret suggestion may be unset if there is
* no suggestion. * no suggestion.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
WrapContentsInBlockquoteElementsWithTransaction( WrapContentsInBlockquoteElementsWithTransaction(
const nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents, const nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents,
const Element& aEditingHost); const Element& aEditingHost);
@ -1456,7 +1458,7 @@ class HTMLEditor final : public EditorBase,
* @return The latest created new block element and a * @return The latest created new block element and a
* suggest point to put caret. * suggest point to put caret.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
CreateOrChangeBlockContainerElement( CreateOrChangeBlockContainerElement(
nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents, nsAtom& aBlockTag, nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents, nsAtom& aBlockTag,
const Element& aEditingHost); const Element& aEditingHost);
@ -1612,8 +1614,9 @@ class HTMLEditor final : public EditorBase,
* New list element may be aListElement if its * New list element may be aListElement if its
* tag name is same as aNewListTag. * tag name is same as aNewListTag.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult ChangeListElementType( [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
Element& aListElement, nsAtom& aListType, nsAtom& aItemType); ChangeListElementType(Element& aListElement, nsAtom& aListType,
nsAtom& aItemType);
/** /**
* ConvertContentAroundRangesToList() converts contents around aRanges to * ConvertContentAroundRangesToList() converts contents around aRanges to
@ -1742,7 +1745,7 @@ class HTMLEditor final : public EditorBase,
* with new element. * with new element.
* @param aTagName The name of new element node. * @param aTagName The name of new element node.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
ReplaceContainerAndCloneAttributesWithTransaction(Element& aOldContainer, ReplaceContainerAndCloneAttributesWithTransaction(Element& aOldContainer,
nsAtom& aTagName) { nsAtom& aTagName) {
return ReplaceContainerWithTransactionInternal( return ReplaceContainerWithTransactionInternal(
@ -1761,7 +1764,7 @@ class HTMLEditor final : public EditorBase,
* @param aAttribute Attribute name to be set to the new element. * @param aAttribute Attribute name to be set to the new element.
* @param aAttributeValue Attribute value to be set to aAttribute. * @param aAttributeValue Attribute value to be set to aAttribute.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
ReplaceContainerWithTransaction(Element& aOldContainer, nsAtom& aTagName, ReplaceContainerWithTransaction(Element& aOldContainer, nsAtom& aTagName,
nsAtom& aAttribute, nsAtom& aAttribute,
const nsAString& aAttributeValue) { const nsAString& aAttributeValue) {
@ -1778,7 +1781,7 @@ class HTMLEditor final : public EditorBase,
* with new element. * with new element.
* @param aTagName The name of new element node. * @param aTagName The name of new element node.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
ReplaceContainerWithTransaction(Element& aOldContainer, nsAtom& aTagName) { ReplaceContainerWithTransaction(Element& aOldContainer, nsAtom& aTagName) {
return ReplaceContainerWithTransactionInternal( return ReplaceContainerWithTransactionInternal(
aOldContainer, aTagName, *nsGkAtoms::_empty, u""_ns, false); aOldContainer, aTagName, *nsGkAtoms::_empty, u""_ns, false);
@ -1807,7 +1810,7 @@ class HTMLEditor final : public EditorBase,
* aContent and be inserted into where aContent * aContent and be inserted into where aContent
* was. * was.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertContainerWithTransaction(nsIContent& aContentToBeWrapped, InsertContainerWithTransaction(nsIContent& aContentToBeWrapped,
nsAtom& aWrapperTagName) { nsAtom& aWrapperTagName) {
return InsertContainerWithTransactionInternal( return InsertContainerWithTransactionInternal(
@ -1831,7 +1834,7 @@ class HTMLEditor final : public EditorBase,
* element. * element.
* @param aAttributeValue Value to be set to aAttribute. * @param aAttributeValue Value to be set to aAttribute.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertContainerWithTransaction(nsIContent& aContentToBeWrapped, InsertContainerWithTransaction(nsIContent& aContentToBeWrapped,
nsAtom& aWrapperTagName, nsAtom& aAttribute, nsAtom& aWrapperTagName, nsAtom& aAttribute,
const nsAString& aAttributeValue) { const nsAString& aAttributeValue) {
@ -2475,7 +2478,7 @@ class HTMLEditor final : public EditorBase,
* first child of aRemovingContainerElement if it will not be start of a * first child of aRemovingContainerElement if it will not be start of a
* hard line after removing aRemovingContainerElement. * hard line after removing aRemovingContainerElement.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
EnsureHardLineBeginsWithFirstChildOf(Element& aRemovingContainerElement); EnsureHardLineBeginsWithFirstChildOf(Element& aRemovingContainerElement);
/** /**
@ -2483,7 +2486,7 @@ class HTMLEditor final : public EditorBase,
* child of aRemovingContainerElement if it will not be end of a hard line * child of aRemovingContainerElement if it will not be end of a hard line
* after removing aRemovingContainerElement. * after removing aRemovingContainerElement.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
EnsureHardLineEndsWithLastChildOf(Element& aRemovingContainerElement); EnsureHardLineEndsWithLastChildOf(Element& aRemovingContainerElement);
/** /**
@ -2546,7 +2549,7 @@ class HTMLEditor final : public EditorBase,
* @return New <div> element which has only a padding <br> * @return New <div> element which has only a padding <br>
* element and is styled to align contents. * element and is styled to align contents.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertDivElementToAlignContents(const EditorDOMPoint& aPointToInsert, InsertDivElementToAlignContents(const EditorDOMPoint& aPointToInsert,
const nsAString& aAlignType, const nsAString& aAlignType,
const Element& aEditingHost); const Element& aEditingHost);
@ -2562,7 +2565,8 @@ class HTMLEditor final : public EditorBase,
* caret and candidate position which may be * caret and candidate position which may be
* outside the <div> element. * outside the <div> element.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult AlignNodesAndDescendants( [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
AlignNodesAndDescendants(
nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents, nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents,
const nsAString& aAlignType, const Element& aEditingHost); const nsAString& aAlignType, const Element& aEditingHost);
@ -3197,10 +3201,11 @@ class HTMLEditor final : public EditorBase,
* @param aSplitAtEdges Splitting can result in empty nodes? * @param aSplitAtEdges Splitting can result in empty nodes?
*/ */
template <typename NodeType> template <typename NodeType>
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateNodeResultBase<NodeType> [[nodiscard]] MOZ_CAN_RUN_SCRIPT
InsertNodeIntoProperAncestorWithTransaction( Result<CreateNodeResultBase<NodeType>, nsresult>
NodeType& aContent, const EditorDOMPoint& aPointToInsert, InsertNodeIntoProperAncestorWithTransaction(
SplitAtEdges aSplitAtEdges); NodeType& aContent, const EditorDOMPoint& aPointToInsert,
SplitAtEdges aSplitAtEdges);
/** /**
* InsertTextWithQuotationsInternal() replaces selection with new content. * InsertTextWithQuotationsInternal() replaces selection with new content.
@ -3229,7 +3234,7 @@ class HTMLEditor final : public EditorBase,
* @param aCloneAllAttributes If true, all attributes of aOldContainer will * @param aCloneAllAttributes If true, all attributes of aOldContainer will
* be copied to the new element. * be copied to the new element.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
ReplaceContainerWithTransactionInternal(Element& aElement, nsAtom& aTagName, ReplaceContainerWithTransactionInternal(Element& aElement, nsAtom& aTagName,
nsAtom& aAttribute, nsAtom& aAttribute,
const nsAString& aAttributeValue, const nsAString& aAttributeValue,
@ -3253,7 +3258,7 @@ class HTMLEditor final : public EditorBase,
* element. * element.
* @param aAttributeValue Value to be set to aAttribute. * @param aAttributeValue Value to be set to aAttribute.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertContainerWithTransactionInternal(nsIContent& aContentToBeWrapped, InsertContainerWithTransactionInternal(nsIContent& aContentToBeWrapped,
nsAtom& aWrapperTagName, nsAtom& aWrapperTagName,
nsAtom& aAttribute, nsAtom& aAttribute,
@ -3507,7 +3512,7 @@ class HTMLEditor final : public EditorBase,
* start of the last inserted cell element * start of the last inserted cell element
* as a point to put caret. * as a point to put caret.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT CreateElementResult [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CreateElementResult, nsresult>
InsertTableCellsWithTransaction(const EditorDOMPoint& aPointToInsert, InsertTableCellsWithTransaction(const EditorDOMPoint& aPointToInsert,
int32_t aNumberOfCellsToInsert); int32_t aNumberOfCellsToInsert);

View file

@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ErrorList.h"
#include "HTMLEditor.h" #include "HTMLEditor.h"
#include <string.h> #include <string.h>
@ -202,13 +203,15 @@ nsresult HTMLEditor::LoadHTML(const nsAString& aInputString) {
EditorDOMPoint pointToPutCaret; EditorDOMPoint pointToPutCaret;
for (nsCOMPtr<nsIContent> contentToInsert = documentFragment->GetFirstChild(); for (nsCOMPtr<nsIContent> contentToInsert = documentFragment->GetFirstChild();
contentToInsert; contentToInsert = documentFragment->GetFirstChild()) { contentToInsert; contentToInsert = documentFragment->GetFirstChild()) {
CreateContentResult insertChildContentNodeResult = Result<CreateContentResult, nsresult> insertChildContentNodeResult =
InsertNodeWithTransaction(*contentToInsert, pointToInsert); InsertNodeWithTransaction(*contentToInsert, pointToInsert);
if (insertChildContentNodeResult.isErr()) { if (MOZ_UNLIKELY(insertChildContentNodeResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertChildContentNodeResult.unwrapErr(); return insertChildContentNodeResult.unwrapErr();
} }
insertChildContentNodeResult.MoveCaretPointTo( CreateContentResult unwrappedInsertChildContentNodeResult =
insertChildContentNodeResult.unwrap();
unwrappedInsertChildContentNodeResult.MoveCaretPointTo(
pointToPutCaret, *this, pointToPutCaret, *this,
{SuggestCaret::OnlyIfHasSuggestion, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt}); SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
@ -884,17 +887,17 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
EditorDOMPoint pointToPutCaret; EditorDOMPoint pointToPutCaret;
for (const OwningNonNull<nsIContent>& child : children) { for (const OwningNonNull<nsIContent>& child : children) {
// MOZ_KnownLive(child) because of bug 1622253 // MOZ_KnownLive(child) because of bug 1622253
CreateContentResult moveChildResult = Result<CreateContentResult, nsresult> moveChildResult =
mHTMLEditor.InsertNodeIntoProperAncestorWithTransaction<nsIContent>( mHTMLEditor.InsertNodeIntoProperAncestorWithTransaction<nsIContent>(
MOZ_KnownLive(child), pointToInsert, MOZ_KnownLive(child), pointToInsert,
SplitAtEdges::eDoNotCreateEmptyContainer); SplitAtEdges::eDoNotCreateEmptyContainer);
inserted |= if (MOZ_UNLIKELY(moveChildResult.isErr())) {
moveChildResult.isOk() || moveChildResult.GotUnexpectedDOMTree();
if (moveChildResult.isErr()) {
// If moving node is moved to different place, we should ignore // If moving node is moved to different place, we should ignore
// this result and keep trying to insert next content node to same // this result and keep trying to insert next content node to same
// position. // position.
if (moveChildResult.GotUnexpectedDOMTree()) { if (moveChildResult.inspectErr() ==
NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE) {
inserted = true;
continue; // the inner `for` loop continue; // the inner `for` loop
} }
NS_WARNING( NS_WARNING(
@ -903,10 +906,12 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
"ignored"); "ignored");
break; // from the inner `for` loop break; // from the inner `for` loop
} }
inserted = true;
lastInsertedPoint.Set(child); lastInsertedPoint.Set(child);
pointToInsert = lastInsertedPoint.NextPoint(); pointToInsert = lastInsertedPoint.NextPoint();
MOZ_ASSERT(pointToInsert.IsSet()); MOZ_ASSERT(pointToInsert.IsSet());
moveChildResult.MoveCaretPointTo( CreateContentResult unwrappedMoveChildResult = moveChildResult.unwrap();
unwrappedMoveChildResult.MoveCaretPointTo(
pointToPutCaret, mHTMLEditor, pointToPutCaret, mHTMLEditor,
{SuggestCaret::OnlyIfHasSuggestion, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt}); SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
@ -961,24 +966,22 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
} }
} }
// MOZ_KnownLive(child) because of bug 1622253 // MOZ_KnownLive(child) because of bug 1622253
CreateContentResult moveChildResult = Result<CreateContentResult, nsresult> moveChildResult =
mHTMLEditor mHTMLEditor
.InsertNodeIntoProperAncestorWithTransaction<nsIContent>( .InsertNodeIntoProperAncestorWithTransaction<nsIContent>(
MOZ_KnownLive(child), pointToInsert, MOZ_KnownLive(child), pointToInsert,
SplitAtEdges::eDoNotCreateEmptyContainer); SplitAtEdges::eDoNotCreateEmptyContainer);
inserted |= if (MOZ_UNLIKELY(moveChildResult.isErr())) {
moveChildResult.isOk() || moveChildResult.GotUnexpectedDOMTree();
if (moveChildResult.isErr()) {
// If moving node is moved to different place, we should ignore // If moving node is moved to different place, we should ignore
// this result and keep trying to insert next content node to // this result and keep trying to insert next content node to
// same position. // same position.
if (moveChildResult.GotUnexpectedDOMTree()) { if (moveChildResult.inspectErr() ==
NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE) {
inserted = true;
continue; // the inner `for` loop continue; // the inner `for` loop
} }
if (moveChildResult.EditorDestroyed()) { if (NS_WARN_IF(moveChildResult.inspectErr() ==
NS_WARNING( NS_ERROR_EDITOR_DESTROYED)) {
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction() "
"caused destroying the editor");
return Err(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
NS_WARNING( NS_WARNING(
@ -987,10 +990,13 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
"ignored"); "ignored");
break; // from the inner `for` loop break; // from the inner `for` loop
} }
inserted = true;
lastInsertedPoint.Set(child); lastInsertedPoint.Set(child);
pointToInsert = lastInsertedPoint.NextPoint(); pointToInsert = lastInsertedPoint.NextPoint();
MOZ_ASSERT(pointToInsert.IsSet()); MOZ_ASSERT(pointToInsert.IsSet());
moveChildResult.MoveCaretPointTo( CreateContentResult unwrappedMoveChildResult =
moveChildResult.unwrap();
unwrappedMoveChildResult.MoveCaretPointTo(
pointToPutCaret, mHTMLEditor, pointToPutCaret, mHTMLEditor,
{SuggestCaret::OnlyIfHasSuggestion, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt}); SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
@ -1042,23 +1048,21 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
EditorDOMPoint pointToPutCaret; EditorDOMPoint pointToPutCaret;
for (const OwningNonNull<nsIContent>& child : children) { for (const OwningNonNull<nsIContent>& child : children) {
// MOZ_KnownLive(child) because of bug 1622253 // MOZ_KnownLive(child) because of bug 1622253
CreateContentResult moveChildResult = Result<CreateContentResult, nsresult> moveChildResult =
mHTMLEditor.InsertNodeIntoProperAncestorWithTransaction<nsIContent>( mHTMLEditor.InsertNodeIntoProperAncestorWithTransaction<nsIContent>(
MOZ_KnownLive(child), pointToInsert, MOZ_KnownLive(child), pointToInsert,
SplitAtEdges::eDoNotCreateEmptyContainer); SplitAtEdges::eDoNotCreateEmptyContainer);
inserted |= if (MOZ_UNLIKELY(moveChildResult.isErr())) {
moveChildResult.isOk() || moveChildResult.GotUnexpectedDOMTree();
if (moveChildResult.isErr()) {
// If moving node is moved to different place, we should ignore // If moving node is moved to different place, we should ignore
// this result and keep trying to insert next content node there. // this result and keep trying to insert next content node there.
if (moveChildResult.GotUnexpectedDOMTree()) { if (moveChildResult.inspectErr() ==
NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE) {
inserted = true;
continue; // the inner `for` loop continue; // the inner `for` loop
} }
if (moveChildResult.EditorDestroyed()) { if (NS_WARN_IF(moveChildResult.inspectErr() ==
NS_WARNING( NS_ERROR_EDITOR_DESTROYED)) {
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction() " return moveChildResult.propagateErr();
"caused destroying the editor");
return Err(NS_ERROR_EDITOR_DESTROYED);
} }
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction(" "HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
@ -1066,10 +1070,12 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
"ignored"); "ignored");
break; // from the inner `for` loop break; // from the inner `for` loop
} }
CreateContentResult unwrappedMoveChildResult = moveChildResult.unwrap();
inserted = true;
lastInsertedPoint.Set(child); lastInsertedPoint.Set(child);
pointToInsert = lastInsertedPoint.NextPoint(); pointToInsert = lastInsertedPoint.NextPoint();
MOZ_ASSERT(pointToInsert.IsSet()); MOZ_ASSERT(pointToInsert.IsSet());
moveChildResult.MoveCaretPointTo( unwrappedMoveChildResult.MoveCaretPointTo(
pointToPutCaret, mHTMLEditor, pointToPutCaret, mHTMLEditor,
{SuggestCaret::OnlyIfHasSuggestion, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt}); SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
@ -1095,14 +1101,14 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
if (!inserted) { if (!inserted) {
// MOZ_KnownLive(content) because 'aArrayOfTopMostChildContents' is // MOZ_KnownLive(content) because 'aArrayOfTopMostChildContents' is
// guaranteed to keep it alive. // guaranteed to keep it alive.
const CreateContentResult moveContentResult = Result<CreateContentResult, nsresult> moveContentResult =
mHTMLEditor.InsertNodeIntoProperAncestorWithTransaction<nsIContent>( mHTMLEditor.InsertNodeIntoProperAncestorWithTransaction<nsIContent>(
MOZ_KnownLive(content), pointToInsert, MOZ_KnownLive(content), pointToInsert,
SplitAtEdges::eDoNotCreateEmptyContainer); SplitAtEdges::eDoNotCreateEmptyContainer);
if (moveContentResult.isOk()) { if (MOZ_LIKELY(moveContentResult.isOk())) {
lastInsertedPoint.Set(content); lastInsertedPoint.Set(content);
pointToInsert = lastInsertedPoint; pointToInsert = lastInsertedPoint;
nsresult rv = moveContentResult.SuggestCaretPointTo( nsresult rv = moveContentResult.inspect().SuggestCaretPointTo(
mHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion, mHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});
@ -1113,7 +1119,8 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR, rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"CreateContentResult::SuggestCaretPointTo() failed, but ignored"); "CreateContentResult::SuggestCaretPointTo() failed, but ignored");
} else if (moveContentResult.GotUnexpectedDOMTree()) { } else if (moveContentResult.inspectErr() ==
NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE) {
// Moving node is moved to different place, we should keep trying to // Moving node is moved to different place, we should keep trying to
// insert the next content to same position. // insert the next content to same position.
} else { } else {
@ -1133,22 +1140,20 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
} }
const OwningNonNull<nsIContent> oldParentContent = const OwningNonNull<nsIContent> oldParentContent =
*childContent->GetParent(); *childContent->GetParent();
const CreateContentResult moveParentResult = Result<CreateContentResult, nsresult> moveParentResult =
mHTMLEditor mHTMLEditor
.InsertNodeIntoProperAncestorWithTransaction<nsIContent>( .InsertNodeIntoProperAncestorWithTransaction<nsIContent>(
oldParentContent, pointToInsert, oldParentContent, pointToInsert,
SplitAtEdges::eDoNotCreateEmptyContainer); SplitAtEdges::eDoNotCreateEmptyContainer);
if (moveParentResult.isErr()) { if (MOZ_UNLIKELY(moveParentResult.isErr())) {
// Moving node is moved to different place, we should keep trying to // Moving node is moved to different place, we should keep trying to
// insert the next content to same position. // insert the next content to same position.
if (moveParentResult.GotUnexpectedDOMTree()) { if (moveParentResult.inspectErr() ==
NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE) {
break; // from the inner `for` loop break; // from the inner `for` loop
} }
if (moveParentResult.EditorDestroyed()) { if (NS_WARN_IF(moveParentResult.inspectErr() ==
NS_WARNING( NS_ERROR_EDITOR_DESTROYED)) {
"HTMLEditor::InsertNodeInToProperAncestorWithTransaction("
"SplitAtEdges::eDoNotCreateEmptyContainer) caused destroying "
"the editor");
return Err(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
NS_WARNING( NS_WARNING(
@ -1159,7 +1164,7 @@ HTMLEditor::HTMLWithContextInserter::InsertContents(
} }
insertedContextParentContent = oldParentContent; insertedContextParentContent = oldParentContent;
pointToInsert.Set(oldParentContent); pointToInsert.Set(oldParentContent);
nsresult rv = moveParentResult.SuggestCaretPointTo( nsresult rv = moveParentResult.inspect().SuggestCaretPointTo(
mHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion, mHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});

View file

@ -5322,22 +5322,23 @@ Result<MoveNodeResult, nsresult> HTMLEditor::MoveNodeOrChildrenWithTransaction(
NS_WARNING_ASSERTION(!error.Failed(), NS_WARNING_ASSERTION(!error.Failed(),
"Element::SetAttr(nsGkAtoms::span) failed"); "Element::SetAttr(nsGkAtoms::span) failed");
if (MOZ_LIKELY(!error.Failed())) { if (MOZ_LIKELY(!error.Failed())) {
CreateElementResult insertSpanElementResult = Result<CreateElementResult, nsresult> insertSpanElementResult =
InsertNodeWithTransaction<Element>(*newSpanElement, InsertNodeWithTransaction<Element>(*newSpanElement,
aPointToInsert); aPointToInsert);
if (NS_WARN_IF(insertSpanElementResult.EditorDestroyed())) { if (MOZ_UNLIKELY(insertSpanElementResult.isErr())) {
return Err(NS_ERROR_EDITOR_DESTROYED); if (NS_WARN_IF(insertSpanElementResult.inspectErr() ==
} NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING_ASSERTION( return Err(NS_ERROR_EDITOR_DESTROYED);
insertSpanElementResult.isOk(), }
"HTMLEditor::InsertNodeWithTransaction() failed, but ignored"); NS_WARNING(
if (MOZ_LIKELY(insertSpanElementResult.isOk())) { "HTMLEditor::InsertNodeWithTransaction() failed, but ignored");
} else {
// We should move the node into the new <span> to preserve the // We should move the node into the new <span> to preserve the
// style. // style.
pointToInsert.Set(newSpanElement, 0u); pointToInsert.Set(newSpanElement, 0u);
// We should put caret after aContentToMove after moving it so that // We should put caret after aContentToMove after moving it so that
// we do not need the suggested caret point here. // we do not need the suggested caret point here.
insertSpanElementResult.IgnoreCaretPointSuggestion(); insertSpanElementResult.inspect().IgnoreCaretPointSuggestion();
} }
} }
} }
@ -5642,19 +5643,17 @@ nsresult HTMLEditor::DeleteMostAncestorMailCiteElementIfEmpty(
return NS_OK; return NS_OK;
} }
CreateElementResult insertBRElementResult = Result<CreateElementResult, nsresult> insertBRElementResult =
InsertBRElement(WithTransaction::Yes, atEmptyMailCiteElement); InsertBRElement(WithTransaction::Yes, atEmptyMailCiteElement);
if (insertBRElementResult.isErr()) { if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return insertBRElementResult.unwrapErr(); return insertBRElementResult.unwrapErr();
} }
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(insertBRElementResult.inspect().GetNewNode());
insertBRElementResult.IgnoreCaretPointSuggestion(); insertBRElementResult.inspect().IgnoreCaretPointSuggestion();
nsresult rv = CollapseSelectionTo( nsresult rv = CollapseSelectionTo(
EditorRawDOMPoint(insertBRElementResult.GetNewNode())); EditorRawDOMPoint(insertBRElementResult.inspect().GetNewNode()));
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) { if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING(
"EditorBase::CollapseSelectionTo() caused destroying the editor");
return NS_ERROR_EDITOR_DESTROYED; return NS_ERROR_EDITOR_DESTROYED;
} }
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
@ -5809,13 +5808,16 @@ HTMLEditor::AutoDeleteRangesHandler::AutoEmptyBlockAncestorDeleter::
if (HTMLEditUtils::IsAnyListElement(atParentOfEmptyListItem.GetContainer())) { if (HTMLEditUtils::IsAnyListElement(atParentOfEmptyListItem.GetContainer())) {
return RefPtr<Element>(); return RefPtr<Element>();
} }
CreateElementResult insertBRElementResult = aHTMLEditor.InsertBRElement( Result<CreateElementResult, nsresult> insertBRElementResult =
WithTransaction::Yes, atParentOfEmptyListItem); aHTMLEditor.InsertBRElement(WithTransaction::Yes,
if (insertBRElementResult.isErr()) { atParentOfEmptyListItem);
if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); NS_WARNING("HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return Err(insertBRElementResult.unwrapErr()); return insertBRElementResult.propagateErr();
} }
nsresult rv = insertBRElementResult.SuggestCaretPointTo( CreateElementResult unwrappedInsertBRElementResult =
insertBRElementResult.unwrap();
nsresult rv = unwrappedInsertBRElementResult.SuggestCaretPointTo(
aHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion, aHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});
@ -5823,8 +5825,8 @@ HTMLEditor::AutoDeleteRangesHandler::AutoEmptyBlockAncestorDeleter::
NS_WARNING("CreateElementResult::SuggestCaretPointTo() failed"); NS_WARNING("CreateElementResult::SuggestCaretPointTo() failed");
return Err(rv); return Err(rv);
} }
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(unwrappedInsertBRElementResult.GetNewNode());
return insertBRElementResult.UnwrapNewNode(); return unwrappedInsertBRElementResult.UnwrapNewNode();
} }
Result<EditorDOMPoint, nsresult> HTMLEditor::AutoDeleteRangesHandler:: Result<EditorDOMPoint, nsresult> HTMLEditor::AutoDeleteRangesHandler::

View file

@ -801,18 +801,20 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::SetInlinePropertyOnNodeImpl(
!aContent.AsElement()->GetAttrCount()) { !aContent.AsElement()->GetAttrCount()) {
spanElement = aContent.AsElement(); spanElement = aContent.AsElement();
} else { } else {
CreateElementResult wrapWithSpanElementResult = Result<CreateElementResult, nsresult> wrapInSpanElementResult =
InsertContainerWithTransaction(aContent, *nsGkAtoms::span); InsertContainerWithTransaction(aContent, *nsGkAtoms::span);
if (wrapWithSpanElementResult.isErr()) { if (MOZ_UNLIKELY(wrapInSpanElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertContainerWithTransaction(nsGkAtoms::span) " "HTMLEditor::InsertContainerWithTransaction(nsGkAtoms::span) "
"failed"); "failed");
return Err(wrapWithSpanElementResult.unwrapErr()); return wrapInSpanElementResult.propagateErr();
} }
MOZ_ASSERT(wrapWithSpanElementResult.GetNewNode()); CreateElementResult unwrappedWrapInSpanElementResult =
wrapWithSpanElementResult.MoveCaretPointTo( wrapInSpanElementResult.unwrap();
MOZ_ASSERT(unwrappedWrapInSpanElementResult.GetNewNode());
unwrappedWrapInSpanElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
spanElement = wrapWithSpanElementResult.UnwrapNewNode(); spanElement = unwrappedWrapInSpanElementResult.UnwrapNewNode();
} }
// Add the CSS styles corresponding to the HTML style request // Add the CSS styles corresponding to the HTML style request
@ -858,16 +860,16 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::SetInlinePropertyOnNodeImpl(
} }
// ok, chuck it in its very own container // ok, chuck it in its very own container
CreateElementResult wrapWithNewElementToFormatResult = Result<CreateElementResult, nsresult> wrapWithNewElementToFormatResult =
InsertContainerWithTransaction( InsertContainerWithTransaction(
aContent, aProperty, aAttribute ? *aAttribute : *nsGkAtoms::_empty, aContent, aProperty, aAttribute ? *aAttribute : *nsGkAtoms::_empty,
aValue); aValue);
if (wrapWithNewElementToFormatResult.isErr()) { if (MOZ_UNLIKELY(wrapWithNewElementToFormatResult.isErr())) {
NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed"); NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed");
return Err(wrapWithNewElementToFormatResult.unwrapErr()); return wrapWithNewElementToFormatResult.propagateErr();
} }
MOZ_ASSERT(wrapWithNewElementToFormatResult.GetNewNode()); MOZ_ASSERT(wrapWithNewElementToFormatResult.inspect().GetNewNode());
return wrapWithNewElementToFormatResult.UnwrapCaretPoint(); return wrapWithNewElementToFormatResult.unwrap().UnwrapCaretPoint();
} }
Result<EditorDOMPoint, nsresult> HTMLEditor::SetInlinePropertyOnNode( Result<EditorDOMPoint, nsresult> HTMLEditor::SetInlinePropertyOnNode(
@ -1446,19 +1448,21 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::RemoveStyleInside(
aElement.HasAttr(kNameSpaceID_None, nsGkAtoms::_class))) { aElement.HasAttr(kNameSpaceID_None, nsGkAtoms::_class))) {
// Move `style` attribute and `class` element to span element before // Move `style` attribute and `class` element to span element before
// removing aElement from the tree. // removing aElement from the tree.
CreateElementResult wrapWithSpanElementResult = Result<CreateElementResult, nsresult> wrapInSpanElementResult =
InsertContainerWithTransaction(aElement, *nsGkAtoms::span); InsertContainerWithTransaction(aElement, *nsGkAtoms::span);
if (wrapWithSpanElementResult.isErr()) { if (wrapInSpanElementResult.isErr()) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertContainerWithTransaction(nsGkAtoms::span) " "HTMLEditor::InsertContainerWithTransaction(nsGkAtoms::span) "
"failed"); "failed");
return Err(wrapWithSpanElementResult.unwrapErr()); return wrapInSpanElementResult.propagateErr();
} }
MOZ_ASSERT(wrapWithSpanElementResult.GetNewNode()); CreateElementResult unwrappedWrapInSpanElementResult =
wrapWithSpanElementResult.MoveCaretPointTo( wrapInSpanElementResult.unwrap();
MOZ_ASSERT(unwrappedWrapInSpanElementResult.GetNewNode());
unwrappedWrapInSpanElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
const RefPtr<Element> spanElement = const RefPtr<Element> spanElement =
wrapWithSpanElementResult.UnwrapNewNode(); unwrappedWrapInSpanElementResult.UnwrapNewNode();
nsresult rv = CloneAttributeWithTransaction(*nsGkAtoms::style, nsresult rv = CloneAttributeWithTransaction(*nsGkAtoms::style,
*spanElement, aElement); *spanElement, aElement);
if (NS_WARN_IF(Destroyed())) { if (NS_WARN_IF(Destroyed())) {
@ -2693,18 +2697,18 @@ nsresult HTMLEditor::IncrementOrDecrementFontSizeAsSubAction(
} }
if (range.InSameContainer() && range.StartRef().IsInTextNode()) { if (range.InSameContainer() && range.StartRef().IsInTextNode()) {
CreateElementResult wrapWithBigOrSmallElementResult = Result<CreateElementResult, nsresult> wrapInBigOrSmallElementResult =
SetFontSizeOnTextNode( SetFontSizeOnTextNode(
MOZ_KnownLive(*range.StartRef().ContainerAs<Text>()), MOZ_KnownLive(*range.StartRef().ContainerAs<Text>()),
range.StartRef().Offset(), range.EndRef().Offset(), range.StartRef().Offset(), range.EndRef().Offset(),
aIncrementOrDecrement); aIncrementOrDecrement);
if (wrapWithBigOrSmallElementResult.isErr()) { if (MOZ_UNLIKELY(wrapInBigOrSmallElementResult.isErr())) {
NS_WARNING("HTMLEditor::SetFontSizeOnTextNode() failed"); NS_WARNING("HTMLEditor::SetFontSizeOnTextNode() failed");
return wrapWithBigOrSmallElementResult.unwrapErr(); return wrapInBigOrSmallElementResult.unwrapErr();
} }
// There is an AutoTransactionsConserveSelection instance so that we don't // There is an AutoTransactionsConserveSelection instance so that we don't
// need to update selection for this change. // need to update selection for this change.
wrapWithBigOrSmallElementResult.IgnoreCaretPointSuggestion(); wrapInBigOrSmallElementResult.inspect().IgnoreCaretPointSuggestion();
continue; continue;
} }
@ -2757,34 +2761,34 @@ nsresult HTMLEditor::IncrementOrDecrementFontSizeAsSubAction(
!range.StartRef().IsEndOfContainer() && !range.StartRef().IsEndOfContainer() &&
EditorUtils::IsEditableContent(*range.StartRef().ContainerAs<Text>(), EditorUtils::IsEditableContent(*range.StartRef().ContainerAs<Text>(),
EditorType::HTML)) { EditorType::HTML)) {
CreateElementResult wrapWithBigOrSmallElementResult = Result<CreateElementResult, nsresult> wrapInBigOrSmallElementResult =
SetFontSizeOnTextNode( SetFontSizeOnTextNode(
MOZ_KnownLive(*range.StartRef().ContainerAs<Text>()), MOZ_KnownLive(*range.StartRef().ContainerAs<Text>()),
range.StartRef().Offset(), range.StartRef().Offset(),
range.StartRef().ContainerAs<Text>()->TextDataLength(), range.StartRef().ContainerAs<Text>()->TextDataLength(),
aIncrementOrDecrement); aIncrementOrDecrement);
if (wrapWithBigOrSmallElementResult.isErr()) { if (MOZ_UNLIKELY(wrapInBigOrSmallElementResult.isErr())) {
NS_WARNING("HTMLEditor::SetFontSizeOnTextNode() failed"); NS_WARNING("HTMLEditor::SetFontSizeOnTextNode() failed");
return wrapWithBigOrSmallElementResult.unwrapErr(); return wrapInBigOrSmallElementResult.unwrapErr();
} }
// There is an AutoTransactionsConserveSelection instance so that we // There is an AutoTransactionsConserveSelection instance so that we
// don't need to update selection for this change. // don't need to update selection for this change.
wrapWithBigOrSmallElementResult.IgnoreCaretPointSuggestion(); wrapInBigOrSmallElementResult.inspect().IgnoreCaretPointSuggestion();
} }
if (range.EndRef().IsInTextNode() && !range.EndRef().IsStartOfContainer() && if (range.EndRef().IsInTextNode() && !range.EndRef().IsStartOfContainer() &&
EditorUtils::IsEditableContent(*range.EndRef().ContainerAs<Text>(), EditorUtils::IsEditableContent(*range.EndRef().ContainerAs<Text>(),
EditorType::HTML)) { EditorType::HTML)) {
CreateElementResult wrapWithBigOrSmallElementResult = Result<CreateElementResult, nsresult> wrapInBigOrSmallElementResult =
SetFontSizeOnTextNode( SetFontSizeOnTextNode(
MOZ_KnownLive(*range.EndRef().ContainerAs<Text>()), 0u, MOZ_KnownLive(*range.EndRef().ContainerAs<Text>()), 0u,
range.EndRef().Offset(), aIncrementOrDecrement); range.EndRef().Offset(), aIncrementOrDecrement);
if (wrapWithBigOrSmallElementResult.isErr()) { if (MOZ_UNLIKELY(wrapInBigOrSmallElementResult.isErr())) {
NS_WARNING("HTMLEditor::SetFontSizeOnTextNode() failed"); NS_WARNING("HTMLEditor::SetFontSizeOnTextNode() failed");
return wrapWithBigOrSmallElementResult.unwrapErr(); return wrapInBigOrSmallElementResult.unwrapErr();
} }
// There is an AutoTransactionsConserveSelection instance so that we // There is an AutoTransactionsConserveSelection instance so that we
// don't need to update selection for this change. // don't need to update selection for this change.
wrapWithBigOrSmallElementResult.IgnoreCaretPointSuggestion(); wrapInBigOrSmallElementResult.inspect().IgnoreCaretPointSuggestion();
} }
} }
@ -2798,7 +2802,7 @@ nsresult HTMLEditor::IncrementOrDecrementFontSizeAsSubAction(
return rv; return rv;
} }
CreateElementResult HTMLEditor::SetFontSizeOnTextNode( Result<CreateElementResult, nsresult> HTMLEditor::SetFontSizeOnTextNode(
Text& aTextNode, uint32_t aStartOffset, uint32_t aEndOffset, Text& aTextNode, uint32_t aStartOffset, uint32_t aEndOffset,
FontSize aIncrementOrDecrement) { FontSize aIncrementOrDecrement) {
// Don't need to do anything if no characters actually selected // Don't need to do anything if no characters actually selected
@ -2878,7 +2882,7 @@ CreateElementResult HTMLEditor::SetFontSizeOnTextNode(
}(); }();
if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) { if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
// Don't warn here since it should be done in the lambda. // Don't warn here since it should be done in the lambda.
return CreateElementResult(pointToPutCaretOrError.unwrapErr()); return pointToPutCaretOrError.propagateErr();
} }
pointToPutCaret = pointToPutCaretOrError.unwrap(); pointToPutCaret = pointToPutCaretOrError.unwrap();
} }
@ -2895,7 +2899,7 @@ CreateElementResult HTMLEditor::SetFontSizeOnTextNode(
MoveNodeToEndWithTransaction(*textNodeForTheRange, *sibling); MoveNodeToEndWithTransaction(*textNodeForTheRange, *sibling);
if (MOZ_UNLIKELY(moveTextNodeResult.isErr())) { if (MOZ_UNLIKELY(moveTextNodeResult.isErr())) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return CreateElementResult(moveTextNodeResult.unwrapErr()); return moveTextNodeResult.propagateErr();
} }
MoveNodeResult unwrappedMoveTextNodeResult = moveTextNodeResult.unwrap(); MoveNodeResult unwrappedMoveTextNodeResult = moveTextNodeResult.unwrap();
unwrappedMoveTextNodeResult.MoveCaretPointTo( unwrappedMoveTextNodeResult.MoveCaretPointTo(
@ -2912,7 +2916,7 @@ CreateElementResult HTMLEditor::SetFontSizeOnTextNode(
EditorDOMPoint(sibling, 0u)); EditorDOMPoint(sibling, 0u));
if (MOZ_UNLIKELY(moveTextNodeResult.isErr())) { if (MOZ_UNLIKELY(moveTextNodeResult.isErr())) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed"); NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return CreateElementResult(moveTextNodeResult.unwrapErr()); return moveTextNodeResult.propagateErr();
} }
MoveNodeResult unwrappedMoveTextNodeResult = moveTextNodeResult.unwrap(); MoveNodeResult unwrappedMoveTextNodeResult = moveTextNodeResult.unwrap();
unwrappedMoveTextNodeResult.MoveCaretPointTo( unwrappedMoveTextNodeResult.MoveCaretPointTo(
@ -2922,17 +2926,19 @@ CreateElementResult HTMLEditor::SetFontSizeOnTextNode(
} }
// Else wrap the node inside font node with appropriate relative size // Else wrap the node inside font node with appropriate relative size
CreateElementResult wrapTextWithBigOrSmallElementResult = Result<CreateElementResult, nsresult> wrapTextInBigOrSmallElementResult =
InsertContainerWithTransaction(*textNodeForTheRange, InsertContainerWithTransaction(*textNodeForTheRange,
MOZ_KnownLive(*bigOrSmallTagName)); MOZ_KnownLive(*bigOrSmallTagName));
if (wrapTextWithBigOrSmallElementResult.isErr()) { if (wrapTextInBigOrSmallElementResult.isErr()) {
NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed"); NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed");
return wrapTextWithBigOrSmallElementResult; return wrapTextInBigOrSmallElementResult;
} }
wrapTextWithBigOrSmallElementResult.MoveCaretPointTo( CreateElementResult unwrappedWrapTextInBigOrSmallElementResult =
wrapTextInBigOrSmallElementResult.unwrap();
unwrappedWrapTextInBigOrSmallElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
return CreateElementResult( return CreateElementResult(
wrapTextWithBigOrSmallElementResult.UnwrapNewNode(), unwrappedWrapTextInBigOrSmallElementResult.UnwrapNewNode(),
std::move(pointToPutCaret)); std::move(pointToPutCaret));
} }
@ -3066,15 +3072,17 @@ Result<EditorDOMPoint, nsresult> HTMLEditor::SetFontSizeWithBigOrSmallElement(
} }
// Otherwise, wrap aContent in new <big> or <small> // Otherwise, wrap aContent in new <big> or <small>
CreateElementResult wrapInBigOrSmallElementResult = Result<CreateElementResult, nsresult> wrapInBigOrSmallElementResult =
InsertContainerWithTransaction(aContent, InsertContainerWithTransaction(aContent,
MOZ_KnownLive(*bigOrSmallTagName)); MOZ_KnownLive(*bigOrSmallTagName));
if (wrapInBigOrSmallElementResult.isErr()) { if (MOZ_UNLIKELY(wrapInBigOrSmallElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed"); NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed");
return Err(wrapInBigOrSmallElementResult.unwrapErr()); return Err(wrapInBigOrSmallElementResult.unwrapErr());
} }
MOZ_ASSERT(wrapInBigOrSmallElementResult.GetNewNode()); CreateElementResult unwrappedWrapInBigOrSmallElementResult =
wrapInBigOrSmallElementResult.MoveCaretPointTo( wrapInBigOrSmallElementResult.unwrap();
MOZ_ASSERT(unwrappedWrapInBigOrSmallElementResult.GetNewNode());
unwrappedWrapInBigOrSmallElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion}); pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
return pointToPutCaret; return pointToPutCaret;
} }

View file

@ -273,15 +273,15 @@ nsresult HTMLEditor::InsertCell(Element* aCell, int32_t aRowSpan,
// actions which may be caused by legacy mutation event listeners or // actions which may be caused by legacy mutation event listeners or
// chrome script. // chrome script.
AutoTransactionsConserveSelection dontChangeSelection(*this); AutoTransactionsConserveSelection dontChangeSelection(*this);
CreateElementResult insertNewCellResult = Result<CreateElementResult, nsresult> insertNewCellResult =
InsertNodeWithTransaction<Element>(*newCell, pointToInsert); InsertNodeWithTransaction<Element>(*newCell, pointToInsert);
if (insertNewCellResult.isErr()) { if (MOZ_UNLIKELY(insertNewCellResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertNewCellResult.unwrapErr(); return insertNewCellResult.unwrapErr();
} }
// Because of dontChangeSelection, we've never allowed to transactions to // Because of dontChangeSelection, we've never allowed to transactions to
// update selection here. // update selection here.
insertNewCellResult.IgnoreCaretPointSuggestion(); insertNewCellResult.inspect().IgnoreCaretPointSuggestion();
return NS_OK; return NS_OK;
} }
@ -350,18 +350,19 @@ NS_IMETHODIMP HTMLEditor::InsertTableCell(int32_t aNumberOfCellsToInsert,
advanced, advanced,
"Failed to set insertion point after current cell, but ignored"); "Failed to set insertion point after current cell, but ignored");
} }
const CreateElementResult insertCellElementResult = Result<CreateElementResult, nsresult> insertCellElementResult =
InsertTableCellsWithTransaction(pointToInsert, aNumberOfCellsToInsert); InsertTableCellsWithTransaction(pointToInsert, aNumberOfCellsToInsert);
if (insertCellElementResult.isErr()) { if (MOZ_UNLIKELY(insertCellElementResult.isErr())) {
NS_WARNING("HTMLEditor::InsertTableCellsWithTransaction() failed"); NS_WARNING("HTMLEditor::InsertTableCellsWithTransaction() failed");
return EditorBase::ToGenericNSResult(insertCellElementResult.inspectErr()); return EditorBase::ToGenericNSResult(insertCellElementResult.unwrapErr());
} }
// We don't need to modify selection here. // We don't need to modify selection here.
insertCellElementResult.IgnoreCaretPointSuggestion(); insertCellElementResult.inspect().IgnoreCaretPointSuggestion();
return NS_OK; return NS_OK;
} }
CreateElementResult HTMLEditor::InsertTableCellsWithTransaction( Result<CreateElementResult, nsresult>
HTMLEditor::InsertTableCellsWithTransaction(
const EditorDOMPoint& aPointToInsert, int32_t aNumberOfCellsToInsert) { const EditorDOMPoint& aPointToInsert, int32_t aNumberOfCellsToInsert) {
MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aPointToInsert.IsSetAndValid()); MOZ_ASSERT(aPointToInsert.IsSetAndValid());
@ -369,7 +370,7 @@ CreateElementResult HTMLEditor::InsertTableCellsWithTransaction(
if (!HTMLEditUtils::IsTableRow(aPointToInsert.GetContainer())) { if (!HTMLEditUtils::IsTableRow(aPointToInsert.GetContainer())) {
NS_WARNING("Tried to insert cell elements to non-<tr> element"); NS_WARNING("Tried to insert cell elements to non-<tr> element");
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
AutoPlaceholderBatch treateAsOneTransaction( AutoPlaceholderBatch treateAsOneTransaction(
@ -381,7 +382,7 @@ CreateElementResult HTMLEditor::InsertTableCellsWithTransaction(
AutoEditSubActionNotifier startToHandleEditSubAction( AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eInsertNode, nsIEditor::eNext, error); *this, EditSubAction::eInsertNode, nsIEditor::eNext, error);
if (NS_WARN_IF(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) { if (NS_WARN_IF(error.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return CreateElementResult(error.StealNSResult()); return Err(error.StealNSResult());
} }
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
!error.Failed(), !error.Failed(),
@ -422,22 +423,25 @@ CreateElementResult HTMLEditor::InsertTableCellsWithTransaction(
"HTMLEditor::CreateElementWithDefaults(nsGkAtoms::td) failed"); "HTMLEditor::CreateElementWithDefaults(nsGkAtoms::td) failed");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
CreateElementResult insertNewCellResult = InsertNodeWithTransaction( Result<CreateElementResult, nsresult> insertNewCellResult =
*newCell, referenceContent InsertNodeWithTransaction(
? EditorDOMPoint(referenceContent) *newCell, referenceContent
: EditorDOMPoint::AtEndOf( ? EditorDOMPoint(referenceContent)
*aPointToInsert.ContainerAs<Element>())); : EditorDOMPoint::AtEndOf(
if (insertNewCellResult.isErr()) { *aPointToInsert.ContainerAs<Element>()));
if (MOZ_UNLIKELY(insertNewCellResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertNewCellResult.unwrapErr(); return insertNewCellResult.unwrapErr();
} }
lastCellElement = insertNewCellResult.UnwrapNewNode(); CreateElementResult unwrappedInsertNewCellResult =
insertNewCellResult.unwrap();
lastCellElement = unwrappedInsertNewCellResult.UnwrapNewNode();
if (!firstCellElement) { if (!firstCellElement) {
firstCellElement = lastCellElement; firstCellElement = lastCellElement;
} }
// Because of dontChangeSelection, we've never allowed to transactions // Because of dontChangeSelection, we've never allowed to transactions
// to update selection here. // to update selection here.
insertNewCellResult.IgnoreCaretPointSuggestion(); unwrappedInsertNewCellResult.IgnoreCaretPointSuggestion();
if (!cellToPutCaret) { if (!cellToPutCaret) {
cellToPutCaret = std::move(newCell); // This is first cell in the row. cellToPutCaret = std::move(newCell); // This is first cell in the row.
} }
@ -451,10 +455,10 @@ CreateElementResult HTMLEditor::InsertTableCellsWithTransaction(
}(); }();
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED || if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED ||
NS_WARN_IF(Destroyed()))) { NS_WARN_IF(Destroyed()))) {
return CreateElementResult(NS_ERROR_EDITOR_DESTROYED); return Err(NS_ERROR_EDITOR_DESTROYED);
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return CreateElementResult(rv); return Err(rv);
} }
MOZ_ASSERT(firstCellElement); MOZ_ASSERT(firstCellElement);
MOZ_ASSERT(lastCellElement); MOZ_ASSERT(lastCellElement);
@ -812,19 +816,22 @@ nsresult HTMLEditor::InsertTableColumnsWithTransaction(
if (NS_WARN_IF(!pointToInsert.IsInContentNode())) { if (NS_WARN_IF(!pointToInsert.IsInContentNode())) {
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE); return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
} }
CreateElementResult insertCellElementsResult = Result<CreateElementResult, nsresult> insertCellElementsResult =
InsertTableCellsWithTransaction(pointToInsert, InsertTableCellsWithTransaction(pointToInsert,
aNumberOfColumnsToInsert); aNumberOfColumnsToInsert);
if (insertCellElementsResult.isErr()) { if (MOZ_UNLIKELY(insertCellElementsResult.isErr())) {
NS_WARNING("HTMLEditor::InsertTableCellsWithTransaction() failed"); NS_WARNING("HTMLEditor::InsertTableCellsWithTransaction() failed");
return Err(insertCellElementsResult.unwrapErr()); return insertCellElementsResult.propagateErr();
} }
CreateElementResult unwrappedInsertCellElementsResult =
insertCellElementsResult.unwrap();
// We'll update selection later into the first inserted cell element in // We'll update selection later into the first inserted cell element in
// the current row. // the current row.
insertCellElementsResult.IgnoreCaretPointSuggestion(); unwrappedInsertCellElementsResult.IgnoreCaretPointSuggestion();
if (pointToInsert.ContainerAs<Element>() == if (pointToInsert.ContainerAs<Element>() ==
aPointToInsert.ContainerAs<Element>()) { aPointToInsert.ContainerAs<Element>()) {
cellElementToPutCaret = insertCellElementsResult.UnwrapNewNode(); cellElementToPutCaret =
unwrappedInsertCellElementsResult.UnwrapNewNode();
MOZ_ASSERT(cellElementToPutCaret); MOZ_ASSERT(cellElementToPutCaret);
MOZ_ASSERT(HTMLEditUtils::IsTableCell(cellElementToPutCaret)); MOZ_ASSERT(HTMLEditUtils::IsTableCell(cellElementToPutCaret));
} }
@ -1147,15 +1154,19 @@ nsresult HTMLEditor::InsertTableRowsWithTransaction(
} }
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert); AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert);
CreateElementResult insertNewRowResult = Result<CreateElementResult, nsresult> insertNewRowResult =
InsertNodeWithTransaction<Element>(*newRowElement, pointToInsert); InsertNodeWithTransaction<Element>(*newRowElement, pointToInsert);
if (insertNewRowResult.isErr() && !insertNewRowResult.EditorDestroyed()) { if (MOZ_UNLIKELY(insertNewRowResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); if (insertNewRowResult.inspectErr() == NS_ERROR_EDITOR_DESTROYED) {
return Err(insertNewRowResult.unwrapErr()); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertNewRowResult.propagateErr();
}
NS_WARNING(
"EditorBase::InsertNodeWithTransaction() failed, but ignored");
} }
firstInsertedTRElement = std::move(newRowElement); firstInsertedTRElement = std::move(newRowElement);
// We'll update selection later. // We'll update selection later.
insertNewRowResult.IgnoreCaretPointSuggestion(); insertNewRowResult.inspect().IgnoreCaretPointSuggestion();
} }
return firstInsertedTRElement; return firstInsertedTRElement;
}(); }();
@ -2909,21 +2920,21 @@ NS_IMETHODIMP HTMLEditor::SwitchTableCellHeaderType(Element* aSourceCell,
// This creates new node, moves children, copies attributes (true) // This creates new node, moves children, copies attributes (true)
// and manages the selection! // and manages the selection!
CreateElementResult newCellElementOrError = Result<CreateElementResult, nsresult> newCellElementOrError =
ReplaceContainerAndCloneAttributesWithTransaction( ReplaceContainerAndCloneAttributesWithTransaction(
*aSourceCell, MOZ_KnownLive(*newCellName)); *aSourceCell, MOZ_KnownLive(*newCellName));
if (newCellElementOrError.isErr()) { if (MOZ_UNLIKELY(newCellElementOrError.isErr())) {
NS_WARNING( NS_WARNING(
"EditorBase::ReplaceContainerAndCloneAttributesWithTransaction() " "EditorBase::ReplaceContainerAndCloneAttributesWithTransaction() "
"failed"); "failed");
return newCellElementOrError.unwrapErr(); return newCellElementOrError.unwrapErr();
} }
// restoreSelectionLater will change selection // restoreSelectionLater will change selection
newCellElementOrError.IgnoreCaretPointSuggestion(); newCellElementOrError.inspect().IgnoreCaretPointSuggestion();
// Return the new cell // Return the new cell
if (aNewCell) { if (aNewCell) {
newCellElementOrError.UnwrapNewNode().forget(aNewCell); newCellElementOrError.unwrap().UnwrapNewNode().forget(aNewCell);
} }
return NS_OK; return NS_OK;
@ -3384,13 +3395,16 @@ nsresult HTMLEditor::MergeCells(RefPtr<Element> aTargetCell,
NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed"); NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
return rv; return rv;
} }
CreateContentResult insertChildContentResult = InsertNodeWithTransaction( Result<CreateContentResult, nsresult> insertChildContentResult =
*cellChild, EditorDOMPoint(aTargetCell, insertIndex)); InsertNodeWithTransaction(*cellChild,
if (insertChildContentResult.isErr()) { EditorDOMPoint(aTargetCell, insertIndex));
if (MOZ_UNLIKELY(insertChildContentResult.isErr())) {
NS_WARNING("EditorBase::InsertNodeWithTransaction() failed"); NS_WARNING("EditorBase::InsertNodeWithTransaction() failed");
return insertChildContentResult.unwrapErr(); return insertChildContentResult.unwrapErr();
} }
insertChildContentResult.MoveCaretPointTo( CreateContentResult unwrappedInsertChildContentResult =
insertChildContentResult.unwrap();
unwrappedInsertChildContentResult.MoveCaretPointTo(
pointToPutCaret, *this, pointToPutCaret, *this,
{SuggestCaret::OnlyIfHasSuggestion, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt}); SuggestCaret::OnlyIfTransactionsAllowedToDoIt});

View file

@ -678,19 +678,20 @@ EditActionResult WhiteSpaceVisibilityKeeper::
"HTMLEditor::JoinNearestEditableNodesWithTransaction()" "HTMLEditor::JoinNearestEditableNodesWithTransaction()"
" failed, but ignored"); " failed, but ignored");
if (aListElementTagName.isSome() && atFirstChildOfRightNode.IsSet()) { if (aListElementTagName.isSome() && atFirstChildOfRightNode.IsSet()) {
CreateElementResult convertListTypeResult = Result<CreateElementResult, nsresult> convertListTypeResult =
aHTMLEditor.ChangeListElementType( aHTMLEditor.ChangeListElementType(
aRightBlockElement, MOZ_KnownLive(*aListElementTagName.ref()), aRightBlockElement, MOZ_KnownLive(*aListElementTagName.ref()),
*nsGkAtoms::li); *nsGkAtoms::li);
if (NS_WARN_IF(convertListTypeResult.EditorDestroyed())) { if (MOZ_UNLIKELY(convertListTypeResult.isErr())) {
return EditActionResult(NS_ERROR_EDITOR_DESTROYED); if (NS_WARN_IF(convertListTypeResult.inspectErr() ==
NS_ERROR_EDITOR_DESTROYED)) {
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING("HTMLEditor::ChangeListElementType() failed, but ignored");
} }
// There is AutoTransactionConserveSelection above, therefore, we don't // There is AutoTransactionConserveSelection above, therefore, we don't
// need to update selection here. // need to update selection here.
convertListTypeResult.IgnoreCaretPointSuggestion(); convertListTypeResult.inspect().IgnoreCaretPointSuggestion();
NS_WARNING_ASSERTION(
convertListTypeResult.isOk(),
"HTMLEditor::ChangeListElementType() failed, but ignored");
} }
ret.MarkAsHandled(); ret.MarkAsHandled();
} else { } else {
@ -748,11 +749,12 @@ EditActionResult WhiteSpaceVisibilityKeeper::
} }
// static // static
CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement( Result<CreateElementResult, nsresult>
WhiteSpaceVisibilityKeeper::InsertBRElement(
HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToInsert, HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToInsert,
const Element& aEditingHost) { const Element& aEditingHost) {
if (MOZ_UNLIKELY(NS_WARN_IF(!aPointToInsert.IsSet()))) { if (MOZ_UNLIKELY(NS_WARN_IF(!aPointToInsert.IsSet()))) {
return CreateElementResult(NS_ERROR_INVALID_ARG); return Err(NS_ERROR_INVALID_ARG);
} }
// MOOSE: for now, we always assume non-PRE formatting. Fix this later. // MOOSE: for now, we always assume non-PRE formatting. Fix this later.
@ -763,7 +765,7 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
&aEditingHost); &aEditingHost);
if (MOZ_UNLIKELY( if (MOZ_UNLIKELY(
NS_WARN_IF(!textFragmentDataAtInsertionPoint.IsInitialized()))) { NS_WARN_IF(!textFragmentDataAtInsertionPoint.IsInitialized()))) {
return CreateElementResult(NS_ERROR_FAILURE); return Err(NS_ERROR_FAILURE);
} }
EditorDOMRange invisibleLeadingWhiteSpaceRangeOfNewLine = EditorDOMRange invisibleLeadingWhiteSpaceRangeOfNewLine =
textFragmentDataAtInsertionPoint textFragmentDataAtInsertionPoint
@ -782,11 +784,11 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
: PointPosition::NotInSameDOMTree; : PointPosition::NotInSameDOMTree;
EditorDOMPoint pointToInsert(aPointToInsert); EditorDOMPoint pointToInsert(aPointToInsert);
EditorDOMPoint atNBSPReplacableWithSP; EditorDOMPoint atNBSPReplaceableWithSP;
if (!invisibleLeadingWhiteSpaceRangeOfNewLine.IsPositioned() && if (!invisibleLeadingWhiteSpaceRangeOfNewLine.IsPositioned() &&
(pointPositionWithVisibleWhiteSpaces == PointPosition::MiddleOfFragment || (pointPositionWithVisibleWhiteSpaces == PointPosition::MiddleOfFragment ||
pointPositionWithVisibleWhiteSpaces == PointPosition::EndOfFragment)) { pointPositionWithVisibleWhiteSpaces == PointPosition::EndOfFragment)) {
atNBSPReplacableWithSP = atNBSPReplaceableWithSP =
textFragmentDataAtInsertionPoint textFragmentDataAtInsertionPoint
.GetPreviousNBSPPointIfNeedToReplaceWithASCIIWhiteSpace( .GetPreviousNBSPPointIfNeedToReplaceWithASCIIWhiteSpace(
pointToInsert) pointToInsert)
@ -802,7 +804,7 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
AutoTrackDOMPoint trackPointToInsert(aHTMLEditor.RangeUpdaterRef(), AutoTrackDOMPoint trackPointToInsert(aHTMLEditor.RangeUpdaterRef(),
&pointToInsert); &pointToInsert);
AutoTrackDOMPoint trackEndOfLineNBSP(aHTMLEditor.RangeUpdaterRef(), AutoTrackDOMPoint trackEndOfLineNBSP(aHTMLEditor.RangeUpdaterRef(),
&atNBSPReplacableWithSP); &atNBSPReplaceableWithSP);
AutoTrackDOMRange trackLeadingWhiteSpaceRange( AutoTrackDOMRange trackLeadingWhiteSpaceRange(
aHTMLEditor.RangeUpdaterRef(), aHTMLEditor.RangeUpdaterRef(),
&invisibleLeadingWhiteSpaceRangeOfNewLine); &invisibleLeadingWhiteSpaceRangeOfNewLine);
@ -810,10 +812,10 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
invisibleTrailingWhiteSpaceRangeOfCurrentLine.StartRef(), invisibleTrailingWhiteSpaceRangeOfCurrentLine.StartRef(),
invisibleTrailingWhiteSpaceRangeOfCurrentLine.EndRef(), invisibleTrailingWhiteSpaceRangeOfCurrentLine.EndRef(),
HTMLEditor::TreatEmptyTextNodes::KeepIfContainerOfRangeBoundaries); HTMLEditor::TreatEmptyTextNodes::KeepIfContainerOfRangeBoundaries);
if (MOZ_UNLIKELY(NS_FAILED(rv))) { if (NS_FAILED(rv)) {
NS_WARNING( NS_WARNING(
"HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed"); "HTMLEditor::DeleteTextAndTextNodesWithTransaction() failed");
return CreateElementResult(rv); return Err(rv);
} }
// Don't refer the following variables anymore unless tracking the // Don't refer the following variables anymore unless tracking the
// change. // change.
@ -842,7 +844,7 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
AutoTrackDOMPoint trackPointToInsert(aHTMLEditor.RangeUpdaterRef(), AutoTrackDOMPoint trackPointToInsert(aHTMLEditor.RangeUpdaterRef(),
&pointToInsert); &pointToInsert);
AutoTrackDOMPoint trackEndOfLineNBSP(aHTMLEditor.RangeUpdaterRef(), AutoTrackDOMPoint trackEndOfLineNBSP(aHTMLEditor.RangeUpdaterRef(),
&atNBSPReplacableWithSP); &atNBSPReplaceableWithSP);
AutoTrackDOMRange trackLeadingWhiteSpaceRange( AutoTrackDOMRange trackLeadingWhiteSpaceRange(
aHTMLEditor.RangeUpdaterRef(), aHTMLEditor.RangeUpdaterRef(),
&invisibleLeadingWhiteSpaceRangeOfNewLine); &invisibleLeadingWhiteSpaceRangeOfNewLine);
@ -861,7 +863,7 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
NS_WARNING( NS_WARNING(
"WhiteSpaceVisibilityKeeper::" "WhiteSpaceVisibilityKeeper::"
"ReplaceTextAndRemoveEmptyTextNodes() failed"); "ReplaceTextAndRemoveEmptyTextNodes() failed");
return CreateElementResult(rv); return Err(rv);
} }
// Don't refer the following variables anymore unless tracking the // Don't refer the following variables anymore unless tracking the
// change. // change.
@ -881,24 +883,24 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
invisibleLeadingWhiteSpaceRangeOfNewLine.StartRef(), invisibleLeadingWhiteSpaceRangeOfNewLine.StartRef(),
invisibleLeadingWhiteSpaceRangeOfNewLine.EndRef(), invisibleLeadingWhiteSpaceRangeOfNewLine.EndRef(),
HTMLEditor::TreatEmptyTextNodes::KeepIfContainerOfRangeBoundaries); HTMLEditor::TreatEmptyTextNodes::KeepIfContainerOfRangeBoundaries);
if (MOZ_UNLIKELY(NS_FAILED(rv))) { if (NS_FAILED(rv)) {
NS_WARNING( NS_WARNING(
"WhiteSpaceVisibilityKeeper::" "WhiteSpaceVisibilityKeeper::"
"DeleteTextAndTextNodesWithTransaction() failed"); "DeleteTextAndTextNodesWithTransaction() failed");
return CreateElementResult(rv); return Err(rv);
} }
// Don't refer the following variables anymore unless tracking the // Don't refer the following variables anymore unless tracking the
// change. // change.
atNBSPReplacableWithSP.Clear(); atNBSPReplaceableWithSP.Clear();
invisibleLeadingWhiteSpaceRangeOfNewLine.Clear(); invisibleLeadingWhiteSpaceRangeOfNewLine.Clear();
invisibleTrailingWhiteSpaceRangeOfCurrentLine.Clear(); invisibleTrailingWhiteSpaceRangeOfCurrentLine.Clear();
} }
} }
// If the `<br>` element is put immediately after an NBSP, it should be // If the `<br>` element is put immediately after an NBSP, it should be
// replaced with an ASCII white-space. // replaced with an ASCII white-space.
else if (atNBSPReplacableWithSP.IsInTextNode()) { else if (atNBSPReplaceableWithSP.IsInTextNode()) {
const EditorDOMPointInText atNBSPReplacedWithASCIIWhiteSpace = const EditorDOMPointInText atNBSPReplacedWithASCIIWhiteSpace =
atNBSPReplacableWithSP.AsInText(); atNBSPReplaceableWithSP.AsInText();
if (!atNBSPReplacedWithASCIIWhiteSpace.IsEndOfContainer() && if (!atNBSPReplacedWithASCIIWhiteSpace.IsEndOfContainer() &&
atNBSPReplacedWithASCIIWhiteSpace.IsCharNBSP()) { atNBSPReplacedWithASCIIWhiteSpace.IsCharNBSP()) {
AutoTrackDOMPoint trackPointToInsert(aHTMLEditor.RangeUpdaterRef(), AutoTrackDOMPoint trackPointToInsert(aHTMLEditor.RangeUpdaterRef(),
@ -908,21 +910,22 @@ CreateElementResult WhiteSpaceVisibilityKeeper::InsertBRElement(
MOZ_KnownLive( MOZ_KnownLive(
*atNBSPReplacedWithASCIIWhiteSpace.ContainerAs<Text>()), *atNBSPReplacedWithASCIIWhiteSpace.ContainerAs<Text>()),
atNBSPReplacedWithASCIIWhiteSpace.Offset(), 1, u" "_ns); atNBSPReplacedWithASCIIWhiteSpace.Offset(), 1, u" "_ns);
if (MOZ_UNLIKELY(NS_FAILED(rv))) { if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::ReplaceTextWithTransaction() failed failed"); NS_WARNING("HTMLEditor::ReplaceTextWithTransaction() failed failed");
return CreateElementResult(rv); return Err(rv);
} }
// Don't refer the following variables anymore unless tracking the // Don't refer the following variables anymore unless tracking the
// change. // change.
atNBSPReplacableWithSP.Clear(); atNBSPReplaceableWithSP.Clear();
invisibleLeadingWhiteSpaceRangeOfNewLine.Clear(); invisibleLeadingWhiteSpaceRangeOfNewLine.Clear();
invisibleTrailingWhiteSpaceRangeOfCurrentLine.Clear(); invisibleTrailingWhiteSpaceRangeOfCurrentLine.Clear();
} }
} }
} }
CreateElementResult insertBRElementResult = aHTMLEditor.InsertBRElement( Result<CreateElementResult, nsresult> insertBRElementResult =
HTMLEditor::WithTransaction::Yes, pointToInsert); aHTMLEditor.InsertBRElement(HTMLEditor::WithTransaction::Yes,
pointToInsert);
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
insertBRElementResult.isOk(), insertBRElementResult.isOk(),
"HTMLEditor::InsertBRElement(WithTransaction::Yes, eNone) failed"); "HTMLEditor::InsertBRElement(WithTransaction::Yes, eNone) failed");
@ -3169,16 +3172,16 @@ nsresult WhiteSpaceVisibilityKeeper::NormalizeVisibleWhiteSpacesAt(
// the beginning of soft wrapped lines, and lets the user see 2 spaces // the beginning of soft wrapped lines, and lets the user see 2 spaces
// when they type 2 spaces. // when they type 2 spaces.
const CreateElementResult insertBRElementResult = Result<CreateElementResult, nsresult> insertBRElementResult =
aHTMLEditor.InsertBRElement(HTMLEditor::WithTransaction::Yes, aHTMLEditor.InsertBRElement(HTMLEditor::WithTransaction::Yes,
atEndOfVisibleWhiteSpaces); atEndOfVisibleWhiteSpaces);
if (insertBRElementResult.isErr()) { if (MOZ_UNLIKELY(insertBRElementResult.isErr())) {
NS_WARNING( NS_WARNING(
"HTMLEditor::InsertBRElement(WithTransaction::Yes) failed"); "HTMLEditor::InsertBRElement(WithTransaction::Yes) failed");
return insertBRElementResult.unwrapErr(); return insertBRElementResult.unwrapErr();
} }
// XXX Is this intentional selection change? // XXX Is this intentional selection change?
nsresult rv = insertBRElementResult.SuggestCaretPointTo( nsresult rv = insertBRElementResult.inspect().SuggestCaretPointTo(
aHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion, aHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt, SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError}); SuggestCaret::AndIgnoreTrivialError});
@ -3189,7 +3192,7 @@ nsresult WhiteSpaceVisibilityKeeper::NormalizeVisibleWhiteSpacesAt(
NS_WARNING_ASSERTION( NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR, rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"CreateElementResult::SuggestCaretPointTo() failed, but ignored"); "CreateElementResult::SuggestCaretPointTo() failed, but ignored");
MOZ_ASSERT(insertBRElementResult.GetNewNode()); MOZ_ASSERT(insertBRElementResult.inspect().GetNewNode());
atPreviousCharOfEndOfVisibleWhiteSpaces = atPreviousCharOfEndOfVisibleWhiteSpaces =
textFragmentData.GetPreviousEditableCharPoint( textFragmentData.GetPreviousEditableCharPoint(

View file

@ -1473,9 +1473,9 @@ class WhiteSpaceVisibilityKeeper final {
* @return If succeeded, returns the new <br> element and * @return If succeeded, returns the new <br> element and
* point to put caret. * point to put caret.
*/ */
[[nodiscard]] MOZ_CAN_RUN_SCRIPT static CreateElementResult InsertBRElement( [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<CreateElementResult, nsresult>
HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToInsert, InsertBRElement(HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToInsert,
const Element& aEditingHost); const Element& aEditingHost);
/** /**
* InsertText() inserts aStringToInsert to aPointToInsert and makes any needed * InsertText() inserts aStringToInsert to aPointToInsert and makes any needed