Changeset 87294 in webkit


Ignore:
Timestamp:
May 25, 2011 7:02:10 AM (13 years ago)
Author:
apavlov@chromium.org
Message:

2011-05-23 Alexander Pavlov <apavlov@chromium.org>

Reviewed by Yury Semikhatsky.

Web Inspector: extreme lagging when searching for "img[src*="
https://bugs.webkit.org/show_bug.cgi?id=61282

No new tests, as this is a refactoring: ElementsTreeElement DOM is manipulated directly
when built and search-highlighted, rather than through innerHTML.

  • inspector/front-end/DOMSyntaxHighlighter.js: (WebInspector.DOMSyntaxHighlighter): (WebInspector.DOMSyntaxHighlighter.prototype.createSpan):
  • inspector/front-end/ElementsPanel.js: (WebInspector.ElementsPanel.prototype._hideSearchHighlights):
  • inspector/front-end/ElementsTreeOutline.js: (WebInspector.ElementsTreeElement.prototype.highlightSearchResults): (WebInspector.ElementsTreeElement.prototype.hideSearchHighlights): (WebInspector.ElementsTreeElement.prototype._updateSearchHighlight.updateEntryShow): (WebInspector.ElementsTreeElement.prototype._updateSearchHighlight.updateEntryHide): (WebInspector.ElementsTreeElement.prototype._updateSearchHighlight): (WebInspector.ElementsTreeElement.prototype._addNewAttribute): (WebInspector.ElementsTreeElement.prototype.updateTitle): (WebInspector.ElementsTreeElement.prototype._buildAttributeDOM): ():
  • inspector/front-end/utilities.js: ():
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r87293 r87294  
     12011-05-23  Alexander Pavlov  <apavlov@chromium.org>
     2
     3        Reviewed by Yury Semikhatsky.
     4
     5        Web Inspector: extreme lagging when searching for "img[src*="
     6        https://bugs.webkit.org/show_bug.cgi?id=61282
     7
     8        No new tests, as this is a refactoring: ElementsTreeElement DOM is manipulated directly
     9        when built and search-highlighted, rather than through innerHTML.
     10
     11        * inspector/front-end/DOMSyntaxHighlighter.js:
     12        (WebInspector.DOMSyntaxHighlighter):
     13        (WebInspector.DOMSyntaxHighlighter.prototype.createSpan):
     14        * inspector/front-end/ElementsPanel.js:
     15        (WebInspector.ElementsPanel.prototype._hideSearchHighlights):
     16        * inspector/front-end/ElementsTreeOutline.js:
     17        (WebInspector.ElementsTreeElement.prototype.highlightSearchResults):
     18        (WebInspector.ElementsTreeElement.prototype.hideSearchHighlights):
     19        (WebInspector.ElementsTreeElement.prototype._updateSearchHighlight.updateEntryShow):
     20        (WebInspector.ElementsTreeElement.prototype._updateSearchHighlight.updateEntryHide):
     21        (WebInspector.ElementsTreeElement.prototype._updateSearchHighlight):
     22        (WebInspector.ElementsTreeElement.prototype._addNewAttribute):
     23        (WebInspector.ElementsTreeElement.prototype.updateTitle):
     24        (WebInspector.ElementsTreeElement.prototype._buildAttributeDOM):
     25        ():
     26        * inspector/front-end/utilities.js:
     27        ():
     28
    1292011-05-25  Leandro Gracia Gil  <leandrogracia@chromium.org>
    230
  • trunk/Source/WebCore/inspector/front-end/DOMSyntaxHighlighter.js

    r86430 r87294  
    2929 */
    3030
    31 WebInspector.DOMSyntaxHighlighter = function(mimeType)
     31WebInspector.DOMSyntaxHighlighter = function(mimeType, stripExtraWhitespace)
    3232{
    3333    this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
     34    this._stripExtraWhitespace = stripExtraWhitespace;
    3435}
    3536
     
    3940        var span = document.createElement("span");
    4041        span.className = "webkit-" + className;
     42        if (this._stripExtraWhitespace)
     43            content = content.replace(/^[\n\r]*/, "").replace(/\s*$/, "");
    4144        span.appendChild(document.createTextNode(content));
    4245        return span;
  • trunk/Source/WebCore/inspector/front-end/ElementsPanel.js

    r86674 r87294  
    394394            var treeElement = this.treeOutline.findTreeElement(node);
    395395            if (treeElement)
    396                 treeElement.highlightSearchResults(null);
     396                treeElement.hideSearchHighlights();
    397397        }
    398398    },
  • trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js

    r86948 r87294  
    330330    highlightSearchResults: function(searchQuery)
    331331    {
    332         if (this._searchQuery === searchQuery)
    333             return;
    334 
    335         if (searchQuery)
    336             delete this._searchHighlightedHTML; // A new search query (not clear-the-current-highlighting).
     332        if (this._searchQuery !== searchQuery) {
     333            this._updateSearchHighlight(false);
     334            delete this._highlightResult; // A new search query.
     335        }
    337336
    338337        this._searchQuery = searchQuery;
     338        this._searchHighlightsVisible = true;
    339339        this.updateTitle(true);
     340    },
     341
     342    hideSearchHighlights: function()
     343    {
     344        delete this._searchHighlightsVisible;
     345        this._updateSearchHighlight(false);
     346    },
     347
     348    _updateSearchHighlight: function(show)
     349    {
     350        if (!this._highlightResult)
     351            return;
     352
     353        function updateEntryShow(entry)
     354        {
     355            switch (entry.type) {
     356                case "added":
     357                    entry.parent.insertBefore(entry.node, entry.nextSibling);
     358                    break;
     359                case "changed":
     360                    entry.node.textContent = entry.newText;
     361                    break;
     362            }
     363        }
     364
     365        function updateEntryHide(entry)
     366        {
     367            switch (entry.type) {
     368                case "added":
     369                    if (entry.node.parentElement)
     370                        entry.node.parentElement.removeChild(entry.node);
     371                    break;
     372                case "changed":
     373                    entry.node.textContent = entry.oldText;
     374                    break;
     375            }
     376        }
     377
     378        var updater = show ? updateEntryShow : updateEntryHide;
     379
     380        for (var i = 0, size = this._highlightResult.length; i < size; ++i)
     381            updater(this._highlightResult[i]);
    340382    },
    341383
     
    839881        // a parent node. Use a temporary span container for the HTML.
    840882        var container = document.createElement("span");
    841         container.innerHTML = this._attributeHTML(" ", "");
     883        this._buildAttributeDOM(container, " ", "");
    842884        var attr = container.firstChild;
    843885        attr.style.marginLeft = "2px"; // overrides the .editing margin rule
     
    11801222            return;
    11811223
    1182         if (onlySearchQueryChanged && this._normalHTML)
    1183             this.titleHTML = this._normalHTML;
    1184         else {
    1185             delete this._normalHTML;
    1186             this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
     1224        if (onlySearchQueryChanged) {
     1225            if (this._highlightResult)
     1226                this._updateSearchHighlight(false);
     1227        } else {
     1228            var highlightElement = document.createElement("span");
     1229            highlightElement.className = "highlight";
     1230            highlightElement.appendChild(this._nodeTitleInfo(WebInspector.linkifyURLAsNode).titleDOM);
     1231            this.title = highlightElement;
     1232            delete this._highlightResult;
    11871233        }
    11881234
     
    11931239    },
    11941240
    1195     _attributeHTML: function(name, value, node, linkify)
     1241    _buildAttributeDOM: function(parentElement, name, value, node, linkify)
    11961242    {
    11971243        var hasText = (value.length > 0);
    1198         var html = "<span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + name.escapeHTML() + "</span>";
     1244        var attrSpanElement = parentElement.createChild("span", "webkit-html-attribute");
     1245        var attrNameElement = attrSpanElement.createChild("span", "webkit-html-attribute-name");
     1246        attrNameElement.textContent = name.escapeHTML();
    11991247
    12001248        if (hasText)
    1201             html += "=&#8203;\"";
     1249            attrSpanElement.appendChild(document.createTextNode("=\u200B\""));
    12021250
    12031251        if (linkify && (name === "src" || name === "href")) {
    12041252            var rewrittenHref = WebInspector.resourceURLForRelatedNode(node, value);
    12051253            value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
    1206             html += linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a");
     1254            attrSpanElement.appendChild(linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a"));
    12071255        } else {
    1208             value = value.escapeHTML().replace(/([\/;:\)\]\}])/g, "$1&#8203;");
    1209             html += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
     1256            value = value.escapeHTML().replace(/([\/;:\)\]\}])/g, "$1\u200B");
     1257            var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value");
     1258            attrValueElement.textContent = value;
    12101259        }
    12111260
    12121261        if (hasText)
    1213             html += "\"";
    1214 
    1215         html += "</span>";
    1216         return html;
    1217     },
    1218 
    1219     _tagHTML: function(tagName, isClosingTag, isDistinctTreeElement, linkify, isShadow)
     1262            attrSpanElement.appendChild(document.createTextNode("\""));
     1263    },
     1264
     1265    _buildTagDOM: function(parentElement, tagName, isClosingTag, isDistinctTreeElement, linkify, isShadow)
    12201266    {
    12211267        var node = this.representedObject;
     
    12251271        if (isShadow)
    12261272            classes.push("shadow");
    1227         var result = "<span class=\"" + classes.join(" ") + "\">&lt;";
    1228         result += "<span " + (isClosingTag ? "" : "class=\"webkit-html-tag-name\"") + ">" + (isClosingTag ? "/" : "") + tagName + "</span>";
     1273        var tagElement = parentElement.createChild("span", classes.join(" "));
     1274        tagElement.appendChild(document.createTextNode("<"));
     1275        var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name");
     1276        tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName;
     1277
    12291278        if (!isClosingTag && node.hasAttributes()) {
    12301279            var attributes = node.attributes();
    12311280            for (var i = 0; i < attributes.length; ++i) {
    12321281                var attr = attributes[i];
    1233                 result += " " + this._attributeHTML(attr.name, attr.value, node, linkify);
    1234             }
    1235         }
    1236         result += "&gt;</span>&#8203;";
    1237 
    1238         return result;
     1282                tagElement.appendChild(document.createTextNode(" "));
     1283                this._buildAttributeDOM(tagElement, attr.name, attr.value, node, linkify);
     1284            }
     1285        }
     1286        tagElement.appendChild(document.createTextNode(">"));
     1287        parentElement.appendChild(document.createTextNode("\u200B"));
    12391288    },
    12401289
     
    12421291    {
    12431292        var node = this.representedObject;
    1244         var info = {titleHTML: "", hasChildren: this.hasChildren};
     1293        var info = {titleDOM: document.createDocumentFragment(), hasChildren: this.hasChildren};
    12451294
    12461295        switch (node.nodeType()) {
    12471296            case Node.DOCUMENT_NODE:
    1248                 info.titleHTML = "Document";
     1297                info.titleDOM.appendChild(document.createTextNode("Document"));
    12491298                break;
    12501299
    12511300            case Node.DOCUMENT_FRAGMENT_NODE:
    1252                 info.titleHTML = "Document Fragment";
     1301                info.titleDOM.appendChild(document.createTextNode("Document Fragment"));
    12531302                break;
    12541303
    12551304            case Node.ATTRIBUTE_NODE:
    12561305                var value = node.value || "\u200B"; // Zero width space to force showing an empty value.
    1257                 info.titleHTML = this._attributeHTML(node.name, value);
     1306                this._buildAttributeDOM(info.titleDOM, node.name, value);
    12581307                break;
    12591308
     
    12611310                var tagName = this.treeOutline.nodeNameToCorrectCase(node.nodeName()).escapeHTML();
    12621311                if (this._elementCloseTag) {
    1263                     info.titleHTML = this._tagHTML(tagName, true, true, false, node.inShadowTree());
     1312                    this._buildTagDOM(info.titleDOM, tagName, true, true, false, node.inShadowTree());
    12641313                    info.hasChildren = false;
    12651314                    break;
    12661315                }
    12671316
    1268                 var titleHTML = this._tagHTML(tagName, false, false, linkify, node.inShadowTree());
     1317                this._buildTagDOM(info.titleDOM, tagName, false, false, linkify, node.inShadowTree());
    12691318
    12701319                var textChild = this._singleTextChild(node);
     
    12721321
    12731322                if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) {
    1274                     if (this.hasChildren)
    1275                         titleHTML += "<span class=\"webkit-html-text-node\">&#8230;</span>&#8203;";
    1276                     titleHTML += this._tagHTML(tagName, true, false, false, node.inShadowTree());
     1323                    if (this.hasChildren) {
     1324                        var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
     1325                        textNodeElement.textContent = "\u2026";
     1326                        info.titleDOM.appendChild(document.createTextNode("\u200B"));
     1327                    }
     1328                    this._buildTagDOM(info.titleDOM, tagName, true, false, false, node.inShadowTree());
    12771329                }
    12781330
     
    12811333                // create a subtree for them
    12821334                if (showInlineText) {
    1283                     titleHTML += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue().escapeHTML() + "</span>&#8203;" + this._tagHTML(tagName, true, false, node.inShadowTree());
     1335                    var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
     1336                    textNodeElement.textContent = textChild.nodeValue().escapeHTML();
     1337                    info.titleDOM.appendChild(document.createTextNode("\u200B"));
     1338                    this._buildTagDOM(info.titleDOM, tagName, true, false, node.inShadowTree());
    12841339                    info.hasChildren = false;
    12851340                }
    1286                 info.titleHTML = titleHTML;
    12871341                break;
    12881342
    12891343            case Node.TEXT_NODE:
    12901344                if (isNodeWhitespace.call(node))
    1291                     info.titleHTML = "(whitespace)";
     1345                    info.titleDOM.appendChild(document.createTextNode("(whitespace)"));
    12921346                else {
    12931347                    if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") {
    1294                         var newNode = document.createElement("span");
     1348                        var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-js-node");
    12951349                        newNode.textContent = node.nodeValue();
    12961350
    1297                         var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript");
     1351                        var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript", true);
    12981352                        javascriptSyntaxHighlighter.syntaxHighlightNode(newNode);
    1299 
    1300                         info.titleHTML = "<span class=\"webkit-html-text-node webkit-html-js-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
    13011353                    } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") {
    1302                         var newNode = document.createElement("span");
     1354                        var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-css-node");
    13031355                        newNode.textContent = node.nodeValue();
    13041356
    1305                         var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css");
     1357                        var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css", true);
    13061358                        cssSyntaxHighlighter.syntaxHighlightNode(newNode);
    1307 
    1308                         info.titleHTML = "<span class=\"webkit-html-text-node webkit-html-css-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
    1309                     } else
    1310                         info.titleHTML = "\"<span class=\"webkit-html-text-node\">" + node.nodeValue().escapeHTML() + "</span>\"";
     1359                    } else {
     1360                        info.titleDOM.appendChild(document.createTextNode("\""));
     1361                        var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
     1362                        textNodeElement.textContent = node.nodeValue().escapeHTML();
     1363                        info.titleDOM.appendChild(document.createTextNode("\""));
     1364                    }
    13111365                }
    13121366                break;
    13131367
    13141368            case Node.COMMENT_NODE:
    1315                 info.titleHTML = "<span class=\"webkit-html-comment\">&lt;!--" + node.nodeValue().escapeHTML() + "--&gt;</span>";
     1369                var commentElement = info.titleDOM.createChild("span", "webkit-html-comment");
     1370                commentElement.appendChild(document.createTextNode("<!--" + node.nodeValue().escapeHTML() + "-->"));
    13161371                break;
    13171372
    13181373            case Node.DOCUMENT_TYPE_NODE:
    1319                 var titleHTML = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + node.nodeName();
     1374                var docTypeElement = info.titleDOM.createChild("span", "webkit-html-doctype");
     1375                docTypeElement.appendChild(document.createTextNode("<!DOCTYPE " + node.nodeName()));
    13201376                if (node.publicId) {
    1321                     titleHTML += " PUBLIC \"" + node.publicId + "\"";
     1377                    docTypeElement.appendChild(document.createTextNode(" PUBLIC \"" + node.publicId + "\""));
    13221378                    if (node.systemId)
    1323                         titleHTML += " \"" + node.systemId + "\"";
     1379                        docTypeElement.appendChild(document.createTextNode(" \"" + node.systemId + "\""));
    13241380                } else if (node.systemId)
    1325                     titleHTML += " SYSTEM \"" + node.systemId + "\"";
     1381                    docTypeElement.appendChild(document.createTextNode(" SYSTEM \"" + node.systemId + "\""));
     1382
    13261383                if (node.internalSubset)
    1327                     titleHTML += " [" + node.internalSubset + "]";
    1328                 titleHTML += "&gt;</span>";
    1329                 info.titleHTML = titleHTML;
     1384                    docTypeElement.appendChild(document.createTextNode(" [" + node.internalSubset + "]"));
     1385
     1386                docTypeElement.appendChild(document.createTextNode(">"));
    13301387                break;
    13311388
    13321389            case Node.CDATA_SECTION_NODE:
    1333                 info.titleHTML = "<span class=\"webkit-html-text-node\">&lt;![CDATA[" + node.nodeValue().escapeHTML() + "]]&gt;</span>";
     1390                var cdataElement = info.titleDOM.createChild("span", "webkit-html-text-node");
     1391                cdataElement.appendChild(document.createTextNode("<![CDATA[" + node.nodeValue().escapeHTML() + "]]>"));
    13341392                break;
    13351393
    13361394            case Node.SHADOW_ROOT_NODE:
    1337                 info.titleHTML = "<span class=\"dom-shadow-root\">(shadow)</span>";
     1395                var cdataElement = info.titleDOM.createChild("span", "dom-shadow-root");
     1396                cdataElement.appendChild(document.createTextNode("(shadow)"));
    13381397                break;
    13391398
    13401399            default:
    1341                 info.titleHTML = this.treeOutline.nodeNameToCorrectCase(node.nodeName()).collapseWhitespace().escapeHTML();
     1400                var defaultElement = info.titleDOM.appendChild(document.createTextNode(this.treeOutline.nodeNameToCorrectCase(node.nodeName()).collapseWhitespace().escapeHTML()));
    13421401        }
    13431402
     
    14241483    _highlightSearchResults: function()
    14251484    {
    1426         if (!this._searchQuery)
    1427             return;
    1428         if (this._searchHighlightedHTML) {
    1429             this.listItemElement.innerHTML = this._searchHighlightedHTML;
    1430             return;
    1431         }
    1432 
    1433         if (!this._normalHTML)
    1434             this._normalHTML = this.titleHTML;
     1485        if (!this._searchQuery || !this._searchHighlightsVisible)
     1486            return;
     1487        if (this._highlightResult) {
     1488            this._updateSearchHighlight(true);
     1489            return;
     1490        }
    14351491
    14361492        var text = this.listItemElement.textContent;
     
    14491505            matchRanges.push({ offset: 0, length: text.length });
    14501506
    1451         highlightSearchResults(this.listItemElement, matchRanges);
    1452         this._searchHighlightedHTML = this.listItemElement.innerHTML;
     1507        this._highlightResult = [];
     1508        highlightSearchResults(this.listItemElement, matchRanges, this._highlightResult);
    14531509    }
    14541510}
  • trunk/Source/WebCore/inspector/front-end/utilities.js

    r86562 r87294  
    259259    return element;
    260260}
     261
     262DocumentFragment.prototype.createChild = Element.prototype.createChild;
    261263
    262264Element.prototype.__defineGetter__("totalOffsetLeft", function()
     
    954956}
    955957
    956 function highlightSearchResults(element, resultRanges)
    957 {
     958function highlightSearchResults(element, resultRanges, changes)
     959{
     960    changes = changes || [];
    958961    var highlightNodes = [];
    959962    var lineText = element.textContent;
     
    9981001            // Selection belongs to a single split mode.
    9991002            textNode.textContent = text.substring(textNodeOffset + resultLength);
     1003            changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
     1004
    10001005            textNode.parentElement.insertBefore(highlightNode, textNode);
     1006            changes.push({ node: highlightNode, type: "added", nextSibling: textNode, parent: textNode.parentElement });
     1007
    10011008            var prefixNode = document.createTextNode(text.substring(0, textNodeOffset));
    10021009            textNode.parentElement.insertBefore(prefixNode, highlightNode);
    1003 
     1010            changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: textNode.parentElement });
    10041011            highlightNodes.push(highlightNode);
    10051012            continue;
     
    10111018        length -= text.length - textNodeOffset;
    10121019        textNode.textContent = text.substring(0, textNodeOffset);
     1020        changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
    10131021
    10141022        while (currentSnapshotItem < snapshotLength) {
     
    10181026            if (length < text.length) {
    10191027                textNode.textContent = text.substring(length);
     1028                changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
    10201029                break;
    10211030            }
     
    10231032            length -= text.length;
    10241033            textNode.textContent = "";
     1034            changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
    10251035        }
    10261036
    10271037        parentElement.insertBefore(highlightNode, anchorElement);
     1038        changes.push({ node: highlightNode, type: "added", nextSibling: anchorElement, parent: parentElement });
    10281039        highlightNodes.push(highlightNode);
    10291040    }
Note: See TracChangeset for help on using the changeset viewer.