зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1860210 - Make `HTMLEditUtils::GetPreviousEditablePoint` and `HTMLEditUtils::GetNextEditablePoint` check ancestor limiter before getting a sibling of ancestor r=m_kato
They check ancestor limiter when they are climbing up the DOM tree if and only if the ancestor does not have a sibling. However, this causes moving into a sibling of the ancestor limiter. Differential Revision: https://phabricator.services.mozilla.com/D192528
This commit is contained in:
Родитель
86217c833b
Коммит
0348ca6476
|
@ -1667,6 +1667,10 @@ EditorDOMPointType HTMLEditUtils::GetPreviousEditablePoint(
|
|||
"HTMLEditUtils::GetPreviousEditablePoint() may return a point "
|
||||
"between table structure elements");
|
||||
|
||||
if (&aContent == aAncestorLimiter) {
|
||||
return EditorDOMPointType();
|
||||
}
|
||||
|
||||
// First, look for previous content.
|
||||
nsIContent* previousContent = aContent.GetPreviousSibling();
|
||||
if (!previousContent) {
|
||||
|
@ -1675,12 +1679,10 @@ EditorDOMPointType HTMLEditUtils::GetPreviousEditablePoint(
|
|||
}
|
||||
nsIContent* inclusiveAncestor = &aContent;
|
||||
for (Element* parentElement : aContent.AncestorsOfType<Element>()) {
|
||||
previousContent = parentElement->GetPreviousSibling();
|
||||
if (!previousContent &&
|
||||
(parentElement == aAncestorLimiter ||
|
||||
if (parentElement == aAncestorLimiter ||
|
||||
!HTMLEditUtils::IsSimplyEditableNode(*parentElement) ||
|
||||
!HTMLEditUtils::CanCrossContentBoundary(*parentElement,
|
||||
aHowToTreatTableBoundary))) {
|
||||
aHowToTreatTableBoundary)) {
|
||||
// If cannot cross the parent element boundary, return the point of
|
||||
// last inclusive ancestor point.
|
||||
return EditorDOMPointType(inclusiveAncestor);
|
||||
|
@ -1693,6 +1695,7 @@ EditorDOMPointType HTMLEditUtils::GetPreviousEditablePoint(
|
|||
inclusiveAncestor = parentElement;
|
||||
}
|
||||
|
||||
previousContent = parentElement->GetPreviousSibling();
|
||||
if (!previousContent) {
|
||||
continue; // Keep looking for previous sibling of an ancestor.
|
||||
}
|
||||
|
@ -1777,6 +1780,10 @@ EditorDOMPointType HTMLEditUtils::GetNextEditablePoint(
|
|||
"HTMLEditUtils::GetPreviousEditablePoint() may return a point "
|
||||
"between table structure elements");
|
||||
|
||||
if (&aContent == aAncestorLimiter) {
|
||||
return EditorDOMPointType();
|
||||
}
|
||||
|
||||
// First, look for next content.
|
||||
nsIContent* nextContent = aContent.GetNextSibling();
|
||||
if (!nextContent) {
|
||||
|
@ -1785,19 +1792,10 @@ EditorDOMPointType HTMLEditUtils::GetNextEditablePoint(
|
|||
}
|
||||
nsIContent* inclusiveAncestor = &aContent;
|
||||
for (Element* parentElement : aContent.AncestorsOfType<Element>()) {
|
||||
// End of the parent element is a next editable point if it's an
|
||||
// element which is not a table structure element.
|
||||
if (!HTMLEditUtils::IsAnyTableElement(parentElement) ||
|
||||
HTMLEditUtils::IsTableCellOrCaption(*parentElement)) {
|
||||
inclusiveAncestor = parentElement;
|
||||
}
|
||||
|
||||
nextContent = parentElement->GetNextSibling();
|
||||
if (!nextContent &&
|
||||
(parentElement == aAncestorLimiter ||
|
||||
if (parentElement == aAncestorLimiter ||
|
||||
!HTMLEditUtils::IsSimplyEditableNode(*parentElement) ||
|
||||
!HTMLEditUtils::CanCrossContentBoundary(*parentElement,
|
||||
aHowToTreatTableBoundary))) {
|
||||
aHowToTreatTableBoundary)) {
|
||||
// If cannot cross the parent element boundary, return the point of
|
||||
// last inclusive ancestor point.
|
||||
return EditorDOMPointType(inclusiveAncestor);
|
||||
|
@ -1810,6 +1808,7 @@ EditorDOMPointType HTMLEditUtils::GetNextEditablePoint(
|
|||
inclusiveAncestor = parentElement;
|
||||
}
|
||||
|
||||
nextContent = parentElement->GetNextSibling();
|
||||
if (!nextContent) {
|
||||
continue; // Keep looking for next sibling of an ancestor.
|
||||
}
|
||||
|
|
|
@ -2062,4 +2062,70 @@ promise_test(async (t) => {
|
|||
checkGetTargetRangesOfInputOnDeleteSomething();
|
||||
}, 'Meta + Backspace at "<p> abc[] def</p>"');
|
||||
|
||||
// If editing host is nested, editing in the nested one shouldn't cause
|
||||
// target ranges extended to outside of it.
|
||||
promise_test(async t => {
|
||||
const innerHTML = "<div contenteditable=\"false\"><div contenteditable=\"\"><p><br></p></div></div>";
|
||||
initializeTest(innerHTML);
|
||||
const p = gEditor.querySelector("p");
|
||||
const innerEditingHost = p.parentNode;
|
||||
document.activeElement?.blur();
|
||||
p.parentNode.focus();
|
||||
gSelection.collapse(p, 0);
|
||||
await sendBackspaceKey();
|
||||
if (gEditor.innerHTML == innerHTML) {
|
||||
checkGetTargetRangesOfBeforeinputOnDeleteSomething({
|
||||
startContainer: p,
|
||||
startOffset: 0,
|
||||
endContainer: p,
|
||||
endOffset: 0,
|
||||
});
|
||||
checkGetTargetRangesOfInputOnDoNothing();
|
||||
} else {
|
||||
checkEditorContentResultAsSubTest(
|
||||
"<div contenteditable=\"false\"><div contenteditable=\"\"><br></div></div>",
|
||||
t.name
|
||||
);
|
||||
checkGetTargetRangesOfBeforeinputOnDeleteSomething({
|
||||
startContainer: innerEditingHost,
|
||||
startOffset: 0,
|
||||
endContainer: p,
|
||||
endOffset: 1,
|
||||
});
|
||||
checkGetTargetRangesOfInputOnDeleteSomething();
|
||||
}
|
||||
}, 'Backspace at "<div contenteditable="false"><div contenteditable=""><p>{}<br></p></div></div>');
|
||||
|
||||
promise_test(async t => {
|
||||
const innerHTML = "<div contenteditable=\"false\">\n <div contenteditable=\"\"><p><br></p></div></div>";
|
||||
initializeTest(innerHTML);
|
||||
const p = gEditor.querySelector("p");
|
||||
const innerEditingHost = p.parentNode;
|
||||
document.activeElement?.blur();
|
||||
p.parentNode.focus();
|
||||
gSelection.collapse(p, 0);
|
||||
await sendBackspaceKey();
|
||||
if (gEditor.innerHTML == innerHTML) {
|
||||
checkGetTargetRangesOfBeforeinputOnDeleteSomething({
|
||||
startContainer: p,
|
||||
startOffset: 0,
|
||||
endContainer: p,
|
||||
endOffset: 0,
|
||||
});
|
||||
checkGetTargetRangesOfInputOnDoNothing();
|
||||
} else {
|
||||
checkEditorContentResultAsSubTest(
|
||||
"<div contenteditable=\"false\">\n <div contenteditable=\"\"><br></div></div>",
|
||||
t.name
|
||||
);
|
||||
checkGetTargetRangesOfBeforeinputOnDeleteSomething({
|
||||
startContainer: innerEditingHost,
|
||||
startOffset: 0,
|
||||
endContainer: p,
|
||||
endOffset: 1,
|
||||
});
|
||||
checkGetTargetRangesOfInputOnDeleteSomething();
|
||||
}
|
||||
}, 'Backspace at "<div contenteditable="false">\n <div contenteditable=""><p>{}<br></p></div></div>');
|
||||
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче