mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1663601 - Make RangeBoundaryBase::GetNextSiblingOfChildAtOffset()
check whether mRef
is nullptr or not r=mbrodesser
`RangeBoundaryBase` stores a previous sibling of child node at offset with `mRef`. Therefore, even if the callers check whether its instance points a child node, `mRef` may be `nullptr` when it points first child of its container. So, `GetNextSiblingOfChildAtOffset()` needs to handle the case. This patch adds the crash case test into `test_dom_input_event_on_htmleditor.html` because of a basic behavior. For now, this patch adds 2 chunks which are coded with using same style as previous ones. However, the test should be redesigned later for making non-dependency of each chunk guaranteed. (The new chunks are completely independent from previously running tests.) Differential Revision: https://phabricator.services.mozilla.com/D89440
This commit is contained in:
parent
7433c1b34d
commit
8bb9ef510a
@ -124,6 +124,16 @@ class RangeBoundaryBase {
|
||||
if (NS_WARN_IF(!mParent) || NS_WARN_IF(!mParent->IsContainerNode())) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!mRef) {
|
||||
MOZ_ASSERT(*Offset(OffsetFilter::kValidOffsets) == 0,
|
||||
"invalid RangeBoundary");
|
||||
nsIContent* firstChild = mParent->GetFirstChild();
|
||||
if (NS_WARN_IF(!firstChild)) {
|
||||
// Already referring the end of the container.
|
||||
return nullptr;
|
||||
}
|
||||
return firstChild->GetNextSibling();
|
||||
}
|
||||
if (NS_WARN_IF(!mRef->GetNextSibling())) {
|
||||
// Already referring the end of the container.
|
||||
return nullptr;
|
||||
|
@ -1249,6 +1249,59 @@ async function runTests() {
|
||||
checkTargetRanges(beforeInputEvent, selectionRanges);
|
||||
ok(!inputEvent, `${aDescription}"input" event shouldn't have been fired at ${action}`);
|
||||
|
||||
// Deleting atomic content
|
||||
editTarget.innerHTML =
|
||||
'<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==">';
|
||||
editTarget.focus();
|
||||
selection.collapse(editTarget, 0);
|
||||
reset();
|
||||
cancelBeforeInput = false;
|
||||
action = 'typing "Delete" to delete the <img> element';
|
||||
synthesizeKey("KEY_Delete", {}, aWindow);
|
||||
is(editTarget.innerHTML, `<br>`,
|
||||
`${aDescription}the <img> should be deleted and padding <br> element should've been inserted instead at ${action}`);
|
||||
ok(beforeInputEvent, `${aDescription}"beforeinput" event should've been fired at ${action}`);
|
||||
is(beforeInputEvent.cancelable, true, `${aDescription}"beforeinput" event for ${action} should be cancelable`);
|
||||
is(beforeInputEvent.inputType, "deleteContentForward", `${aDescription}inputType of "beforeinput" event should be "deleteContentForward"`);
|
||||
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, [{startContainer: editTarget,
|
||||
startOffset: 0,
|
||||
endContainer: editTarget,
|
||||
endOffset: 1}]);
|
||||
ok(inputEvent, `${aDescription}"input" event should've been fired at ${action}`);
|
||||
is(inputEvent.cancelable, false, `${aDescription}"input" event for ${action} should never be cancelable`);
|
||||
is(inputEvent.inputType, "deleteContentForward", `${aDescription}inputType of "input" event should be "deleteContentForward"`);
|
||||
is(inputEvent.data, null, `${aDescription}data of "input" event for ${action} should be null`);
|
||||
is(inputEvent.dataTransfer, null, `${aDescription}dataTransfer of "input" event for ${action} should be null`);
|
||||
checkTargetRanges(inputEvent, []);
|
||||
|
||||
editTarget.innerHTML =
|
||||
'<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==">';
|
||||
editTarget.focus();
|
||||
selection.collapse(editTarget, 1);
|
||||
reset();
|
||||
cancelBeforeInput = false;
|
||||
action = 'typing "Backspace" to delete the <img> element';
|
||||
synthesizeKey("KEY_Backspace", {}, aWindow);
|
||||
is(editTarget.innerHTML, `<br>`,
|
||||
`${aDescription}the <img> should be deleted and padding <br> element should've been inserted instead at ${action}`);
|
||||
ok(beforeInputEvent, `${aDescription}"beforeinput" event should've been fired at ${action}`);
|
||||
is(beforeInputEvent.cancelable, true, `${aDescription}"beforeinput" event for ${action} should be cancelable`);
|
||||
is(beforeInputEvent.inputType, "deleteContentBackward", `${aDescription}inputType of "beforeinput" event should be "deleteContentBackward"`);
|
||||
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, [{startContainer: editTarget,
|
||||
startOffset: 0,
|
||||
endContainer: editTarget,
|
||||
endOffset: 1}]);
|
||||
ok(inputEvent, `${aDescription}"input" event should've been fired at ${action}`);
|
||||
is(inputEvent.cancelable, false, `${aDescription}"input" event for ${action} should never be cancelable`);
|
||||
is(inputEvent.inputType, "deleteContentBackward", `${aDescription}inputType of "input" event should be "deleteContentBackward"`);
|
||||
is(inputEvent.data, null, `${aDescription}data of "input" event for ${action} should be null`);
|
||||
is(inputEvent.dataTransfer, null, `${aDescription}dataTransfer of "input" event for ${action} should be null`);
|
||||
checkTargetRanges(inputEvent, []);
|
||||
|
||||
aWindow.removeEventListener("beforeinput", beforeInputHandler, true);
|
||||
aWindow.removeEventListener("input", inputHandler, true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user