Commit 931cb029 authored by David Tseng's avatar David Tseng Committed by Commit Bot

Detect invalidated prior lines in editing state machine

When lines in the midst of editing operations are invalid, output the current line rather than attempting to make intra line diffs.

type 'abc' within a textarea. Press enter. Verify we do not trigger intra line state machine changes and output 'abc deleted'. Rather, ensure we trigger output of the entire new line 'new line'.

Test: 
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I5b1252687e1463ca29f237bc4c86a87f0f5bb781
Reviewed-on: https://chromium-review.googlesource.com/1054698
Commit-Queue: David Tseng <dtseng@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558108}
parent 6e93fd00
...@@ -303,7 +303,11 @@ AutomationRichEditableText.prototype = { ...@@ -303,7 +303,11 @@ AutomationRichEditableText.prototype = {
} }
// Selection stayed within the same line(s) and didn't cross into new lines. // Selection stayed within the same line(s) and didn't cross into new lines.
if (anchorLine.isSameLine(prevAnchorLine) &&
// We must validate the previous lines as state changes in the accessibility
// tree may have invalidated the lines.
if (prevAnchorLine.isValidLine() && prevFocusLine.isValidLine() &&
anchorLine.isSameLine(prevAnchorLine) &&
focusLine.isSameLine(prevFocusLine)) { focusLine.isSameLine(prevFocusLine)) {
// Intra-line changes. // Intra-line changes.
this.changed(new cvox.TextChangeEvent( this.changed(new cvox.TextChangeEvent(
...@@ -1028,6 +1032,60 @@ editing.EditableLine.prototype = { ...@@ -1028,6 +1032,60 @@ editing.EditableLine.prototype = {
return AutomationUtil.getDirection( return AutomationUtil.getDirection(
this.lineStartContainer_, otherLine.lineStartContainer_) == this.lineStartContainer_, otherLine.lineStartContainer_) ==
Dir.FORWARD; Dir.FORWARD;
},
/**
* Performs a validation that this line still refers to a line given its
* internally tracked state.
*/
isValidLine: function() {
if (!this.lineStartContainer_ || !this.lineEndContainer_)
return false;
var start = new cursors.Cursor(
this.lineStartContainer_, this.localLineStartContainerOffset_);
var end = new cursors.Cursor(
this.lineEndContainer_, this.localLineEndContainerOffset_ - 1);
var localStart = start.deepEquivalent || start;
var localEnd = end.deepEquivalent || end;
var localStartNode = localStart.node;
var localEndNode = localEnd.node;
// Unfortunately, there are asymmetric errors in lines, so we need to check
// in both directions.
var testStartNode = localStartNode;
do {
if (testStartNode == localEndNode)
return true;
// Hack/workaround for broken *OnLine links.
if (testStartNode.nextOnLine && testStartNode.nextOnLine.role)
testStartNode = testStartNode.nextOnLine;
else if (
testStartNode.nextSibling &&
testStartNode.nextSibling.previousOnLine == testStartNode)
testStartNode = testStartNode.nextSibling;
else
break;
} while (testStartNode);
var testEndNode = localEndNode;
do {
if (testEndNode == localStartNode)
return true;
// Hack/workaround for broken *OnLine links.
if (testEndNode.previousOnLine && testEndNode.previousOnLine.role)
testEndNode = testEndNode.previousOnLine;
else if (
testEndNode.previousSibling &&
testEndNode.previousSibling.nextOnLine == testEndNode)
testEndNode = testEndNode.previousSibling;
else
break;
} while (testEndNode);
return false;
} }
}; };
......
...@@ -854,3 +854,45 @@ TEST_F('EditingTest', 'EditableLineBaseLineAnchorOrFocus', function() { ...@@ -854,3 +854,45 @@ TEST_F('EditingTest', 'EditableLineBaseLineAnchorOrFocus', function() {
assertEquals(3, e1.endOffset); assertEquals(3, e1.endOffset);
}) })
}); });
TEST_F('EditingTest', 'IsValidLine', function() {
this.runWithLoadedTree(function() {/*!
<div contenteditable role="textbox">
<p style="word-spacing:100000px">this is a test</p>
<p>end</p>
</div>
*/}, function(root) {
// Each word is on its own line, but parented by a static text.
var text, endText;
[text, endText] = root.findAll({role: RoleType.STATIC_TEXT});
// The EditableLine object automatically adjusts to surround the line no
// matter what the input is.
var line = new editing.EditableLine(text, 0, text, 0);
assertTrue(line.isValidLine());
// During the course of editing operations, this line may become
// invalidted. For example, if a user starts typing into the line, the
// bounding nodes might change.
// Simulate that here by modifying private state.
// This puts the line at offset 8 (|this is a|).
line.localLineStartContainerOffset_ = 0;
line.localLineEndContainerOffset_ = 8;
assertFalse(line.isValidLine());
// This puts us in the first line.
line.localLineStartContainerOffset_ = 0;
line.localLineEndContainerOffset_ = 4;
assertTrue(line.isValidLine());
// This is still fine (for our purposes) because the line is still intact.
line.localLineStartContainerOffset_ = 0;
line.localLineEndContainerOffset_ = 2;
assertTrue(line.isValidLine());
// The line has changed. The end has been moved for some reason.
line.lineEndContainer_ = endText;
assertFalse(line.isValidLine());
})
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment