summaryrefslogtreecommitdiffstats
path: root/editor/libeditor
diff options
context:
space:
mode:
Diffstat (limited to 'editor/libeditor')
-rw-r--r--editor/libeditor/AutoRangeArray.cpp9
-rw-r--r--editor/libeditor/AutoRangeArray.h1
-rw-r--r--editor/libeditor/EditorBase.cpp23
-rw-r--r--editor/libeditor/EditorBase.h19
-rw-r--r--editor/libeditor/EditorCommands.cpp17
-rw-r--r--editor/libeditor/HTMLEditor.cpp44
-rw-r--r--editor/libeditor/HTMLEditorCommands.cpp21
-rw-r--r--editor/libeditor/HTMLEditorDeleteHandler.cpp1134
-rw-r--r--editor/libeditor/TextEditor.cpp1
-rw-r--r--editor/libeditor/tests/browserscope/test_richtext.html2
-rw-r--r--editor/libeditor/tests/mochitest.toml2
-rw-r--r--editor/libeditor/tests/test_bug1053048.html2
-rw-r--r--editor/libeditor/tests/test_bug1649005.html2
-rw-r--r--editor/libeditor/tests/test_bug1659276.html2
-rw-r--r--editor/libeditor/tests/test_bug502673.html2
-rw-r--r--editor/libeditor/tests/test_bug525389.html2
-rw-r--r--editor/libeditor/tests/test_bug569988.html10
-rw-r--r--editor/libeditor/tests/test_bug607584.xhtml14
-rw-r--r--editor/libeditor/tests/test_bug611182.html2
-rw-r--r--editor/libeditor/tests/test_bug616590.xhtml14
-rw-r--r--editor/libeditor/tests/test_bug674770-1.html4
-rw-r--r--editor/libeditor/tests/test_bug674770-2.html2
-rw-r--r--editor/libeditor/tests/test_bug780908.xhtml14
-rw-r--r--editor/libeditor/tests/test_command_state_when_readonly.html149
-rw-r--r--editor/libeditor/tests/test_composition_with_highlight_in_texteditor.html6
-rw-r--r--editor/libeditor/tests/test_contenteditable_text_input_handling.html5
-rw-r--r--editor/libeditor/tests/test_dragdrop.html12
-rw-r--r--editor/libeditor/tests/test_execCommandPaste_noTarget.html2
-rw-r--r--editor/libeditor/tests/test_htmleditor_keyevent_handling.html8
-rw-r--r--editor/libeditor/tests/test_middle_click_paste.html4
-rw-r--r--editor/libeditor/tests/test_nsIEditor_documentIsEmpty.html2
-rw-r--r--editor/libeditor/tests/test_paste_redirect_focus_in_paste_event_listener.html6
-rw-r--r--editor/libeditor/tests/test_texteditor_keyevent_handling.html12
-rw-r--r--editor/libeditor/tests/test_texteditor_wrapping_long_line.html2
34 files changed, 925 insertions, 626 deletions
diff --git a/editor/libeditor/AutoRangeArray.cpp b/editor/libeditor/AutoRangeArray.cpp
index be89671760..57b9b26a35 100644
--- a/editor/libeditor/AutoRangeArray.cpp
+++ b/editor/libeditor/AutoRangeArray.cpp
@@ -86,6 +86,15 @@ AutoRangeArray::~AutoRangeArray() {
}
}
+AutoRangeArray::AutoRangeArray(nsRange& aRange) {
+ MOZ_ASSERT(aRange.IsPositioned());
+ if (NS_WARN_IF(!aRange.IsPositioned())) {
+ return;
+ }
+ mRanges.AppendElement(aRange);
+ mAnchorFocusRange = &aRange;
+}
+
// static
bool AutoRangeArray::IsEditableRange(const dom::AbstractRange& aRange,
const Element& aEditingHost) {
diff --git a/editor/libeditor/AutoRangeArray.h b/editor/libeditor/AutoRangeArray.h
index e2dd2e0149..3f3c4bf5b6 100644
--- a/editor/libeditor/AutoRangeArray.h
+++ b/editor/libeditor/AutoRangeArray.h
@@ -43,6 +43,7 @@ class MOZ_STACK_CLASS AutoRangeArray final {
explicit AutoRangeArray(const EditorDOMRangeBase<PointType>& aRange);
template <typename PT, typename CT>
explicit AutoRangeArray(const EditorDOMPointBase<PT, CT>& aPoint);
+ explicit AutoRangeArray(nsRange& aRange);
// The copy constructor copies everything except saved ranges.
explicit AutoRangeArray(const AutoRangeArray& aOther);
diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp
index 22452c59d2..e8120d93d9 100644
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -4869,6 +4869,29 @@ nsresult EditorBase::DeleteSelectionWithTransaction(
return NS_OK;
}
+Result<CaretPoint, nsresult> EditorBase::DeleteRangeWithTransaction(
+ nsIEditor::EDirection aDirectionAndAmount,
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete) {
+ MOZ_ASSERT(IsEditActionDataAvailable());
+ MOZ_ASSERT(!Destroyed());
+ MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
+
+ HowToHandleCollapsedRange howToHandleCollapsedRange =
+ EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
+ if (MOZ_UNLIKELY(aRangeToDelete.Collapsed() &&
+ howToHandleCollapsedRange ==
+ HowToHandleCollapsedRange::Ignore)) {
+ return CaretPoint(EditorDOMPoint(aRangeToDelete.StartRef()));
+ }
+
+ AutoRangeArray rangesToDelete(aRangeToDelete);
+ Result<CaretPoint, nsresult> result = DeleteRangesWithTransaction(
+ aDirectionAndAmount, aStripWrappers, rangesToDelete);
+ NS_WARNING_ASSERTION(result.isOk(),
+ "EditorBase::DeleteRangesWithTransaction() failed");
+ return result;
+}
+
Result<CaretPoint, nsresult> EditorBase::DeleteRangesWithTransaction(
nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers,
diff --git a/editor/libeditor/EditorBase.h b/editor/libeditor/EditorBase.h
index 952b8aa3f6..83f53ff215 100644
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -2519,6 +2519,25 @@ class EditorBase : public nsIEditor,
nsIEditor::EStripWrappers aStripWrappers);
/**
+ * DeleteRangeWithTransaction() removes content in aRangeToDelete or content
+ * around collapsed aRangeToDelete with transactions and remove empty
+ * inclusive ancestor inline elements of the collapsed range after removing
+ * the contents.
+ *
+ * @param aDirectionAndAmount How much range should be removed.
+ * @param aStripWrappers Whether the parent blocks should be removed
+ * when they become empty.
+ * Note that this must be `nsIEditor::eNoStrip`
+ * if this is a TextEditor because anyway it'll
+ * be ignored.
+ * @param aRangeToDelete The range to delete content.
+ */
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
+ DeleteRangeWithTransaction(nsIEditor::EDirection aDirectionAndAmount,
+ nsIEditor::EStripWrappers aStripWrappers,
+ nsRange& aRangeToDelete);
+
+ /**
* DeleteRangesWithTransaction() removes content in aRangesToDelete or content
* around collapsed ranges in aRangesToDelete with transactions and remove
* empty inclusive ancestor inline elements of collapsed ranges after
diff --git a/editor/libeditor/EditorCommands.cpp b/editor/libeditor/EditorCommands.cpp
index beb4f060ad..45f9e3198f 100644
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -269,7 +269,8 @@ bool UndoCommand::IsCommandEnabled(Command aCommand,
if (!aEditorBase) {
return false;
}
- return aEditorBase->IsSelectionEditable() && aEditorBase->CanUndo();
+ return aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable() &&
+ aEditorBase->CanUndo();
}
nsresult UndoCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -297,7 +298,8 @@ bool RedoCommand::IsCommandEnabled(Command aCommand,
if (!aEditorBase) {
return false;
}
- return aEditorBase->IsSelectionEditable() && aEditorBase->CanRedo();
+ return aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable() &&
+ aEditorBase->CanRedo();
}
nsresult RedoCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -548,7 +550,7 @@ bool SwitchTextDirectionCommand::IsCommandEnabled(
if (!aEditorBase) {
return false;
}
- return aEditorBase->IsSelectionEditable();
+ return aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable();
}
nsresult SwitchTextDirectionCommand::DoCommand(Command aCommand,
@@ -581,7 +583,8 @@ bool DeleteCommand::IsCommandEnabled(Command aCommand,
// We can generally delete whenever the selection is editable. However,
// cmd_delete doesn't make sense if the selection is collapsed because it's
// directionless.
- bool isEnabled = aEditorBase->IsSelectionEditable();
+ bool isEnabled =
+ aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable();
if (aCommand == Command::Delete && isEnabled) {
return aEditorBase->CanDeleteSelection();
@@ -820,7 +823,7 @@ bool InsertPlaintextCommand::IsCommandEnabled(Command aCommand,
if (!aEditorBase) {
return false;
}
- return aEditorBase->IsSelectionEditable();
+ return aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable();
}
nsresult InsertPlaintextCommand::DoCommand(Command aCommand,
@@ -877,7 +880,7 @@ bool InsertParagraphCommand::IsCommandEnabled(Command aCommand,
if (!aEditorBase || aEditorBase->IsSingleLineEditor()) {
return false;
}
- return aEditorBase->IsSelectionEditable();
+ return aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable();
}
nsresult InsertParagraphCommand::DoCommand(Command aCommand,
@@ -918,7 +921,7 @@ bool InsertLineBreakCommand::IsCommandEnabled(Command aCommand,
if (!aEditorBase || aEditorBase->IsSingleLineEditor()) {
return false;
}
- return aEditorBase->IsSelectionEditable();
+ return aEditorBase->IsModifiable() && aEditorBase->IsSelectionEditable();
}
nsresult InsertLineBreakCommand::DoCommand(Command aCommand,
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
index 9f4aab3dab..e9ea8887b7 100644
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -719,14 +719,33 @@ void HTMLEditor::UpdateRootElement() {
nsresult HTMLEditor::FocusedElementOrDocumentBecomesEditable(
Document& aDocument, Element* aElement) {
+ const bool isInDesignMode =
+ (IsInDesignMode() && (!aElement || aElement->IsInDesignMode()));
+
// If we should've already handled focus event, selection limiter should not
- // be set. Therefore, if it's set, we should do nothing here.
+ // be set. However, IMEStateManager is not notified the pseudo focus change
+ // in this case. Therefore, we need to notify IMEStateManager of this.
if (GetSelectionAncestorLimiter()) {
+ if (isInDesignMode) {
+ return NS_OK;
+ }
+ // Although editor is already initialized due to re-used, ISM may not
+ // create IME content observer yet. So we have to create it.
+ IMEState newState;
+ nsresult rv = GetPreferredIMEState(&newState);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("EditorBase::GetPreferredIMEState() failed");
+ return NS_OK;
+ }
+ if (const RefPtr<Element> focusedElement = GetFocusedElement()) {
+ MOZ_ASSERT(focusedElement == aElement);
+ IMEStateManager::UpdateIMEState(newState, focusedElement, *this);
+ }
return NS_OK;
}
// If we should be in the design mode, we want to handle focus event fired
// on the document node. Therefore, we should emulate it here.
- if (IsInDesignMode() && (!aElement || aElement->IsInDesignMode())) {
+ if (isInDesignMode) {
MOZ_ASSERT(&aDocument == GetDocument());
nsresult rv = OnFocus(aDocument);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HTMLEditor::OnFocus() failed");
@@ -5949,14 +5968,23 @@ bool HTMLEditor::IsEmpty() const {
return true;
}
- // XXX Oddly, we check body or document element's state instead of
- // active editing host. Must be a bug.
- Element* bodyOrDocumentElement = GetRoot();
- if (!bodyOrDocumentElement) {
- return true;
+ const Element* activeElement =
+ GetDocument() ? GetDocument()->GetActiveElement() : nullptr;
+ const Element* editingHostOrBodyOrRootElement =
+ activeElement && activeElement->IsEditable()
+ ? ComputeEditingHost(*activeElement, LimitInBodyElement::No)
+ : ComputeEditingHost(LimitInBodyElement::No);
+ if (MOZ_UNLIKELY(!editingHostOrBodyOrRootElement)) {
+ // If there is no active element nor no selection range in the document,
+ // let's check entire the document as what we do traditionally.
+ editingHostOrBodyOrRootElement = GetRoot();
+ if (!editingHostOrBodyOrRootElement) {
+ return true;
+ }
}
- for (nsIContent* childContent = bodyOrDocumentElement->GetFirstChild();
+ for (nsIContent* childContent =
+ editingHostOrBodyOrRootElement->GetFirstChild();
childContent; childContent = childContent->GetNextSibling()) {
if (!childContent->IsText() || childContent->Length()) {
return false;
diff --git a/editor/libeditor/HTMLEditorCommands.cpp b/editor/libeditor/HTMLEditorCommands.cpp
index 1864299a3a..ecccc7c491 100644
--- a/editor/libeditor/HTMLEditorCommands.cpp
+++ b/editor/libeditor/HTMLEditorCommands.cpp
@@ -52,7 +52,7 @@ bool StateUpdatingCommandBase::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
- if (!htmlEditor->IsSelectionEditable()) {
+ if (!htmlEditor->IsModifiable() || !htmlEditor->IsSelectionEditable()) {
return false;
}
if (aCommand == Command::FormatAbsolutePosition) {
@@ -355,8 +355,7 @@ bool RemoveListCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
-
- if (!htmlEditor->IsSelectionEditable()) {
+ if (!htmlEditor->IsModifiable() || !htmlEditor->IsSelectionEditable()) {
return false;
}
@@ -401,7 +400,7 @@ bool IndentCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult IndentCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -434,7 +433,7 @@ bool OutdentCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult OutdentCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -467,7 +466,7 @@ bool MultiStateCommandBase::IsCommandEnabled(Command aCommand,
return false;
}
// should be disabled sometimes, like if the current selection is an image
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult MultiStateCommandBase::DoCommand(Command aCommand,
@@ -1047,7 +1046,7 @@ bool RemoveStylesCommand::IsCommandEnabled(Command aCommand,
return false;
}
// test if we have any styles?
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult RemoveStylesCommand::DoCommand(Command aCommand,
@@ -1085,7 +1084,7 @@ bool IncreaseFontSizeCommand::IsCommandEnabled(Command aCommand,
return false;
}
// test if we are at max size?
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult IncreaseFontSizeCommand::DoCommand(Command aCommand,
@@ -1121,7 +1120,7 @@ bool DecreaseFontSizeCommand::IsCommandEnabled(Command aCommand,
return false;
}
// test if we are at min size?
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult DecreaseFontSizeCommand::DoCommand(Command aCommand,
@@ -1156,7 +1155,7 @@ bool InsertHTMLCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
nsresult InsertHTMLCommand::DoCommand(Command aCommand, EditorBase& aEditorBase,
@@ -1213,7 +1212,7 @@ bool InsertTagCommand::IsCommandEnabled(Command aCommand,
if (!htmlEditor) {
return false;
}
- return htmlEditor->IsSelectionEditable();
+ return htmlEditor->IsModifiable() && htmlEditor->IsSelectionEditable();
}
// corresponding STATE_ATTRIBUTE is: src (img) and href (a)
diff --git a/editor/libeditor/HTMLEditorDeleteHandler.cpp b/editor/libeditor/HTMLEditorDeleteHandler.cpp
index 18f9eda88e..39bb95151e 100644
--- a/editor/libeditor/HTMLEditorDeleteHandler.cpp
+++ b/editor/libeditor/HTMLEditorDeleteHandler.cpp
@@ -152,9 +152,20 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
const Element& aEditingHost);
private:
- bool IsHandlingRecursively() const { return mParent != nullptr; }
+ [[nodiscard]] bool IsHandlingRecursively() const {
+ return mParent != nullptr;
+ }
- bool CanFallbackToDeleteRangesWithTransaction(
+ [[nodiscard]] bool CanFallbackToDeleteRangeWithTransaction(
+ const nsRange& aRangeToDelete) const {
+ return !IsHandlingRecursively() &&
+ (!aRangeToDelete.Collapsed() ||
+ EditorBase::HowToHandleCollapsedRangeFor(
+ mOriginalDirectionAndAmount) !=
+ EditorBase::HowToHandleCollapsedRange::Ignore);
+ }
+
+ [[nodiscard]] bool CanFallbackToDeleteRangesWithTransaction(
const AutoRangeArray& aRangesToDelete) const {
return !IsHandlingRecursively() && !aRangesToDelete.Ranges().IsEmpty() &&
(!aRangesToDelete.IsCollapsed() ||
@@ -405,6 +416,20 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
const EditorDOMPoint& aPoint);
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
+ FallbackToDeleteRangeWithTransaction(HTMLEditor& aHTMLEditor,
+ nsRange& aRangeToDelete) const {
+ MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
+ MOZ_ASSERT(CanFallbackToDeleteRangeWithTransaction(aRangeToDelete));
+ Result<CaretPoint, nsresult> caretPointOrError =
+ aHTMLEditor.DeleteRangeWithTransaction(mOriginalDirectionAndAmount,
+ mOriginalStripWrappers,
+ aRangeToDelete);
+ NS_WARNING_ASSERTION(caretPointOrError.isOk(),
+ "EditorBase::DeleteRangeWithTransaction() failed");
+ return caretPointOrError;
+ }
+
+ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
FallbackToDeleteRangesWithTransaction(HTMLEditor& aHTMLEditor,
AutoRangeArray& aRangesToDelete) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
@@ -414,26 +439,68 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
mOriginalStripWrappers,
aRangesToDelete);
NS_WARNING_ASSERTION(caretPointOrError.isOk(),
- "HTMLEditor::DeleteRangesWithTransaction() failed");
+ "EditorBase::DeleteRangesWithTransaction() failed");
return caretPointOrError;
}
/**
- * ComputeRangesToDeleteRangesWithTransaction() computes target ranges
- * which will be called by `EditorBase::DeleteRangesWithTransaction()`.
+ * Compute target range(s) which will be called by
+ * `EditorBase::DeleteRangeWithTransaction()` or
+ * `EditorBase::DeleteRangesWithTransaction()`.
* TODO: We should not use it for consistency with each deletion handler
* in this and nested classes.
*/
+ nsresult ComputeRangeToDeleteRangeWithTransaction(
+ const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
+ nsRange& aRange, const Element& aEditingHost) const;
nsresult ComputeRangesToDeleteRangesWithTransaction(
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete) const;
+ AutoRangeArray& aRangesToDelete, const Element& aEditingHost) const {
+ MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ const EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
+ EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
+ if (NS_WARN_IF(aRangesToDelete.IsCollapsed() &&
+ howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::Ignore)) {
+ return NS_ERROR_FAILURE;
+ }
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ if (range->Collapsed()) {
+ continue;
+ }
+ nsresult rv = ComputeRangeToDeleteRangeWithTransaction(
+ aHTMLEditor, aDirectionAndAmount, range, aEditingHost);
+ if (NS_FAILED(rv)) {
+ NS_WARNING(
+ "AutoDeleteRangesHandler::ComputeRangeToDeleteRangeWithTransaction("
+ ") failed");
+ return rv;
+ }
+ }
+ return NS_OK;
+ }
+
+ nsresult FallbackToComputeRangeToDeleteRangeWithTransaction(
+ const HTMLEditor& aHTMLEditor, nsRange& aRangeToDelete,
+ const Element& aEditingHost) const {
+ MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
+ MOZ_ASSERT(CanFallbackToDeleteRangeWithTransaction(aRangeToDelete));
+ nsresult rv = ComputeRangeToDeleteRangeWithTransaction(
+ aHTMLEditor, mOriginalDirectionAndAmount, aRangeToDelete, aEditingHost);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "AutoDeleteRangesHandler::"
+ "ComputeRangeToDeleteRangeWithTransaction() failed");
+ return rv;
+ }
nsresult FallbackToComputeRangesToDeleteRangesWithTransaction(
- const HTMLEditor& aHTMLEditor, AutoRangeArray& aRangesToDelete) const {
+ const HTMLEditor& aHTMLEditor, AutoRangeArray& aRangesToDelete,
+ const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(CanFallbackToDeleteRangesWithTransaction(aRangesToDelete));
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
- aHTMLEditor, mOriginalDirectionAndAmount, aRangesToDelete);
+ aHTMLEditor, mOriginalDirectionAndAmount, aRangesToDelete,
+ aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
"ComputeRangesToDeleteRangesWithTransaction() failed");
@@ -493,18 +560,18 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
const WSRunScanner& aWSRunScannerAtCaret);
/**
- * PrepareToDeleteNonCollapsedRanges() considers left block element and
+ * PrepareToDeleteNonCollapsedRange() considers left block element and
* right block element which are inclusive ancestor block element of
- * start and end container of first range of aRangesToDelete.
+ * start and end container of aRangeToDelete
*
* @param aHTMLEditor The HTML editor.
- * @param aRangesToDelete Ranges to delete. Must not be
+ * @param aRangeToDelete The range to delete. Must not be
* collapsed.
* @return true if can continue to handle the
* deletion.
*/
- bool PrepareToDeleteNonCollapsedRanges(
- const HTMLEditor& aHTMLEditor, const AutoRangeArray& aRangesToDelete);
+ bool PrepareToDeleteNonCollapsedRange(const HTMLEditor& aHTMLEditor,
+ const nsRange& aRangeToDelete);
/**
* Run() executes the joining.
@@ -514,14 +581,13 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
* @param aStripWrappers Must be eStrip or eNoStrip.
* @param aCaretPoint The caret point (i.e., selection start
* or end).
- * @param aRangesToDelete Ranges to delete of the caller.
- * This should be collapsed and match
- * with aCaretPoint.
+ * @param aRangeToDelete The range to delete. This should be
+ * collapsed and match with aCaretPoint.
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult> Run(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers,
- const EditorDOMPoint& aCaretPoint, AutoRangeArray& aRangesToDelete,
+ const EditorDOMPoint& aCaretPoint, nsRange& aRangeToDelete,
const Element& aEditingHost) {
switch (mMode) {
case Mode::JoinCurrentBlock: {
@@ -537,7 +603,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
Result<EditActionResult, nsresult> result =
HandleDeleteAtOtherBlockBoundary(aHTMLEditor, aDirectionAndAmount,
aStripWrappers, aCaretPoint,
- aRangesToDelete, aEditingHost);
+ aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(result.isOk(),
"AutoBlockElementsJoiner::"
"HandleDeleteAtOtherBlockBoundary() failed");
@@ -552,8 +618,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
return result;
}
case Mode::JoinBlocksInSameParent:
- case Mode::DeleteContentInRanges:
- case Mode::DeleteNonCollapsedRanges:
+ case Mode::DeleteContentInRange:
+ case Mode::DeleteNonCollapsedRange:
MOZ_ASSERT_UNREACHABLE(
"This mode should be handled in the other Run()");
return Err(NS_ERROR_UNEXPECTED);
@@ -563,41 +629,41 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
return Err(NS_ERROR_NOT_INITIALIZED);
}
- nsresult ComputeRangesToDelete(const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- const EditorDOMPoint& aCaretPoint,
- AutoRangeArray& aRangesToDelete,
- const Element& aEditingHost) const {
+ nsresult ComputeRangeToDelete(const HTMLEditor& aHTMLEditor,
+ nsIEditor::EDirection aDirectionAndAmount,
+ const EditorDOMPoint& aCaretPoint,
+ nsRange& aRangeToDelete,
+ const Element& aEditingHost) const {
switch (mMode) {
case Mode::JoinCurrentBlock: {
- nsresult rv = ComputeRangesToDeleteAtCurrentBlockBoundary(
- aHTMLEditor, aCaretPoint, aRangesToDelete, aEditingHost);
+ nsresult rv = ComputeRangeToDeleteAtCurrentBlockBoundary(
+ aHTMLEditor, aCaretPoint, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
- "ComputeRangesToDeleteAtCurrentBlockBoundary() failed");
+ "ComputeRangeToDeleteAtCurrentBlockBoundary() failed");
return rv;
}
case Mode::JoinOtherBlock: {
- nsresult rv = ComputeRangesToDeleteAtOtherBlockBoundary(
- aHTMLEditor, aDirectionAndAmount, aCaretPoint, aRangesToDelete,
+ nsresult rv = ComputeRangeToDeleteAtOtherBlockBoundary(
+ aHTMLEditor, aDirectionAndAmount, aCaretPoint, aRangeToDelete,
aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
- "ComputeRangesToDeleteAtOtherBlockBoundary() failed");
+ "ComputeRangeToDeleteAtOtherBlockBoundary() failed");
return rv;
}
case Mode::DeleteBRElement: {
- nsresult rv = ComputeRangesToDeleteBRElement(aRangesToDelete);
+ nsresult rv = ComputeRangeToDeleteBRElement(aRangeToDelete);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
- "ComputeRangesToDeleteBRElement() failed");
+ "ComputeRangeToDeleteBRElement() failed");
return rv;
}
case Mode::JoinBlocksInSameParent:
- case Mode::DeleteContentInRanges:
- case Mode::DeleteNonCollapsedRanges:
+ case Mode::DeleteContentInRange:
+ case Mode::DeleteNonCollapsedRange:
MOZ_ASSERT_UNREACHABLE(
"This mode should be handled in the other "
"ComputeRangesToDelete()");
@@ -615,7 +681,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
* @param aDirectionAndAmount Direction of the deletion.
* @param aStripWrappers Whether delete or keep new empty
* ancestor elements.
- * @param aRangesToDelete Ranges to delete. Must not be
+ * @param aRangeToDelete The range to delete. Must not be
* collapsed.
* @param aSelectionWasCollapsed Whether selection was or was not
* collapsed when starting to handle
@@ -623,8 +689,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult> Run(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost) {
switch (mMode) {
@@ -638,26 +703,25 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
Result<EditActionResult, nsresult> result =
JoinBlockElementsInSameParent(
aHTMLEditor, aDirectionAndAmount, aStripWrappers,
- aRangesToDelete, aSelectionWasCollapsed, aEditingHost);
+ aRangeToDelete, aSelectionWasCollapsed, aEditingHost);
NS_WARNING_ASSERTION(result.isOk(),
"AutoBlockElementsJoiner::"
"JoinBlockElementsInSameParent() failed");
return result;
}
- case Mode::DeleteContentInRanges: {
- Result<EditActionResult, nsresult> result =
- DeleteContentInRanges(aHTMLEditor, aDirectionAndAmount,
- aStripWrappers, aRangesToDelete);
+ case Mode::DeleteContentInRange: {
+ Result<EditActionResult, nsresult> result = DeleteContentInRange(
+ aHTMLEditor, aDirectionAndAmount, aStripWrappers, aRangeToDelete);
NS_WARNING_ASSERTION(
result.isOk(),
- "AutoBlockElementsJoiner::DeleteContentInRanges() failed");
+ "AutoBlockElementsJoiner::DeleteContentInRange() failed");
return result;
}
- case Mode::DeleteNonCollapsedRanges: {
+ case Mode::DeleteNonCollapsedRange: {
Result<EditActionResult, nsresult> result =
- HandleDeleteNonCollapsedRanges(
+ HandleDeleteNonCollapsedRange(
aHTMLEditor, aDirectionAndAmount, aStripWrappers,
- aRangesToDelete, aSelectionWasCollapsed, aEditingHost);
+ aRangeToDelete, aSelectionWasCollapsed, aEditingHost);
NS_WARNING_ASSERTION(result.isOk(),
"AutoBlockElementsJoiner::"
"HandleDeleteNonCollapsedRange() failed");
@@ -671,10 +735,9 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
return Err(NS_ERROR_NOT_INITIALIZED);
}
- nsresult ComputeRangesToDelete(
+ nsresult ComputeRangeToDelete(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost) const {
switch (mMode) {
@@ -686,25 +749,25 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
"ComputeRangesToDelete()");
return NS_ERROR_UNEXPECTED;
case Mode::JoinBlocksInSameParent: {
- nsresult rv = ComputeRangesToJoinBlockElementsInSameParent(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
+ nsresult rv = ComputeRangeToJoinBlockElementsInSameParent(
+ aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
"ComputeRangesToJoinBlockElementsInSameParent() failed");
return rv;
}
- case Mode::DeleteContentInRanges: {
- nsresult rv = ComputeRangesToDeleteContentInRanges(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
+ case Mode::DeleteContentInRange: {
+ nsresult rv = ComputeRangeToDeleteContentInRange(
+ aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoBlockElementsJoiner::"
"ComputeRangesToDeleteContentInRanges() failed");
return rv;
}
- case Mode::DeleteNonCollapsedRanges: {
- nsresult rv = ComputeRangesToDeleteNonCollapsedRanges(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete,
+ case Mode::DeleteNonCollapsedRange: {
+ nsresult rv = ComputeRangeToDeleteNonCollapsedRange(
+ aHTMLEditor, aDirectionAndAmount, aRangeToDelete,
aSelectionWasCollapsed, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
@@ -731,63 +794,59 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
HandleDeleteAtCurrentBlockBoundary(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
const EditorDOMPoint& aCaretPoint, const Element& aEditingHost);
- nsresult ComputeRangesToDeleteAtCurrentBlockBoundary(
+ nsresult ComputeRangeToDeleteAtCurrentBlockBoundary(
const HTMLEditor& aHTMLEditor, const EditorDOMPoint& aCaretPoint,
- AutoRangeArray& aRangesToDelete, const Element& aEditingHost) const;
+ nsRange& aRangeToDelete, const Element& aEditingHost) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
HandleDeleteAtOtherBlockBoundary(HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers,
const EditorDOMPoint& aCaretPoint,
- AutoRangeArray& aRangesToDelete,
+ nsRange& aRangeToDelete,
const Element& aEditingHost);
// FYI: This method may modify selection, but it won't cause running
// script because of `AutoHideSelectionChanges` which blocks
// selection change listeners and the selection change event
// dispatcher.
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
- ComputeRangesToDeleteAtOtherBlockBoundary(
+ ComputeRangeToDeleteAtOtherBlockBoundary(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
- const EditorDOMPoint& aCaretPoint, AutoRangeArray& aRangesToDelete,
+ const EditorDOMPoint& aCaretPoint, nsRange& aRangeToDelete,
const Element& aEditingHost) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
JoinBlockElementsInSameParent(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost);
- nsresult ComputeRangesToJoinBlockElementsInSameParent(
+ nsresult ComputeRangeToJoinBlockElementsInSameParent(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete) const;
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
+ const Element& aEditingHost) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
DeleteBRElement(HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
const Element& aEditingHost);
- nsresult ComputeRangesToDeleteBRElement(
- AutoRangeArray& aRangesToDelete) const;
+ nsresult ComputeRangeToDeleteBRElement(nsRange& aRangeToDelete) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
- DeleteContentInRanges(HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete);
- nsresult ComputeRangesToDeleteContentInRanges(
+ DeleteContentInRange(HTMLEditor& aHTMLEditor,
+ nsIEditor::EDirection aDirectionAndAmount,
+ nsIEditor::EStripWrappers aStripWrappers,
+ nsRange& aRangeToDelete);
+ nsresult ComputeRangeToDeleteContentInRange(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete) const;
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRange,
+ const Element& aEditingHost) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<EditActionResult, nsresult>
- HandleDeleteNonCollapsedRanges(
+ HandleDeleteNonCollapsedRange(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost);
- nsresult ComputeRangesToDeleteNonCollapsedRanges(
+ nsresult ComputeRangeToDeleteNonCollapsedRange(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost) const;
@@ -829,7 +888,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed)
const;
Result<bool, nsresult>
- ComputeRangesToDeleteNodesEntirelyInRangeButKeepTableStructure(
+ ComputeRangeToDeleteNodesEntirelyInRangeButKeepTableStructure(
const HTMLEditor& aHTMLEditor, nsRange& aRange,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed)
const;
@@ -900,17 +959,17 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
}
/**
- * ComputeRangesToDelete() extends aRangesToDelete includes the element
+ * ComputeRangesToDelete() extends aRangeToDelete includes the element
* boundaries between joining blocks. If they won't be joined, this
* collapses the range to aCaretPoint.
*/
- nsresult ComputeRangesToDelete(const HTMLEditor& aHTMLEditor,
- const EditorDOMPoint& aCaretPoint,
- AutoRangeArray& aRangesToDelete) const;
+ nsresult ComputeRangeToDelete(const HTMLEditor& aHTMLEditor,
+ const EditorDOMPoint& aCaretPoint,
+ nsRange& aRangeToDelete) const;
/**
* Join inclusive ancestor block elements which are found by preceding
- * Preare() call.
+ * Prepare() call.
* The right element is always joined to the left element.
* If the elements are the same type and not nested within each other,
* JoinEditableNodesWithTransaction() is called (example, joining two
@@ -971,8 +1030,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
JoinOtherBlock,
JoinBlocksInSameParent,
DeleteBRElement,
- DeleteContentInRanges,
- DeleteNonCollapsedRanges,
+ DeleteContentInRange,
+ DeleteNonCollapsedRange,
};
AutoDeleteRangesHandler* mDeleteRangesHandler;
const AutoDeleteRangesHandler& mDeleteRangesHandlerConst;
@@ -1291,7 +1350,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDelete(
return NS_SUCCESS_DOM_NO_OPERATION;
}
nsresult rv = FallbackToComputeRangesToDeleteRangesWithTransaction(
- aHTMLEditor, aRangesToDelete);
+ aHTMLEditor, aRangesToDelete, *editingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
@@ -1770,40 +1829,57 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteAroundCollapsedRanges(
if (NS_WARN_IF(!aScanFromCaretPointResult.GetContent()->IsElement())) {
return NS_ERROR_FAILURE;
}
- AutoBlockElementsJoiner joiner(*this);
- if (!joiner.PrepareToDeleteAtOtherBlockBoundary(
- aHTMLEditor, aDirectionAndAmount,
- *aScanFromCaretPointResult.ElementPtr(),
- aWSRunScannerAtCaret.ScanStartRef(), aWSRunScannerAtCaret)) {
- return NS_SUCCESS_DOM_NO_OPERATION;
+ MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ bool handled = false;
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ MOZ_ASSERT(range->IsPositioned());
+ AutoBlockElementsJoiner joiner(*this);
+ if (!joiner.PrepareToDeleteAtOtherBlockBoundary(
+ aHTMLEditor, aDirectionAndAmount,
+ *aScanFromCaretPointResult.ElementPtr(),
+ aWSRunScannerAtCaret.ScanStartRef(), aWSRunScannerAtCaret)) {
+ continue;
+ }
+ handled = true;
+ nsresult rv = joiner.ComputeRangeToDelete(
+ aHTMLEditor, aDirectionAndAmount, aWSRunScannerAtCaret.ScanStartRef(),
+ range, aEditingHost);
+ if (NS_FAILED(rv)) {
+ NS_WARNING(
+ "AutoBlockElementsJoiner::ComputeRangeToDelete() failed (other "
+ "block boundary)");
+ return rv;
+ }
}
- nsresult rv = joiner.ComputeRangesToDelete(
- aHTMLEditor, aDirectionAndAmount, aWSRunScannerAtCaret.ScanStartRef(),
- aRangesToDelete, aEditingHost);
- NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
- "AutoBlockElementsJoiner::ComputeRangesToDelete() "
- "failed (other block boundary)");
- return rv;
+ return handled ? NS_OK : NS_SUCCESS_DOM_NO_OPERATION;
}
if (aScanFromCaretPointResult.ReachedCurrentBlockBoundary()) {
if (NS_WARN_IF(!aScanFromCaretPointResult.GetContent()->IsElement())) {
return NS_ERROR_FAILURE;
}
- AutoBlockElementsJoiner joiner(*this);
- if (!joiner.PrepareToDeleteAtCurrentBlockBoundary(
- aHTMLEditor, aDirectionAndAmount,
- *aScanFromCaretPointResult.ElementPtr(),
- aWSRunScannerAtCaret.ScanStartRef())) {
- return NS_SUCCESS_DOM_NO_OPERATION;
+ MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ bool handled = false;
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ AutoBlockElementsJoiner joiner(*this);
+ if (!joiner.PrepareToDeleteAtCurrentBlockBoundary(
+ aHTMLEditor, aDirectionAndAmount,
+ *aScanFromCaretPointResult.ElementPtr(),
+ aWSRunScannerAtCaret.ScanStartRef())) {
+ continue;
+ }
+ handled = true;
+ nsresult rv = joiner.ComputeRangeToDelete(
+ aHTMLEditor, aDirectionAndAmount, aWSRunScannerAtCaret.ScanStartRef(),
+ range, aEditingHost);
+ if (NS_FAILED(rv)) {
+ NS_WARNING(
+ "AutoBlockElementsJoiner::ComputeRangeToDelete() failed (current "
+ "block boundary)");
+ return rv;
+ }
}
- nsresult rv = joiner.ComputeRangesToDelete(
- aHTMLEditor, aDirectionAndAmount, aWSRunScannerAtCaret.ScanStartRef(),
- aRangesToDelete, aEditingHost);
- NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
- "AutoBlockElementsJoiner::ComputeRangesToDelete() "
- "failed (current block boundary)");
- return rv;
+ return handled ? NS_OK : NS_SUCCESS_DOM_NO_OPERATION;
}
return NS_OK;
@@ -1946,40 +2022,62 @@ HTMLEditor::AutoDeleteRangesHandler::HandleDeleteAroundCollapsedRanges(
if (NS_WARN_IF(!aScanFromCaretPointResult.GetContent()->IsElement())) {
return Err(NS_ERROR_FAILURE);
}
- AutoBlockElementsJoiner joiner(*this);
- if (!joiner.PrepareToDeleteAtOtherBlockBoundary(
- aHTMLEditor, aDirectionAndAmount,
- *aScanFromCaretPointResult.ElementPtr(),
- aWSRunScannerAtCaret.ScanStartRef(), aWSRunScannerAtCaret)) {
- return EditActionResult::CanceledResult();
+ MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ bool allRangesNotHandled = true;
+ auto ret = EditActionResult::IgnoredResult();
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ AutoBlockElementsJoiner joiner(*this);
+ if (!joiner.PrepareToDeleteAtOtherBlockBoundary(
+ aHTMLEditor, aDirectionAndAmount,
+ *aScanFromCaretPointResult.ElementPtr(),
+ aWSRunScannerAtCaret.ScanStartRef(), aWSRunScannerAtCaret)) {
+ continue;
+ }
+ allRangesNotHandled = false;
+ Result<EditActionResult, nsresult> result =
+ joiner.Run(aHTMLEditor, aDirectionAndAmount, aStripWrappers,
+ aWSRunScannerAtCaret.ScanStartRef(), MOZ_KnownLive(range),
+ aEditingHost);
+ if (MOZ_UNLIKELY(result.isErr())) {
+ NS_WARNING(
+ "AutoBlockElementsJoiner::Run() failed (other block boundary)");
+ return result;
+ }
+ ret |= result.inspect();
}
- Result<EditActionResult, nsresult> result = joiner.Run(
- aHTMLEditor, aDirectionAndAmount, aStripWrappers,
- aWSRunScannerAtCaret.ScanStartRef(), aRangesToDelete, aEditingHost);
- NS_WARNING_ASSERTION(
- result.isOk(),
- "AutoBlockElementsJoiner::Run() failed (other block boundary)");
- return result;
+ return allRangesNotHandled ? EditActionResult::CanceledResult()
+ : std::move(ret);
}
if (aScanFromCaretPointResult.ReachedCurrentBlockBoundary()) {
if (NS_WARN_IF(!aScanFromCaretPointResult.GetContent()->IsElement())) {
return Err(NS_ERROR_FAILURE);
}
- AutoBlockElementsJoiner joiner(*this);
- if (!joiner.PrepareToDeleteAtCurrentBlockBoundary(
- aHTMLEditor, aDirectionAndAmount,
- *aScanFromCaretPointResult.ElementPtr(),
- aWSRunScannerAtCaret.ScanStartRef())) {
- return EditActionResult::CanceledResult();
+ MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ bool allRangesNotHandled = true;
+ auto ret = EditActionResult::IgnoredResult();
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ AutoBlockElementsJoiner joiner(*this);
+ if (!joiner.PrepareToDeleteAtCurrentBlockBoundary(
+ aHTMLEditor, aDirectionAndAmount,
+ *aScanFromCaretPointResult.ElementPtr(),
+ aWSRunScannerAtCaret.ScanStartRef())) {
+ continue;
+ }
+ allRangesNotHandled = false;
+ Result<EditActionResult, nsresult> result =
+ joiner.Run(aHTMLEditor, aDirectionAndAmount, aStripWrappers,
+ aWSRunScannerAtCaret.ScanStartRef(), MOZ_KnownLive(range),
+ aEditingHost);
+ if (MOZ_UNLIKELY(result.isErr())) {
+ NS_WARNING(
+ "AutoBlockElementsJoiner::Run() failed (current block boundary)");
+ return result;
+ }
+ ret |= result.inspect();
}
- Result<EditActionResult, nsresult> result = joiner.Run(
- aHTMLEditor, aDirectionAndAmount, aStripWrappers,
- aWSRunScannerAtCaret.ScanStartRef(), aRangesToDelete, aEditingHost);
- NS_WARNING_ASSERTION(
- result.isOk(),
- "AutoBlockElementsJoiner::Run() failed (current block boundary)");
- return result;
+ return allRangesNotHandled ? EditActionResult::CanceledResult()
+ : std::move(ret);
}
MOZ_ASSERT_UNREACHABLE("New type of reached content hasn't been handled yet");
@@ -2439,13 +2537,14 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToDeleteBRElement(AutoRangeArray& aRangesToDelete) const {
+ ComputeRangeToDeleteBRElement(nsRange& aRangeToDelete) const {
MOZ_ASSERT(mBRElement);
// XXX Why don't we scan invisible leading white-spaces which follows the
// `<br>` element?
- nsresult rv = aRangesToDelete.SelectNode(*mBRElement);
- NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AutoRangeArray::SelectNode() failed");
- return rv;
+ IgnoredErrorResult error;
+ aRangeToDelete.SelectNode(*mBRElement, error);
+ NS_WARNING_ASSERTION(!error.Failed(), "nsRange::SelectNode() failed");
+ return error.StealNSResult();
}
Result<EditActionResult, nsresult>
@@ -2545,10 +2644,10 @@ HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::DeleteBRElement(
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToDeleteAtOtherBlockBoundary(
+ ComputeRangeToDeleteAtOtherBlockBoundary(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount,
- const EditorDOMPoint& aCaretPoint, AutoRangeArray& aRangesToDelete,
+ const EditorDOMPoint& aCaretPoint, nsRange& aRangeToDelete,
const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(aCaretPoint.IsSetAndValid());
@@ -2557,20 +2656,19 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
if (HTMLEditUtils::GetInclusiveAncestorAnyTableElement(*mLeftContent) !=
HTMLEditUtils::GetInclusiveAncestorAnyTableElement(*mRightContent)) {
- if (!mDeleteRangesHandlerConst.CanFallbackToDeleteRangesWithTransaction(
- aRangesToDelete)) {
- nsresult rv = aRangesToDelete.Collapse(aCaretPoint);
- NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
- "AutoRangeArray::Collapse() failed");
+ if (!mDeleteRangesHandlerConst.CanFallbackToDeleteRangeWithTransaction(
+ aRangeToDelete)) {
+ nsresult rv = aRangeToDelete.CollapseTo(aCaretPoint.ToRawRangeBoundary());
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsRange::CollapseTo() failed");
return rv;
}
nsresult rv = mDeleteRangesHandlerConst
- .FallbackToComputeRangesToDeleteRangesWithTransaction(
- aHTMLEditor, aRangesToDelete);
+ .FallbackToComputeRangeToDeleteRangeWithTransaction(
+ aHTMLEditor, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
- "FallbackToComputeRangesToDeleteRangesWithTransaction() failed");
+ "FallbackToComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
@@ -2585,11 +2683,10 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
if (canJoinThem.inspect() && joiner.CanJoinBlocks() &&
!joiner.ShouldDeleteLeafContentInstead()) {
nsresult rv =
- joiner.ComputeRangesToDelete(aHTMLEditor, aCaretPoint, aRangesToDelete);
- NS_WARNING_ASSERTION(
- NS_SUCCEEDED(rv),
- "AutoInclusiveAncestorBlockElementsJoiner::ComputeRangesToDelete() "
- "failed");
+ joiner.ComputeRangeToDelete(aHTMLEditor, aCaretPoint, aRangeToDelete);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "AutoInclusiveAncestorBlockElementsJoiner::"
+ "ComputeRangeToDelete() failed");
return rv;
}
@@ -2612,11 +2709,11 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
: EditorRawDOMPoint(mLeafContentInOtherBlock, 0);
// If new caret position is same as current caret position, we can do
// nothing anymore.
- if (aRangesToDelete.IsCollapsed() &&
- aRangesToDelete.FocusRef() == newCaretPoint.ToRawRangeBoundary()) {
+ if (aRangeToDelete.Collapsed() &&
+ aRangeToDelete.EndRef() == newCaretPoint.ToRawRangeBoundary()) {
return NS_OK;
}
- // TODO: Stop modifying the `Selection` for computing the targer ranges.
+ // TODO: Stop modifying the `Selection` for computing the target ranges.
nsresult rv = aHTMLEditor.CollapseSelectionTo(newCaretPoint);
if (MOZ_UNLIKELY(rv == NS_ERROR_EDITOR_DESTROYED)) {
NS_WARNING(
@@ -2626,13 +2723,25 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::CollapseSelectionTo() failed");
if (NS_SUCCEEDED(rv)) {
- aRangesToDelete.Initialize(aHTMLEditor.SelectionRef());
+ AutoRangeArray rangeArray(aHTMLEditor.SelectionRef());
AutoDeleteRangesHandler anotherHandler(mDeleteRangesHandlerConst);
rv = anotherHandler.ComputeRangesToDelete(aHTMLEditor, aDirectionAndAmount,
- aRangesToDelete, aEditingHost);
- NS_WARNING_ASSERTION(
- NS_SUCCEEDED(rv),
- "Recursive AutoDeleteRangesHandler::ComputeRangesToDelete() failed");
+ rangeArray, aEditingHost);
+ if (NS_SUCCEEDED(rv)) {
+ if (MOZ_LIKELY(!rangeArray.Ranges().IsEmpty())) {
+ MOZ_ASSERT(rangeArray.Ranges().Length() == 1);
+ aRangeToDelete.SetStartAndEnd(rangeArray.FirstRangeRef()->StartRef(),
+ rangeArray.FirstRangeRef()->EndRef());
+ } else {
+ NS_WARNING(
+ "Recursive AutoDeleteRangesHandler::ComputeRangesToDelete() "
+ "returned no range");
+ rv = NS_ERROR_FAILURE;
+ }
+ } else {
+ NS_WARNING(
+ "Recursive AutoDeleteRangesHandler::ComputeRangesToDelete() failed");
+ }
}
// Restore selection.
nsresult rvCollapsingSelectionTo =
@@ -2654,7 +2763,7 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
AutoBlockElementsJoiner::HandleDeleteAtOtherBlockBoundary(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers,
- const EditorDOMPoint& aCaretPoint, AutoRangeArray& aRangesToDelete,
+ const EditorDOMPoint& aCaretPoint, nsRange& aRangeToDelete,
const Element& aEditingHost) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
MOZ_ASSERT(aCaretPoint.IsSetAndValid());
@@ -2666,13 +2775,13 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
HTMLEditUtils::GetInclusiveAncestorAnyTableElement(*mRightContent)) {
// If we have not deleted `<br>` element and are not called recursively,
// we should call `DeleteRangesWithTransaction()` here.
- if (!mDeleteRangesHandler->CanFallbackToDeleteRangesWithTransaction(
- aRangesToDelete)) {
+ if (!mDeleteRangesHandler->CanFallbackToDeleteRangeWithTransaction(
+ aRangeToDelete)) {
return EditActionResult::IgnoredResult();
}
Result<CaretPoint, nsresult> caretPointOrError =
- mDeleteRangesHandler->FallbackToDeleteRangesWithTransaction(
- aHTMLEditor, aRangesToDelete);
+ mDeleteRangesHandler->FallbackToDeleteRangeWithTransaction(
+ aHTMLEditor, aRangeToDelete);
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
NS_WARNING(
"AutoDeleteRangesHandler::FallbackToDeleteRangesWithTransaction() "
@@ -2789,8 +2898,8 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
: EditorRawDOMPoint(mLeafContentInOtherBlock, 0);
// If new caret position is same as current caret position, we can do
// nothing anymore.
- if (aRangesToDelete.IsCollapsed() &&
- aRangesToDelete.FocusRef() == newCaretPoint.ToRawRangeBoundary()) {
+ if (aRangeToDelete.Collapsed() &&
+ aRangeToDelete.EndRef() == newCaretPoint.ToRawRangeBoundary()) {
return EditActionResult::CanceledResult();
}
nsresult rv = aHTMLEditor.CollapseSelectionTo(newCaretPoint);
@@ -2945,9 +3054,9 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToDeleteAtCurrentBlockBoundary(
+ ComputeRangeToDeleteAtCurrentBlockBoundary(
const HTMLEditor& aHTMLEditor, const EditorDOMPoint& aCaretPoint,
- AutoRangeArray& aRangesToDelete, const Element& aEditingHost) const {
+ nsRange& aRangeToDelete, const Element& aEditingHost) const {
MOZ_ASSERT(mLeftContent);
MOZ_ASSERT(mRightContent);
@@ -2961,7 +3070,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
}
if (canJoinThem.inspect()) {
nsresult rv =
- joiner.ComputeRangesToDelete(aHTMLEditor, aCaretPoint, aRangesToDelete);
+ joiner.ComputeRangeToDelete(aHTMLEditor, aCaretPoint, aRangeToDelete);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoInclusiveAncestorBlockElementsJoiner::"
"ComputeRangesToDelete() failed");
@@ -2970,8 +3079,8 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
// In this case, nothing will be deleted so that the affected range should
// be collapsed.
- nsresult rv = aRangesToDelete.Collapse(aCaretPoint);
- NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AutoRangeArray::Collapse() failed");
+ nsresult rv = aRangeToDelete.CollapseTo(aCaretPoint.ToRawRangeBoundary());
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsRange::CollapseTo() failed");
return rv;
}
@@ -3145,7 +3254,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteNonCollapsedRanges(
aRangesToDelete.FirstRangeRef()->GetEndContainer()) {
if (!aRangesToDelete.FirstRangeRef()->Collapsed()) {
nsresult rv = ComputeRangesToDeleteRangesWithTransaction(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
+ aHTMLEditor, aDirectionAndAmount, aRangesToDelete, aEditingHost);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction("
@@ -3169,17 +3278,23 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteNonCollapsedRanges(
aDirectionAndAmount = nsIEditor::ePrevious;
}
- AutoBlockElementsJoiner joiner(*this);
- if (!joiner.PrepareToDeleteNonCollapsedRanges(aHTMLEditor, aRangesToDelete)) {
- return NS_ERROR_FAILURE;
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ if (MOZ_UNLIKELY(range->Collapsed())) {
+ continue;
+ }
+ AutoBlockElementsJoiner joiner(*this);
+ if (!joiner.PrepareToDeleteNonCollapsedRange(aHTMLEditor, range)) {
+ return NS_ERROR_FAILURE;
+ }
+ nsresult rv =
+ joiner.ComputeRangeToDelete(aHTMLEditor, aDirectionAndAmount, range,
+ aSelectionWasCollapsed, aEditingHost);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("AutoBlockElementsJoiner::ComputeRangeToDelete() failed");
+ return rv;
+ }
}
- nsresult rv = joiner.ComputeRangesToDelete(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete, aSelectionWasCollapsed,
- aEditingHost);
- NS_WARNING_ASSERTION(
- NS_SUCCEEDED(rv),
- "AutoBlockElementsJoiner::ComputeRangesToDelete() failed");
- return rv;
+ return NS_OK;
}
Result<EditActionResult, nsresult>
@@ -3351,29 +3466,40 @@ HTMLEditor::AutoDeleteRangesHandler::HandleDeleteNonCollapsedRanges(
aDirectionAndAmount = nsIEditor::ePrevious;
}
- AutoBlockElementsJoiner joiner(*this);
- if (!joiner.PrepareToDeleteNonCollapsedRanges(aHTMLEditor, aRangesToDelete)) {
- return Err(NS_ERROR_FAILURE);
+ MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ auto ret = EditActionResult::IgnoredResult();
+ for (const OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
+ if (MOZ_UNLIKELY(range->Collapsed())) {
+ continue;
+ }
+ AutoBlockElementsJoiner joiner(*this);
+ if (!joiner.PrepareToDeleteNonCollapsedRange(aHTMLEditor, range)) {
+ return Err(NS_ERROR_FAILURE);
+ }
+ Result<EditActionResult, nsresult> result =
+ joiner.Run(aHTMLEditor, aDirectionAndAmount, aStripWrappers,
+ MOZ_KnownLive(range), aSelectionWasCollapsed, aEditingHost);
+ if (MOZ_UNLIKELY(result.isErr())) {
+ NS_WARNING("AutoBlockElementsJoiner::Run() failed");
+ return result;
+ }
+ ret |= result.inspect();
}
- Result<EditActionResult, nsresult> result =
- joiner.Run(aHTMLEditor, aDirectionAndAmount, aStripWrappers,
- aRangesToDelete, aSelectionWasCollapsed, aEditingHost);
- NS_WARNING_ASSERTION(result.isOk(), "AutoBlockElementsJoiner::Run() failed");
- return result;
+ return ret;
}
bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- PrepareToDeleteNonCollapsedRanges(const HTMLEditor& aHTMLEditor,
- const AutoRangeArray& aRangesToDelete) {
+ PrepareToDeleteNonCollapsedRange(const HTMLEditor& aHTMLEditor,
+ const nsRange& aRangeToDelete) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
mLeftContent = HTMLEditUtils::GetInclusiveAncestorElement(
- *aRangesToDelete.FirstRangeRef()->GetStartContainer()->AsContent(),
+ *aRangeToDelete.GetStartContainer()->AsContent(),
HTMLEditUtils::ClosestEditableBlockElement,
BlockInlineCheck::UseComputedDisplayOutsideStyle);
mRightContent = HTMLEditUtils::GetInclusiveAncestorElement(
- *aRangesToDelete.FirstRangeRef()->GetEndContainer()->AsContent(),
+ *aRangeToDelete.GetEndContainer()->AsContent(),
HTMLEditUtils::ClosestEditableBlockElement,
BlockInlineCheck::UseComputedDisplayOutsideStyle);
// Note that mLeftContent and/or mRightContent can be nullptr if editing host
@@ -3381,15 +3507,11 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
// one or one reaches an inline editing host, we can just delete the content
// in ranges.
if (mLeftContent == mRightContent || !mLeftContent || !mRightContent) {
- MOZ_ASSERT_IF(!mLeftContent || !mRightContent,
- aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost() == aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->AsContent()
- ->GetEditingHost());
- mMode = Mode::DeleteContentInRanges;
+ MOZ_ASSERT_IF(
+ !mLeftContent || !mRightContent,
+ aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost() ==
+ aRangeToDelete.GetEndContainer()->AsContent()->GetEditingHost());
+ mMode = Mode::DeleteContentInRange;
return true;
}
@@ -3406,100 +3528,79 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
return true;
}
- mMode = Mode::DeleteNonCollapsedRanges;
+ mMode = Mode::DeleteNonCollapsedRange;
return true;
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToDeleteContentInRanges(
+ ComputeRangeToDeleteContentInRange(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete) const {
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
+ const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
- MOZ_ASSERT(mMode == Mode::DeleteContentInRanges);
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost() == aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->AsContent()
- ->GetEditingHost());
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
+ MOZ_ASSERT(mMode == Mode::DeleteContentInRange);
+ MOZ_ASSERT(aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost());
+ MOZ_ASSERT(
+ aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost() ==
+ aRangeToDelete.GetEndContainer()->AsContent()->GetEditingHost());
MOZ_ASSERT(!mLeftContent == !mRightContent);
MOZ_ASSERT_IF(mLeftContent, mLeftContent->IsElement());
- MOZ_ASSERT_IF(mLeftContent, aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->IsInclusiveDescendantOf(mLeftContent));
+ MOZ_ASSERT_IF(mLeftContent,
+ aRangeToDelete.GetStartContainer()->IsInclusiveDescendantOf(
+ mLeftContent));
MOZ_ASSERT_IF(mRightContent, mRightContent->IsElement());
- MOZ_ASSERT_IF(mRightContent, aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->IsInclusiveDescendantOf(mRightContent));
- MOZ_ASSERT_IF(!mLeftContent,
- HTMLEditUtils::IsInlineContent(
- *aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost(),
- BlockInlineCheck::UseComputedDisplayOutsideStyle));
+ MOZ_ASSERT_IF(
+ mRightContent,
+ aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
+ MOZ_ASSERT_IF(
+ !mLeftContent,
+ HTMLEditUtils::IsInlineContent(
+ *aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost(),
+ BlockInlineCheck::UseComputedDisplayOutsideStyle));
nsresult rv =
- mDeleteRangesHandlerConst.ComputeRangesToDeleteRangesWithTransaction(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
+ mDeleteRangesHandlerConst.ComputeRangeToDeleteRangeWithTransaction(
+ aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
- "ComputeRangesToDeleteRangesWithTransaction() failed");
+ "ComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
- AutoBlockElementsJoiner::DeleteContentInRanges(
+ AutoBlockElementsJoiner::DeleteContentInRange(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete) {
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
- MOZ_ASSERT(mMode == Mode::DeleteContentInRanges);
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
+ MOZ_ASSERT(mMode == Mode::DeleteContentInRange);
MOZ_ASSERT(mDeleteRangesHandler);
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost() == aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->AsContent()
- ->GetEditingHost());
+ MOZ_ASSERT(aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost());
+ MOZ_ASSERT(
+ aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost() ==
+ aRangeToDelete.GetEndContainer()->AsContent()->GetEditingHost());
MOZ_ASSERT_IF(mLeftContent, mLeftContent->IsElement());
- MOZ_ASSERT_IF(mLeftContent, aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->IsInclusiveDescendantOf(mLeftContent));
+ MOZ_ASSERT_IF(mLeftContent,
+ aRangeToDelete.GetStartContainer()->IsInclusiveDescendantOf(
+ mLeftContent));
MOZ_ASSERT_IF(mRightContent, mRightContent->IsElement());
- MOZ_ASSERT_IF(mRightContent, aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->IsInclusiveDescendantOf(mRightContent));
- MOZ_ASSERT_IF(!mLeftContent,
- HTMLEditUtils::IsInlineContent(
- *aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->AsContent()
- ->GetEditingHost(),
- BlockInlineCheck::UseComputedDisplayOutsideStyle));
-
- // XXX This is also odd. We do we simply use
- // `DeleteRangesWithTransaction()` only when **first** range is in
- // same block?
+ MOZ_ASSERT_IF(
+ mRightContent,
+ aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
+ MOZ_ASSERT_IF(
+ !mLeftContent,
+ HTMLEditUtils::IsInlineContent(
+ *aRangeToDelete.GetStartContainer()->AsContent()->GetEditingHost(),
+ BlockInlineCheck::UseComputedDisplayOutsideStyle));
+
{
+ AutoRangeArray rangesToDelete(aRangeToDelete);
AutoTrackDOMRange firstRangeTracker(aHTMLEditor.RangeUpdaterRef(),
- &aRangesToDelete.FirstRangeRef());
+ &rangesToDelete.FirstRangeRef());
Result<CaretPoint, nsresult> caretPointOrError =
- aHTMLEditor.DeleteRangesWithTransaction(
- aDirectionAndAmount, aStripWrappers, aRangesToDelete);
+ aHTMLEditor.DeleteRangesWithTransaction(aDirectionAndAmount,
+ aStripWrappers, rangesToDelete);
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
if (NS_WARN_IF(caretPointOrError.inspectErr() ==
NS_ERROR_EDITOR_DESTROYED)) {
@@ -3522,15 +3623,15 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
}
}
- if (NS_WARN_IF(!aRangesToDelete.FirstRangeRef()->IsPositioned())) {
+ if (NS_WARN_IF(!aRangeToDelete.IsPositioned())) {
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
nsresult rv =
mDeleteRangesHandler->DeleteUnnecessaryNodesAndCollapseSelection(
aHTMLEditor, aDirectionAndAmount,
- EditorDOMPoint(aRangesToDelete.FirstRangeRef()->StartRef()),
- EditorDOMPoint(aRangesToDelete.FirstRangeRef()->EndRef()));
+ EditorDOMPoint(aRangeToDelete.StartRef()),
+ EditorDOMPoint(aRangeToDelete.EndRef()));
if (NS_FAILED(rv)) {
NS_WARNING(
"AutoDeleteRangesHandler::DeleteUnnecessaryNodesAndCollapseSelection() "
@@ -3541,63 +3642,59 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToJoinBlockElementsInSameParent(
+ ComputeRangeToJoinBlockElementsInSameParent(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete) const {
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
+ const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
MOZ_ASSERT(mMode == Mode::JoinBlocksInSameParent);
MOZ_ASSERT(mLeftContent);
MOZ_ASSERT(mLeftContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->IsInclusiveDescendantOf(mLeftContent));
+ MOZ_ASSERT(aRangeToDelete.GetStartContainer()->IsInclusiveDescendantOf(
+ mLeftContent));
MOZ_ASSERT(mRightContent);
MOZ_ASSERT(mRightContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->IsInclusiveDescendantOf(mRightContent));
+ MOZ_ASSERT(
+ aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
MOZ_ASSERT(mLeftContent->GetParentNode() == mRightContent->GetParentNode());
nsresult rv =
- mDeleteRangesHandlerConst.ComputeRangesToDeleteRangesWithTransaction(
- aHTMLEditor, aDirectionAndAmount, aRangesToDelete);
+ mDeleteRangesHandlerConst.ComputeRangeToDeleteRangeWithTransaction(
+ aHTMLEditor, aDirectionAndAmount, aRangeToDelete, aEditingHost);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoDeleteRangesHandler::"
- "ComputeRangesToDeleteRangesWithTransaction() failed");
+ "ComputeRangeToDeleteRangeWithTransaction() failed");
return rv;
}
Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
AutoBlockElementsJoiner::JoinBlockElementsInSameParent(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete,
SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
MOZ_ASSERT(mMode == Mode::JoinBlocksInSameParent);
MOZ_ASSERT(mLeftContent);
MOZ_ASSERT(mLeftContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->IsInclusiveDescendantOf(mLeftContent));
+ MOZ_ASSERT(aRangeToDelete.GetStartContainer()->IsInclusiveDescendantOf(
+ mLeftContent));
MOZ_ASSERT(mRightContent);
MOZ_ASSERT(mRightContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->IsInclusiveDescendantOf(mRightContent));
+ MOZ_ASSERT(
+ aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
MOZ_ASSERT(mLeftContent->GetParentNode() == mRightContent->GetParentNode());
const bool backspaceInRightBlock =
aSelectionWasCollapsed == SelectionWasCollapsed::Yes &&
nsIEditor::DirectionIsBackspace(aDirectionAndAmount);
+ AutoRangeArray rangesToDelete(aRangeToDelete);
Result<CaretPoint, nsresult> caretPointOrError =
aHTMLEditor.DeleteRangesWithTransaction(aDirectionAndAmount,
- aStripWrappers, aRangesToDelete);
+ aStripWrappers, rangesToDelete);
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
NS_WARNING("EditorBase::DeleteRangesWithTransaction() failed");
return caretPointOrError.propagateErr();
@@ -3686,7 +3783,7 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
Result<bool, nsresult>
HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToDeleteNodesEntirelyInRangeButKeepTableStructure(
+ ComputeRangeToDeleteNodesEntirelyInRangeButKeepTableStructure(
const HTMLEditor& aHTMLEditor, nsRange& aRange,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed)
const {
@@ -3841,39 +3938,34 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- ComputeRangesToDeleteNonCollapsedRanges(
+ ComputeRangeToDeleteNonCollapsedRange(
const HTMLEditor& aHTMLEditor,
- nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EDirection aDirectionAndAmount, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
MOZ_ASSERT(mLeftContent);
MOZ_ASSERT(mLeftContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->IsInclusiveDescendantOf(mLeftContent));
+ MOZ_ASSERT(aRangeToDelete.GetStartContainer()->IsInclusiveDescendantOf(
+ mLeftContent));
MOZ_ASSERT(mRightContent);
MOZ_ASSERT(mRightContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->IsInclusiveDescendantOf(mRightContent));
+ MOZ_ASSERT(
+ aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
- for (OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
- Result<bool, nsresult> result =
- ComputeRangesToDeleteNodesEntirelyInRangeButKeepTableStructure(
- aHTMLEditor, range, aSelectionWasCollapsed);
- if (result.isErr()) {
- NS_WARNING(
- "AutoBlockElementsJoiner::"
- "ComputeRangesToDeleteNodesEntirelyInRangeButKeepTableStructure() "
- "failed");
- return result.unwrapErr();
- }
- if (!result.unwrap()) {
- return NS_OK;
- }
+ Result<bool, nsresult> result =
+ ComputeRangeToDeleteNodesEntirelyInRangeButKeepTableStructure(
+ aHTMLEditor, aRangeToDelete, aSelectionWasCollapsed);
+ if (result.isErr()) {
+ NS_WARNING(
+ "AutoBlockElementsJoiner::"
+ "ComputeRangeToDeleteNodesEntirelyInRangeButKeepTableStructure() "
+ "failed");
+ return result.unwrapErr();
+ }
+ if (!result.unwrap()) {
+ return NS_OK;
}
AutoInclusiveAncestorBlockElementsJoiner joiner(*mLeftContent,
@@ -3893,68 +3985,62 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
return NS_OK;
}
- nsresult rv = joiner.ComputeRangesToDelete(aHTMLEditor, EditorDOMPoint(),
- aRangesToDelete);
+ nsresult rv = joiner.ComputeRangeToDelete(aHTMLEditor, EditorDOMPoint(),
+ aRangeToDelete);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
- "AutoInclusiveAncestorBlockElementsJoiner::ComputeRangesToDelete() "
+ "AutoInclusiveAncestorBlockElementsJoiner::ComputeRangeToDelete() "
"failed");
return rv;
}
Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
- AutoBlockElementsJoiner::HandleDeleteNonCollapsedRanges(
+ AutoBlockElementsJoiner::HandleDeleteNonCollapsedRange(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- nsIEditor::EStripWrappers aStripWrappers,
- AutoRangeArray& aRangesToDelete,
+ nsIEditor::EStripWrappers aStripWrappers, nsRange& aRangeToDelete,
AutoDeleteRangesHandler::SelectionWasCollapsed aSelectionWasCollapsed,
const Element& aEditingHost) {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.IsCollapsed());
+ MOZ_ASSERT(!aRangeToDelete.Collapsed());
MOZ_ASSERT(mDeleteRangesHandler);
MOZ_ASSERT(mLeftContent);
MOZ_ASSERT(mLeftContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetStartContainer()
- ->IsInclusiveDescendantOf(mLeftContent));
+ MOZ_ASSERT(aRangeToDelete.GetStartContainer()->IsInclusiveDescendantOf(
+ mLeftContent));
MOZ_ASSERT(mRightContent);
MOZ_ASSERT(mRightContent->IsElement());
- MOZ_ASSERT(aRangesToDelete.FirstRangeRef()
- ->GetEndContainer()
- ->IsInclusiveDescendantOf(mRightContent));
+ MOZ_ASSERT(
+ aRangeToDelete.GetEndContainer()->IsInclusiveDescendantOf(mRightContent));
const bool backspaceInRightBlock =
aSelectionWasCollapsed == SelectionWasCollapsed::Yes &&
nsIEditor::DirectionIsBackspace(aDirectionAndAmount);
- // Otherwise, delete every nodes in all ranges, then, clean up something.
+ // Otherwise, delete every nodes in the range, then, clean up something.
EditActionResult result = EditActionResult::IgnoredResult();
EditorDOMPoint pointToPutCaret;
while (true) {
+ OwningNonNull<nsRange> rangeToDelete(aRangeToDelete);
AutoTrackDOMRange firstRangeTracker(aHTMLEditor.RangeUpdaterRef(),
- &aRangesToDelete.FirstRangeRef());
-
- bool joinInclusiveAncestorBlockElements = true;
- for (auto& range : aRangesToDelete.Ranges()) {
- Result<bool, nsresult> deleteResult =
- DeleteNodesEntirelyInRangeButKeepTableStructure(
- aHTMLEditor, MOZ_KnownLive(range), aSelectionWasCollapsed);
- if (MOZ_UNLIKELY(deleteResult.isErr())) {
- NS_WARNING(
- "AutoBlockElementsJoiner::"
- "DeleteNodesEntirelyInRangeButKeepTableStructure() failed");
- return deleteResult.propagateErr();
- }
- // XXX Completely odd. Why don't we join blocks around each range?
- joinInclusiveAncestorBlockElements &= deleteResult.unwrap();
+ &rangeToDelete);
+
+ Result<bool, nsresult> deleteResult =
+ DeleteNodesEntirelyInRangeButKeepTableStructure(
+ aHTMLEditor, rangeToDelete, aSelectionWasCollapsed);
+ if (MOZ_UNLIKELY(deleteResult.isErr())) {
+ NS_WARNING(
+ "AutoBlockElementsJoiner::"
+ "DeleteNodesEntirelyInRangeButKeepTableStructure() failed");
+ return deleteResult.propagateErr();
}
+ const bool joinInclusiveAncestorBlockElements = deleteResult.unwrap();
+
// Check endpoints for possible text deletion. We can assume that if
- // text node is found, we can delete to end or to begining as
+ // text node is found, we can delete to end or to beginning as
// appropriate, since the case where both sel endpoints in same text
// node was already handled (we wouldn't be here)
- nsresult rv = DeleteTextAtStartAndEndOfRange(
- aHTMLEditor, MOZ_KnownLive(aRangesToDelete.FirstRangeRef()));
+ nsresult rv = DeleteTextAtStartAndEndOfRange(aHTMLEditor, rangeToDelete);
if (NS_FAILED(rv)) {
NS_WARNING(
"AutoBlockElementsJoiner::DeleteTextAtStartAndEndOfRange() failed");
@@ -3978,7 +4064,7 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
// be collapsed to the end of the selection, if deleting backward the
// selection should be collapsed to the beginning of the selection.
// But if we're not joining then the selection should collapse to the
- // beginning of the selection if we'redeleting forward, because the
+ // beginning of the selection if we're deleting forward, because the
// end of the selection will still be in the next block. And same
// thing for deleting backwards (selection should collapse to the end,
// because the beginning will still be in the first block). See Bug
@@ -4024,7 +4110,7 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
// AutoInclusiveAncestorBlockElementsJoiner computed new caret position, we
// should use it. Otherwise, we should keep the traditional behavior.
if (result.Handled() && pointToPutCaret.IsSet()) {
- EditorDOMRange range(aRangesToDelete.FirstRangeRef());
+ EditorDOMRange range(aRangeToDelete);
nsresult rv =
mDeleteRangesHandler->DeleteUnnecessaryNodes(aHTMLEditor, range);
if (NS_FAILED(rv)) {
@@ -4054,8 +4140,8 @@ Result<EditActionResult, nsresult> HTMLEditor::AutoDeleteRangesHandler::
nsresult rv =
mDeleteRangesHandler->DeleteUnnecessaryNodesAndCollapseSelection(
aHTMLEditor, aDirectionAndAmount,
- EditorDOMPoint(aRangesToDelete.FirstRangeRef()->StartRef()),
- EditorDOMPoint(aRangesToDelete.FirstRangeRef()->EndRef()));
+ EditorDOMPoint(aRangeToDelete.StartRef()),
+ EditorDOMPoint(aRangeToDelete.EndRef()));
if (NS_FAILED(rv)) {
NS_WARNING(
"AutoDeleteRangesHandler::DeleteUnnecessaryNodesAndCollapseSelection() "
@@ -4316,21 +4402,26 @@ HTMLEditor::AutoDeleteRangesHandler::DeleteParentBlocksWithTransactionIfEmpty(
}
nsresult
-HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
+HTMLEditor::AutoDeleteRangesHandler::ComputeRangeToDeleteRangeWithTransaction(
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
- AutoRangeArray& aRangesToDelete) const {
+ nsRange& aRangeToDelete, const Element& aEditingHost) const {
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
- MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
- EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
+ const EditorBase::HowToHandleCollapsedRange howToHandleCollapsedRange =
EditorBase::HowToHandleCollapsedRangeFor(aDirectionAndAmount);
- if (NS_WARN_IF(aRangesToDelete.IsCollapsed() &&
- howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::Ignore)) {
- return NS_ERROR_FAILURE;
+ if (MOZ_UNLIKELY(aRangeToDelete.Collapsed() &&
+ howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::Ignore)) {
+ return NS_SUCCESS_DOM_NO_OPERATION;
}
- auto extendRangeToSelectCharacterForward =
+ // If it's not collapsed, `DeleteRangeTransaction::Create()` will be called
+ // with it and `DeleteRangeTransaction` won't modify the range.
+ if (!aRangeToDelete.Collapsed()) {
+ return NS_OK;
+ }
+
+ const auto ExtendRangeToSelectCharacterForward =
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
const nsTextFragment& textFragment =
aCaretPoint.ContainerAs<Text>()->TextFragment();
@@ -4352,7 +4443,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"nsRange::SetStartAndEnd() failed");
};
- auto extendRangeToSelectCharacterBackward =
+ const auto ExtendRangeToSelectCharacterBackward =
[](nsRange& aRange, const EditorRawDOMPointInText& aCaretPoint) -> void {
if (aCaretPoint.IsStartOfContainer()) {
return;
@@ -4378,127 +4469,116 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction(
"nsRange::SetStartAndEnd() failed");
};
- RefPtr<Element> editingHost = aHTMLEditor.ComputeEditingHost();
- for (OwningNonNull<nsRange>& range : aRangesToDelete.Ranges()) {
- // If it's not collapsed, `DeleteRangeTransaction::Create()` will be called
- // with it and `DeleteRangeTransaction` won't modify the range.
- if (!range->Collapsed()) {
- continue;
+ // In the other cases, `EditorBase::CreateTransactionForCollapsedRange()`
+ // will handle the collapsed range.
+ EditorRawDOMPoint caretPoint(aRangeToDelete.StartRef());
+ if (howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
+ caretPoint.IsStartOfContainer()) {
+ nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
+ *caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
+ BlockInlineCheck::Unused, &aEditingHost);
+ if (!previousEditableContent) {
+ return NS_OK;
}
-
- if (howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::Ignore) {
- continue;
+ if (!previousEditableContent->IsText()) {
+ IgnoredErrorResult ignoredError;
+ aRangeToDelete.SelectNode(*previousEditableContent, ignoredError);
+ NS_WARNING_ASSERTION(!ignoredError.Failed(),
+ "nsRange::SelectNode() failed");
+ return NS_OK;
}
- // In the other cases, `EditorBase::CreateTransactionForCollapsedRange()`
- // will handle the collapsed range.
- EditorRawDOMPoint caretPoint(range->StartRef());
- if (howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::ExtendBackward &&
- caretPoint.IsStartOfContainer()) {
- nsIContent* previousEditableContent = HTMLEditUtils::GetPreviousContent(
- *caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
- BlockInlineCheck::Unused, editingHost);
- if (!previousEditableContent) {
- continue;
- }
- if (!previousEditableContent->IsText()) {
- IgnoredErrorResult ignoredError;
- range->SelectNode(*previousEditableContent, ignoredError);
- NS_WARNING_ASSERTION(!ignoredError.Failed(),
- "nsRange::SelectNode() failed");
- continue;
- }
+ ExtendRangeToSelectCharacterBackward(
+ aRangeToDelete,
+ EditorRawDOMPointInText::AtEndOf(*previousEditableContent->AsText()));
+ return NS_OK;
+ }
- extendRangeToSelectCharacterBackward(
- range,
- EditorRawDOMPointInText::AtEndOf(*previousEditableContent->AsText()));
- continue;
+ if (howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::ExtendForward &&
+ caretPoint.IsEndOfContainer()) {
+ nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
+ *caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
+ BlockInlineCheck::Unused, &aEditingHost);
+ if (!nextEditableContent) {
+ return NS_OK;
}
- if (howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::ExtendForward &&
- caretPoint.IsEndOfContainer()) {
- nsIContent* nextEditableContent = HTMLEditUtils::GetNextContent(
- *caretPoint.GetContainer(), {WalkTreeOption::IgnoreNonEditableNode},
- BlockInlineCheck::Unused, editingHost);
- if (!nextEditableContent) {
- continue;
- }
-
- if (!nextEditableContent->IsText()) {
- IgnoredErrorResult ignoredError;
- range->SelectNode(*nextEditableContent, ignoredError);
- NS_WARNING_ASSERTION(!ignoredError.Failed(),
- "nsRange::SelectNode() failed");
- continue;
- }
-
- extendRangeToSelectCharacterForward(
- range, EditorRawDOMPointInText(nextEditableContent->AsText(), 0));
- continue;
+ if (!nextEditableContent->IsText()) {
+ IgnoredErrorResult ignoredError;
+ aRangeToDelete.SelectNode(*nextEditableContent, ignoredError);
+ NS_WARNING_ASSERTION(!ignoredError.Failed(),
+ "nsRange::SelectNode() failed");
+ return NS_OK;
}
- if (caretPoint.IsInTextNode()) {
- if (howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
- extendRangeToSelectCharacterBackward(
- range, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
- caretPoint.Offset()));
- continue;
- }
- extendRangeToSelectCharacterForward(
- range, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
- caretPoint.Offset()));
- continue;
+ ExtendRangeToSelectCharacterForward(
+ aRangeToDelete,
+ EditorRawDOMPointInText(nextEditableContent->AsText(), 0));
+ return NS_OK;
+ }
+
+ if (caretPoint.IsInTextNode()) {
+ if (howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
+ ExtendRangeToSelectCharacterBackward(
+ aRangeToDelete,
+ EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
+ caretPoint.Offset()));
+ return NS_OK;
}
+ ExtendRangeToSelectCharacterForward(
+ aRangeToDelete, EditorRawDOMPointInText(caretPoint.ContainerAs<Text>(),
+ caretPoint.Offset()));
+ return NS_OK;
+ }
- nsIContent* editableContent =
+ nsIContent* editableContent =
+ howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::ExtendBackward
+ ? HTMLEditUtils::GetPreviousContent(
+ caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
+ BlockInlineCheck::Unused, &aEditingHost)
+ : HTMLEditUtils::GetNextContent(
+ caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
+ BlockInlineCheck::Unused, &aEditingHost);
+ if (!editableContent) {
+ return NS_OK;
+ }
+ while (editableContent && editableContent->IsCharacterData() &&
+ !editableContent->Length()) {
+ editableContent =
howToHandleCollapsedRange ==
EditorBase::HowToHandleCollapsedRange::ExtendBackward
? HTMLEditUtils::GetPreviousContent(
- caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
- BlockInlineCheck::Unused, editingHost)
+ *editableContent, {WalkTreeOption::IgnoreNonEditableNode},
+ BlockInlineCheck::Unused, &aEditingHost)
: HTMLEditUtils::GetNextContent(
- caretPoint, {WalkTreeOption::IgnoreNonEditableNode},
- BlockInlineCheck::Unused, editingHost);
- if (!editableContent) {
- continue;
- }
- while (editableContent && editableContent->IsCharacterData() &&
- !editableContent->Length()) {
- editableContent =
- howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::ExtendBackward
- ? HTMLEditUtils::GetPreviousContent(
- *editableContent, {WalkTreeOption::IgnoreNonEditableNode},
- BlockInlineCheck::Unused, editingHost)
- : HTMLEditUtils::GetNextContent(
- *editableContent, {WalkTreeOption::IgnoreNonEditableNode},
- BlockInlineCheck::Unused, editingHost);
- }
- if (!editableContent) {
- continue;
- }
+ *editableContent, {WalkTreeOption::IgnoreNonEditableNode},
+ BlockInlineCheck::Unused, &aEditingHost);
+ }
+ if (!editableContent) {
+ return NS_OK;
+ }
- if (!editableContent->IsText()) {
- IgnoredErrorResult ignoredError;
- range->SelectNode(*editableContent, ignoredError);
- NS_WARNING_ASSERTION(!ignoredError.Failed(),
- "nsRange::SelectNode() failed");
- continue;
- }
+ if (!editableContent->IsText()) {
+ IgnoredErrorResult ignoredError;
+ aRangeToDelete.SelectNode(*editableContent, ignoredError);
+ NS_WARNING_ASSERTION(!ignoredError.Failed(),
+ "nsRange::SelectNode() failed, but ignored");
+ return NS_OK;
+ }
- if (howToHandleCollapsedRange ==
- EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
- extendRangeToSelectCharacterBackward(
- range, EditorRawDOMPointInText::AtEndOf(*editableContent->AsText()));
- continue;
- }
- extendRangeToSelectCharacterForward(
- range, EditorRawDOMPointInText(editableContent->AsText(), 0));
+ if (howToHandleCollapsedRange ==
+ EditorBase::HowToHandleCollapsedRange::ExtendBackward) {
+ ExtendRangeToSelectCharacterBackward(
+ aRangeToDelete,
+ EditorRawDOMPointInText::AtEndOf(*editableContent->AsText()));
+ return NS_OK;
}
+ ExtendRangeToSelectCharacterForward(
+ aRangeToDelete, EditorRawDOMPointInText(editableContent->AsText(), 0));
return NS_OK;
}
@@ -4893,10 +4973,9 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler::
}
nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
- AutoInclusiveAncestorBlockElementsJoiner::ComputeRangesToDelete(
+ AutoInclusiveAncestorBlockElementsJoiner::ComputeRangeToDelete(
const HTMLEditor& aHTMLEditor, const EditorDOMPoint& aCaretPoint,
- AutoRangeArray& aRangesToDelete) const {
- MOZ_ASSERT(!aRangesToDelete.Ranges().IsEmpty());
+ nsRange& aRangeToDelete) const {
MOZ_ASSERT(mLeftBlockElement);
MOZ_ASSERT(mRightBlockElement);
@@ -4904,8 +4983,8 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
if (!aCaretPoint.IsSet()) {
return NS_OK; // The ranges are not collapsed, keep them as-is.
}
- nsresult rv = aRangesToDelete.Collapse(aCaretPoint);
- NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AutoRangeArray::Collapse() failed");
+ nsresult rv = aRangeToDelete.CollapseTo(aCaretPoint.ToRawRangeBoundary());
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsRange::CollapseTo() failed");
return rv;
}
@@ -4927,8 +5006,7 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
if (!aCaretPoint.IsSet()) {
// Don't shrink the original range.
bool noNeedToChangeStart = false;
- const auto atStart =
- aRangesToDelete.GetFirstRangeStartPoint<EditorDOMPoint>();
+ const EditorDOMPoint atStart(aRangeToDelete.StartRef());
if (atStart.IsBefore(range.StartRef())) {
// If the range starts from end of a container, and computed block
// boundaries range starts from an invisible `<br>` element, we
@@ -4948,22 +5026,19 @@ nsresult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
: nullptr;
if (!nextContent || nextContent != range.StartRef().GetChild()) {
noNeedToChangeStart = true;
- range.SetStart(
- aRangesToDelete.GetFirstRangeStartPoint<EditorDOMPoint>());
+ range.SetStart(EditorRawDOMPoint(aRangeToDelete.StartRef()));
}
}
- if (range.EndRef().IsBefore(
- aRangesToDelete.GetFirstRangeEndPoint<EditorRawDOMPoint>())) {
+ if (range.EndRef().IsBefore(EditorRawDOMPoint(aRangeToDelete.EndRef()))) {
if (noNeedToChangeStart) {
return NS_OK; // We don't need to modify the range.
}
- range.SetEnd(aRangesToDelete.GetFirstRangeEndPoint<EditorDOMPoint>());
+ range.SetEnd(EditorRawDOMPoint(aRangeToDelete.EndRef()));
}
}
- // XXX Oddly, we join blocks only at the first range.
- nsresult rv = aRangesToDelete.FirstRangeRef()->SetStartAndEnd(
- range.StartRef().ToRawRangeBoundary(),
- range.EndRef().ToRawRangeBoundary());
+ nsresult rv =
+ aRangeToDelete.SetStartAndEnd(range.StartRef().ToRawRangeBoundary(),
+ range.EndRef().ToRawRangeBoundary());
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AutoRangeArray::SetStartAndEnd() failed");
return rv;
@@ -6666,23 +6741,31 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete(
return Err(NS_ERROR_FAILURE);
}
- // Look for the common ancestor's block element. It's fine that we get
- // non-editable block element which is ancestor of inline editing host
- // because the following code checks editing host too.
- const Element* const maybeNonEditableBlockElement =
- HTMLEditUtils::GetInclusiveAncestorElement(
- *commonAncestor, HTMLEditUtils::ClosestBlockElement,
- BlockInlineCheck::UseComputedDisplayOutsideStyle);
- if (NS_WARN_IF(!maybeNonEditableBlockElement)) {
+ // Editing host may be nested and outer one could have focus. Let's use
+ // the closest editing host instead.
+ const RefPtr<Element> closestEditingHost =
+ aHTMLEditor.ComputeEditingHost(*commonAncestor, LimitInBodyElement::No);
+ if (NS_WARN_IF(!closestEditingHost)) {
return Err(NS_ERROR_FAILURE);
}
- // Set up for loops and cache our root element
- RefPtr<Element> editingHost = aHTMLEditor.ComputeEditingHost();
- if (NS_WARN_IF(!editingHost)) {
- return Err(NS_ERROR_FAILURE);
- }
+ // Look for the common ancestor's block element in the editing host. It's
+ // fine that we get non-editable block element which is ancestor of inline
+ // editing host because the following code checks editing host too.
+ const RefPtr<Element> closestBlockAncestorOrInlineEditingHost = [&]() {
+ // Note that if non-closest editing host has focus, found block may be
+ // non-editable.
+ if (Element* const maybeEditableBlockElement =
+ HTMLEditUtils::GetInclusiveAncestorElement(
+ *commonAncestor, HTMLEditUtils::ClosestBlockElement,
+ BlockInlineCheck::UseComputedDisplayOutsideStyle,
+ closestEditingHost)) {
+ return maybeEditableBlockElement;
+ }
+ return closestEditingHost.get();
+ }();
+ // Set up for loops and cache our root element
// If only one list element is selected, and if the list element is empty,
// we should delete only the list element. Or if the list element is not
// empty, we should make the list has only one empty list item element.
@@ -6712,18 +6795,18 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete(
// Find previous visible things before start of selection
EditorRawDOMRange rangeToDelete(aRangeToDelete);
- if (rangeToDelete.StartRef().GetContainer() != maybeNonEditableBlockElement &&
- rangeToDelete.StartRef().GetContainer() != editingHost) {
+ if (rangeToDelete.StartRef().GetContainer() !=
+ closestBlockAncestorOrInlineEditingHost) {
for (;;) {
WSScanResult backwardScanFromStartResult =
WSRunScanner::ScanPreviousVisibleNodeOrBlockBoundary(
- editingHost, rangeToDelete.StartRef(),
+ closestEditingHost, rangeToDelete.StartRef(),
BlockInlineCheck::UseComputedDisplayOutsideStyle);
if (!backwardScanFromStartResult.ReachedCurrentBlockBoundary()) {
break;
}
MOZ_ASSERT(backwardScanFromStartResult.GetContent() ==
- WSRunScanner(editingHost, rangeToDelete.StartRef(),
+ WSRunScanner(closestEditingHost, rangeToDelete.StartRef(),
BlockInlineCheck::UseComputedDisplayOutsideStyle)
.GetStartReasonContent());
// We want to keep looking up. But stop if we are crossing table
@@ -6731,8 +6814,8 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete(
if (HTMLEditUtils::IsAnyTableElement(
backwardScanFromStartResult.GetContent()) ||
backwardScanFromStartResult.GetContent() ==
- maybeNonEditableBlockElement ||
- backwardScanFromStartResult.GetContent() == editingHost) {
+ closestBlockAncestorOrInlineEditingHost ||
+ backwardScanFromStartResult.GetContent() == closestEditingHost) {
break;
}
// Don't cross list element boundary because we don't want to delete list
@@ -6767,11 +6850,11 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete(
// Find next visible things after end of selection
EditorDOMPoint atFirstInvisibleBRElement;
- if (rangeToDelete.EndRef().GetContainer() != maybeNonEditableBlockElement &&
- rangeToDelete.EndRef().GetContainer() != editingHost) {
+ if (rangeToDelete.EndRef().GetContainer() !=
+ closestBlockAncestorOrInlineEditingHost) {
for (;;) {
WSRunScanner wsScannerAtEnd(
- editingHost, rangeToDelete.EndRef(),
+ closestEditingHost, rangeToDelete.EndRef(),
BlockInlineCheck::UseComputedDisplayOutsideStyle);
WSScanResult forwardScanFromEndResult =
wsScannerAtEnd.ScanNextVisibleNodeOrBlockBoundaryFrom(
@@ -6806,8 +6889,7 @@ HTMLEditor::AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete(
if (HTMLEditUtils::IsAnyTableElement(
forwardScanFromEndResult.GetContent()) ||
forwardScanFromEndResult.GetContent() ==
- maybeNonEditableBlockElement ||
- forwardScanFromEndResult.GetContent() == editingHost) {
+ closestBlockAncestorOrInlineEditingHost) {
break;
}
// Don't cross flex-item/grid-item boundary to make new content inserted
diff --git a/editor/libeditor/TextEditor.cpp b/editor/libeditor/TextEditor.cpp
index 2403dd1f55..9f6fb86eb3 100644
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -40,7 +40,6 @@
#include "nsCaret.h"
#include "nsCharTraits.h"
#include "nsComponentManagerUtils.h"
-#include "nsContentCID.h"
#include "nsContentList.h"
#include "nsDebug.h"
#include "nsDependentSubstring.h"
diff --git a/editor/libeditor/tests/browserscope/test_richtext.html b/editor/libeditor/tests/browserscope/test_richtext.html
index c07f0a366a..3322522929 100644
--- a/editor/libeditor/tests/browserscope/test_richtext.html
+++ b/editor/libeditor/tests/browserscope/test_richtext.html
@@ -23,7 +23,7 @@ SimpleTest.waitForExplicitFinish();
// Running all of the tests can take a long time, try to account for it
SimpleTest.requestLongerTimeout(5);
-function sendScore(results, continueParams) {
+function sendScore(results) {
ok(results.length > 1, "At least one test should have been run");
for (var i = 1; i < results.length; ++i) {
var result = results[i];
diff --git a/editor/libeditor/tests/mochitest.toml b/editor/libeditor/tests/mochitest.toml
index 5af13503f7..15a6d4c379 100644
--- a/editor/libeditor/tests/mochitest.toml
+++ b/editor/libeditor/tests/mochitest.toml
@@ -418,6 +418,8 @@ skip-if = ["os == 'android'"] #Bug 1575739
["test_cmd_paragraphState.html"]
+["test_command_state_when_readonly.html"]
+
["test_composition_event_created_in_chrome.html"]
["test_composition_with_highlight_in_texteditor.html"]
diff --git a/editor/libeditor/tests/test_bug1053048.html b/editor/libeditor/tests/test_bug1053048.html
index 4f9df5e602..416d6442d6 100644
--- a/editor/libeditor/tests/test_bug1053048.html
+++ b/editor/libeditor/tests/test_bug1053048.html
@@ -37,7 +37,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1053048
// synthesizing the key press. So, we don't need to check whether a
// notification actually comes here.
let selectionListener = {
- notifySelectionChanged(aDocument, aSelection, aReason, aAmount) {
+ notifySelectionChanged() {
ok(true, "selectionStart: " + textarea.selectionStart);
ok(true, "selectionEnd: " + textarea.selectionEnd);
},
diff --git a/editor/libeditor/tests/test_bug1649005.html b/editor/libeditor/tests/test_bug1649005.html
index fbd8e16ef8..5e08e16493 100644
--- a/editor/libeditor/tests/test_bug1649005.html
+++ b/editor/libeditor/tests/test_bug1649005.html
@@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1649005
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script>
/** Test for bug 1649005, bug 1779343 **/
- window.addEventListener("DOMContentLoaded", (event) => {
+ window.addEventListener("DOMContentLoaded", () => {
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
document.body.textContent = ""; // It would be \n\n otherwise...
diff --git a/editor/libeditor/tests/test_bug1659276.html b/editor/libeditor/tests/test_bug1659276.html
index 6789db2e77..6286e58327 100644
--- a/editor/libeditor/tests/test_bug1659276.html
+++ b/editor/libeditor/tests/test_bug1659276.html
@@ -63,7 +63,7 @@ SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(async () => {
function waitForTickOfRefeshDriver() {
function awaitOneRefresh() {
- return new Promise(function(aResolve, aReject) {
+ return new Promise(function(aResolve) {
requestAnimationFrame(aResolve);
});
}
diff --git a/editor/libeditor/tests/test_bug502673.html b/editor/libeditor/tests/test_bug502673.html
index 0850cf3de0..fcfb1f329e 100644
--- a/editor/libeditor/tests/test_bug502673.html
+++ b/editor/libeditor/tests/test_bug502673.html
@@ -37,7 +37,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=502673
editor.removeDocumentStateListener(this);
},
- NotifyDocumentStateChanged(aNowDirty) {
+ NotifyDocumentStateChanged() {
var editor = SpecialPowers.wrap(this.input).editor;
editor.removeDocumentStateListener(this);
},
diff --git a/editor/libeditor/tests/test_bug525389.html b/editor/libeditor/tests/test_bug525389.html
index 500720d92a..25c6e2b8e3 100644
--- a/editor/libeditor/tests/test_bug525389.html
+++ b/editor/libeditor/tests/test_bug525389.html
@@ -17,7 +17,7 @@ function getLoadContext() {
async function runTest() {
var pasteCount = 0;
- var pasteFunc = function(event) { pasteCount++; };
+ var pasteFunc = function() { pasteCount++; };
function verifyContent(s) {
var e = document.getElementById("i1");
diff --git a/editor/libeditor/tests/test_bug569988.html b/editor/libeditor/tests/test_bug569988.html
index c4d4b040ba..6181668374 100644
--- a/editor/libeditor/tests/test_bug569988.html
+++ b/editor/libeditor/tests/test_bug569988.html
@@ -33,7 +33,7 @@ function runTest() {
os.addObserver(onPromptLoad, "common-dialog-loaded");
os.addObserver(onPromptLoad, "tabmodal-dialog-loaded");
- function onPromptLoad(subject, topic, data) {
+ function onPromptLoad(subject) {
let ui = subject.Dialog ? subject.Dialog.ui : undefined;
if (!ui) {
// subject is an tab prompt, find the elements ourselves
@@ -54,19 +54,15 @@ function runTest() {
sendAsyncMessage("ok", [true, "onPromptFocus is called"]);
gPromptInput.removeEventListener("focus", onPromptFocus);
- var listenerService = Services.els;
-
var listener = {
handleEvent: function _hv(aEvent) {
var isPrevented = aEvent.defaultPrevented;
sendAsyncMessage("ok", [!isPrevented,
"ESC key event is prevented by editor"]);
- listenerService.removeSystemEventListener(gPromptInput, "keypress",
- listener, false);
+ gPromptInput.removeEventListener("keypress", listener, { mozSystemGroup: true });
},
};
- listenerService.addSystemEventListener(gPromptInput, "keypress",
- listener, false);
+ gPromptInput.addEventListener("keypress", listener, { mozSystemGroup: true });
sendAsyncMessage("info", "sending key");
var EventUtils = {};
diff --git a/editor/libeditor/tests/test_bug607584.xhtml b/editor/libeditor/tests/test_bug607584.xhtml
index f610de544b..37bb3dc5a4 100644
--- a/editor/libeditor/tests/test_bug607584.xhtml
+++ b/editor/libeditor/tests/test_bug607584.xhtml
@@ -44,7 +44,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607584
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
"nsISupportsWeakReference"]),
- onStateChange(aWebProgress, aRequest, aStateFlags, aStatus)
+ onStateChange(aWebProgress, aRequest, aStateFlags)
{
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
{
@@ -71,25 +71,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607584
},
- onProgressChange(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
+ onProgressChange()
{
},
- onLocationChange(aWebProgress, aRequest, aLocation, aFlags)
+ onLocationChange()
{
},
- onStatusChange(aWebProgress, aRequest, aStatus, aMessage)
+ onStatusChange()
{
},
- onSecurityChange(aWebProgress, aRequest, aState)
+ onSecurityChange()
{
},
- onContentBlockingEvent(aWebProgress, aRequest, aEvent)
+ onContentBlockingEvent()
{
},
diff --git a/editor/libeditor/tests/test_bug611182.html b/editor/libeditor/tests/test_bug611182.html
index 7843156fda..125dcacb62 100644
--- a/editor/libeditor/tests/test_bug611182.html
+++ b/editor/libeditor/tests/test_bug611182.html
@@ -92,7 +92,7 @@ SimpleTest.waitForFocus(function() {
// start running all tests.
var myXHR = new XMLHttpRequest();
myXHR.open("GET", "file_bug611182.sjs?queryTotalTests");
- myXHR.onload = function(e) {
+ myXHR.onload = function() {
totalTests = myXHR.responseText;
runAllTests();
};
diff --git a/editor/libeditor/tests/test_bug616590.xhtml b/editor/libeditor/tests/test_bug616590.xhtml
index 1f6cb3d0f8..4a4bad7224 100644
--- a/editor/libeditor/tests/test_bug616590.xhtml
+++ b/editor/libeditor/tests/test_bug616590.xhtml
@@ -43,7 +43,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=616590
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
"nsISupportsWeakReference"]),
- onStateChange(aWebProgress, aRequest, aStateFlags, aStatus)
+ onStateChange(aWebProgress, aRequest, aStateFlags)
{
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
{
@@ -60,25 +60,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=616590
},
- onProgressChange(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
+ onProgressChange()
{
},
- onLocationChange(aWebProgress, aRequest, aLocation, aFlags)
+ onLocationChange()
{
},
- onStatusChange(aWebProgress, aRequest, aStatus, aMessage)
+ onStatusChange()
{
},
- onSecurityChange(aWebProgress, aRequest, aState)
+ onSecurityChange()
{
},
- onContentBlockingEvent(aWebProgress, aRequest, aEvent)
+ onContentBlockingEvent()
{
},
diff --git a/editor/libeditor/tests/test_bug674770-1.html b/editor/libeditor/tests/test_bug674770-1.html
index 0b6089e0ef..d8e792ccd2 100644
--- a/editor/libeditor/tests/test_bug674770-1.html
+++ b/editor/libeditor/tests/test_bug674770-1.html
@@ -55,7 +55,7 @@ function startTests() {
SimpleTest.executeSoon(runNextTest);
}, false);
- SpecialPowers.addSystemEventListener(window, "auxclick", function(aEvent) {
+ SpecialPowers.wrap(window).addEventListener("auxclick", function(aEvent) {
// When the click event should cause default action, e.g., opening the link,
// the event shouldn't have been consumed except the link handler.
// However, in e10s mode, it's not consumed during propagating the event but
@@ -74,7 +74,7 @@ function startTests() {
// In this case, "storage" event won't be fired.
SimpleTest.executeSoon(runNextTest);
}
- }, false);
+ }, { mozSystemGroup: true });
SimpleTest.executeSoon(runNextTest);
}
diff --git a/editor/libeditor/tests/test_bug674770-2.html b/editor/libeditor/tests/test_bug674770-2.html
index 9b05277052..ab2fbca68b 100644
--- a/editor/libeditor/tests/test_bug674770-2.html
+++ b/editor/libeditor/tests/test_bug674770-2.html
@@ -320,7 +320,7 @@ function initForBodyEditableDocumentTests() {
frameDocument.getElementById("editor2").removeEventListener("click", clickEventHandler);
iframe.onload =
- function(aEvent) { SimpleTest.executeSoon(runBodyEditableDocumentTests1); };
+ function() { SimpleTest.executeSoon(runBodyEditableDocumentTests1); };
iframe.srcdoc = "<body contenteditable>body:</body>";
}
diff --git a/editor/libeditor/tests/test_bug780908.xhtml b/editor/libeditor/tests/test_bug780908.xhtml
index 590316ef46..6bfa306a71 100644
--- a/editor/libeditor/tests/test_bug780908.xhtml
+++ b/editor/libeditor/tests/test_bug780908.xhtml
@@ -46,7 +46,7 @@ adapted from test_bug607584.xhtml by Kent James <kent@caspia.com>
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
"nsISupportsWeakReference"]),
- onStateChange(aWebProgress, aRequest, aStateFlags, aStatus)
+ onStateChange(aWebProgress, aRequest, aStateFlags)
{
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
{
@@ -69,25 +69,23 @@ adapted from test_bug607584.xhtml by Kent James <kent@caspia.com>
},
- onProgressChange(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
+ onProgressChange()
{
},
- onLocationChange(aWebProgress, aRequest, aLocation, aFlags)
+ onLocationChange()
{
},
- onStatusChange(aWebProgress, aRequest, aStatus, aMessage)
+ onStatusChange()
{
},
- onSecurityChange(aWebProgress, aRequest, aState)
+ onSecurityChange()
{
},
- onContentBlockingEvent(aWebProgress, aRequest, aEvent)
+ onContentBlockingEvent()
{
},
diff --git a/editor/libeditor/tests/test_command_state_when_readonly.html b/editor/libeditor/tests/test_command_state_when_readonly.html
new file mode 100644
index 0000000000..7b4daaa1b3
--- /dev/null
+++ b/editor/libeditor/tests/test_command_state_when_readonly.html
@@ -0,0 +1,149 @@
+<!doctype html>
+<title>Test for nsIEditor.isCommandEnabled for normal and read-only editors</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<div contenteditable></div>
+<script>
+ let node = document.querySelector("div");
+ node.focus();
+ let htmlEditor =
+ SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
+
+ // Supported environments for each command. Supported values for each
+ // environment property:
+ // content: "empty", "non-empty", "cleared"
+ // selected: true, false
+ // readonly: true, false
+ //
+ // If an environment definition does not state a certain property, the command
+ // supports all possible values for that property. The following definition:
+ // "cmd_copy": [{content: "non-empty", selected: true}],
+ // is equivalent to:
+ // "cmd_copy": [
+ // {content: "non-empty", selected: true, readonly: true},
+ // {content: "non-empty", selected: true, readonly: false},
+ // ],
+ const TEST_COMMANDS = {
+ "cmd_selectAll": [{content: "non-empty"}],
+
+ "cmd_copy": [{content: "non-empty", selected: true}],
+
+ "cmd_cut": [{content: "non-empty", selected: true, readonly: false}],
+ "cmd_delete": [{content: "non-empty", selected: true, readonly: false}],
+ "cmd_removeList":[{content: "non-empty", selected: true, readonly: false}],
+
+ "cmd_undo": [{content: "cleared", readonly: false}],
+ "cmd_redo": [{content: "cleared", readonly: false}],
+
+ "cmd_switchTextDirection": [{readonly: false}],
+ "cmd_bold": [{readonly: false}],
+ "cmd_italic": [{readonly: false}],
+ "cmd_underline": [{readonly: false}],
+ "cmd_em": [{readonly: false}],
+ "cmd_strong": [{readonly: false}],
+ "cmd_strikethrough": [{readonly: false}],
+ "cmd_superscript": [{readonly: false}],
+ "cmd_subscript": [{readonly: false}],
+ "cmd_indent": [{readonly: false}],
+ "cmd_outdent": [{readonly: false}],
+ "cmd_formatBlock": [{readonly: false}],
+ "cmd_paragraphState": [{readonly: false}],
+ "cmd_fontFace": [{readonly: false}],
+ "cmd_fontSize": [{readonly: false}],
+ "cmd_fontColor": [{readonly: false}],
+ "cmd_backgroundColor": [{readonly: false}],
+ "cmd_highlight": [{readonly: false}],
+ "cmd_align": [{readonly: false}],
+ "cmd_removeStyles": [{readonly: false}],
+ "cmd_increaseFont": [{readonly: false}],
+ "cmd_decreaseFont": [{readonly: false}],
+ "cmd_insertHR": [{readonly: false}],
+ "cmd_insertHTML": [{readonly: false}],
+ "cmd_insertText": [{readonly: false}],
+ "cmd_insertParagraph": [{readonly: false}],
+ "cmd_insertLineBreak": [{readonly: false}],
+ "cmd_tt":[{readonly: false}],
+ "cmd_nobreak":[{readonly: false}],
+ "cmd_cite":[{readonly: false}],
+ "cmd_abbr":[{readonly: false}],
+ "cmd_acronym":[{readonly: false}],
+ "cmd_code":[{readonly: false}],
+ "cmd_samp":[{readonly: false}],
+ "cmd_var":[{readonly: false}],
+ "cmd_removeLinks":[{readonly: false}],
+ "cmd_ol":[{readonly: false}],
+ "cmd_ul":[{readonly: false}],
+ "cmd_dt":[{readonly: false}],
+ "cmd_dd":[{readonly: false}],
+
+ // InsertTagCommand
+ "cmd_insertImageNoUI": [{readonly: false}],
+ "cmd_insertLinkNoUI": [{readonly: false}],
+ };
+
+ function testCommands(content) {
+ for (let readonly of [true, false]){
+ if (readonly) {
+ htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
+ } else {
+ htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
+ }
+
+ for (let selected of [true, false]) {
+ let selection = window.getSelection();
+ selection.collapse(node);
+
+ if (selected) {
+ if (content == "non-empty") {
+ // The command cmd_removeList needs selected text inside a list. It
+ // does not matter for all other commands, so lets just select that.
+ let range = document.createRange();
+ let li = document.querySelector("li");
+ range.selectNodeContents(li);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ } else {
+ document.execCommand("selectAll");
+ }
+ }
+
+ for (let [cmd, supports] of Object.entries(TEST_COMMANDS)) {
+ // Check if the command should support this environment.
+ let expected = supports.some(supported =>
+ content == (supported?.content ?? content) &&
+ readonly == (supported?.readonly ?? readonly) &&
+ selected == (supported?.selected ?? selected)
+ )
+ is(
+ SpecialPowers.isCommandEnabled(window, cmd),
+ expected,
+ `Enabled state of command ${cmd} should be ${
+ expected ? "TRUE" : "FALSE"
+ } for ${JSON.stringify({content, selected, readonly})}`
+ );
+ }
+ }
+ }
+ }
+
+ testCommands("empty");
+
+ // The cmd_removeList command needs a list.
+ node.innerHTML = "<ul><li><span>abcd</span></li></ul>";
+ testCommands("non-empty");
+
+ // Make some content modifications to enable undo and redo.
+ node.innerText = "ABC";
+ is(node.innerText.trim(), "ABC", "phase 1");
+ document.execCommand("selectAll");
+ synthesizeKey("KEY_Backspace");
+ is(node.innerText.trim(), "", "phase 2");
+ synthesizeKey("3");
+ is(node.innerText.trim(), "3", "phase 3");
+ SpecialPowers.doCommand(window, "cmd_undo");
+ is(node.innerText.trim(), "", "phase 4");
+
+ node.innerHTML = "";
+ testCommands("cleared");
+</script>
diff --git a/editor/libeditor/tests/test_composition_with_highlight_in_texteditor.html b/editor/libeditor/tests/test_composition_with_highlight_in_texteditor.html
index d6bb703231..0990d87adb 100644
--- a/editor/libeditor/tests/test_composition_with_highlight_in_texteditor.html
+++ b/editor/libeditor/tests/test_composition_with_highlight_in_texteditor.html
@@ -23,9 +23,9 @@ SimpleTest.waitForFocus(() => {
);
const editActionListener = {
QueryInterface: SpecialPowers.ChromeUtils.generateQI(["nsIEditActionListener"]),
- WillDeleteText: (textNode, offset, length) => {},
- DidInsertText: (textNode, offset, aString) => {},
- WillDeleteRanges: (rangesToDelete) => {},
+ WillDeleteText: () => {},
+ DidInsertText: () => {},
+ WillDeleteRanges: () => {},
};
// Highlight "a"
findSelection.setBaseAndExtent(
diff --git a/editor/libeditor/tests/test_contenteditable_text_input_handling.html b/editor/libeditor/tests/test_contenteditable_text_input_handling.html
index c00056a0f0..13a00a65b8 100644
--- a/editor/libeditor/tests/test_contenteditable_text_input_handling.html
+++ b/editor/libeditor/tests/test_contenteditable_text_input_handling.html
@@ -34,8 +34,7 @@ function runTests() {
aEvent.preventDefault(); // prevent the browser default behavior
},
};
- var els = Services.els;
- els.addSystemEventListener(window, "keypress", listener, false);
+ SpecialPowers.wrap(window).addEventListener("keypress", listener, { mozSystemGroup: true });
var staticContent = document.getElementById("static");
staticContent._defaultValue = getTextValue(staticContent);
@@ -306,7 +305,7 @@ function runTests() {
testTextInput(inputInEditor);
testTextInput(textareaInEditor);
- els.removeSystemEventListener(window, "keypress", listener, false);
+ SpecialPowers.wrap(window).removeEventListener("keypress", listener, { mozSystemGroup: true });
SimpleTest.finish();
}
diff --git a/editor/libeditor/tests/test_dragdrop.html b/editor/libeditor/tests/test_dragdrop.html
index 6295661faa..5c7d940928 100644
--- a/editor/libeditor/tests/test_dragdrop.html
+++ b/editor/libeditor/tests/test_dragdrop.html
@@ -3101,7 +3101,7 @@ async function doTest() {
beforeinputEvents = [];
inputEvents = [];
dragEvents = [];
- const onDragStart = aEvent => {
+ const onDragStart = () => {
input.style.display = "none";
document.documentElement.scrollTop;
input.style.display = "";
@@ -3147,7 +3147,7 @@ async function doTest() {
beforeinputEvents = [];
inputEvents = [];
dragEvents = [];
- const onDragStart = aEvent => {
+ const onDragStart = () => {
textarea.style.display = "none";
document.documentElement.scrollTop;
textarea.style.display = "";
@@ -3193,13 +3193,13 @@ async function doTest() {
beforeinputEvents = [];
inputEvents = [];
dragEvents = [];
- const onMouseMove = aEvent => {
+ const onMouseMove = () => {
input.style.display = "none";
document.documentElement.scrollTop;
input.style.display = "";
document.documentElement.scrollTop;
};
- const onMouseDown = aEvent => {
+ const onMouseDown = () => {
document.addEventListener("mousemove", onMouseMove, {once: true});
}
const onDrop = aEvent => {
@@ -3243,13 +3243,13 @@ async function doTest() {
beforeinputEvents = [];
inputEvents = [];
dragEvents = [];
- const onMouseMove = aEvent => {
+ const onMouseMove = () => {
textarea.style.display = "none";
document.documentElement.scrollTop;
textarea.style.display = "";
document.documentElement.scrollTop;
};
- const onMouseDown = aEvent => {
+ const onMouseDown = () => {
document.addEventListener("mousemove", onMouseMove, {once: true});
}
const onDrop = aEvent => {
diff --git a/editor/libeditor/tests/test_execCommandPaste_noTarget.html b/editor/libeditor/tests/test_execCommandPaste_noTarget.html
index 6586ca768d..70de112a78 100644
--- a/editor/libeditor/tests/test_execCommandPaste_noTarget.html
+++ b/editor/libeditor/tests/test_execCommandPaste_noTarget.html
@@ -32,7 +32,7 @@
// Check that reading text from the clipboard in non-privileged contexts
// still doesn't work.
- function onpstfail(e) {
+ function onpstfail() {
ok(false, "Should not see paste event triggered by non-privileged call");
}
document.addEventListener("paste", onpstfail);
diff --git a/editor/libeditor/tests/test_htmleditor_keyevent_handling.html b/editor/libeditor/tests/test_htmleditor_keyevent_handling.html
index 58666beb35..6fb79212e2 100644
--- a/editor/libeditor/tests/test_htmleditor_keyevent_handling.html
+++ b/editor/libeditor/tests/test_htmleditor_keyevent_handling.html
@@ -79,8 +79,8 @@ async function runTests() {
getDesciption(aPreventedOnBubbling) + "prevented on bubbling phase");
}
- SpecialPowers.addSystemEventListener(window, "keypress", listener, true);
- SpecialPowers.addSystemEventListener(window, "keypress", listener, false);
+ SpecialPowers.wrap(window).addEventListener("keypress", listener, { capture: true, mozSystemGroup: true });
+ SpecialPowers.wrap(window).addEventListener("keypress", listener, { capture: false, mozSystemGroup: true });
// eslint-disable-next-line complexity
async function doTest(
@@ -754,8 +754,8 @@ async function runTests() {
await doTest(htmlEditor, "readonly and non-tabbable HTML editor but plaintext mode",
true, false, true);
- SpecialPowers.removeSystemEventListener(window, "keypress", listener, true);
- SpecialPowers.removeSystemEventListener(window, "keypress", listener, false);
+ SpecialPowers.wrap(window).removeEventListener("keypress", listener, { capture: true, mozSystemGroup: true });
+ SpecialPowers.wrap(window).removeEventListener("keypress", listener, { capture: false, mozSystemGroup: true });
SimpleTest.finish();
}
diff --git a/editor/libeditor/tests/test_middle_click_paste.html b/editor/libeditor/tests/test_middle_click_paste.html
index eaa918c194..d34411e54b 100644
--- a/editor/libeditor/tests/test_middle_click_paste.html
+++ b/editor/libeditor/tests/test_middle_click_paste.html
@@ -224,7 +224,7 @@ async function doTextareaTests(aTextarea) {
aTextarea.value = "";
let pasteEventCount = 0;
- function pasteEventLogger(event) {
+ function pasteEventLogger() {
pasteEventCount++;
}
aTextarea.addEventListener("paste", pasteEventLogger);
@@ -381,7 +381,7 @@ async function doContenteditableTests(aEditableDiv) {
aEditableDiv.innerHTML = "";
let pasteEventCount = 0;
- function pasteEventLogger(event) {
+ function pasteEventLogger() {
pasteEventCount++;
}
aEditableDiv.addEventListener("paste", pasteEventLogger);
diff --git a/editor/libeditor/tests/test_nsIEditor_documentIsEmpty.html b/editor/libeditor/tests/test_nsIEditor_documentIsEmpty.html
index 49c1db78a9..1e60e58191 100644
--- a/editor/libeditor/tests/test_nsIEditor_documentIsEmpty.html
+++ b/editor/libeditor/tests/test_nsIEditor_documentIsEmpty.html
@@ -80,7 +80,7 @@
ok(true, "nsIEditor.documentIsEmpty should throw an exception when no editing host has focus");
}
document.querySelector("div[contenteditable]").focus();
- todo_is(getHTMLEditor().documentIsEmpty, true,
+ is(getHTMLEditor().documentIsEmpty, true,
"nsIEditor.documentIsEmpty should be true when editing host does not have contents");
document.body.innerHTML = "<div contenteditable><br></div>";
diff --git a/editor/libeditor/tests/test_paste_redirect_focus_in_paste_event_listener.html b/editor/libeditor/tests/test_paste_redirect_focus_in_paste_event_listener.html
index b82938158e..89d7531fa5 100644
--- a/editor/libeditor/tests/test_paste_redirect_focus_in_paste_event_listener.html
+++ b/editor/libeditor/tests/test_paste_redirect_focus_in_paste_event_listener.html
@@ -57,7 +57,7 @@ SimpleTest.waitForFocus(async () => {
const editableElementDesc = `<${
editableElement.tagName.toLocaleLowerCase()
}${editableElement.hasAttribute("contenteditable") ? " contenteditable" : ""}>`;
- (test_from_editableElement_to_input => {
+ (() => {
const input = document.querySelector("#dest > input");
editableElement.focus();
editableElement.addEventListener(
@@ -84,7 +84,7 @@ SimpleTest.waitForFocus(async () => {
input.value = "";
})();
- (test_from_editableElement_to_contenteditable => {
+ (() => {
const contentEditable = document.querySelector("#dest > div[contenteditable]");
editableElement.focus();
editableElement.addEventListener(
@@ -111,7 +111,7 @@ SimpleTest.waitForFocus(async () => {
contentEditable.innerHTML = "<br>";
})();
- (test_from_editableElement_to_non_editable => {
+ (() => {
const button = document.querySelector("#dest > button");
editableElement.focus();
editableElement.addEventListener(
diff --git a/editor/libeditor/tests/test_texteditor_keyevent_handling.html b/editor/libeditor/tests/test_texteditor_keyevent_handling.html
index 2c80181b3c..6b3d5f4608 100644
--- a/editor/libeditor/tests/test_texteditor_keyevent_handling.html
+++ b/editor/libeditor/tests/test_texteditor_keyevent_handling.html
@@ -80,10 +80,8 @@ async function runTests() {
}
var parentElement = document.getElementById("display");
- SpecialPowers.addSystemEventListener(parentElement, "keypress", listener,
- true);
- SpecialPowers.addSystemEventListener(parentElement, "keypress", listener,
- false);
+ SpecialPowers.wrap(parentElement).addEventListener("keypress", listener, { capture: true, mozSystemGroup: true });
+ SpecialPowers.wrap(parentElement).addEventListener("keypress", listener, { capture: false, mozSystemGroup: true });
async function doTest(aElement, aDescription, aIsSingleLine, aIsReadonly) {
function reset(aText) {
@@ -457,10 +455,8 @@ async function runTests() {
textarea.setAttribute("readonly", "readonly");
await doTest(textarea, "<textarea readonly>", false, true);
- SpecialPowers.removeSystemEventListener(parentElement, "keypress", listener,
- true);
- SpecialPowers.removeSystemEventListener(parentElement, "keypress", listener,
- false);
+ SpecialPowers.wrap(parentElement).removeEventListener("keypress", listener, { capture: true, mozSystemGroup: true });
+ SpecialPowers.wrap(parentElement).removeEventListener("keypress", listener, { capture: false, mozSystemGroup: true });
SimpleTest.finish();
}
diff --git a/editor/libeditor/tests/test_texteditor_wrapping_long_line.html b/editor/libeditor/tests/test_texteditor_wrapping_long_line.html
index 14a445bbb0..013e563a27 100644
--- a/editor/libeditor/tests/test_texteditor_wrapping_long_line.html
+++ b/editor/libeditor/tests/test_texteditor_wrapping_long_line.html
@@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1733878
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script>
/** Test for bug 1733878 **/
- window.addEventListener("DOMContentLoaded", (event) => {
+ window.addEventListener("DOMContentLoaded", () => {
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
document.body.textContent = ""; // It would be \n\n otherwise...