зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1663797 - Make delete handler of `HTMLEditor` not try to join `<html>`, `<head>` and `<body>` r=m_kato
It'll fail to join them when its utility methods actually join them. However, it should be considered earlier timing because the preparation DOM tree changes before joining them causes creating odd tree (see the removed cases of the test). Therefore, we should make them stop handling deletion before modifying the DOM tree. Depends on D89579 Differential Revision: https://phabricator.services.mozilla.com/D89580
This commit is contained in:
Родитель
ec6be89428
Коммит
d060d644d6
|
@ -4459,6 +4459,12 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
|
|||
// adjacent block
|
||||
mMode = Mode::JoinCurrentBlock;
|
||||
|
||||
// Don't break the basic structure of the HTML document.
|
||||
if (aCurrentBlockElement.IsAnyOfHTMLElements(nsGkAtoms::html, nsGkAtoms::head,
|
||||
nsGkAtoms::body)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure it's not a table element. If so, cancel the operation
|
||||
// (translation: users cannot backspace or delete across table cells)
|
||||
if (HTMLEditUtils::IsAnyTableElement(&aCurrentBlockElement)) {
|
||||
|
@ -6004,6 +6010,16 @@ Result<bool, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
|||
return Err(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
// Don't join the blocks if both of them are basic structure of the HTML
|
||||
// document (Note that `<body>` can be joined with its children).
|
||||
if (mLeftBlockElement->IsAnyOfHTMLElements(nsGkAtoms::html, nsGkAtoms::head,
|
||||
nsGkAtoms::body) &&
|
||||
mRightBlockElement->IsAnyOfHTMLElements(nsGkAtoms::html, nsGkAtoms::head,
|
||||
nsGkAtoms::body)) {
|
||||
mCanJoinBlocks = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HTMLEditUtils::IsAnyTableElement(mLeftBlockElement) ||
|
||||
HTMLEditUtils::IsAnyTableElement(mRightBlockElement)) {
|
||||
// Do not try to merge table elements, cancel the deletion.
|
||||
|
|
|
@ -218,22 +218,13 @@ async function runTests() {
|
|||
is(beforeInputEvent.data, null, `${aDescription}data of "beforeinput" event for ${action} should be null`);
|
||||
is(beforeInputEvent.dataTransfer, null, `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
|
||||
checkTargetRanges(beforeInputEvent, selectionRanges);
|
||||
if (!isEditTargetIsDescendantOfEditingHost) {
|
||||
ok(!inputEvent, `${aDescription}"input" event shouldn't be fired at ${action}`);
|
||||
} else {
|
||||
todo(!inputEvent, `${aDescription}"input" event should be fired at ${action} but we replace the padding <br> element`);
|
||||
}
|
||||
ok(!inputEvent, `${aDescription}"input" event shouldn't be fired at ${action}`);
|
||||
|
||||
reset();
|
||||
cancelBeforeInput = false;
|
||||
action = 'typing "B"';
|
||||
synthesizeKey("B", {shiftKey: true}, aWindow);
|
||||
// XXX This inconsistency must be a bug.
|
||||
if (!isEditTargetIsDescendantOfEditingHost) {
|
||||
is(editTarget.innerHTML, "B<br>", `${aDescription}"B" should've been inserted by ${action}`);
|
||||
} else {
|
||||
is(editTarget.innerHTML, "B", `${aDescription}"B" should've been inserted by ${action}`);
|
||||
}
|
||||
is(editTarget.innerHTML, "B<br>", `${aDescription}"B" should've been inserted by ${action}`);
|
||||
is(beforeInputEvent.cancelable, true, `${aDescription}"beforeinput" event for ${action} should be cancelable`);
|
||||
is(beforeInputEvent.inputType, "insertText", `${aDescription}inputType of "beforeinput" event for ${action} should be "insertText"`);
|
||||
is(beforeInputEvent.data, "B", `${aDescription}data of "beforeinput" event for ${action} should be "B"`);
|
||||
|
@ -249,12 +240,7 @@ async function runTests() {
|
|||
cancelBeforeInput = true;
|
||||
action = 'typing "Enter"';
|
||||
synthesizeKey("KEY_Enter", {}, aWindow);
|
||||
// XXX This inconsistency must be a bug.
|
||||
if (!isEditTargetIsDescendantOfEditingHost) {
|
||||
is(editTarget.innerHTML, "B<br>", `${aDescription}shouldn't modify the editor by ${action} since "beforeinput" was canceled`);
|
||||
} else {
|
||||
is(editTarget.innerHTML, "B", `${aDescription}shouldn't modify the editor by ${action} since "beforeinput" was canceled`);
|
||||
}
|
||||
is(editTarget.innerHTML, "B<br>", `${aDescription}shouldn't modify the editor by ${action} since "beforeinput" was canceled`);
|
||||
ok(beforeInputEvent, `${aDescription}"beforeinput" event should've been fired at ${action}`);
|
||||
ok(!inputEvent, `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
|
||||
|
||||
|
@ -1317,10 +1303,10 @@ async function runTests() {
|
|||
"Editor3, div has contenteditable attribute");
|
||||
doTests(document.getElementById("editor4").contentDocument,
|
||||
document.getElementById("editor4").contentWindow,
|
||||
"Editor4, html and div has contenteditable attribute");
|
||||
"Editor4, html and div have contenteditable attribute");
|
||||
doTests(document.getElementById("editor5").contentDocument,
|
||||
document.getElementById("editor5").contentWindow,
|
||||
"Editor5, html and div has contenteditable attribute");
|
||||
"Editor5, html and div have contenteditable attribute");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче