Diff
Modified: trunk/LayoutTests/ChangeLog (97627 => 97628)
--- trunk/LayoutTests/ChangeLog 2011-10-17 16:47:37 UTC (rev 97627)
+++ trunk/LayoutTests/ChangeLog 2011-10-17 16:56:13 UTC (rev 97628)
@@ -1,3 +1,13 @@
+2011-10-17 Vsevolod Vlasov <[email protected]>
+
+ Web Inspector: Search matches highlighting in text does not work correctly.
+ https://bugs.webkit.org/show_bug.cgi?id=70244
+
+ Reviewed by Pavel Feldman.
+
+ * inspector/utilities-highlight-results-expected.txt: Added.
+ * inspector/utilities-highlight-results.html: Added.
+
2011-10-17 Chris Fleizach <[email protected]>
AX: webkit won't always send live region notifications
Added: trunk/LayoutTests/inspector/utilities-highlight-results-expected.txt (0 => 97628)
--- trunk/LayoutTests/inspector/utilities-highlight-results-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/utilities-highlight-results-expected.txt 2011-10-17 16:56:13 UTC (rev 97628)
@@ -0,0 +1,52 @@
+Tests how utilities functions highlight text and then revert/re-apply highlighting changes.
+
+Bug 70244
+--------- Running test: ----------
+After highlight: [function]
+After revert: function
+After apply: [function]
+--------- Running test: ----------
+After highlight: [functio]n
+After revert: function
+After apply: [functio]n
+--------- Running test: ----------
+After highlight: f[unction]
+After revert: function
+After apply: f[unction]
+--------- Running test: ----------
+After highlight: f[unctio]n
+After revert: function
+After apply: f[unctio]n
+--------- Running test: ----------
+After highlight: [function functionName]
+After revert: function functionName
+After apply: [function functionName]
+--------- Running test: ----------
+After highlight: [function functionNam]e
+After revert: function functionName
+After apply: [function functionNam]e
+--------- Running test: ----------
+After highlight: f[unction functionName]
+After revert: function functionName
+After apply: f[unction functionName]
+--------- Running test: ----------
+After highlight: f[unction functionNam]e
+After revert: function functionName
+After apply: f[unction functionNam]e
+--------- Running test: ----------
+After highlight: functio[n f]unctionName
+After revert: function functionName
+After apply: functio[n f]unctionName
+--------- Running test: ----------
+After highlight: [f]unction[ ][f]unctionName
+After revert: function functionName
+After apply: [f]unction[ ][f]unctionName
+--------- Running test: ----------
+After highlight: functio[n][ ]functionNam[e]
+After revert: function functionName
+After apply: functio[n][ ]functionNam[e]
+--------- Running test: ----------
+After highlight: [f]unctio[n f]unctionNam[e]
+After revert: function functionName
+After apply: [f]unctio[n f]unctionNam[e]
+
Property changes on: trunk/LayoutTests/inspector/utilities-highlight-results-expected.txt
___________________________________________________________________
Added: svn:eol-style
Added: trunk/LayoutTests/inspector/utilities-highlight-results.html (0 => 97628)
--- trunk/LayoutTests/inspector/utilities-highlight-results.html (rev 0)
+++ trunk/LayoutTests/inspector/utilities-highlight-results.html 2011-10-17 16:56:13 UTC (rev 97628)
@@ -0,0 +1,92 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+function test()
+{
+ function dumpTextNodesAsString(node)
+ {
+ var result = "";
+ function dumpTextNode(node)
+ {
+ var str = node.textContent;
+ if (node.parentElement.className)
+ result += "[" + str + "]";
+ else
+ result += str;
+ };
+
+ function dumpElement(element)
+ {
+ for (var i = 0; i < element.childNodes.length; i++)
+ dumpNode(element.childNodes[i]);
+ }
+
+ function dumpNode(node)
+ {
+ if (node.nodeType === Node.TEXT_NODE)
+ dumpTextNode(node);
+ else if (node.nodeType === Node.ELEMENT_NODE)
+ dumpElement(node);
+ };
+
+ dumpNode(node);
+
+ return result;
+ }
+
+ function performTestForElement(element, ranges)
+ {
+ var changes = [];
+ InspectorTest.addResult("--------- Running test: ----------");
+ highlightRangesWithStyleClass(element, ranges, "highlighted", changes);
+ InspectorTest.addResult("After highlight: " + dumpTextNodesAsString(element));
+ revertDomChanges(changes);
+ InspectorTest.addResult("After revert: " + dumpTextNodesAsString(element));
+ applyDomChanges(changes);
+ InspectorTest.addResult("After apply: " + dumpTextNodesAsString(element));
+ }
+
+ function textElement(strings)
+ {
+ var element = document.createElement("div");
+ for (var i = 0; i < strings.length; i++) {
+ var span = document.createElement("span");
+ span.textContent = strings[i];
+ element.appendChild(span);
+ }
+ return element;
+ }
+
+ function range(offset, length)
+ {
+ var result = {};
+ result.offset = offset;
+ result.length = length;
+ return result;
+ }
+
+ performTestForElement(textElement(["function"]), [range(0, 8)]); // Highlight whole text node.
+ performTestForElement(textElement(["function"]), [range(0, 7)]); // Highlight only text node beginning.
+ performTestForElement(textElement(["function"]), [range(1, 7)]); // Highlight only text node ending.
+ performTestForElement(textElement(["function"]), [range(1, 6)]); // Highlight in the middle of text node.
+
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(0, 21)]); // Highlight all text in 3 text nodes.
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(0, 20)]); // Highlight all text in 3 text nodes except for the last character.
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(1, 20)]); // Highlight all text in 3 text nodes except for the first character.
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(1, 19)]); // Highlight all text in 3 text nodes except for the first and the last characters.
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(7, 3)]); // Highlight like that "functio[n f]unctionName"
+
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(0, 1), range(8, 1), range(9, 1)]); // Highlight first characters in text nodes.
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(7, 1), range(8, 1), range(20, 1)]); // Highlight last characters in text node.
+ performTestForElement(textElement(["function", " ", "functionName"]), [range(0, 1), range(7, 3), range(20, 1)]); // Highlight like that: "[f]unctio[n f]unctionNam[e]"
+ InspectorTest.completeTest();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+ <p>Tests how utilities functions highlight text and then revert/re-apply highlighting changes.</p>
+ <a href="" 70244</a>
+</body>
+</html>
Property changes on: trunk/LayoutTests/inspector/utilities-highlight-results.html
___________________________________________________________________
Added: svn:eol-style
Modified: trunk/Source/WebCore/ChangeLog (97627 => 97628)
--- trunk/Source/WebCore/ChangeLog 2011-10-17 16:47:37 UTC (rev 97627)
+++ trunk/Source/WebCore/ChangeLog 2011-10-17 16:56:13 UTC (rev 97628)
@@ -1,3 +1,15 @@
+2011-10-17 Vsevolod Vlasov <[email protected]>
+
+ Web Inspector: Search matches highlighting in text does not work correctly.
+ https://bugs.webkit.org/show_bug.cgi?id=70244
+
+ Reviewed by Pavel Feldman.
+
+ Test: inspector/utilities-highlight-results.html
+
+ * inspector/front-end/utilities.js:
+ ():
+
2011-10-17 Chris Fleizach <[email protected]>
AX: webkit won't always send live region notifications
Modified: trunk/Source/WebCore/inspector/front-end/utilities.js (97627 => 97628)
--- trunk/Source/WebCore/inspector/front-end/utilities.js 2011-10-17 16:47:37 UTC (rev 97627)
+++ trunk/Source/WebCore/inspector/front-end/utilities.js 2011-10-17 16:56:13 UTC (rev 97628)
@@ -874,82 +874,73 @@
var textNodeSnapshot = ownerDocument.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var snapshotLength = textNodeSnapshot.snapshotLength;
- var snapshotNodeOffset = 0;
- var currentSnapshotItem = 0;
+ if (snapshotLength === 0)
+ return highlightNodes;
+ var nodeRanges = [];
+ var rangeEndOffset = 0;
+ for (var i = 0; i < snapshotLength; ++i) {
+ var range = {};
+ range.offset = rangeEndOffset;
+ range.length = textNodeSnapshot.snapshotItem(i).textContent.length;
+ rangeEndOffset = range.offset + range.length;
+ nodeRanges.push(range);
+ }
+
+ var startIndex = 0;
for (var i = 0; i < resultRanges.length; ++i) {
- var resultLength = resultRanges[i].length;
var startOffset = resultRanges[i].offset;
- var endOffset = startOffset + resultLength;
- var length = resultLength;
- var textNode;
- var textNodeOffset;
- var found;
+ var endOffset = startOffset + resultRanges[i].length;
- while (currentSnapshotItem < snapshotLength) {
- textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
- var textNodeLength = textNode.nodeValue.length;
- if (snapshotNodeOffset + textNodeLength > startOffset) {
- textNodeOffset = startOffset - snapshotNodeOffset;
- snapshotNodeOffset += textNodeLength;
- found = true;
- break;
- }
- snapshotNodeOffset += textNodeLength;
- }
-
- if (!found) {
- textNode = element;
- textNodeOffset = 0;
- }
-
+ while (startIndex < snapshotLength && nodeRanges[startIndex].offset + nodeRanges[startIndex].length <= startOffset)
+ startIndex++;
+ var endIndex = startIndex;
+ while (endIndex < snapshotLength && nodeRanges[endIndex].offset + nodeRanges[endIndex].length < endOffset)
+ endIndex++;
+ if (endIndex === snapshotLength)
+ break;
+
var highlightNode = ownerDocument.createElement("span");
highlightNode.className = styleClass;
highlightNode.textContent = lineText.substring(startOffset, endOffset);
- var text = textNode.textContent;
- if (textNodeOffset + resultLength < text.length) {
- // Selection belongs to a single split mode.
- textNode.textContent = text.substring(textNodeOffset + resultLength);
- changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
+ var lastTextNode = textNodeSnapshot.snapshotItem(endIndex);
+ var lastText = lastTextNode.textContent;
+ lastTextNode.textContent = lastText.substring(endOffset - nodeRanges[endIndex].offset);
+ changes.push({ node: lastTextNode, type: "changed", oldText: lastText, newText: lastTextNode.textContent });
+
+ if (startIndex === endIndex) {
+ lastTextNode.parentElement.insertBefore(highlightNode, lastTextNode);
+ changes.push({ node: highlightNode, type: "added", nextSibling: lastTextNode, parent: lastTextNode.parentElement });
+ highlightNodes.push(highlightNode);
+
+ var prefixNode = ownerDocument.createTextNode(lastText.substring(0, startOffset - nodeRanges[startIndex].offset));
+ lastTextNode.parentElement.insertBefore(prefixNode, highlightNode);
+ changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: lastTextNode.parentElement });
+ } else {
+ var firstTextNode = textNodeSnapshot.snapshotItem(startIndex);
+ var firstText = firstTextNode.textContent;
+ var anchorElement = firstTextNode.nextSibling;
- textNode.parentElement.insertBefore(highlightNode, textNode);
- changes.push({ node: highlightNode, type: "added", nextSibling: textNode, parent: textNode.parentElement });
-
- var prefixNode = ownerDocument.createTextNode(text.substring(0, textNodeOffset));
- textNode.parentElement.insertBefore(prefixNode, highlightNode);
- changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: textNode.parentElement });
+ firstTextNode.parentElement.insertBefore(highlightNode, anchorElement);
+ changes.push({ node: highlightNode, type: "added", nextSibling: anchorElement, parent: firstTextNode.parentElement });
highlightNodes.push(highlightNode);
- continue;
- }
- var parentElement = textNode.parentElement;
- var anchorElement = textNode.nextSibling;
+ firstTextNode.textContent = firstText.substring(0, startOffset - nodeRanges[startIndex].offset);
+ changes.push({ node: firstTextNode, type: "changed", oldText: firstText, newText: firstTextNode.textContent });
- length -= text.length - textNodeOffset;
- textNode.textContent = text.substring(0, textNodeOffset);
- changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
-
- while (currentSnapshotItem < snapshotLength) {
- textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
- snapshotNodeOffset += textNode.nodeValue.length;
- text = textNode.textContent;
- if (length < text.length) {
- textNode.textContent = text.substring(length);
+ for (var j = startIndex + 1; j < endIndex; j++) {
+ var textNode = textNodeSnapshot.snapshotItem(j);
+ var text = textNode.textContent;
+ textNode.textContent = "";
changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
- break;
}
-
- length -= text.length;
- textNode.textContent = "";
- changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
}
-
- parentElement.insertBefore(highlightNode, anchorElement);
- changes.push({ node: highlightNode, type: "added", nextSibling: anchorElement, parent: parentElement });
- highlightNodes.push(highlightNode);
+ startIndex = endIndex;
+ nodeRanges[startIndex].offset = endOffset;
+ nodeRanges[startIndex].length = lastTextNode.textContent.length;
+
}
-
return highlightNodes;
}
@@ -970,7 +961,7 @@
function revertDomChanges(domChanges)
{
- for (var i = 0, size = domChanges.length; i < size; ++i) {
+ for (var i = domChanges.length - 1; i >= 0; --i) {
var entry = domChanges[i];
switch (entry.type) {
case "added":