зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1675883 - Use SetStartAndEndInLimiter() in SetSelectionInternal() r=masayuki
Differential Revision: https://phabricator.services.mozilla.com/D96503
This commit is contained in:
Родитель
cd031ba211
Коммит
21c2a81d5e
|
@ -793,25 +793,6 @@ already_AddRefed<TextEditor> nsTextControlFrame::GetTextEditor() {
|
|||
nsresult nsTextControlFrame::SetSelectionInternal(
|
||||
nsINode* aStartNode, uint32_t aStartOffset, nsINode* aEndNode,
|
||||
uint32_t aEndOffset, nsITextControlFrame::SelectionDirection aDirection) {
|
||||
// Create a new range to represent the new selection.
|
||||
// Note that we use a new range to avoid having to do
|
||||
// isIncreasing checks to avoid possible errors.
|
||||
|
||||
// Be careful to use internal nsRange methods which do not check to make sure
|
||||
// we have access to the node.
|
||||
// XXXbz nsRange::SetStartAndEnd takes int32_t (and ranges generally work on
|
||||
// int32_t), but we're passing uint32_t. The good news is that at this point
|
||||
// our endpoints should really be within our length, so not really that big.
|
||||
// And if they _are_ that big, SetStartAndEnd() will simply error out, which
|
||||
// is not too bad for a case we don't expect to happen.
|
||||
ErrorResult error;
|
||||
RefPtr<nsRange> range =
|
||||
nsRange::Create(aStartNode, aStartOffset, aEndNode, aEndOffset, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
MOZ_ASSERT(range);
|
||||
|
||||
// Get the selection, clear it and add the new range to it!
|
||||
TextControlElement* textControlElement =
|
||||
TextControlElement::FromNode(GetContent());
|
||||
|
@ -831,16 +812,10 @@ nsresult nsTextControlFrame::SetSelectionInternal(
|
|||
direction = (aDirection == eBackward) ? eDirPrevious : eDirNext;
|
||||
}
|
||||
|
||||
selection->RemoveAllRanges(error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
selection->AddRangeAndSelectFramesAndNotifyListeners(
|
||||
*range, error); // NOTE: can destroy the world
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
ErrorResult error;
|
||||
selection->SetStartAndEndInLimiter(*aStartNode, aStartOffset, *aEndNode,
|
||||
aEndOffset, error);
|
||||
MOZ_TRY(error.StealNSResult());
|
||||
|
||||
selection->SetDirection(direction);
|
||||
return NS_OK;
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Test selectionchange events from text controls</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<link rel="stylesheet" href="/fonts/ahem.css">
|
||||
<style>
|
||||
input,
|
||||
textarea {
|
||||
font: 16px/1 Ahem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<input id="input" value="XXXXXXXXXXXXXXXXXXX" width="200"><br>
|
||||
<textarea id="textarea" width="200">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</textarea>
|
||||
|
||||
<script>
|
||||
class SelectionChangeCollector {
|
||||
constructor(target) {
|
||||
this.events = [];
|
||||
target.addEventListener("selectionchange", ev => {
|
||||
this.events.push(ev);
|
||||
});
|
||||
}
|
||||
clear() {
|
||||
this.events.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const data = {
|
||||
input: new SelectionChangeCollector(input),
|
||||
textarea: new SelectionChangeCollector(textarea),
|
||||
async initialize() {
|
||||
input.blur();
|
||||
textarea.blur();
|
||||
input.selectionStart = input.selectionEnd = 0;
|
||||
textarea.selectionStart = textarea.selectionEnd = 0;
|
||||
await this.spin();
|
||||
this.input.clear();
|
||||
this.textarea.clear();
|
||||
},
|
||||
spin() {
|
||||
return new Promise(setTimeout);
|
||||
},
|
||||
};
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.selectionStart = 1;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 1);
|
||||
}, "Modifying selectionStart value of the textarea element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.selectionEnd = 1;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 1);
|
||||
}, "Modifying selectionEnd value of the textarea element");
|
||||
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.setSelectionRange(0, 4);
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 1);
|
||||
}, "Calling setSelectionRange on the textarea element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
input.selectionStart = 0;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.input.events.length, 0);
|
||||
}, "Setting initial zero selectionStart value on the input element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
input.selectionEnd = 0;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.input.events.length, 0);
|
||||
}, "Setting initial zero selectionEnd value on the input element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.selectionStart = 0;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 0);
|
||||
}, "Setting initial zero selectionStart value on the textarea element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.selectionStart = 2;
|
||||
textarea.selectionStart = 2;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 1);
|
||||
}, "Setting the same selectionStart value on the textarea element twice");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.selectionEnd = 0;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 0);
|
||||
}, "Setting initial zero selectionEnd value on the textarea element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.selectionEnd = 2;
|
||||
textarea.selectionEnd = 2;
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 1);
|
||||
}, "Setting the same selectionEnd value on the textarea element twice");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.setSelectionRange(0, 0);
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 0);
|
||||
}, "Setting initial zero selection range on the textarea element");
|
||||
|
||||
promise_test(async () => {
|
||||
await data.initialize();
|
||||
|
||||
textarea.setSelectionRange(3, 3);
|
||||
textarea.setSelectionRange(3, 3);
|
||||
|
||||
await data.spin();
|
||||
assert_equals(data.textarea.events.length, 1);
|
||||
}, "Setting the same selection range on the textarea element twice");
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче