diff --git a/editor/libeditor/EditorDOMPoint.h b/editor/libeditor/EditorDOMPoint.h index 24f168b6003a..8ef492831c5d 100644 --- a/editor/libeditor/EditorDOMPoint.h +++ b/editor/libeditor/EditorDOMPoint.h @@ -1214,6 +1214,34 @@ class EditorDOMRangeBase final { return EditorDOMRangeInTexts(mStart.AsInText(), mEnd.AsInText()); } + bool EnsureNotInNativeAnonymousSubtree() { + if (mStart.IsInNativeAnonymousSubtree()) { + nsIContent* parent = nullptr; + for (parent = mStart.ContainerAsContent() + ->GetClosestNativeAnonymousSubtreeRootParent(); + parent && parent->IsInNativeAnonymousSubtree(); + parent = parent->GetClosestNativeAnonymousSubtreeRootParent()) { + } + if (MOZ_UNLIKELY(!parent)) { + return false; + } + mStart.Set(parent); + } + if (mEnd.IsInNativeAnonymousSubtree()) { + nsIContent* parent = nullptr; + for (parent = mEnd.ContainerAsContent() + ->GetClosestNativeAnonymousSubtreeRootParent(); + parent && parent->IsInNativeAnonymousSubtree(); + parent = parent->GetClosestNativeAnonymousSubtreeRootParent()) { + } + if (MOZ_UNLIKELY(!parent)) { + return false; + } + mEnd.SetAfter(parent); + } + return true; + } + private: EditorDOMPointType mStart; EditorDOMPointType mEnd; diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index d00732087387..be34887609fc 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -387,38 +387,43 @@ nsresult HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal() { // Note that this won't prevent explicit selection setting from working. AutoTransactionsConserveSelection dontChangeMySelection(*this); - switch (GetTopLevelEditSubAction()) { - case EditSubAction::eInsertText: - case EditSubAction::eInsertTextComingFromIME: - case EditSubAction::eInsertLineBreak: - case EditSubAction::eInsertParagraphSeparator: - case EditSubAction::eDeleteText: { - // XXX We should investigate whether this is really needed because it - // seems that the following code does not handle the white-spaces. - RefPtr extendedChangedRange = - CreateRangeIncludingAdjuscentWhiteSpaces(EditorRawDOMRange( - *TopLevelEditSubActionDataRef().mChangedRange)); - if (extendedChangedRange) { - MOZ_ASSERT(extendedChangedRange->IsPositioned()); - // Use extended range temporarily. - TopLevelEditSubActionDataRef().mChangedRange = - std::move(extendedChangedRange); + { + EditorRawDOMRange changedRange( + *TopLevelEditSubActionDataRef().mChangedRange); + if (changedRange.IsPositioned() && + changedRange.EnsureNotInNativeAnonymousSubtree()) { + switch (GetTopLevelEditSubAction()) { + case EditSubAction::eInsertText: + case EditSubAction::eInsertTextComingFromIME: + case EditSubAction::eInsertLineBreak: + case EditSubAction::eInsertParagraphSeparator: + case EditSubAction::eDeleteText: { + // XXX We should investigate whether this is really needed because + // it seems that the following code does not handle the + // white-spaces. + RefPtr extendedChangedRange = + CreateRangeIncludingAdjuscentWhiteSpaces(changedRange); + if (extendedChangedRange) { + MOZ_ASSERT(extendedChangedRange->IsPositioned()); + // Use extended range temporarily. + TopLevelEditSubActionDataRef().mChangedRange = + std::move(extendedChangedRange); + } + break; + } + default: { + RefPtr extendedChangedRange = + CreateRangeExtendedToHardLineStartAndEnd( + changedRange, GetTopLevelEditSubAction()); + if (extendedChangedRange) { + MOZ_ASSERT(extendedChangedRange->IsPositioned()); + // Use extended range temporarily. + TopLevelEditSubActionDataRef().mChangedRange = + std::move(extendedChangedRange); + } + break; + } } - break; - } - default: { - RefPtr extendedChangedRange = - CreateRangeExtendedToHardLineStartAndEnd( - EditorRawDOMRange( - *TopLevelEditSubActionDataRef().mChangedRange), - GetTopLevelEditSubAction()); - if (extendedChangedRange) { - MOZ_ASSERT(extendedChangedRange->IsPositioned()); - // Use extended range temporarily. - TopLevelEditSubActionDataRef().mChangedRange = - std::move(extendedChangedRange); - } - break; } } @@ -6144,9 +6149,14 @@ void HTMLEditor::GetSelectionRangesExtendedToIncludeAdjuscentWhiteSpaces( MOZ_ASSERT(SelectionRef().RangeCount() == rangeCount); const nsRange* selectionRange = SelectionRef().GetRangeAt(i); MOZ_ASSERT(selectionRange); - - RefPtr extendedRange = CreateRangeIncludingAdjuscentWhiteSpaces( - EditorRawDOMRange(*selectionRange)); + EditorRawDOMRange rawRange(*selectionRange); + if (!rawRange.IsPositioned() || + !rawRange.EnsureNotInNativeAnonymousSubtree()) { + continue; // ignore ranges which are in orphan fragment which were + // disconnected from native anonymous subtrees + } + RefPtr extendedRange = + CreateRangeIncludingAdjuscentWhiteSpaces(rawRange); if (!extendedRange) { extendedRange = selectionRange->CloneRange(); } @@ -6169,13 +6179,17 @@ void HTMLEditor::GetSelectionRangesExtendedToHardLineStartAndEnd( // blocks that we will affect. This call alters opRange. nsRange* selectionRange = SelectionRef().GetRangeAt(i); MOZ_ASSERT(selectionRange); - - RefPtr extendedRange = CreateRangeExtendedToHardLineStartAndEnd( - EditorRawDOMRange(*selectionRange), aEditSubAction); + EditorRawDOMRange rawRange(*selectionRange); + if (!rawRange.IsPositioned() || + !rawRange.EnsureNotInNativeAnonymousSubtree()) { + continue; // ignore ranges which are in orphan fragment which were + // disconnected from native anonymous subtrees + } + RefPtr extendedRange = + CreateRangeExtendedToHardLineStartAndEnd(rawRange, aEditSubAction); if (!extendedRange) { extendedRange = selectionRange->CloneRange(); } - aOutArrayOfRanges.AppendElement(extendedRange); } } @@ -6227,9 +6241,7 @@ void HTMLEditor::SelectBRElementIfCollapsedInEmptyBlock( template already_AddRefed HTMLEditor::CreateRangeIncludingAdjuscentWhiteSpaces( const EditorDOMRangeType& aRange) { - if (!aRange.IsPositioned()) { - return nullptr; - } + MOZ_DIAGNOSTIC_ASSERT(aRange.IsPositioned()); return CreateRangeIncludingAdjuscentWhiteSpaces(aRange.StartRef(), aRange.EndRef()); } @@ -6238,6 +6250,9 @@ template already_AddRefed HTMLEditor::CreateRangeIncludingAdjuscentWhiteSpaces( const EditorDOMPointType1& aStartPoint, const EditorDOMPointType2& aEndPoint) { + MOZ_DIAGNOSTIC_ASSERT(!aStartPoint.IsInNativeAnonymousSubtree()); + MOZ_DIAGNOSTIC_ASSERT(!aEndPoint.IsInNativeAnonymousSubtree()); + if (!aStartPoint.IsInContentNode() || !aEndPoint.IsInContentNode()) { NS_WARNING_ASSERTION(aStartPoint.IsSet(), "aStartPoint was not set"); NS_WARNING_ASSERTION(aEndPoint.IsSet(), "aEndPoint was not set"); @@ -6314,6 +6329,9 @@ template already_AddRefed HTMLEditor::CreateRangeExtendedToHardLineStartAndEnd( const EditorDOMPointType1& aStartPoint, const EditorDOMPointType2& aEndPoint, EditSubAction aEditSubAction) const { + MOZ_DIAGNOSTIC_ASSERT(!aStartPoint.IsInNativeAnonymousSubtree()); + MOZ_DIAGNOSTIC_ASSERT(!aEndPoint.IsInNativeAnonymousSubtree()); + if (NS_WARN_IF(!aStartPoint.IsSet()) || NS_WARN_IF(!aEndPoint.IsSet())) { return nullptr; } @@ -6345,8 +6363,8 @@ already_AddRefed HTMLEditor::CreateRangeExtendedToHardLineStartAndEnd( return nullptr; } endPoint = GetCurrentHardLineEndPoint(endPoint, *editingHost); - EditorRawDOMPoint lastRawPoint(endPoint); - lastRawPoint.RewindOffset(); + EditorRawDOMPoint lastRawPoint( + endPoint.IsStartOfContainer() ? endPoint : endPoint.PreviousPoint()); // XXX GetCurrentHardLineEndPoint() may return point of editing host. // Perhaps, we should change it and stop checking it here since this // check may be expensive. diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index ba9aedf7bf4a..c42543e0dec4 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -1366,9 +1366,12 @@ class HTMLEditor final : public EditorBase, nsTArray>& aOutArrayOfContents, EditSubAction aEditSubAction, CollectNonEditableNodes aCollectNonEditableNodes) { - if (NS_WARN_IF(!aPointInOneHardLine.IsSet())) { + if (MOZ_UNLIKELY( + NS_WARN_IF(!aPointInOneHardLine.IsSet()) || + NS_WARN_IF(aPointInOneHardLine.IsInNativeAnonymousSubtree()))) { return NS_ERROR_INVALID_ARG; } + RefPtr oneLineRange = CreateRangeExtendedToHardLineStartAndEnd( aPointInOneHardLine, aPointInOneHardLine, aEditSubAction); if (!oneLineRange) { diff --git a/editor/libeditor/HTMLEditorDeleteHandler.cpp b/editor/libeditor/HTMLEditorDeleteHandler.cpp index da3be1bea1ba..441a8588b9d0 100644 --- a/editor/libeditor/HTMLEditorDeleteHandler.cpp +++ b/editor/libeditor/HTMLEditorDeleteHandler.cpp @@ -4610,6 +4610,11 @@ EditActionResult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner:: template Result HTMLEditor::CanMoveOrDeleteSomethingInHardLine( const EditorDOMPointBase& aPointInHardLine) const { + if (MOZ_UNLIKELY(NS_WARN_IF(!aPointInHardLine.IsSet()) || + NS_WARN_IF(aPointInHardLine.IsInNativeAnonymousSubtree()))) { + return Err(NS_ERROR_INVALID_ARG); + } + RefPtr oneLineRange = CreateRangeExtendedToHardLineStartAndEnd( aPointInHardLine, aPointInHardLine, EditSubAction::eMergeBlockContents); if (!oneLineRange || oneLineRange->Collapsed() || diff --git a/testing/web-platform/tests/editing/crashtests/selection-modify-around-input-in-contenteditable.html b/testing/web-platform/tests/editing/crashtests/selection-modify-around-input-in-contenteditable.html new file mode 100644 index 000000000000..90b615da5cdd --- /dev/null +++ b/testing/web-platform/tests/editing/crashtests/selection-modify-around-input-in-contenteditable.html @@ -0,0 +1,22 @@ + + + + + + + +
+ + + +
+
+ + \ No newline at end of file