Title: [205035] trunk
Revision
205035
Author
commit-qu...@webkit.org
Date
2016-08-26 13:29:17 -0700 (Fri, 26 Aug 2016)

Log Message

Web Inspector: Some CSS selectors in the UI aren't escaped
https://bugs.webkit.org/show_bug.cgi?id=151378

Patch by Devin Rousso <dcrousso+web...@gmail.com> on 2016-08-26
Reviewed by Joseph Pecoraro.

Source/_javascript_Core:

Change ElementData from sending a className string to using an array of
classes, allowing for proper escaping of each class value.

* inspector/protocol/OverlayTypes.json:

Source/WebCore:

No new tests, but logic and results of existing tests updated:
* inspector/dom/content-node-region-info.html:
* inspector/dom/content-node-region-info-expected.txt:
* inspector/dom/highlightNode-expected.txt:
* inspector/dom/highlightSelector.html:
* inspector/dom/highlightSelector-expected.txt:

* inspector/InspectorOverlay.cpp:
(WebCore::buildObjectForElementData):

* inspector/InspectorOverlayPage.css:
(.pseudo-type):
(.tag-name): Deleted.

* inspector/InspectorOverlayPage.js:
(_createElementTitle):

Source/WebInspectorUI:

* UserInterface/Base/DOMUtilities.js:
(WebInspector.displayNameForNode): Deleted.
(WebInspector.linkifyNodeReference):
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

* UserInterface/Models/DOMNode.js:
(WebInspector.DOMNode.prototype.get escapedIdSelector):
(WebInspector.DOMNode.prototype.get escapedClassSelector):
(WebInspector.DOMNode.prototype.get displayName):
(WebInspector.DOMNode.prototype.appropriateSelectorFor):
Rework escaping of ids and class names into separate public functions using CSS.escape.

* UserInterface/Views/CSSStyleDeclarationSection.js:
(WebInspector.CSSStyleDeclarationSection.prototype.refresh):
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

* UserInterface/Views/DOMTreeDataGridNode.js:
(WebInspector.DOMTreeDataGridNode.prototype._createNameCellDocumentFragment):
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

* UserInterface/Views/DOMTreeElementPathComponent.js:
(WebInspector.DOMTreeElementPathComponent):
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

* UserInterface/Views/LayerTreeDataGridNode.js:
(WebInspector.LayerTreeDataGridNode.prototype.set layer):
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

* UserInterface/Views/VisualStyleSelectorSection.js:
(WebInspector.VisualStyleSelectorSection.prototype.update):
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

LayoutTests:

* inspector/dom/content-node-region-info.html:
* inspector/dom/content-node-region-info-expected.txt:
Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.

* inspector/dom/highlightNode-expected.txt:
* inspector/dom/highlightSelector.html:
* inspector/dom/highlightSelector-expected.txt:
Changed result to replace className with new classes array.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (205034 => 205035)


--- trunk/LayoutTests/ChangeLog	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/LayoutTests/ChangeLog	2016-08-26 20:29:17 UTC (rev 205035)
@@ -1,3 +1,19 @@
+2016-08-26  Devin Rousso  <dcrousso+web...@gmail.com>
+
+        Web Inspector: Some CSS selectors in the UI aren't escaped
+        https://bugs.webkit.org/show_bug.cgi?id=151378
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/dom/content-node-region-info.html:
+        * inspector/dom/content-node-region-info-expected.txt:
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
+        * inspector/dom/highlightNode-expected.txt:
+        * inspector/dom/highlightSelector.html:
+        * inspector/dom/highlightSelector-expected.txt:
+        Changed result to replace className with new classes array.
+
 2016-08-26  Chris Dumez  <cdu...@apple.com>
 
         HTMLAreaElement's coords attributes parsing does not comply with the HTML specification

Modified: trunk/LayoutTests/inspector/dom/content-node-region-info.html (205034 => 205035)


--- trunk/LayoutTests/inspector/dom/content-node-region-info.html	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/LayoutTests/inspector/dom/content-node-region-info.html	2016-08-26 20:29:17 UTC (rev 205035)
@@ -27,8 +27,9 @@
 <script>
 function test()
 {
-    var queryList = ["#flow", ".contentNode1", ".contentNode2", "body", "#region1", "#region2"];
-    var documentNodeId;
+    let displayNameGetter = Object.getOwnPropertyDescriptor(WebInspector.DOMNode.prototype, "displayName").get;
+    let queryList = ["#flow", ".contentNode1", ".contentNode2", "body", "#region1", "#region2"];
+    let documentNodeId = null;
 
     WebInspector.domTreeManager.requestDocument(function(documentNode) {
         documentNodeId = documentNode.id;
@@ -36,6 +37,11 @@
         next();
     });
 
+    function regionMapFunction(region)
+    {
+        return displayNameGetter.call(region);
+    }
+
     function query(selector, callback)
     {
         InspectorTest.log("\nSelector: " + selector);
@@ -44,7 +50,7 @@
                 InspectorTest.log("DOM node not found.");
                 callback();
             }
-            var domNode = WebInspector.domTreeManager.nodeForId(contentNodeId);
+            let domNode = WebInspector.domTreeManager.nodeForId(contentNodeId);
             WebInspector.domTreeManager.getNodeContentFlowInfo(domNode, function(error, result) {
                 console.assert(!error);
                 if (result) {
@@ -51,7 +57,7 @@
                     InspectorTest.log("Region flow name: " + (result.regionFlow ? result.regionFlow.name : "none"));
                     InspectorTest.log("Content flow name: " + (result.contentFlow ? result.contentFlow.name : "none"));
                     InspectorTest.log("Regions count: " + (result.regions ? result.regions.length : "N/A"));
-                    InspectorTest.log("Regions: " + (result.regions ? result.regions.map(WebInspector.displayNameForNode).join(", ") : "N/A"));
+                    InspectorTest.log("Regions: " + (result.regions ? result.regions.map(regionMapFunction).join(", ") : "N/A"));
                 } else
                     InspectorTest.log("No region flow information.");
                 callback();

Modified: trunk/LayoutTests/inspector/dom/highlightNode-expected.txt (205034 => 205035)


--- trunk/LayoutTests/inspector/dom/highlightNode-expected.txt	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/LayoutTests/inspector/dom/highlightNode-expected.txt	2016-08-26 20:29:17 UTC (rev 205035)
@@ -8,7 +8,7 @@
 
 -- Running test case: MainFrameNodeViaNodeId
 PASS: Should be one highlighted node.
-Highlighted Element Data: {"tagName":"div","idValue":"id-one","className":".class-two","size":{"width":100,"height":200},"role":""}
+Highlighted Element Data: {"tagName":"div","idValue":"id-one","classes":["class-two"],"size":{"width":100,"height":200},"role":""}
 
 -- Running test case: ChildFrameNodeViaNodeId
 PASS: Should be one highlighted node.
@@ -16,7 +16,7 @@
 
 -- Running test case: MainFrameNodeViaObjectId
 PASS: Should be one highlighted node.
-Highlighted Element Data: {"tagName":"div","idValue":"id-one","className":".class-two","size":{"width":100,"height":200},"role":""}
+Highlighted Element Data: {"tagName":"div","idValue":"id-one","classes":["class-two"],"size":{"width":100,"height":200},"role":""}
 
 -- Running test case: ChildFrameNodeViaObjectId
 PASS: Should be one highlighted node.

Modified: trunk/LayoutTests/inspector/dom/highlightSelector-expected.txt (205034 => 205035)


--- trunk/LayoutTests/inspector/dom/highlightSelector-expected.txt	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/LayoutTests/inspector/dom/highlightSelector-expected.txt	2016-08-26 20:29:17 UTC (rev 205035)
@@ -9,8 +9,8 @@
 PASS: Should highlight 3 element(s).
 Highlighted Elements:
 {"tagName":"div","idValue":"","size":{"width":500,"height":500},"role":""}
-{"tagName":"div","idValue":"","className":".class-one","size":{"width":10,"height":20},"role":""}
-{"tagName":"div","idValue":"id-one","className":".class-two","size":{"width":100,"height":200},"role":""}
+{"tagName":"div","idValue":"","classes":["class-one",".escaped"],"size":{"width":10,"height":20},"role":""}
+{"tagName":"div","idValue":"id-one","classes":["class-two"],"size":{"width":100,"height":200},"role":""}
 
 -- Running test case: MainFrameWithClassSelector
 - Frame: <main-frame>
@@ -17,15 +17,22 @@
 - Selector: .class-one
 PASS: Should highlight 2 element(s).
 Highlighted Elements:
-{"tagName":"div","idValue":"","className":".class-one","size":{"width":10,"height":20},"role":""}
-{"tagName":"iframe","idValue":"","className":".class-one","size":{"width":304,"height":154},"role":"group"}
+{"tagName":"div","idValue":"","classes":["class-one",".escaped"],"size":{"width":10,"height":20},"role":""}
+{"tagName":"iframe","idValue":"","classes":["class-one"],"size":{"width":304,"height":154},"role":"group"}
 
+-- Running test case: MainFrameWithMultipleClassSelector
+- Frame: <main-frame>
+- Selector: .class-one.\.escaped
+PASS: Should highlight 1 element(s).
+Highlighted Elements:
+{"tagName":"div","idValue":"","classes":["class-one",".escaped"],"size":{"width":10,"height":20},"role":""}
+
 -- Running test case: MainFrameIdSelector
 - Frame: <main-frame>
 - Selector: #id-one
 PASS: Should highlight 1 element(s).
 Highlighted Elements:
-{"tagName":"div","idValue":"id-one","className":".class-two","size":{"width":100,"height":200},"role":""}
+{"tagName":"div","idValue":"id-one","classes":["class-two"],"size":{"width":100,"height":200},"role":""}
 
 -- Running test case: MainFrameMultipleSelectors
 - Frame: <main-frame>
@@ -32,9 +39,9 @@
 - Selector: .class-one, .class-two
 PASS: Should highlight 3 element(s).
 Highlighted Elements:
-{"tagName":"div","idValue":"","className":".class-one","size":{"width":10,"height":20},"role":""}
-{"tagName":"div","idValue":"id-one","className":".class-two","size":{"width":100,"height":200},"role":""}
-{"tagName":"iframe","idValue":"","className":".class-one","size":{"width":304,"height":154},"role":"group"}
+{"tagName":"div","idValue":"","classes":["class-one",".escaped"],"size":{"width":10,"height":20},"role":""}
+{"tagName":"div","idValue":"id-one","classes":["class-two"],"size":{"width":100,"height":200},"role":""}
+{"tagName":"iframe","idValue":"","classes":["class-one"],"size":{"width":304,"height":154},"role":"group"}
 
 -- Running test case: MissingOptionalFrameIdShouldUseMainFrame
 - Frame: Not Provided
@@ -41,7 +48,7 @@
 - Selector: iframe.class-one
 PASS: Should highlight 1 element(s).
 Highlighted Elements:
-{"tagName":"iframe","idValue":"","className":".class-one","size":{"width":304,"height":154},"role":"group"}
+{"tagName":"iframe","idValue":"","classes":["class-one"],"size":{"width":304,"height":154},"role":"group"}
 
 -- Running test case: MainFrameNonMatchingSelector
 - Frame: <main-frame>

Modified: trunk/LayoutTests/inspector/dom/highlightSelector.html (205034 => 205035)


--- trunk/LayoutTests/inspector/dom/highlightSelector.html	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/LayoutTests/inspector/dom/highlightSelector.html	2016-08-26 20:29:17 UTC (rev 205035)
@@ -30,6 +30,12 @@
             expectedElements: 2,
         },
         {
+            name: "MainFrameWithMultipleClassSelector",
+            frameId: mainFrameId,
+            selector: ".class-one.\\.escaped",
+            expectedElements: 1,
+        },
+        {
             name: "MainFrameIdSelector",
             frameId: mainFrameId,
             selector: "#id-one",
@@ -133,7 +139,7 @@
 <body _onload_="runTest()">
     <p>Tests for the DOM.highlightSelector command.</p>
     <div style="width: 500px; height: 500px">
-        <div class="class-one" style="width: 10px; height: 20px"></div>
+        <div class="class-one .escaped" style="width: 10px; height: 20px"></div>
         <div id="id-one" class="class-two" style="width:100px; height: 200px"></div>
         <iframe class="class-one" src=""
     </div>

Modified: trunk/Source/_javascript_Core/ChangeLog (205034 => 205035)


--- trunk/Source/_javascript_Core/ChangeLog	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-08-26 20:29:17 UTC (rev 205035)
@@ -1,3 +1,15 @@
+2016-08-26  Devin Rousso  <dcrousso+web...@gmail.com>
+
+        Web Inspector: Some CSS selectors in the UI aren't escaped
+        https://bugs.webkit.org/show_bug.cgi?id=151378
+
+        Reviewed by Joseph Pecoraro.
+
+        Change ElementData from sending a className string to using an array of
+        classes, allowing for proper escaping of each class value.
+
+        * inspector/protocol/OverlayTypes.json:
+
 2016-08-26  Joseph Pecoraro  <pecor...@apple.com>
 
         Web Inspector: ScriptProfilerAgent and HeapAgent should do less work when frontend disconnects

Modified: trunk/Source/_javascript_Core/inspector/protocol/OverlayTypes.json (205034 => 205035)


--- trunk/Source/_javascript_Core/inspector/protocol/OverlayTypes.json	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/_javascript_Core/inspector/protocol/OverlayTypes.json	2016-08-26 20:29:17 UTC (rev 205035)
@@ -83,9 +83,10 @@
             "properties": [
                 { "name": "tagName", "type": "string" },
                 { "name": "idValue", "type": "string", "description": "The value of the element's 'id' attribute." },
-                { "name": "className", "type": "string", "optional": true },
+                { "name": "classes", "type": "array", "items": { "type": "string" }, "optional": true },
                 { "name": "size", "$ref": "Size", "optional": true },
                 { "name": "role", "type": "string", "description": "Computed accessibility role for the element.", "optional": true },
+                { "name": "pseudoElement", "type": "string", "optional": true },
                 { "name": "regionFlowData", "$ref": "RegionFlowData", "optional": true },
                 { "name": "contentFlowData", "$ref": "ContentFlowData", "optional": true },
                 { "name": "shapeOutsideData", "$ref": "ShapeOutsideData", "optional": true }

Modified: trunk/Source/WebCore/ChangeLog (205034 => 205035)


--- trunk/Source/WebCore/ChangeLog	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebCore/ChangeLog	2016-08-26 20:29:17 UTC (rev 205035)
@@ -1,3 +1,27 @@
+2016-08-26  Devin Rousso  <dcrousso+web...@gmail.com>
+
+        Web Inspector: Some CSS selectors in the UI aren't escaped
+        https://bugs.webkit.org/show_bug.cgi?id=151378
+
+        Reviewed by Joseph Pecoraro.
+
+        No new tests, but logic and results of existing tests updated:
+        * inspector/dom/content-node-region-info.html:
+        * inspector/dom/content-node-region-info-expected.txt:
+        * inspector/dom/highlightNode-expected.txt:
+        * inspector/dom/highlightSelector.html:
+        * inspector/dom/highlightSelector-expected.txt:
+
+        * inspector/InspectorOverlay.cpp:
+        (WebCore::buildObjectForElementData):
+
+        * inspector/InspectorOverlayPage.css:
+        (.pseudo-type):
+        (.tag-name): Deleted.
+
+        * inspector/InspectorOverlayPage.js:
+        (_createElementTitle):
+
 2016-08-25  Brent Fulgham  <bfulg...@apple.com>
 
         Crash when getting font bounding rect

Modified: trunk/Source/WebCore/inspector/InspectorOverlay.cpp (205034 => 205035)


--- trunk/Source/WebCore/inspector/InspectorOverlay.cpp	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebCore/inspector/InspectorOverlay.cpp	2016-08-26 20:29:17 UTC (rev 205035)
@@ -58,7 +58,6 @@
 #include <bindings/ScriptValue.h>
 #include <inspector/InspectorProtocolObjects.h>
 #include <inspector/InspectorValues.h>
-#include <wtf/text/StringBuilder.h>
 
 using namespace Inspector;
 
@@ -713,28 +712,27 @@
         .setIdValue(element.getIdAttribute())
         .release();
 
-    StringBuilder classNames;
     if (element.hasClass() && is<StyledElement>(element)) {
+        auto classes = Inspector::Protocol::Array<String>::create();
         HashSet<AtomicString> usedClassNames;
         const SpaceSplitString& classNamesString = downcast<StyledElement>(element).classNames();
-        size_t classNameCount = classNamesString.size();
-        for (size_t i = 0; i < classNameCount; ++i) {
+        for (size_t i = 0; i < classNamesString.size(); ++i) {
             const AtomicString& className = classNamesString[i];
             if (usedClassNames.contains(className))
                 continue;
+
             usedClassNames.add(className);
-            classNames.append('.');
-            classNames.append(className);
+            classes->addItem(className);
         }
+        elementData->setClasses(WTFMove(classes));
     }
+
     if (node->isPseudoElement()) {
         if (node->pseudoId() == BEFORE)
-            classNames.appendLiteral("::before");
+            elementData->setPseudoElement("before");
         else if (node->pseudoId() == AFTER)
-            classNames.appendLiteral("::after");
+            elementData->setPseudoElement("after");
     }
-    if (!classNames.isEmpty())
-        elementData->setClassName(classNames.toString());
 
     RenderElement* renderer = element.renderer();
     if (!renderer)

Modified: trunk/Source/WebCore/inspector/InspectorOverlayPage.css (205034 => 205035)


--- trunk/Source/WebCore/inspector/InspectorOverlayPage.css	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebCore/inspector/InspectorOverlayPage.css	2016-08-26 20:29:17 UTC (rev 205035)
@@ -59,7 +59,8 @@
     position: absolute;
 }
 
-.tag-name {
+.tag-name,
+.pseudo-type {
     /* Keep this in sync with XMLViewer.css (.tag) */
     color: rgb(136, 18, 128);
 }

Modified: trunk/Source/WebCore/inspector/InspectorOverlayPage.js (205034 => 205035)


--- trunk/Source/WebCore/inspector/InspectorOverlayPage.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebCore/inspector/InspectorOverlayPage.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -263,12 +263,17 @@
 
 function _createElementTitle(elementData)
 {
-    var builder = new DOMBuilder("div", "element-title");
-    
+    let builder = new DOMBuilder("div", "element-title");
+
     builder.appendSpanIfNotNull("tag-name", elementData.tagName);
-    builder.appendSpanIfNotNull("node-id", elementData.idValue, "#");
-    builder.appendSpanIfNotNull("class-name", _truncateString(elementData.className, 50));
+    builder.appendSpanIfNotNull("node-id", CSS.escape(elementData.idValue), "#");
 
+    let classes = elementData.classes;
+    if (classes && classes.length)
+        builder.appendSpan("class-name", _truncateString(classes.map((className) => "." + CSS.escape(className)).join(""), 50));
+
+    builder.appendSpanIfNotNull("pseudo-type", elementData.pseudoElement, "::");
+
     builder.appendTextNode(" ");
     builder.appendSpan("node-width", elementData.size.width);
     // \xd7 is the code for the &times; HTML entity.

Modified: trunk/Source/WebInspectorUI/ChangeLog (205034 => 205035)


--- trunk/Source/WebInspectorUI/ChangeLog	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/ChangeLog	2016-08-26 20:29:17 UTC (rev 205035)
@@ -1,3 +1,42 @@
+2016-08-26  Devin Rousso  <dcrousso+web...@gmail.com>
+
+        Web Inspector: Some CSS selectors in the UI aren't escaped
+        https://bugs.webkit.org/show_bug.cgi?id=151378
+
+        Reviewed by Joseph Pecoraro.
+
+        * UserInterface/Base/DOMUtilities.js:
+        (WebInspector.displayNameForNode): Deleted.
+        (WebInspector.linkifyNodeReference):
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
+        * UserInterface/Models/DOMNode.js:
+        (WebInspector.DOMNode.prototype.get escapedIdSelector):
+        (WebInspector.DOMNode.prototype.get escapedClassSelector):
+        (WebInspector.DOMNode.prototype.get displayName):
+        (WebInspector.DOMNode.prototype.appropriateSelectorFor):
+        Rework escaping of ids and class names into separate public functions using CSS.escape.
+
+        * UserInterface/Views/CSSStyleDeclarationSection.js:
+        (WebInspector.CSSStyleDeclarationSection.prototype.refresh):
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
+        * UserInterface/Views/DOMTreeDataGridNode.js:
+        (WebInspector.DOMTreeDataGridNode.prototype._createNameCellDocumentFragment):
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
+        * UserInterface/Views/DOMTreeElementPathComponent.js:
+        (WebInspector.DOMTreeElementPathComponent):
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
+        * UserInterface/Views/LayerTreeDataGridNode.js:
+        (WebInspector.LayerTreeDataGridNode.prototype.set layer):
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
+        * UserInterface/Views/VisualStyleSelectorSection.js:
+        (WebInspector.VisualStyleSelectorSection.prototype.update):
+        Use DOMNode.prototype.displayName instead of WebInspector.displayNameForNode.
+
 2016-08-24  Matt Baker  <mattba...@apple.com>
 
         Web Inspector: unexpected cursor changes while dragging ruler handle in rendering frames timeline

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/DOMUtilities.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Base/DOMUtilities.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/DOMUtilities.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -29,36 +29,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.displayNameForNode = function(node)
-{
-    var title = node.nodeNameInCorrectCase();
-
-    var idAttribute = node.getAttribute("id");
-    if (idAttribute) {
-        if (/[\s'"]/.test(idAttribute)) {
-            idAttribute = idAttribute.replace(/\\/g, "\\\\").replace(/\"/g, "\\\"");
-            title += "[id=\"" + idAttribute + "\"]";
-        } else
-            title += "#" + idAttribute;
-    }
-
-    var classAttribute = node.getAttribute("class");
-    if (classAttribute) {
-        var classes = classAttribute.trim().split(/\s+/);
-        var foundClasses = {};
-
-        for (var i = 0; i < classes.length; ++i) {
-            var className = classes[i];
-            if (className && !(className in foundClasses)) {
-                title += "." + className;
-                foundClasses[className] = true;
-            }
-        }
-    }
-
-    return title;
-};
-
 WebInspector.roleSelectorForNode = function(node)
 {
     // This is proposed syntax for CSS 4 computed role selector :role(foo) and subject to change.
@@ -89,7 +59,7 @@
 
 WebInspector.linkifyNodeReference = function(node, maxLength)
 {
-    let displayName = WebInspector.displayNameForNode(node);
+    let displayName = node.displayName;
     if (!isNaN(maxLength))
         displayName = displayName.truncate(maxLength);
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNode.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -520,28 +520,62 @@
         return path.join(",");
     }
 
+    get escapedIdSelector()
+    {
+        let id = this.getAttribute("id");
+        if (!id)
+            return "";
+
+        id = id.trim();
+        if (!id.length)
+            return "";
+
+        id = CSS.escape(id);
+        if (/[\s'"]/.test(id))
+            return `[id=\"${id}\"]`;
+
+        return `#${id}`;
+    }
+
+    get escapedClassSelector()
+    {
+        let classes = this.getAttribute("class");
+        if (!classes)
+            return "";
+
+        classes = classes.trim();
+        if (!classes.length)
+            return "";
+
+        let foundClasses = new Set;
+        return classes.split(/\s+/).reduce((selector, className) => {
+            if (!className.length || foundClasses.has(className))
+                return selector;
+
+            foundClasses.add(className);
+            return `${selector}.${CSS.escape(className)}`;
+        }, "");
+    }
+
+    get displayName()
+    {
+        return this.nodeNameInCorrectCase() + this.escapedIdSelector + this.escapedClassSelector;
+    }
+
     appropriateSelectorFor(justSelector)
     {
         if (this.isPseudoElement())
             return this.parentNode.appropriateSelectorFor() + "::" + this._pseudoType;
 
-        var lowerCaseName = this.localName() || this.nodeName().toLowerCase();
+        let lowerCaseName = this.localName() || this.nodeName().toLowerCase();
 
-        var id = this.getAttribute("id");
-        if (id) {
-            if (/[\s'"]/.test(id)) {
-                id = id.replace(/\\/g, "\\\\").replace(/\"/g, "\\\"");
-                selector = lowerCaseName + "[id=\"" + id + "\"]";
-            } else
-                selector = "#" + id;
-            return (justSelector ? selector : lowerCaseName + selector);
-        }
+        let id = this.escapedIdSelector;
+        if (id.length)
+            return justSelector ? id : lowerCaseName + id;
 
-        var className = this.getAttribute("class");
-        if (className) {
-            var selector = "." + className.trim().replace(/\s+/g, ".");
-            return (justSelector ? selector : lowerCaseName + selector);
-        }
+        let classes = this.escapedClassSelector;
+        if (classes.length)
+            return justSelector ? classes : lowerCaseName + classes;
 
         if (lowerCaseName === "input" && this.getAttribute("type"))
             return lowerCaseName + "[type=\"" + this.getAttribute("type") + "\"]";

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -261,12 +261,12 @@
             break;
 
         case WebInspector.CSSStyleDeclaration.Type.Inline:
-            appendSelectorTextKnownToMatch.call(this, WebInspector.displayNameForNode(this._style.node));
+            appendSelectorTextKnownToMatch.call(this, this._style.node.displayName);
             this._originElement.append(WebInspector.UIString("Style Attribute"));
             break;
 
         case WebInspector.CSSStyleDeclaration.Type.Attribute:
-            appendSelectorTextKnownToMatch.call(this, WebInspector.displayNameForNode(this._style.node));
+            appendSelectorTextKnownToMatch.call(this, this._style.node.displayName);
             this._originElement.append(WebInspector.UIString("HTML Attributes"));
             break;
         }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeDataGridNode.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeDataGridNode.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeDataGridNode.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -53,7 +53,7 @@
     _createNameCellDocumentFragment()
     {
         let fragment = document.createDocumentFragment();
-        let mainTitle = WebInspector.displayNameForNode(this._domNode);
+        let mainTitle = this._domNode.displayName;
         fragment.append(mainTitle);
 
         let goToButton = fragment.appendChild(WebInspector.createGoToArrowButton());

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -39,7 +39,7 @@
                 title = "::" + node.pseudoType();
             } else {
                 className = WebInspector.DOMTreeElementPathComponent.DOMElementIconStyleClassName;
-                title = WebInspector.displayNameForNode(node);
+                title = node.displayName;
             }
             break;
 
@@ -75,7 +75,7 @@
             if (node.shadowRootType())
                 title = WebInspector.UIString("Shadow Content");
             else
-                title = WebInspector.displayNameForNode(node);
+                title = node.displayName;
             break;
 
         case Node.PROCESSING_INSTRUCTION_NODE:

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayerTreeDataGridNode.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LayerTreeDataGridNode.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayerTreeDataGridNode.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -63,7 +63,7 @@
         var domNode = WebInspector.domTreeManager.nodeForId(layer.nodeId);
 
         this.data = {
-            name: domNode ? WebInspector.displayNameForNode(domNode) : WebInspector.UIString("Unknown node"),
+            name: domNode ? domNode.displayName : WebInspector.UIString("Unknown node"),
             paintCount: layer.paintCount || emDash,
             memory: Number.bytesToString(layer.memory || 0)
         };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleSelectorSection.js (205034 => 205035)


--- trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleSelectorSection.js	2016-08-26 20:22:24 UTC (rev 205034)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/VisualStyleSelectorSection.js	2016-08-26 20:29:17 UTC (rev 205035)
@@ -191,7 +191,7 @@
                     continue;
 
                 if (!divider) {
-                    let dividerText = WebInspector.UIString("Inherited from %s").format(WebInspector.displayNameForNode(inherited.node));
+                    let dividerText = WebInspector.UIString("Inherited from %s").format(inherited.node.displayName);
                     divider = new WebInspector.GeneralTreeElement("section-divider", dividerText);
                     divider.selectable = false;
                     this._selectors.appendChild(divider);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to