зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1663370 - part 9: Make `AutoInclusiveAncestorBlockElementsJoiner::Prepare()` consider whether it will NOT join the elements or not r=m_kato
This makes `AutoInclusiveAncestorBlockElementsJoiner` stores whether `Run()` will return "ignored" or not when `Prepare()` is called. And this patch adds `NS_ASSERTION()` to compare the result of `Run()` and the guess. Note that this shouldn't used for considering whether its user call or not `Run()` actually for the risk of regressions and if we do it with current implementation, some web apps may be broken if they do modify the DOM tree at white-space adjustment before joining the left and right block elements. The method will be used by `ComputeTargetRanges()` which will be implemented by bug 1658702. Depends on D89578 Differential Revision: https://phabricator.services.mozilla.com/D89579
This commit is contained in:
Родитель
9ed84efbc7
Коммит
7effeb6cde
|
@ -2921,7 +2921,8 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
|||
aInclusiveDescendantOfLeftBlockElement),
|
||||
mInclusiveDescendantOfRightBlockElement(
|
||||
aInclusiveDescendantOfRightBlockElement),
|
||||
mCanJoinBlocks(false) {}
|
||||
mCanJoinBlocks(false),
|
||||
mFallbackToDeleteLeafContent(false) {}
|
||||
|
||||
bool IsSet() const { return mLeftBlockElement && mRightBlockElement; }
|
||||
bool IsSameBlockElement() const {
|
||||
|
@ -2939,6 +2940,17 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
|||
*/
|
||||
bool CanJoinBlocks() const { return mCanJoinBlocks; }
|
||||
|
||||
/**
|
||||
* When this returns true, `Run()` must return "ignored" so that
|
||||
* caller can skip calling `Run()`. This is available only when
|
||||
* `CanJoinBlocks()` returns `true`.
|
||||
* TODO: This should be merged into `CanJoinBlocks()` in the future.
|
||||
*/
|
||||
bool ShouldDeleteLeafContentInstead() const {
|
||||
MOZ_ASSERT(CanJoinBlocks());
|
||||
return mFallbackToDeleteLeafContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join inclusive ancestor block elements which are found by preceding
|
||||
* Preare() call.
|
||||
|
@ -2954,6 +2966,35 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
|||
Run(HTMLEditor& aHTMLEditor);
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method returns true when
|
||||
* `MergeFirstLineOfRightBlockElementIntoDescendantLeftBlockElement()`,
|
||||
* `MergeFirstLineOfRightBlockElementIntoAncestorLeftBlockElement()` and
|
||||
* `MergeFirstLineOfRightBlockElementIntoLeftBlockElement()` handle it
|
||||
* with the `if` block of their main blocks.
|
||||
*/
|
||||
bool CanMergeLeftAndRightBlockElements() const {
|
||||
if (!IsSet()) {
|
||||
return false;
|
||||
}
|
||||
// `MergeFirstLineOfRightBlockElementIntoDescendantLeftBlockElement()`
|
||||
if (mPointContainingTheOtherBlockElement.GetContainer() ==
|
||||
mRightBlockElement) {
|
||||
return mNewListElementTagNameOfRightListElement.isSome();
|
||||
}
|
||||
// `MergeFirstLineOfRightBlockElementIntoAncestorLeftBlockElement()`
|
||||
if (mPointContainingTheOtherBlockElement.GetContainer() ==
|
||||
mLeftBlockElement) {
|
||||
return mNewListElementTagNameOfRightListElement.isSome() &&
|
||||
!mRightBlockElement->GetChildCount();
|
||||
}
|
||||
MOZ_ASSERT(!mPointContainingTheOtherBlockElement.IsSet());
|
||||
// `MergeFirstLineOfRightBlockElementIntoLeftBlockElement()`
|
||||
return mNewListElementTagNameOfRightListElement.isSome() ||
|
||||
mLeftBlockElement->NodeInfo()->NameAtom() ==
|
||||
mRightBlockElement->NodeInfo()->NameAtom();
|
||||
}
|
||||
|
||||
OwningNonNull<nsIContent> mInclusiveDescendantOfLeftBlockElement;
|
||||
OwningNonNull<nsIContent> mInclusiveDescendantOfRightBlockElement;
|
||||
RefPtr<Element> mLeftBlockElement;
|
||||
|
@ -2962,6 +3003,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
|||
EditorDOMPoint mPointContainingTheOtherBlockElement;
|
||||
RefPtr<dom::HTMLBRElement> mPrecedingInvisibleBRElement;
|
||||
bool mCanJoinBlocks;
|
||||
bool mFallbackToDeleteLeafContent;
|
||||
}; // HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
||||
// AutoInclusiveAncestorBlockElementsJoiner
|
||||
|
||||
|
@ -4345,6 +4387,19 @@ EditActionResult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
|||
NS_WARNING("AutoInclusiveAncestorBlockElementsJoiner::Run() failed");
|
||||
return result;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (joiner.ShouldDeleteLeafContentInstead()) {
|
||||
NS_ASSERTION(
|
||||
result.Ignored(),
|
||||
"Assumed `AutoInclusiveAncestorBlockElementsJoiner::Run()` "
|
||||
"retruning ignored, but returned not ignored");
|
||||
} else {
|
||||
NS_ASSERTION(
|
||||
!result.Ignored(),
|
||||
"Assumed `AutoInclusiveAncestorBlockElementsJoiner::Run()` "
|
||||
"retruning handled, but returned ignored");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
}
|
||||
|
||||
// If AutoInclusiveAncestorBlockElementsJoiner didn't handle it and it's not
|
||||
|
@ -4463,6 +4518,17 @@ EditActionResult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
|||
NS_WARNING("AutoInclusiveAncestorBlockElementsJoiner::Run() failed");
|
||||
return result;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (joiner.ShouldDeleteLeafContentInstead()) {
|
||||
NS_ASSERTION(result.Ignored(),
|
||||
"Assumed `AutoInclusiveAncestorBlockElementsJoiner::Run()` "
|
||||
"retruning ignored, but returned not ignored");
|
||||
} else {
|
||||
NS_ASSERTION(!result.Ignored(),
|
||||
"Assumed `AutoInclusiveAncestorBlockElementsJoiner::Run()` "
|
||||
"retruning handled, but returned ignored");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
}
|
||||
// This should claim that trying to join the block means that
|
||||
// this handles the action because the caller shouldn't do anything
|
||||
|
@ -4915,6 +4981,17 @@ EditActionResult HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
|||
NS_WARNING("AutoInclusiveAncestorBlockElementsJoiner::Run() failed");
|
||||
return result;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (joiner.ShouldDeleteLeafContentInstead()) {
|
||||
NS_ASSERTION(result.Ignored(),
|
||||
"Assumed `AutoInclusiveAncestorBlockElementsJoiner::Run()` "
|
||||
"retruning ignored, but returned not ignored");
|
||||
} else {
|
||||
NS_ASSERTION(!result.Ignored(),
|
||||
"Assumed `AutoInclusiveAncestorBlockElementsJoiner::Run()` "
|
||||
"retruning handled, but returned ignored");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5937,6 +6014,7 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
|||
// Bail if both blocks the same
|
||||
if (IsSameBlockElement()) {
|
||||
mCanJoinBlocks = true; // XXX Anyway, Run() will ingore this case.
|
||||
mFallbackToDeleteLeafContent = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5986,15 +6064,71 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
|||
mPrecedingInvisibleBRElement =
|
||||
WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound(
|
||||
aHTMLEditor, EditorDOMPoint::AtEndOf(mLeftBlockElement));
|
||||
// `WhiteSpaceVisibilityKeeper::
|
||||
// MergeFirstLineOfRightBlockElementIntoDescendantLeftBlockElement()`
|
||||
// returns ignored when:
|
||||
// - No preceding invisible `<br>` element and
|
||||
// - mNewListElementTagNameOfRightListElement is nothing and
|
||||
// - There is no content to move from right block element.
|
||||
if (!mPrecedingInvisibleBRElement) {
|
||||
if (CanMergeLeftAndRightBlockElements()) {
|
||||
// Always marked as handled in this case.
|
||||
mFallbackToDeleteLeafContent = false;
|
||||
} else {
|
||||
// Marked as handled only when it actually moves a content node.
|
||||
Result<bool, nsresult> firstLineHasContent =
|
||||
aHTMLEditor.CanMoveOrDeleteSomethingInHardLine(
|
||||
mPointContainingTheOtherBlockElement.NextPoint());
|
||||
mFallbackToDeleteLeafContent =
|
||||
firstLineHasContent.isOk() && !firstLineHasContent.inspect();
|
||||
}
|
||||
} else {
|
||||
// Marked as handled when deleting the invisible `<br>` element.
|
||||
mFallbackToDeleteLeafContent = false;
|
||||
}
|
||||
} else if (mPointContainingTheOtherBlockElement.GetContainer() ==
|
||||
mLeftBlockElement) {
|
||||
mPrecedingInvisibleBRElement =
|
||||
WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound(
|
||||
aHTMLEditor, mPointContainingTheOtherBlockElement);
|
||||
// `WhiteSpaceVisibilityKeeper::
|
||||
// MergeFirstLineOfRightBlockElementIntoAncestorLeftBlockElement()`
|
||||
// returns ignored when:
|
||||
// - No preceding invisible `<br>` element and
|
||||
// - mNewListElementTagNameOfRightListElement is some and
|
||||
// - The right block element has no children
|
||||
// or,
|
||||
// - No preceding invisible `<br>` element and
|
||||
// - mNewListElementTagNameOfRightListElement is nothing and
|
||||
// - There is no content to move from right block element.
|
||||
if (!mPrecedingInvisibleBRElement) {
|
||||
if (CanMergeLeftAndRightBlockElements()) {
|
||||
// Marked as handled only when it actualy moves a content node.
|
||||
Result<bool, nsresult> rightBlockHasContent =
|
||||
aHTMLEditor.CanMoveChildren(*mRightBlockElement,
|
||||
*mLeftBlockElement);
|
||||
mFallbackToDeleteLeafContent =
|
||||
rightBlockHasContent.isOk() && !rightBlockHasContent.inspect();
|
||||
} else {
|
||||
// Marked as handled only when it actually moves a content node.
|
||||
Result<bool, nsresult> firstLineHasContent =
|
||||
aHTMLEditor.CanMoveOrDeleteSomethingInHardLine(
|
||||
EditorRawDOMPoint(mRightBlockElement, 0));
|
||||
mFallbackToDeleteLeafContent =
|
||||
firstLineHasContent.isOk() && !firstLineHasContent.inspect();
|
||||
}
|
||||
} else {
|
||||
// Marked as handled when deleting the invisible `<br>` element.
|
||||
mFallbackToDeleteLeafContent = false;
|
||||
}
|
||||
} else {
|
||||
mPrecedingInvisibleBRElement =
|
||||
WSRunScanner::GetPrecedingBRElementUnlessVisibleContentFound(
|
||||
aHTMLEditor, EditorDOMPoint::AtEndOf(mLeftBlockElement));
|
||||
// `WhiteSpaceVisibilityKeeper::
|
||||
// MergeFirstLineOfRightBlockElementIntoLeftBlockElement()` always
|
||||
// return "handled".
|
||||
mFallbackToDeleteLeafContent = false;
|
||||
}
|
||||
|
||||
mCanJoinBlocks = true;
|
||||
|
|
|
@ -160,6 +160,8 @@ EditActionResult WhiteSpaceVisibilityKeeper::
|
|||
aPrecedingInvisibleBRElement == invisibleBRElementAtEndOfLeftBlockElement,
|
||||
"The preceding invisible BR element computation was different");
|
||||
EditActionResult ret(NS_OK);
|
||||
// NOTE: Keep syncing with CanMergeLeftAndRightBlockElements() of
|
||||
// AutoInclusiveAncestorBlockElementsJoiner.
|
||||
if (NS_WARN_IF(aListElementTagName.isSome())) {
|
||||
// Since 2002, here was the following comment:
|
||||
// > The idea here is to take all children in rightListElement that are
|
||||
|
@ -301,6 +303,8 @@ EditActionResult WhiteSpaceVisibilityKeeper::
|
|||
aPrecedingInvisibleBRElement == invisibleBRElementBeforeLeftBlockElement,
|
||||
"The preceding invisible BR element computation was different");
|
||||
EditActionResult ret(NS_OK);
|
||||
// NOTE: Keep syncing with CanMergeLeftAndRightBlockElements() of
|
||||
// AutoInclusiveAncestorBlockElementsJoiner.
|
||||
if (aListElementTagName.isSome()) {
|
||||
// XXX Why do we ignore the error from MoveChildrenWithTransaction()?
|
||||
MOZ_ASSERT(originalLeftBlockElement == atLeftBlockChild.GetContainer(),
|
||||
|
|
Загрузка…
Ссылка в новой задаче