Bug 1571375 - Don't remove white space when committing composition. r=masayuki

This is regression by bug 1530649.

After landing bug 1530649, we try to scan end point of replacement text. But
in this bug's situation, afterRun becomes same as current ws run by landing
bug 1530649. To get white space type of next of replacement end, we have to
scan around end point again.

Differential Revision: https://phabricator.services.mozilla.com/D45947

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Makoto Kato 2019-09-18 03:56:25 +00:00
Родитель 746966587f
Коммит c147a2e204
3 изменённых файлов: 74 добавлений и 8 удалений

Просмотреть файл

@ -275,7 +275,12 @@ nsresult WSRunObject::InsertText(Document& aDocument,
}
WSFragment* beforeRun = FindNearestRun(mScanStartPoint, false);
WSFragment* afterRun = FindNearestRun(mScanEndPoint, true);
// If mScanStartPoint isn't equal to mScanEndPoint, it will replace text (i.e.
// committing composition). And afterRun will be end point of replaced range.
// So we want to know this white space type (trailing whitespace etc) of
// this end point, not inserted (start) point, so we re-scan white space type.
WSRunObject afterRunObject(mHTMLEditor, mScanEndPoint);
WSFragment* afterRun = afterRunObject.FindNearestRun(mScanEndPoint, true);
EditorDOMPoint pointToInsert(mScanStartPoint);
nsAutoString theString(aStringToInsert);
@ -668,7 +673,7 @@ nsresult WSRunScanner::GetWSNodes() {
// collect up an array of nodes that are contiguous with the insertion point
// and which contain only whitespace. Stop if you reach non-ws text or a new
// block boundary.
EditorDOMPoint start(mScanStartPoint), end(mScanEndPoint);
EditorDOMPoint start(mScanStartPoint), end(mScanStartPoint);
nsCOMPtr<nsINode> wsBoundingParent = GetWSBoundingParent();
// first look backwards to find preceding ws nodes
@ -777,12 +782,11 @@ nsresult WSRunScanner::GetWSNodes() {
}
// then look ahead to find following ws nodes
if (Text* textNode = mScanEndPoint.GetContainerAsText()) {
if (Text* textNode = end.GetContainerAsText()) {
// don't need to put it on list. it already is from code above
const nsTextFragment* textFrag = &textNode->TextFragment();
if (!mScanEndPoint.IsEndOfContainer()) {
for (uint32_t i = mScanEndPoint.Offset(); i < textNode->TextLength();
i++) {
if (!end.IsEndOfContainer()) {
for (uint32_t i = end.Offset(); i < textNode->TextLength(); i++) {
// sanity bounds check the char position. bug 136165
if (i >= textFrag->GetLength()) {
MOZ_ASSERT_UNREACHABLE("looking beyond end of text fragment");

Просмотреть файл

@ -139,8 +139,12 @@ class MOZ_STACK_CLASS WSRunScanner {
* host. aScanEndPoint (aScanEndNode and aScanEndOffset) must be later
* point from aScanStartPoint (aScanStartNode and aScanStartOffset).
* The end point is currently used only with InsertText(). Therefore,
* currently, this assumes that the range does not cross block boundary. If
* you use aScanEndPoint newly, please test enough.
* currently, this assumes that the range does not cross block boundary.
*
* Actually, WSRunScanner scans white space type at mScanStartPoint position
* only.
*
* If you use aScanEndPoint newly, please test enough.
*/
template <typename PT, typename CT>
WSRunScanner(const HTMLEditor* aHTMLEditor,

Просмотреть файл

@ -30,6 +30,8 @@
src="data:text/html,&lt;div contenteditable id='contenteditable'&gt;&lt;/div&gt;"></iframe><br/>
<iframe id="iframe5" width="200" height="50" src="data:text/html,&lt;input id='input'&gt;"></iframe>
<iframe id="iframe6" width="200" height="50" src="data:text/html,&lt;input id='password' type='password'&gt;"></iframe><br/>
<iframe id="iframe7" width="300" height="150"
src="data:text/html,&lt;span contenteditable id='contenteditable'&gt;&lt;/span&gt;"></iframe><br/>
<input id="input" type="text"/><br/>
<input id="password" type="password"/><br/>
</p>
@ -5186,6 +5188,61 @@ function runBug1530649Test()
"runBug1530649Test: Committing the new composition string shouldn't remove the last space");
}
function runBug1571375Test()
{
let contenteditableBySpan = document.getElementById("iframe7").contentDocument.getElementById("contenteditable");
let windowOfContenteditableBySpan = document.getElementById("iframe7").contentWindow;
let selection = windowOfContenteditableBySpan.getSelection();
let doc = document.getElementById("iframe7").contentDocument;
contenteditableBySpan.focus();
contenteditableBySpan.innerHTML = "hello world";
let range = doc.createRange();
range.setStart(contenteditableBySpan.firstChild, 6);
range.setEnd(contenteditableBySpan.firstChild, 11);
selection.removeAllRanges();
selection.addRange(range);
synthesizeCompositionChange({
composition: {string: "world", clauses: [{length: 5, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
caret: { start: 5, length: 0 },
});
synthesizeComposition({type: "compositioncommit", data: "world", key: " "});
is(contenteditableBySpan.innerHTML, "hello world",
"runBug1571375Test: space must not be removed by commit");
contenteditableBySpan.innerHTML = "hello world";
range = doc.createRange();
range.setStart(contenteditableBySpan.firstChild, 0);
range.setEnd(contenteditableBySpan.firstChild, 5);
selection.removeAllRanges();
selection.addRange(range);
synthesizeCompositionChange({
composition: {string: "hello", clauses: [{length: 5, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
caret: { start: 5, length: 0 },
});
synthesizeComposition({type: "compositioncommit", data: "hello", key: " "});
is(contenteditableBySpan.innerHTML, "hello world",
"runBug1571375Test: space must not be removed by commit");
contenteditableBySpan.innerHTML = "hello world<div>.</div>";
range = doc.createRange();
range.setStart(contenteditableBySpan.firstChild, 6);
range.setEnd(contenteditableBySpan.firstChild, 11);
selection.removeAllRanges();
selection.addRange(range);
synthesizeCompositionChange({
composition: {string: "world", clauses: [{length: 5, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
caret: {start: 0, length: 0}}
);
synthesizeComposition({type: "compositioncommit", data: "world", key: " "});
is(contenteditableBySpan.innerHTML, "hello world<div>.</div>",
"runBug1571375Test: space must not be removed by commit");
}
function runCSSTransformTest()
{
textarea.focus();
@ -9105,6 +9162,7 @@ async function runTest()
runBug722639Test();
runBug1375825Test();
runBug1530649Test();
runBug1571375Test();
runForceCommitTest();
runNestedSettingValue();
runBug811755Test();