Bug 1939220 - part 3: Make TextFragmentData::BoundaryData not depend on the editing host r=m_kato
Its role is scanning the DOM. Therefore, it can know which node is an editing host during a scan. Therefore, it does not require the editing host parameter. To fix that, some utility methods of `HTMLEditUtils` needs to work with non-editable nodes. Therefore, this patch also updates `HTMLEditUtils`. Finally, this gets rid of the `NS_ASSERTION`s in the constructor of `TextFragmentData` because it'll be available with non-editable nodes too. Although current all callers assume that it works as in an editing host. Differential Revision: https://phabricator.services.mozilla.com/D232934
This commit is contained in:
@@ -879,6 +879,10 @@ class EditorDOMPointBase final {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsInContentNodeAndValid() const {
|
||||
return IsInContentNode() && IsSetAndValid();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsInComposedDoc() const {
|
||||
return IsSet() && mParent->IsInComposedDoc();
|
||||
}
|
||||
@@ -887,6 +891,10 @@ class EditorDOMPointBase final {
|
||||
return IsInComposedDoc() && IsSetAndValid();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsInContentNodeAndValidInComposedDoc() const {
|
||||
return IsInContentNode() && IsSetAndValidInComposedDoc();
|
||||
}
|
||||
|
||||
bool IsStartOfContainer() const {
|
||||
// If we're referring the first point in the container:
|
||||
// If mParent is not a container like a text node, mOffset is 0.
|
||||
|
||||
@@ -3362,13 +3362,12 @@ HTMLEditor::DeleteTextAndNormalizeSurroundingWhiteSpaces(
|
||||
*newCaretPosition.ContainerAs<nsIContent>(),
|
||||
HTMLEditUtils::ClosestEditableBlockElementOrInlineEditingHost,
|
||||
BlockInlineCheck::UseComputedDisplayStyle)) {
|
||||
Element* editingHost = ComputeEditingHost();
|
||||
// Try to put caret next to immediately after previous editable leaf.
|
||||
nsIContent* previousContent =
|
||||
HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
newCaretPosition, *editableBlockElementOrInlineEditingHost,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode},
|
||||
BlockInlineCheck::UseComputedDisplayStyle, editingHost);
|
||||
newCaretPosition, {LeafNodeType::LeafNodeOrNonEditableNode},
|
||||
BlockInlineCheck::UseComputedDisplayStyle,
|
||||
editableBlockElementOrInlineEditingHost);
|
||||
if (previousContent &&
|
||||
!HTMLEditUtils::IsBlockElement(
|
||||
*previousContent, BlockInlineCheck::UseComputedDisplayStyle)) {
|
||||
@@ -3383,10 +3382,9 @@ HTMLEditor::DeleteTextAndNormalizeSurroundingWhiteSpaces(
|
||||
else if (nsIContent* nextContent =
|
||||
HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
newCaretPosition,
|
||||
*editableBlockElementOrInlineEditingHost,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode},
|
||||
BlockInlineCheck::UseComputedDisplayStyle,
|
||||
editingHost)) {
|
||||
editableBlockElementOrInlineEditingHost)) {
|
||||
newCaretPosition = nextContent->IsText() ||
|
||||
HTMLEditUtils::IsContainerNode(*nextContent)
|
||||
? EditorDOMPoint(nextContent, 0)
|
||||
|
||||
@@ -1043,8 +1043,9 @@ Maybe<EditorLineBreakType> HTMLEditUtils::GetUnnecessaryLineBreak(
|
||||
content =
|
||||
aScanLineBreak == ScanLineBreak::AtEndOfBlock
|
||||
? HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*content, aBlockElement, leafNodeOrNonEditableNode,
|
||||
BlockInlineCheck::UseComputedDisplayStyle)
|
||||
*content, leafNodeOrNonEditableNode,
|
||||
BlockInlineCheck::UseComputedDisplayStyle,
|
||||
&aBlockElement)
|
||||
: HTMLEditUtils::GetPreviousContent(
|
||||
*content, onlyPrecedingLine,
|
||||
BlockInlineCheck::UseComputedDisplayStyle,
|
||||
@@ -1118,13 +1119,12 @@ Maybe<EditorLineBreakType> HTMLEditUtils::GetUnnecessaryLineBreak(
|
||||
BlockInlineCheck::UseComputedDisplayStyle);
|
||||
for (nsIContent* content =
|
||||
HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*lastLineBreakContent, *blockElement,
|
||||
leafNodeOrNonEditableNodeOrChildBlock,
|
||||
BlockInlineCheck::UseComputedDisplayStyle);
|
||||
*lastLineBreakContent, leafNodeOrNonEditableNodeOrChildBlock,
|
||||
BlockInlineCheck::UseComputedDisplayStyle, blockElement);
|
||||
content;
|
||||
content = HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*content, *blockElement, leafNodeOrNonEditableNodeOrChildBlock,
|
||||
BlockInlineCheck::UseComputedDisplayStyle)) {
|
||||
*content, leafNodeOrNonEditableNodeOrChildBlock,
|
||||
BlockInlineCheck::UseComputedDisplayStyle, blockElement)) {
|
||||
if (HTMLEditUtils::IsBlockElement(
|
||||
*content, BlockInlineCheck::UseComputedDisplayStyle) ||
|
||||
(content->IsElement() && !content->IsHTMLElement())) {
|
||||
@@ -2223,7 +2223,8 @@ Element* HTMLEditUtils::GetAncestorElement(
|
||||
MOZ_ASSERT(
|
||||
aAncestorTypes.contains(AncestorType::ClosestBlockElement) ||
|
||||
aAncestorTypes.contains(AncestorType::MostDistantInlineElementInBlock) ||
|
||||
aAncestorTypes.contains(AncestorType::ButtonElement));
|
||||
aAncestorTypes.contains(AncestorType::ButtonElement) ||
|
||||
aAncestorTypes.contains(AncestorType::AllowRootOrAncestorLimiterElement));
|
||||
|
||||
if (&aContent == aAncestorLimiter) {
|
||||
return nullptr;
|
||||
@@ -2242,7 +2243,12 @@ Element* HTMLEditUtils::GetAncestorElement(
|
||||
aAncestorTypes.contains(AncestorType::IgnoreHRElement);
|
||||
const bool lookingForButtonElement =
|
||||
aAncestorTypes.contains(AncestorType::ButtonElement);
|
||||
const bool lookingForAnyElement =
|
||||
aAncestorTypes.contains(AncestorType::AllowRootOrAncestorLimiterElement);
|
||||
auto IsSearchingElementType = [&](const nsIContent& aContent) -> bool {
|
||||
if (lookingForAnyElement) {
|
||||
return aContent.IsElement();
|
||||
}
|
||||
if (!aContent.IsElement() ||
|
||||
(ignoreHRElement && aContent.IsHTMLElement(nsGkAtoms::hr))) {
|
||||
return false;
|
||||
@@ -2267,6 +2273,9 @@ Element* HTMLEditUtils::GetAncestorElement(
|
||||
}
|
||||
if (ignoreHRElement && element->IsHTMLElement(nsGkAtoms::hr)) {
|
||||
if (element == aAncestorLimiter) {
|
||||
if (lookingForAnyElement) {
|
||||
lastAncestorElement = element;
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -2285,6 +2294,9 @@ Element* HTMLEditUtils::GetAncestorElement(
|
||||
}
|
||||
if (element == aAncestorLimiter || element == theBodyElement ||
|
||||
element == theDocumentElement) {
|
||||
if (lookingForAnyElement) {
|
||||
lastAncestorElement = element;
|
||||
}
|
||||
break;
|
||||
}
|
||||
lastAncestorElement = element;
|
||||
@@ -2302,7 +2314,8 @@ Element* HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
MOZ_ASSERT(
|
||||
aAncestorTypes.contains(AncestorType::ClosestBlockElement) ||
|
||||
aAncestorTypes.contains(AncestorType::MostDistantInlineElementInBlock) ||
|
||||
aAncestorTypes.contains(AncestorType::ButtonElement));
|
||||
aAncestorTypes.contains(AncestorType::ButtonElement) ||
|
||||
aAncestorTypes.contains(AncestorType::AllowRootOrAncestorLimiterElement));
|
||||
|
||||
const Element* theBodyElement = aContent.OwnerDoc()->GetBody();
|
||||
const Element* theDocumentElement = aContent.OwnerDoc()->GetDocumentElement();
|
||||
@@ -2316,7 +2329,12 @@ Element* HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
aAncestorTypes.contains(AncestorType::ButtonElement);
|
||||
const bool ignoreHRElement =
|
||||
aAncestorTypes.contains(AncestorType::IgnoreHRElement);
|
||||
const bool lookingForAnyElement =
|
||||
aAncestorTypes.contains(AncestorType::AllowRootOrAncestorLimiterElement);
|
||||
auto IsSearchingElementType = [&](const nsIContent& aContent) -> bool {
|
||||
if (lookingForAnyElement) {
|
||||
return aContent.IsElement();
|
||||
}
|
||||
if (!aContent.IsElement() ||
|
||||
(ignoreHRElement && aContent.IsHTMLElement(nsGkAtoms::hr))) {
|
||||
return false;
|
||||
@@ -2374,7 +2392,10 @@ Element* HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
}
|
||||
|
||||
if (&aContent == aAncestorLimiter) {
|
||||
return nullptr;
|
||||
return aAncestorTypes.contains(
|
||||
AncestorType::AllowRootOrAncestorLimiterElement)
|
||||
? Element::FromNode(const_cast<nsIContent&>(aContent))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
return HTMLEditUtils::GetAncestorElement(aContent, aAncestorTypes,
|
||||
|
||||
@@ -1294,21 +1294,15 @@ class HTMLEditUtils final {
|
||||
/**
|
||||
* GetNextLeafContentOrNextBlockElement() returns next leaf content or
|
||||
* next block element of aStartContent inside aAncestorLimiter.
|
||||
* Note that the result may be a contet outside aCurrentBlock if
|
||||
* aStartContent equals aCurrentBlock.
|
||||
*
|
||||
* @param aStartContent The start content to scan next content.
|
||||
* @param aCurrentBlock Must be ancestor of aStartContent. Dispite
|
||||
* the name, inline content is allowed if
|
||||
* aStartContent is in an inline editing host.
|
||||
* @param aLeafNodeTypes See LeafNodeType.
|
||||
* @param aAncestorLimiter Optional, setting this guarantees the
|
||||
* result is in aAncestorLimiter unless
|
||||
* aStartContent is not a descendant of this.
|
||||
* @param aAncestorLimiter Optional, if you set this, it must be an
|
||||
* inclusive ancestor of aStartContent.
|
||||
*/
|
||||
static nsIContent* GetNextLeafContentOrNextBlockElement(
|
||||
const nsIContent& aStartContent, const nsIContent& aCurrentBlock,
|
||||
const LeafNodeTypes& aLeafNodeTypes, BlockInlineCheck aBlockInlineCheck,
|
||||
const nsIContent& aStartContent, const LeafNodeTypes& aLeafNodeTypes,
|
||||
BlockInlineCheck aBlockInlineCheck,
|
||||
const Element* aAncestorLimiter = nullptr) {
|
||||
MOZ_ASSERT_IF(
|
||||
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
|
||||
@@ -1325,11 +1319,8 @@ class HTMLEditUtils final {
|
||||
return nullptr;
|
||||
}
|
||||
for (Element* parentElement : aStartContent.AncestorsOfType<Element>()) {
|
||||
if (parentElement == &aCurrentBlock) {
|
||||
return nullptr;
|
||||
}
|
||||
if (parentElement == aAncestorLimiter) {
|
||||
NS_WARNING("Reached editing host while climbing up the DOM tree");
|
||||
if (parentElement == aAncestorLimiter ||
|
||||
HTMLEditUtils::IsBlockElement(*parentElement, aBlockInlineCheck)) {
|
||||
return nullptr;
|
||||
}
|
||||
nextContent = parentElement->GetNextSibling();
|
||||
@@ -1371,8 +1362,7 @@ class HTMLEditUtils final {
|
||||
template <typename PT, typename CT>
|
||||
static nsIContent* GetNextLeafContentOrNextBlockElement(
|
||||
const EditorDOMPointBase<PT, CT>& aStartPoint,
|
||||
const nsIContent& aCurrentBlock, const LeafNodeTypes& aLeafNodeTypes,
|
||||
BlockInlineCheck aBlockInlineCheck,
|
||||
const LeafNodeTypes& aLeafNodeTypes, BlockInlineCheck aBlockInlineCheck,
|
||||
const Element* aAncestorLimiter = nullptr) {
|
||||
MOZ_ASSERT(aStartPoint.IsSet());
|
||||
MOZ_ASSERT_IF(
|
||||
@@ -1386,28 +1376,30 @@ class HTMLEditUtils final {
|
||||
}
|
||||
if (aStartPoint.IsInTextNode()) {
|
||||
return HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*aStartPoint.template ContainerAs<Text>(), aCurrentBlock,
|
||||
aLeafNodeTypes, aBlockInlineCheck, aAncestorLimiter);
|
||||
*aStartPoint.template ContainerAs<Text>(), aLeafNodeTypes,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
if (!HTMLEditUtils::IsContainerNode(
|
||||
*aStartPoint.template ContainerAs<nsIContent>())) {
|
||||
return HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aCurrentBlock,
|
||||
aLeafNodeTypes, aBlockInlineCheck, aAncestorLimiter);
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aLeafNodeTypes,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> nextContent = aStartPoint.GetChild();
|
||||
if (!nextContent) {
|
||||
if (aStartPoint.GetContainer() == &aCurrentBlock) {
|
||||
if (aStartPoint.GetContainer() == aAncestorLimiter ||
|
||||
HTMLEditUtils::IsBlockElement(
|
||||
*aStartPoint.template ContainerAs<nsIContent>(),
|
||||
aBlockInlineCheck)) {
|
||||
// We are at end of the block.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We are at end of non-block container
|
||||
return HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aCurrentBlock,
|
||||
aLeafNodeTypes, IgnoreInsideBlockBoundary(aBlockInlineCheck),
|
||||
aAncestorLimiter);
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aLeafNodeTypes,
|
||||
IgnoreInsideBlockBoundary(aBlockInlineCheck), aAncestorLimiter);
|
||||
}
|
||||
|
||||
// We have a next node. If it's a block, return it.
|
||||
@@ -1435,21 +1427,15 @@ class HTMLEditUtils final {
|
||||
* GetPreviousLeafContentOrPreviousBlockElement() returns previous leaf
|
||||
* content or previous block element of aStartContent inside
|
||||
* aAncestorLimiter.
|
||||
* Note that the result may be a content outside aCurrentBlock if
|
||||
* aStartContent equals aCurrentBlock.
|
||||
*
|
||||
* @param aStartContent The start content to scan previous content.
|
||||
* @param aCurrentBlock Must be ancestor of aStartContent. Despite
|
||||
* the name, inline content is allowed if
|
||||
* aStartContent is in an inline editing host.
|
||||
* @param aLeafNodeTypes See LeafNodeType.
|
||||
* @param aAncestorLimiter Optional, setting this guarantees the
|
||||
* result is in aAncestorLimiter unless
|
||||
* aStartContent is not a descendant of this.
|
||||
* @param aAncestorLimiter Optional, if you set this, it must be an
|
||||
* inclusive ancestor of aStartContent.
|
||||
*/
|
||||
static nsIContent* GetPreviousLeafContentOrPreviousBlockElement(
|
||||
const nsIContent& aStartContent, const nsIContent& aCurrentBlock,
|
||||
const LeafNodeTypes& aLeafNodeTypes, BlockInlineCheck aBlockInlineCheck,
|
||||
const nsIContent& aStartContent, const LeafNodeTypes& aLeafNodeTypes,
|
||||
BlockInlineCheck aBlockInlineCheck,
|
||||
const Element* aAncestorLimiter = nullptr) {
|
||||
MOZ_ASSERT_IF(
|
||||
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
|
||||
@@ -1468,11 +1454,8 @@ class HTMLEditUtils final {
|
||||
return nullptr;
|
||||
}
|
||||
for (Element* parentElement : aStartContent.AncestorsOfType<Element>()) {
|
||||
if (parentElement == &aCurrentBlock) {
|
||||
return nullptr;
|
||||
}
|
||||
if (parentElement == aAncestorLimiter) {
|
||||
NS_WARNING("Reached editing host while climbing up the DOM tree");
|
||||
if (parentElement == aAncestorLimiter ||
|
||||
HTMLEditUtils::IsBlockElement(*parentElement, aBlockInlineCheck)) {
|
||||
return nullptr;
|
||||
}
|
||||
previousContent = parentElement->GetPreviousSibling();
|
||||
@@ -1514,8 +1497,7 @@ class HTMLEditUtils final {
|
||||
template <typename PT, typename CT>
|
||||
static nsIContent* GetPreviousLeafContentOrPreviousBlockElement(
|
||||
const EditorDOMPointBase<PT, CT>& aStartPoint,
|
||||
const nsIContent& aCurrentBlock, const LeafNodeTypes& aLeafNodeTypes,
|
||||
BlockInlineCheck aBlockInlineCheck,
|
||||
const LeafNodeTypes& aLeafNodeTypes, BlockInlineCheck aBlockInlineCheck,
|
||||
const Element* aAncestorLimiter = nullptr) {
|
||||
MOZ_ASSERT(aStartPoint.IsSet());
|
||||
MOZ_ASSERT_IF(
|
||||
@@ -1529,27 +1511,29 @@ class HTMLEditUtils final {
|
||||
}
|
||||
if (aStartPoint.IsInTextNode()) {
|
||||
return HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*aStartPoint.template ContainerAs<Text>(), aCurrentBlock,
|
||||
aLeafNodeTypes, aBlockInlineCheck, aAncestorLimiter);
|
||||
*aStartPoint.template ContainerAs<Text>(), aLeafNodeTypes,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
if (!HTMLEditUtils::IsContainerNode(
|
||||
*aStartPoint.template ContainerAs<nsIContent>())) {
|
||||
return HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aCurrentBlock,
|
||||
aLeafNodeTypes, aBlockInlineCheck, aAncestorLimiter);
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aLeafNodeTypes,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
if (aStartPoint.IsStartOfContainer()) {
|
||||
if (aStartPoint.GetContainer() == &aCurrentBlock) {
|
||||
if (aStartPoint.GetContainer() == aAncestorLimiter ||
|
||||
HTMLEditUtils::IsBlockElement(
|
||||
*aStartPoint.template ContainerAs<nsIContent>(),
|
||||
aBlockInlineCheck)) {
|
||||
// We are at start of the block.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We are at start of non-block container
|
||||
return HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aCurrentBlock,
|
||||
aLeafNodeTypes, IgnoreInsideBlockBoundary(aBlockInlineCheck),
|
||||
aAncestorLimiter);
|
||||
*aStartPoint.template ContainerAs<nsIContent>(), aLeafNodeTypes,
|
||||
IgnoreInsideBlockBoundary(aBlockInlineCheck), aAncestorLimiter);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> previousContent =
|
||||
@@ -1620,11 +1604,23 @@ class HTMLEditUtils final {
|
||||
* aAncestorTypes.
|
||||
*/
|
||||
enum class AncestorType {
|
||||
// If there is an ancestor block, it's a limiter of the scan.
|
||||
ClosestBlockElement,
|
||||
// If there is no ancestor block in the range, the topmost inline element is
|
||||
// a limiter of the scan.
|
||||
MostDistantInlineElementInBlock,
|
||||
EditableElement,
|
||||
IgnoreHRElement, // Ignore ancestor <hr> element since invalid structure
|
||||
// Ignore ancestor <hr> elements to check whether a block.
|
||||
IgnoreHRElement,
|
||||
// If there is an ancestor <button> element, it's also a limiter of the
|
||||
// scan.
|
||||
ButtonElement,
|
||||
// The root element of the scan start node or the ancestor limiter may be
|
||||
// return if there is no proper element.
|
||||
AllowRootOrAncestorLimiterElement,
|
||||
|
||||
// Limit to editable elements. If it reaches an non-editable element,
|
||||
// return its child element.
|
||||
EditableElement,
|
||||
};
|
||||
using AncestorTypes = EnumSet<AncestorType>;
|
||||
constexpr static AncestorTypes
|
||||
|
||||
@@ -1181,7 +1181,7 @@ nsresult HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
|
||||
// Chromium collapses selection to start of the editing host when this
|
||||
// is the last leaf content. So, we don't need special handling here.
|
||||
leafContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*leafElement, *editingHost,
|
||||
*leafElement,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode,
|
||||
LeafNodeType::LeafNodeOrChildBlock},
|
||||
BlockInlineCheck::UseComputedDisplayStyle, editingHost);
|
||||
@@ -1207,7 +1207,7 @@ nsresult HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
|
||||
}
|
||||
// If it's an invisible text node, keep scanning next leaf.
|
||||
leafContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*leafContent, *editingHost,
|
||||
*leafContent,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode,
|
||||
LeafNodeType::LeafNodeOrChildBlock},
|
||||
BlockInlineCheck::UseComputedDisplayStyle, editingHost);
|
||||
@@ -1254,7 +1254,7 @@ nsresult HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
|
||||
// Otherwise, we must meet an empty block element or a data node like
|
||||
// comment node. Let's ignore it.
|
||||
leafContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*leafContent, *editingHost,
|
||||
*leafContent,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode,
|
||||
LeafNodeType::LeafNodeOrChildBlock},
|
||||
BlockInlineCheck::UseComputedDisplayStyle, editingHost);
|
||||
|
||||
@@ -927,20 +927,13 @@ class MOZ_STACK_CLASS WSRunScanner final {
|
||||
* this returns the data at aPoint.
|
||||
*
|
||||
* @param aPoint Scan start point.
|
||||
* @param aEditableBlockParentOrTopmostEditableInlineElement
|
||||
* Nearest editable block parent element of
|
||||
* aPoint if there is. Otherwise, inline editing
|
||||
* host.
|
||||
* @param aEditingHost Active editing host.
|
||||
* @param aNBSPData Optional. If set, this recodes first and last
|
||||
* NBSP positions.
|
||||
*/
|
||||
template <typename EditorDOMPointType>
|
||||
static BoundaryData ScanCollapsibleWhiteSpaceStartFrom(
|
||||
const EditorDOMPointType& aPoint,
|
||||
const Element& aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
const Element* aEditingHost, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck);
|
||||
const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck, const Element& aAncestorLimiter);
|
||||
|
||||
/**
|
||||
* ScanCollapsibleWhiteSpaceEndFrom() returns end boundary data of
|
||||
@@ -949,20 +942,13 @@ class MOZ_STACK_CLASS WSRunScanner final {
|
||||
* this returns the data at aPoint.
|
||||
*
|
||||
* @param aPoint Scan start point.
|
||||
* @param aEditableBlockParentOrTopmostEditableInlineElement
|
||||
* Nearest editable block parent element of
|
||||
* aPoint if there is. Otherwise, inline editing
|
||||
* host.
|
||||
* @param aEditingHost Active editing host.
|
||||
* @param aNBSPData Optional. If set, this recodes first and last
|
||||
* NBSP positions.
|
||||
*/
|
||||
template <typename EditorDOMPointType>
|
||||
static BoundaryData ScanCollapsibleWhiteSpaceEndFrom(
|
||||
const EditorDOMPointType& aPoint,
|
||||
const Element& aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
const Element* aEditingHost, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck);
|
||||
const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck, const Element& aAncestorLimiter);
|
||||
|
||||
BoundaryData() = default;
|
||||
template <typename EditorDOMPointType>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "HTMLEditUtils.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/AncestorIterator.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsDebug.h"
|
||||
@@ -21,6 +22,8 @@ namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
using AncestorType = HTMLEditUtils::AncestorType;
|
||||
using AncestorTypes = HTMLEditUtils::AncestorTypes;
|
||||
using LeafNodeType = HTMLEditUtils::LeafNodeType;
|
||||
|
||||
template WSRunScanner::TextFragmentData::TextFragmentData(
|
||||
@@ -72,58 +75,60 @@ NS_INSTANTIATE_CONST_METHOD_RETURNING_ANY_EDITOR_DOM_POINT(
|
||||
const EditorDOMPointInText& aPointAtASCIIWhiteSpace,
|
||||
nsIEditor::EDirection aDirectionToDelete);
|
||||
|
||||
constexpr static const AncestorTypes kScanAnyRootAncestorTypes = {
|
||||
// If the point is in a block, we need to scan only in the block
|
||||
AncestorType::ClosestBlockElement,
|
||||
// So, we want a root element of the (shadow) tree root element of the
|
||||
// point
|
||||
// if there is no parent block
|
||||
AncestorType::AllowRootOrAncestorLimiterElement,
|
||||
// Basically, given point shouldn't be a void element, so, ignore
|
||||
// ancestor
|
||||
// void elements
|
||||
AncestorType::IgnoreHRElement};
|
||||
constexpr static const AncestorTypes kScanEditableRootAncestorTypes = {
|
||||
// Only editable elements
|
||||
AncestorType::EditableElement,
|
||||
// And the others are same as kScanAnyRootAncestorTypes
|
||||
AncestorType::ClosestBlockElement,
|
||||
AncestorType::AllowRootOrAncestorLimiterElement,
|
||||
AncestorType::IgnoreHRElement};
|
||||
|
||||
template <typename EditorDOMPointType>
|
||||
WSRunScanner::TextFragmentData::TextFragmentData(
|
||||
const EditorDOMPointType& aPoint, const Element* aEditingHost,
|
||||
BlockInlineCheck aBlockInlineCheck)
|
||||
: mEditingHost(aEditingHost), mBlockInlineCheck(aBlockInlineCheck) {
|
||||
if (!aPoint.IsSetAndValid()) {
|
||||
NS_WARNING("aPoint was invalid");
|
||||
return;
|
||||
}
|
||||
if (!aPoint.IsInContentNode()) {
|
||||
NS_WARNING("aPoint was in Document or DocumentFragment");
|
||||
// I.e., we're try to modify outside of root element. We don't need to
|
||||
// support such odd case because web apps cannot append text nodes as
|
||||
// direct child of Document node.
|
||||
if (NS_WARN_IF(!aPoint.IsInContentNodeAndValidInComposedDoc()) ||
|
||||
NS_WARN_IF(!aPoint.GetContainerOrContainerParentElement())) {
|
||||
// We don't need to support composing in uncomposed tree.
|
||||
return;
|
||||
}
|
||||
|
||||
mScanStartPoint = aPoint.template To<EditorDOMPoint>();
|
||||
NS_ASSERTION(
|
||||
EditorUtils::IsEditableContent(*mScanStartPoint.ContainerAs<nsIContent>(),
|
||||
EditorType::HTML),
|
||||
"Given content is not editable");
|
||||
NS_ASSERTION(
|
||||
mScanStartPoint.ContainerAs<nsIContent>()->GetAsElementOrParentElement(),
|
||||
"Given content is not an element and an orphan node");
|
||||
if (NS_WARN_IF(!EditorUtils::IsEditableContent(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>(), EditorType::HTML))) {
|
||||
return;
|
||||
}
|
||||
const Element* editableBlockElementOrInlineEditingHost =
|
||||
const Element* const
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement =
|
||||
HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>(),
|
||||
HTMLEditUtils::ClosestEditableBlockElementOrInlineEditingHost,
|
||||
HTMLEditUtils::IsSimplyEditableNode(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>())
|
||||
? kScanEditableRootAncestorTypes
|
||||
: kScanAnyRootAncestorTypes,
|
||||
aBlockInlineCheck);
|
||||
if (!editableBlockElementOrInlineEditingHost) {
|
||||
NS_WARNING(
|
||||
"HTMLEditUtils::GetInclusiveAncestorElement(HTMLEditUtils::"
|
||||
"ClosestEditableBlockElementOrInlineEditingHost) couldn't find "
|
||||
"editing host");
|
||||
if (NS_WARN_IF(
|
||||
!editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStart = BoundaryData::ScanCollapsibleWhiteSpaceStartFrom(
|
||||
mScanStartPoint, *editableBlockElementOrInlineEditingHost, mEditingHost,
|
||||
&mNBSPData, aBlockInlineCheck);
|
||||
mScanStartPoint, &mNBSPData, aBlockInlineCheck,
|
||||
*editableBlockElementOrInlineEditingHostOrNonEditableRootElement);
|
||||
MOZ_ASSERT_IF(mStart.IsNonCollapsibleCharacters(),
|
||||
!mStart.PointRef().IsPreviousCharPreformattedNewLine());
|
||||
MOZ_ASSERT_IF(mStart.IsPreformattedLineBreak(),
|
||||
mStart.PointRef().IsPreviousCharPreformattedNewLine());
|
||||
mEnd = BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
mScanStartPoint, *editableBlockElementOrInlineEditingHost, mEditingHost,
|
||||
&mNBSPData, aBlockInlineCheck);
|
||||
mScanStartPoint, &mNBSPData, aBlockInlineCheck,
|
||||
*editableBlockElementOrInlineEditingHostOrNonEditableRootElement);
|
||||
MOZ_ASSERT_IF(mEnd.IsNonCollapsibleCharacters(),
|
||||
!mEnd.PointRef().IsCharPreformattedNewLine());
|
||||
MOZ_ASSERT_IF(mEnd.IsPreformattedLineBreak(),
|
||||
@@ -196,12 +201,9 @@ Maybe<WSRunScanner::TextFragmentData::BoundaryData> WSRunScanner::
|
||||
template <typename EditorDOMPointType>
|
||||
WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData::
|
||||
BoundaryData::ScanCollapsibleWhiteSpaceStartFrom(
|
||||
const EditorDOMPointType& aPoint,
|
||||
const Element& aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
const Element* aEditingHost, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck) {
|
||||
const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck, const Element& aAncestorLimiter) {
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
MOZ_ASSERT(aEditableBlockParentOrTopmostEditableInlineElement.IsEditable());
|
||||
|
||||
if (aPoint.IsInTextNode() && !aPoint.IsStartOfContainer()) {
|
||||
Maybe<BoundaryData> startInTextNode =
|
||||
@@ -213,26 +215,20 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData::
|
||||
// The text node does not have visible character, let's keep scanning
|
||||
// preceding nodes.
|
||||
return BoundaryData::ScanCollapsibleWhiteSpaceStartFrom(
|
||||
EditorDOMPoint(aPoint.template ContainerAs<Text>(), 0),
|
||||
aEditableBlockParentOrTopmostEditableInlineElement, aEditingHost,
|
||||
aNBSPData, aBlockInlineCheck);
|
||||
EditorDOMPoint(aPoint.template ContainerAs<Text>(), 0), aNBSPData,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
// Then, we need to check previous leaf node.
|
||||
nsIContent* previousLeafContentOrBlock =
|
||||
HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
aPoint, aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode}, aBlockInlineCheck,
|
||||
aEditingHost);
|
||||
aPoint, {LeafNodeType::LeafNodeOrNonEditableNode}, aBlockInlineCheck,
|
||||
&aAncestorLimiter);
|
||||
if (!previousLeafContentOrBlock) {
|
||||
// No previous content means that we reached
|
||||
// aEditableBlockParentOrTopmostEditableInlineElement boundary.
|
||||
return BoundaryData(aPoint,
|
||||
const_cast<Element&>(
|
||||
aEditableBlockParentOrTopmostEditableInlineElement),
|
||||
HTMLEditUtils::IsBlockElement(
|
||||
aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
aBlockInlineCheck)
|
||||
// No previous content means that we reached the aAncestorLimiter boundary.
|
||||
return BoundaryData(
|
||||
aPoint, const_cast<Element&>(aAncestorLimiter),
|
||||
HTMLEditUtils::IsBlockElement(aAncestorLimiter, aBlockInlineCheck)
|
||||
? WSType::CurrentBlockBoundary
|
||||
: WSType::InlineEditingHostBoundary);
|
||||
}
|
||||
@@ -259,8 +255,7 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData::
|
||||
// looking for the previous one.
|
||||
return BoundaryData::ScanCollapsibleWhiteSpaceStartFrom(
|
||||
EditorDOMPointInText(previousLeafContentOrBlock->AsText(), 0),
|
||||
aEditableBlockParentOrTopmostEditableInlineElement, aEditingHost,
|
||||
aNBSPData, aBlockInlineCheck);
|
||||
aNBSPData, aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
Maybe<BoundaryData> startInTextNode =
|
||||
@@ -274,9 +269,8 @@ WSRunScanner::TextFragmentData::BoundaryData WSRunScanner::TextFragmentData::
|
||||
// The text node does not have visible character, let's keep scanning
|
||||
// preceding nodes.
|
||||
return BoundaryData::ScanCollapsibleWhiteSpaceStartFrom(
|
||||
EditorDOMPointInText(previousLeafContentOrBlock->AsText(), 0),
|
||||
aEditableBlockParentOrTopmostEditableInlineElement, aEditingHost,
|
||||
aNBSPData, aBlockInlineCheck);
|
||||
EditorDOMPointInText(previousLeafContentOrBlock->AsText(), 0), aNBSPData,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -343,12 +337,9 @@ Maybe<WSRunScanner::TextFragmentData::BoundaryData> WSRunScanner::
|
||||
template <typename EditorDOMPointType>
|
||||
WSRunScanner::TextFragmentData::BoundaryData
|
||||
WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
const EditorDOMPointType& aPoint,
|
||||
const Element& aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
const Element* aEditingHost, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck) {
|
||||
const EditorDOMPointType& aPoint, NoBreakingSpaceData* aNBSPData,
|
||||
BlockInlineCheck aBlockInlineCheck, const Element& aAncestorLimiter) {
|
||||
MOZ_ASSERT(aPoint.IsSetAndValid());
|
||||
MOZ_ASSERT(aEditableBlockParentOrTopmostEditableInlineElement.IsEditable());
|
||||
|
||||
if (aPoint.IsInTextNode() && !aPoint.IsEndOfContainer()) {
|
||||
Maybe<BoundaryData> endInTextNode =
|
||||
@@ -361,25 +352,20 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
// following nodes.
|
||||
return BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
EditorDOMPointInText::AtEndOf(*aPoint.template ContainerAs<Text>()),
|
||||
aEditableBlockParentOrTopmostEditableInlineElement, aEditingHost,
|
||||
aNBSPData, aBlockInlineCheck);
|
||||
aNBSPData, aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
// Then, we need to check next leaf node.
|
||||
nsIContent* nextLeafContentOrBlock =
|
||||
HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
aPoint, aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode}, aBlockInlineCheck,
|
||||
aEditingHost);
|
||||
aPoint, {LeafNodeType::LeafNodeOrNonEditableNode}, aBlockInlineCheck,
|
||||
&aAncestorLimiter);
|
||||
if (!nextLeafContentOrBlock) {
|
||||
// No next content means that we reached
|
||||
// aEditableBlockParentOrTopmostEditableInlineElement boundary.
|
||||
return BoundaryData(aPoint.template To<EditorDOMPoint>(),
|
||||
const_cast<Element&>(
|
||||
aEditableBlockParentOrTopmostEditableInlineElement),
|
||||
HTMLEditUtils::IsBlockElement(
|
||||
aEditableBlockParentOrTopmostEditableInlineElement,
|
||||
aBlockInlineCheck)
|
||||
// No next content means that we reached aAncestorLimiter boundary.
|
||||
return BoundaryData(
|
||||
aPoint.template To<EditorDOMPoint>(),
|
||||
const_cast<Element&>(aAncestorLimiter),
|
||||
HTMLEditUtils::IsBlockElement(aAncestorLimiter, aBlockInlineCheck)
|
||||
? WSType::CurrentBlockBoundary
|
||||
: WSType::InlineEditingHostBoundary);
|
||||
}
|
||||
@@ -407,9 +393,8 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
// Note that even if the empty text node is preformatted, we should keep
|
||||
// looking for the next one.
|
||||
return BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
EditorDOMPointInText(nextLeafContentOrBlock->AsText(), 0),
|
||||
aEditableBlockParentOrTopmostEditableInlineElement, aEditingHost,
|
||||
aNBSPData, aBlockInlineCheck);
|
||||
EditorDOMPointInText(nextLeafContentOrBlock->AsText(), 0), aNBSPData,
|
||||
aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
Maybe<BoundaryData> endInTextNode =
|
||||
@@ -424,8 +409,7 @@ WSRunScanner::TextFragmentData::BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
// following nodes.
|
||||
return BoundaryData::ScanCollapsibleWhiteSpaceEndFrom(
|
||||
EditorDOMPointInText::AtEndOf(*nextLeafContentOrBlock->AsText()),
|
||||
aEditableBlockParentOrTopmostEditableInlineElement, aEditingHost,
|
||||
aNBSPData, aBlockInlineCheck);
|
||||
aNBSPData, aBlockInlineCheck, aAncestorLimiter);
|
||||
}
|
||||
|
||||
const EditorDOMRange&
|
||||
@@ -837,39 +821,30 @@ WSRunScanner::TextFragmentData::GetInclusiveNextEditableCharPoint(
|
||||
return EditorDOMPointType();
|
||||
}
|
||||
|
||||
NS_ASSERTION(
|
||||
EditorUtils::IsEditableContent(*mScanStartPoint.ContainerAs<nsIContent>(),
|
||||
EditorType::HTML),
|
||||
"Given content is not editable");
|
||||
NS_ASSERTION(
|
||||
mScanStartPoint.ContainerAs<nsIContent>()->GetAsElementOrParentElement(),
|
||||
"Given content is not an element and an orphan node");
|
||||
nsIContent* editableBlockElementOrInlineEditingHost =
|
||||
mScanStartPoint.ContainerAs<nsIContent>() &&
|
||||
EditorUtils::IsEditableContent(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>(), EditorType::HTML)
|
||||
? HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
const Element* const
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement =
|
||||
HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>(),
|
||||
HTMLEditUtils::ClosestEditableBlockElementOrInlineEditingHost,
|
||||
mBlockInlineCheck)
|
||||
: nullptr;
|
||||
if (NS_WARN_IF(!editableBlockElementOrInlineEditingHost)) {
|
||||
// Meaning that the container of `mScanStartPoint` is not editable.
|
||||
editableBlockElementOrInlineEditingHost =
|
||||
mScanStartPoint.ContainerAs<nsIContent>();
|
||||
HTMLEditUtils::IsSimplyEditableNode(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>())
|
||||
? kScanEditableRootAncestorTypes
|
||||
: kScanAnyRootAncestorTypes,
|
||||
mBlockInlineCheck);
|
||||
if (NS_WARN_IF(
|
||||
!editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) {
|
||||
return EditorDOMPointType();
|
||||
}
|
||||
|
||||
for (nsIContent* nextContent =
|
||||
HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*point.ContainerAs<nsIContent>(),
|
||||
*editableBlockElementOrInlineEditingHost,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode}, mBlockInlineCheck,
|
||||
mEditingHost);
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement);
|
||||
nextContent;
|
||||
nextContent = HTMLEditUtils::GetNextLeafContentOrNextBlockElement(
|
||||
*nextContent, *editableBlockElementOrInlineEditingHost,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode}, mBlockInlineCheck,
|
||||
mEditingHost)) {
|
||||
*nextContent, {LeafNodeType::LeafNodeOrNonEditableNode},
|
||||
mBlockInlineCheck,
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) {
|
||||
if (!nextContent->IsText() || !nextContent->IsEditable()) {
|
||||
if (nextContent == GetEndReasonContent()) {
|
||||
break; // Reached end of current runs.
|
||||
@@ -921,40 +896,32 @@ EditorDOMPointType WSRunScanner::TextFragmentData::GetPreviousEditableCharPoint(
|
||||
return EditorDOMPointType();
|
||||
}
|
||||
|
||||
NS_ASSERTION(
|
||||
EditorUtils::IsEditableContent(*mScanStartPoint.ContainerAs<nsIContent>(),
|
||||
EditorType::HTML),
|
||||
"Given content is not editable");
|
||||
NS_ASSERTION(
|
||||
mScanStartPoint.ContainerAs<nsIContent>()->GetAsElementOrParentElement(),
|
||||
"Given content is not an element and an orphan node");
|
||||
nsIContent* editableBlockElementOrInlineEditingHost =
|
||||
mScanStartPoint.ContainerAs<nsIContent>() &&
|
||||
EditorUtils::IsEditableContent(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>(), EditorType::HTML)
|
||||
? HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
const Element* const
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement =
|
||||
HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>(),
|
||||
HTMLEditUtils::ClosestEditableBlockElementOrInlineEditingHost,
|
||||
mBlockInlineCheck)
|
||||
: nullptr;
|
||||
if (NS_WARN_IF(!editableBlockElementOrInlineEditingHost)) {
|
||||
// Meaning that the container of `mScanStartPoint` is not editable.
|
||||
editableBlockElementOrInlineEditingHost =
|
||||
mScanStartPoint.ContainerAs<nsIContent>();
|
||||
HTMLEditUtils::IsSimplyEditableNode(
|
||||
*mScanStartPoint.ContainerAs<nsIContent>())
|
||||
? kScanEditableRootAncestorTypes
|
||||
: kScanAnyRootAncestorTypes,
|
||||
mBlockInlineCheck);
|
||||
if (NS_WARN_IF(
|
||||
!editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) {
|
||||
return EditorDOMPointType();
|
||||
}
|
||||
|
||||
for (nsIContent* previousContent =
|
||||
for (
|
||||
nsIContent* previousContent =
|
||||
HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*point.ContainerAs<nsIContent>(),
|
||||
*editableBlockElementOrInlineEditingHost,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode}, mBlockInlineCheck,
|
||||
mEditingHost);
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement);
|
||||
previousContent;
|
||||
previousContent =
|
||||
HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement(
|
||||
*previousContent, *editableBlockElementOrInlineEditingHost,
|
||||
{LeafNodeType::LeafNodeOrNonEditableNode}, mBlockInlineCheck,
|
||||
mEditingHost)) {
|
||||
*previousContent, {LeafNodeType::LeafNodeOrNonEditableNode},
|
||||
mBlockInlineCheck,
|
||||
editableBlockElementOrInlineEditingHostOrNonEditableRootElement)) {
|
||||
if (!previousContent->IsText() || !previousContent->IsEditable()) {
|
||||
if (previousContent == GetStartReasonContent()) {
|
||||
break; // Reached start of current runs.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[insertparagraph-in-non-splittable-element.html]
|
||||
max-asserts: 2
|
||||
[insertParagraph in iframe of <div><iframe srcdoc="abc"></iframe></div>]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[white-spaces-after-execCommand-delete.tentative.html]
|
||||
prefs: [editor.white_space_normalization.blink_compatible:true]
|
||||
max-asserts: 4
|
||||
[execCommand("delete", false, ""): "a [\]|| c"]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[white-spaces-after-execCommand-forwarddelete.tentative.html]
|
||||
prefs: [editor.white_space_normalization.blink_compatible:true]
|
||||
max-asserts: 3
|
||||
[execCommand("forwarddelete", false, ""): " [\] b" (length of whitespace sequence: 10)]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -156,7 +156,6 @@
|
||||
[delete.html?2001-3000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 3
|
||||
[[["delete",""\]\] "foo<blockquote>[\]bar</blockquote>" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[inserthorizontalrule.html]
|
||||
max-asserts: 8
|
||||
max-asserts: 8 # in nsTextFrame.cpp
|
||||
bug: 1909069
|
||||
[[["inserthorizontalrule",""\]\] "<span>foo[</span><span>\]bar</span>" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
[inserthtml.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 14
|
||||
min-asserts: 5
|
||||
[[["defaultparagraphseparator","div"\],["inserthtml","<li>abc"\]\] "<p>foo[bar\]baz" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
[justifycenter.html?1-1000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["justifycenter",""\]\] "foo[\]bar<p>extra" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
@@ -114,7 +113,6 @@
|
||||
[justifycenter.html?1001-2000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["justifycenter",""\]\] "<center><p>[foo<p>bar\]</center><p>extra" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
@@ -341,7 +339,6 @@
|
||||
[justifycenter.html?2001-3000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["justifycenter",""\]\] "<table align=center data-start=0 data-end=1><tbody><tr><td>foo<td>bar<td>baz</table><p>extra" queryCommandValue("defaultparagraphseparator") after]
|
||||
expected: FAIL
|
||||
|
||||
@@ -751,7 +748,6 @@
|
||||
[justifycenter.html?3001-4000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["justifycenter",""\]\] "<div style=text-align:justify><p>[foo\]<p>bar</div><p>extra" queryCommandState("justifycenter") after]
|
||||
expected: FAIL
|
||||
|
||||
@@ -900,7 +896,6 @@
|
||||
[justifycenter.html?4001-5000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["justifycenter",""\]\] "<div style=text-align:center><p>foo</div><p>[bar\]<div style=text-align:center><p>baz</div><p>extra" queryCommandState("justifycenter") after]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1160,7 +1155,6 @@
|
||||
[justifycenter.html?5001-6000]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["justifycenter",""\]\] "<div align=left>{<div align=center>foo</div>}</div>" queryCommandState("justifycenter") before]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1519,7 +1513,6 @@
|
||||
[justifycenter.html?6001-last]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 8
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["justifycenter",""\]\] "<div style=text-align:center><p>foo</div> <p>[bar\]</p> <div style=text-align:center><p>baz</div>" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[justifyfull.html?1-1000]
|
||||
max-asserts: 9
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["justifyfull",""\]\] "foo[\]bar<p>extra" compare innerHTML]
|
||||
|
||||
@@ -403,7 +403,6 @@
|
||||
|
||||
|
||||
[justifyleft.html?2001-last]
|
||||
max-asserts: 9
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["justifyleft",""\]\] "<div style=text-align:left>[foo<div style=text-align:left contenteditable=false>bar</div>baz\]</div><p>extra" queryCommandValue("defaultparagraphseparator") before]
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
[input-events-get-target-ranges-backspace.tentative.html]
|
||||
max-asserts: 2 # An assertion in the constructor of TextFragmentData
|
||||
min-asserts: 0 # But sometimes not counted correctly
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Alt + Backspace at "<p>abc def[\] ghi</p>"]
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
[input-events-get-target-ranges-forwarddelete.tentative.html]
|
||||
max-asserts: 5
|
||||
min-asserts: 0
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Alt + Delete at "<p>abc [\]def ghi</p>" - comparing innerHTML]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html?Delete]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
max-asserts: 17
|
||||
max-asserts: 8 # in WhiteSpaceVisibilityKeeper::MergeFirstLineOfRightBlockElementIntoLeftBlockElement
|
||||
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
|
||||
|
||||
[input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html?Backspace]
|
||||
max-asserts: 17
|
||||
max-asserts: 8 # in WhiteSpaceVisibilityKeeper::MergeFirstLineOfRightBlockElementIntoLeftBlockElement
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>"]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[input-events-get-target-ranges-joining-dl-elements.tentative.html?Delete]
|
||||
max-asserts: 41
|
||||
max-asserts: 24 # in WhiteSpaceVisibilityKeeper::MergeFirstLineOfRightBlockElementIntoLeftBlockElement
|
||||
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><dl><dd>}list-item3</dd></dl>"]
|
||||
expected: FAIL
|
||||
|
||||
@@ -830,7 +830,7 @@
|
||||
|
||||
|
||||
[input-events-get-target-ranges-joining-dl-elements.tentative.html?Backspace]
|
||||
max-asserts: 41
|
||||
max-asserts: 24 # in WhiteSpaceVisibilityKeeper::MergeFirstLineOfRightBlockElementIntoLeftBlockElement
|
||||
[Backspace at "<dl><dd>list-item1</dd><dt>list-item2</dt></dl><dl><dd>[\]list-item3</dd><dt>list-item4</dt></dl>"]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[input-events-get-target-ranges-non-collapsed-selection.tentative.html?Backspace]
|
||||
max-asserts: 11
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Backspace at "<p>{abc}<br></p>"]
|
||||
@@ -13,8 +12,6 @@
|
||||
|
||||
|
||||
[input-events-get-target-ranges-non-collapsed-selection.tentative.html?Delete]
|
||||
max-asserts: 11
|
||||
min-asserts: 0
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Delete at "<p>{abc}<br></p>"]
|
||||
@@ -31,7 +28,6 @@
|
||||
|
||||
|
||||
[input-events-get-target-ranges-non-collapsed-selection.tentative.html?TypingA]
|
||||
max-asserts: 11
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[TypingA at "<p>{abc}<br></p>"]
|
||||
|
||||
Reference in New Issue
Block a user