<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[193029] branches/safari-601-branch</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/193029">193029</a></dd>
<dt>Author</dt> <dd>timothy@apple.com</dd>
<dt>Date</dt> <dd>2015-12-03 10:33:18 -0800 (Thu, 03 Dec 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/187496">r187496</a>. rdar://problem/23221163</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601branchLayoutTestsChangeLog">branches/safari-601-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceJavaScriptCoreChangeLog">branches/safari-601-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceJavaScriptCoreinspectorprotocolDOMjson">branches/safari-601-branch/Source/JavaScriptCore/inspector/protocol/DOM.json</a></li>
<li><a href="#branchessafari601branchSourceWebCoreChangeLog">branches/safari-601-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceWebCoredomPseudoElementcpp">branches/safari-601-branch/Source/WebCore/dom/PseudoElement.cpp</a></li>
<li><a href="#branchessafari601branchSourceWebCoredomPseudoElementh">branches/safari-601-branch/Source/WebCore/dom/PseudoElement.h</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorCSSAgentcpp">branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorCSSAgenth">branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.h</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorDOMAgentcpp">branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorDOMAgenth">branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.h</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorInstrumentationcpp">branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorInstrumentationh">branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.h</a></li>
<li><a href="#branchessafari601branchSourceWebCoreinspectorInspectorOverlaycpp">branches/safari-601-branch/Source/WebCore/inspector/InspectorOverlay.cpp</a></li>
<li><a href="#branchessafari601branchSourceWebCorestyleStyleResolveTreecpp">branches/safari-601-branch/Source/WebCore/style/StyleResolveTree.cpp</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIChangeLog">branches/safari-601-branch/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceControllersDOMTreeManagerjs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceModelsDOMNodejs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceProtocolDOMObserverjs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsCSSStyleDetailsSidebarPaneljs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementjs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementPathComponentjs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinecss">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinejs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsPathComponentIconscss">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceViewsRulesStyleDetailsPanelcss">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari601branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodeexpectedtxt">branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodehtml">branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectordompseudoelementdynamicexpectedtxt">branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectordompseudoelementdynamichtml">branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectordompseudoelementstaticexpectedtxt">branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectordompseudoelementstatichtml">branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/ChangeLog (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2015-12-01 Timothy Hatcher <timothy@apple.com>
</span><span class="cx">
</span><ins>+ Merge r187496. rdar://problem/23221163
+
+ 2015-07-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Show Pseudo Elements in DOM Tree
+ https://bugs.webkit.org/show_bug.cgi?id=139612
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt: Added.
+ * inspector/css/pseudo-element-matches-for-pseudo-element-node.html: Added.
+ * inspector/dom/pseudo-element-dynamic-expected.txt: Added.
+ * inspector/dom/pseudo-element-dynamic.html: Added.
+ * inspector/dom/pseudo-element-static-expected.txt: Added.
+ * inspector/dom/pseudo-element-static.html: Added.
+
+2015-12-01 Timothy Hatcher <timothy@apple.com>
+
</ins><span class="cx"> Merge r187249. rdar://problem/23221163
</span><span class="cx">
</span><span class="cx"> 2015-07-23 Devin Rousso <drousso@apple.com>
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodeexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt (0 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt         (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+Testing that we can get computed and matched rules for pseudo element nodes.
+
+TEST ELEMENT: Has Before Pseudo Element
+PASS: Got ::before pseudo element for #x
+Refreshing styles for ::before pseudo element
+
+PASS: No Inline Styles
+PASS: No Attribute Styles
+PASS: No Inherited Styles
+PASS: No Pseudo Element Styles
+PASS: Has Computed Styles
+PROPERTY: content: before;
+PROPERTY: color: rgb(0, 0, 255);
+MATCHED RULE:
+ SELECTOR: input:before
+ SELECTOR: #x:before [matched]
+ SELECTOR: div
+
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodehtml"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html (0 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html         (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script>
+function test() {
+ var nodeStyles = null;
+
+ function validateStyles() {
+ InspectorTest.log("");
+
+ InspectorTest.expectThat(!nodeStyles.inlineStyle, "No Inline Styles");
+ InspectorTest.expectThat(!nodeStyles.attributesStyle, "No Attribute Styles");
+ InspectorTest.expectThat(!nodeStyles.inheritedRules.length, "No Inherited Styles");
+ InspectorTest.expectThat(!Object.keys(nodeStyles.pseudoElements).length, "No Pseudo Element Styles");
+
+ InspectorTest.expectThat(nodeStyles.computedStyle, "Has Computed Styles");
+ InspectorTest.log("PROPERTY: " + nodeStyles.computedStyle.propertyForName("content").text);
+ InspectorTest.log("PROPERTY: " + nodeStyles.computedStyle.propertyForName("color").text);
+
+ for (var rule of nodeStyles.matchedRules) {
+ InspectorTest.log("MATCHED RULE:");
+ for (var i = 0; i < rule.selectors.length; ++i) {
+ var selector = rule.selectors[i];
+ var matched = rule.matchedSelectorIndices.includes(i);
+ InspectorTest.log(" SELECTOR: " + selector.text + (matched ? " [matched]" : ""));
+ }
+ }
+
+ InspectorTest.completeTest();
+ }
+
+ WebInspector.domTreeManager.requestDocument(function(documentNode) {
+ WebInspector.domTreeManager.querySelector(documentNode.id, "#x", function(contentNodeId) {
+ var domNode = WebInspector.domTreeManager.nodeForId(contentNodeId);
+ InspectorTest.assert(domNode);
+ var beforePseudoElementDOMNode = domNode.beforePseudoElement();
+ InspectorTest.expectThat(beforePseudoElementDOMNode, "Got ::before pseudo element for #x");
+ InspectorTest.log("Refreshing styles for ::before pseudo element");
+ nodeStyles = WebInspector.cssStyleManager.stylesForNode(beforePseudoElementDOMNode);
+ nodeStyles.addEventListener(WebInspector.DOMNodeStyles.Event.Refreshed, validateStyles);
+ nodeStyles.refresh();
+ });
+ });
+
+}
+</script>
+</head>
+<body onload="runTest()">
+ <p>Testing that we can get computed and matched rules for pseudo element nodes.</p>
+
+ <style>
+ input:before, #x:before, div { content: "before"; color: blue; }
+ </style>
+
+ <div id="x">TEST ELEMENT: Has Before Pseudo Element</div>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectordompseudoelementdynamicexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt (0 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt         (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+Test for dynamic DOMNode pseudo element support, pseudo elements getting added and removed dynamically.
+
+TEST ELEMENT
+
+PASS: Got DOMNode for #x
+PASS: DOMNode has no pseudo elements
+
+Add :before
+EVENT: NodeInserted
+
+Verify :before was added
+PASS: #x DOMNode has pseudo elements
+PASS: DOMNode has 1 pseudo elements
+PASS: DOMNode has a before pseudo element
+PASS: DOMNode does not have an after pseudo element
+PASS: New DOMNode is the beforePseudoElement
+PASS: New DOMNode is a child of #x
+PASS: New DOMNode is a before pseudo element
+
+Remove :before
+EVENT: NodeRemoved
+
+Verify :before was removed
+PASS: #x DOMNode has no pseudo elements
+PASS: Removed DOMNode was the before pseudo element
+PASS: Removed DOMNode has no parent
+PASS: Removed DOMNode was a before pseudo element
+
+Add :after
+EVENT: NodeInserted
+
+Verify :after was added
+PASS: #x DOMNode has pseudo elements
+PASS: DOMNode has 1 pseudo elements
+PASS: DOMNode does not have a before pseudo element
+PASS: DOMNode has an after pseudo element
+PASS: New DOMNode is the afterPseudoElement
+PASS: New DOMNode is a child of #x
+PASS: New DOMNode is an after pseudo element
+
+Remove :after
+EVENT: NodeRemoved
+
+Verify :after was removed
+PASS: #x DOMNode has no pseudo elements
+PASS: Removed DOMNode was the after pseudo element
+PASS: Removed DOMNode has no parent
+PASS: Removed DOMNode was an after pseudo element
+
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectordompseudoelementdynamichtml"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html (0 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html         (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -0,0 +1,156 @@
</span><ins>+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script>
+function test() {
+
+ var testDOMNode = null;
+ var insertedOrRemovedDOMNode = null;
+ var previousInsertedDOMNode = null;
+
+ var steps = [
+ {
+ name: "Add :before",
+ action: function() {
+ InspectorTest.evaluateInPage("document.getElementById('x').classList.add('b')");
+ }
+ },
+ {
+ name: "Verify :before was added",
+ action: function() {
+ InspectorTest.expectThat(testDOMNode.hasPseudoElements(), "#x DOMNode has pseudo elements");
+ InspectorTest.expectThat(testDOMNode.pseudoElements().size === 1, "DOMNode has 1 pseudo elements");
+ InspectorTest.expectThat(testDOMNode.beforePseudoElement(), "DOMNode has a before pseudo element");
+ InspectorTest.expectThat(!testDOMNode.afterPseudoElement(), "DOMNode does not have an after pseudo element");
+
+ InspectorTest.expectThat(insertedOrRemovedDOMNode === testDOMNode.beforePseudoElement(), "New DOMNode is the beforePseudoElement");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === testDOMNode, "New DOMNode is a child of #x");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, "New DOMNode is a before pseudo element");
+
+ previousInsertedDOMNode = insertedOrRemovedDOMNode;
+ next();
+ }
+ },
+ {
+ name: "Remove :before",
+ action: function() {
+ InspectorTest.evaluateInPage("document.getElementById('x').classList.remove('b')");
+ }
+ },
+ {
+ name: "Verify :before was removed",
+ action: function() {
+ InspectorTest.expectThat(!testDOMNode.hasPseudoElements(), "#x DOMNode has no pseudo elements");
+ InspectorTest.assert(testDOMNode.pseudoElements().size === 0);
+ InspectorTest.assert(!testDOMNode.beforePseudoElement());
+ InspectorTest.assert(!testDOMNode.afterPseudoElement());
+
+ InspectorTest.expectThat(insertedOrRemovedDOMNode === previousInsertedDOMNode, "Removed DOMNode was the before pseudo element");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === null, "Removed DOMNode has no parent");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, "Removed DOMNode was a before pseudo element");
+
+ previousInsertedDOMNode = null;
+ next();
+ }
+ },
+ {
+ name: "Add :after",
+ action: function() {
+ InspectorTest.evaluateInPage("document.getElementById('x').classList.add('a')");
+ }
+ },
+ {
+ name: "Verify :after was added",
+ action: function() {
+ InspectorTest.expectThat(testDOMNode.hasPseudoElements(), "#x DOMNode has pseudo elements");
+ InspectorTest.expectThat(testDOMNode.pseudoElements().size === 1, "DOMNode has 1 pseudo elements");
+ InspectorTest.expectThat(!testDOMNode.beforePseudoElement(), "DOMNode does not have a before pseudo element");
+ InspectorTest.expectThat(testDOMNode.afterPseudoElement(), "DOMNode has an after pseudo element");
+
+ InspectorTest.expectThat(insertedOrRemovedDOMNode === testDOMNode.afterPseudoElement(), "New DOMNode is the afterPseudoElement");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === testDOMNode, "New DOMNode is a child of #x");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.After, "New DOMNode is an after pseudo element");
+
+ previousInsertedDOMNode = insertedOrRemovedDOMNode;
+ next();
+ }
+ },
+ {
+ name: "Remove :after",
+ action: function() {
+ InspectorTest.evaluateInPage("document.getElementById('x').classList.remove('a')");
+ }
+ },
+ {
+ name: "Verify :after was removed",
+ action: function() {
+ InspectorTest.expectThat(!testDOMNode.hasPseudoElements(), "#x DOMNode has no pseudo elements");
+ InspectorTest.assert(testDOMNode.pseudoElements().size === 0);
+ InspectorTest.assert(!testDOMNode.beforePseudoElement());
+ InspectorTest.assert(!testDOMNode.afterPseudoElement());
+
+ InspectorTest.expectThat(insertedOrRemovedDOMNode === previousInsertedDOMNode, "Removed DOMNode was the after pseudo element");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === null, "Removed DOMNode has no parent");
+ InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.After, "Removed DOMNode was an after pseudo element");
+
+ previousInsertedDOMNode = null;
+ next();
+ }
+ },
+ ];
+
+ function next()
+ {
+ var step = steps.shift();
+ if (step) {
+ InspectorTest.log("");
+ InspectorTest.log(step.name);
+ step.action();
+ return;
+ }
+ InspectorTest.completeTest();
+ }
+
+ WebInspector.domTreeManager.requestDocument(function(documentNode) {
+ WebInspector.domTreeManager.querySelector(documentNode.id, "#x", function(nodeId) {
+ testDOMNode = WebInspector.domTreeManager.nodeForId(nodeId);
+ InspectorTest.log("");
+ InspectorTest.expectThat(testDOMNode, "Got DOMNode for #x");
+ InspectorTest.assert(!testDOMNode.pseudoType());
+ InspectorTest.expectThat(!testDOMNode.hasPseudoElements(), "DOMNode has no pseudo elements");
+ InspectorTest.assert(testDOMNode.pseudoElements().size === 0);
+ InspectorTest.assert(!testDOMNode.beforePseudoElement());
+ InspectorTest.assert(!testDOMNode.afterPseudoElement());
+ next();
+ });
+ });
+
+ WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.NodeInserted, function(event) {
+ // Test logging will add nodes to the test page. Ignore any elements added that are not children of our test node.
+ if (event.data.parent !== testDOMNode)
+ return;
+
+ InspectorTest.log("EVENT: NodeInserted");
+ insertedOrRemovedDOMNode = event.data.node;
+ next();
+ });
+
+ WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.NodeRemoved, function(event) {
+ InspectorTest.log("EVENT: NodeRemoved");
+ insertedOrRemovedDOMNode = event.data.node;
+ next();
+ });
+}
+</script>
+</head>
+<body onload="runTest()">
+ <p>Test for dynamic DOMNode pseudo element support, pseudo elements getting added and removed dynamically.</p>
+
+ <style>
+ .b:before { content: "before"; }
+ .a:after { content: "after"; }
+ </style>
+
+ <div id="x">TEST ELEMENT</div>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectordompseudoelementstaticexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt (0 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt         (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+Test for basic DOMNode pseudo element support.
+
+TEST ELEMENT: No Pseudo Elements
+TEST ELEMENT: Has Before Pseudo Element
+TEST ELEMENT: Has After Pseudo Element
+TEST ELEMENT: Has Before and After Pseudo Elements
+
+PASS: Got DOMNode for #none
+PASS: DOMNode has no pseudo elements
+
+PASS: Got DOMNode for #b
+PASS: DOMNode has pseudo elements
+PASS: DOMNode has 1 pseudo elements
+PASS: DOMNode has a before pseudo element
+PASS: DOMNode does not have an after pseudo element
+PASS: DOMNode for before pseudo element has the right type
+
+PASS: Got DOMNode for #a
+PASS: DOMNode has pseudo elements
+PASS: DOMNode has 1 pseudo elements
+PASS: DOMNode does not have a before pseudo element
+PASS: DOMNode has an after pseudo element
+PASS: DOMNode for after pseudo element has the right type
+
+PASS: Got DOMNode for #x
+PASS: DOMNode has pseudo elements
+PASS: DOMNode has 2 pseudo elements
+PASS: DOMNode has a before pseudo element
+PASS: DOMNode has an after pseudo element
+PASS: DOMNode for before pseudo element has the right type
+PASS: DOMNode for after pseudo element has the right type
+
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectordompseudoelementstatichtml"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static.html (0 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static.html         (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/dom/pseudo-element-static.html        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script>
+function test() {
+ WebInspector.domTreeManager.requestDocument(function(documentNode) {
+ WebInspector.domTreeManager.querySelector(documentNode.id, "#none", function(nodeId) {
+ var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+ InspectorTest.log("");
+ InspectorTest.expectThat(domNode, "Got DOMNode for #none");
+ InspectorTest.assert(!domNode.pseudoType());
+ InspectorTest.expectThat(!domNode.hasPseudoElements(), "DOMNode has no pseudo elements");
+ InspectorTest.assert(domNode.pseudoElements().size === 0);
+ InspectorTest.assert(!domNode.beforePseudoElement());
+ InspectorTest.assert(!domNode.afterPseudoElement());
+ });
+
+ WebInspector.domTreeManager.querySelector(documentNode.id, "#b", function(nodeId) {
+ var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+ InspectorTest.log("");
+ InspectorTest.expectThat(domNode, "Got DOMNode for #b");
+ InspectorTest.assert(!domNode.pseudoType());
+ InspectorTest.expectThat(domNode.hasPseudoElements(), "DOMNode has pseudo elements");
+ InspectorTest.expectThat(domNode.pseudoElements().size === 1, "DOMNode has 1 pseudo elements");
+ InspectorTest.expectThat(domNode.beforePseudoElement(), "DOMNode has a before pseudo element");
+ InspectorTest.expectThat(!domNode.afterPseudoElement(), "DOMNode does not have an after pseudo element");
+ InspectorTest.expectThat(domNode.beforePseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, "DOMNode for before pseudo element has the right type");
+ });
+
+ WebInspector.domTreeManager.querySelector(documentNode.id, "#a", function(nodeId) {
+ var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+ InspectorTest.log("");
+ InspectorTest.expectThat(domNode, "Got DOMNode for #a");
+ InspectorTest.assert(!domNode.pseudoType());
+ InspectorTest.expectThat(domNode.hasPseudoElements(), "DOMNode has pseudo elements");
+ InspectorTest.expectThat(domNode.pseudoElements().size === 1, "DOMNode has 1 pseudo elements");
+ InspectorTest.expectThat(!domNode.beforePseudoElement(), "DOMNode does not have a before pseudo element");
+ InspectorTest.expectThat(domNode.afterPseudoElement(), "DOMNode has an after pseudo element");
+ InspectorTest.expectThat(domNode.afterPseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.After, "DOMNode for after pseudo element has the right type");
+ });
+
+ WebInspector.domTreeManager.querySelector(documentNode.id, "#x", function(nodeId) {
+ var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+ InspectorTest.log("");
+ InspectorTest.expectThat(domNode, "Got DOMNode for #x");
+ InspectorTest.assert(!domNode.pseudoType());
+ InspectorTest.expectThat(domNode.hasPseudoElements(), "DOMNode has pseudo elements");
+ InspectorTest.expectThat(domNode.pseudoElements().size === 2, "DOMNode has 2 pseudo elements");
+ InspectorTest.expectThat(domNode.beforePseudoElement(), "DOMNode has a before pseudo element");
+ InspectorTest.expectThat(domNode.afterPseudoElement(), "DOMNode has an after pseudo element");
+ InspectorTest.expectThat(domNode.beforePseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, "DOMNode for before pseudo element has the right type");
+ InspectorTest.expectThat(domNode.afterPseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.After, "DOMNode for after pseudo element has the right type");
+ InspectorTest.completeTest();
+ });
+ });
+}
+</script>
+</head>
+<body onload="runTest()">
+ <p>Test for basic DOMNode pseudo element support.</p>
+
+ <style>
+ #x:before, #b:before { content: "before"; }
+ #x:after, #a:after { content: "after"; }
+ </style>
+
+ <div id="none">TEST ELEMENT: No Pseudo Elements</div>
+ <div id="b">TEST ELEMENT: Has Before Pseudo Element</div>
+ <div id="a">TEST ELEMENT: Has After Pseudo Element</div>
+ <div id="x">TEST ELEMENT: Has Before and After Pseudo Elements</div>
+
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari601branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/JavaScriptCore/ChangeLog (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/JavaScriptCore/ChangeLog        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/JavaScriptCore/ChangeLog        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -1,5 +1,21 @@
</span><span class="cx"> 2015-12-01 Timothy Hatcher <timothy@apple.com>
</span><span class="cx">
</span><ins>+ Merge r187496. rdar://problem/23221163
+
+ 2015-07-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Show Pseudo Elements in DOM Tree
+ https://bugs.webkit.org/show_bug.cgi?id=139612
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/protocol/DOM.json:
+ Add new properties to DOMNode if it is a pseudo element or if it has
+ pseudo element children. Add new events for if a pseudo element is
+ added or removed dynamically to an existing DOMNode.
+
+2015-12-01 Timothy Hatcher <timothy@apple.com>
+
</ins><span class="cx"> Merge r187249. rdar://problem/23221163
</span><span class="cx">
</span><span class="cx"> 2015-07-23 Devin Rousso <drousso@apple.com>
</span></span></pre></div>
<a id="branchessafari601branchSourceJavaScriptCoreinspectorprotocolDOMjson"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/JavaScriptCore/inspector/protocol/DOM.json (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/JavaScriptCore/inspector/protocol/DOM.json        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/JavaScriptCore/inspector/protocol/DOM.json        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -14,6 +14,12 @@
</span><span class="cx"> "description": "Unique DOM node identifier used to reference a node that may not have been pushed to the front-end."
</span><span class="cx"> },
</span><span class="cx"> {
</span><ins>+ "id": "PseudoType",
+ "type": "string",
+ "enum": ["before", "after"],
+ "description": "Pseudo element type."
+ },
+ {
</ins><span class="cx"> "id": "LiveRegionRelevant",
</span><span class="cx"> "type": "string",
</span><span class="cx"> "enum": ["additions", "removals", "text"],
</span><span class="lines">@@ -39,10 +45,12 @@
</span><span class="cx"> { "name": "xmlVersion", "type": "string", "optional": true, "description": "<code>Document</code>'s XML version in case of XML documents." },
</span><span class="cx"> { "name": "name", "type": "string", "optional": true, "description": "<code>Attr</code>'s name." },
</span><span class="cx"> { "name": "value", "type": "string", "optional": true, "description": "<code>Attr</code>'s value." },
</span><ins>+ { "name": "pseudoType", "$ref": "PseudoType", "optional": true, "description": "Pseudo element type for this node." },
</ins><span class="cx"> { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Frame ID for frame owner elements." },
</span><span class="cx"> { "name": "contentDocument", "$ref": "Node", "optional": true, "description": "Content document for frame owner elements." },
</span><span class="cx"> { "name": "shadowRoots", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Shadow root list for given element host." },
</span><span class="cx"> { "name": "templateContent", "$ref": "Node", "optional": true, "description": "Content document fragment for template elements" },
</span><ins>+ { "name": "pseudoElements", "type": "array", "items": { "$ref": "Node" }, "optional": true, "description": "Pseudo elements associated with this node." },
</ins><span class="cx"> { "name": "role", "type": "string", "optional": true, "description": "Computed value for first recognized role token, default role per element, or overridden role." }
</span><span class="cx"> ],
</span><span class="cx"> "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type."
</span><span class="lines">@@ -526,6 +534,22 @@
</span><span class="cx"> { "name": "rootId", "$ref": "NodeId", "description": "Shadow root id." }
</span><span class="cx"> ],
</span><span class="cx"> "description": "Called when shadow root is popped from the element."
</span><ins>+ },
+ {
+ "name": "pseudoElementAdded",
+ "parameters": [
+ { "name": "parentId", "$ref": "NodeId", "description": "Pseudo element's parent element id." },
+ { "name": "pseudoElement", "$ref": "Node", "description": "The added pseudo element." }
+ ],
+ "description": "Called when a pseudo element is added to an element."
+ },
+ {
+ "name": "pseudoElementRemoved",
+ "parameters": [
+ { "name": "parentId", "$ref": "NodeId", "description": "Pseudo element's parent element id." },
+ { "name": "pseudoElementId", "$ref": "NodeId", "description": "The removed pseudo element id." }
+ ],
+ "description": "Called when a pseudo element is removed from an element."
</ins><span class="cx"> }
</span><span class="cx"> ]
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/ChangeLog (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/ChangeLog        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/ChangeLog        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -1,5 +1,84 @@
</span><span class="cx"> 2015-12-01 Timothy Hatcher <timothy@apple.com>
</span><span class="cx">
</span><ins>+ Merge r187496. rdar://problem/23221163
+
+ 2015-07-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Show Pseudo Elements in DOM Tree
+ https://bugs.webkit.org/show_bug.cgi?id=139612
+
+ Reviewed by Timothy Hatcher.
+
+ Tests: inspector/css/pseudo-element-matches-for-pseudo-element-node.html
+ inspector/dom/pseudo-element-dynamic.html
+ inspector/dom/pseudo-element-static.html
+
+ Much of this patch was modelled after the Blink implementation of
+ pseudo element inspection.
+
+ * dom/PseudoElement.h:
+ * dom/PseudoElement.cpp:
+ (WebCore::PseudoElement::~PseudoElement):
+ (WebCore::PseudoElement::clearHostElement):
+ Since InspectorDOMAgent may hold a reference to this PseudoElement we
+ can't report it as destroyed in the destructor, as that wouldn't be
+ reached if the inspector holds a reference. Move this to when the
+ psuedo element is disconnected, which is immediately before destruction.
+
+ * inspector/InspectorCSSAgent.h:
+ * inspector/InspectorCSSAgent.cpp:
+ (WebCore::InspectorCSSAgent::getMatchedStylesForNode):
+ When computing styles for a pseudo element, compute styles from the
+ host element for just the pseudo element's pseudo type. Likewise
+ only include matched results, not inherited or others.
+
+ (WebCore::InspectorCSSAgent::buildArrayForMatchedRuleList):
+ Add the pseudo type to the checker context to try and detect exactly
+ which selector in a list of selectors matched the pseudo element.
+
+ * inspector/InspectorDOMAgent.h:
+ * inspector/InspectorDOMAgent.cpp:
+ (WebCore::InspectorDOMAgent::unbind):
+ When unbinding an element, also unbind any pseudo element children
+ it may have had and bound.
+
+ (WebCore::InspectorDOMAgent::assertEditableNode):
+ (WebCore::InspectorDOMAgent::assertEditableElement):
+ (WebCore::InspectorDOMAgent::removeNode):
+ Improve grammar in error message. Don't allow editing pseudo elements.
+
+ (WebCore::pseudoElementType):
+ (WebCore::InspectorDOMAgent::buildObjectForNode):
+ (WebCore::InspectorDOMAgent::buildArrayForPseudoElements):
+ If a node is a pseudo element include its pseudoType.
+ If a node has pseudo element children include them.
+
+ (WebCore::InspectorDOMAgent::pseudoElementCreated):
+ (WebCore::InspectorDOMAgent::pseudoElementDestroyed):
+ When pseudo elements are dynamically created or destroyed
+ push pseudo element nodes to the frontend if needed.
+
+ * inspector/InspectorInstrumentation.cpp:
+ (WebCore::InspectorInstrumentation::pseudoElementCreatedImpl):
+ (WebCore::InspectorInstrumentation::pseudoElementDestroyedImpl):
+ * inspector/InspectorInstrumentation.h:
+ (WebCore::InspectorInstrumentation::pseudoElementCreated):
+ (WebCore::InspectorInstrumentation::pseudoElementDestroyed):
+ (WebCore::InspectorInstrumentation::layerTreeDidChange):
+ (WebCore::InspectorInstrumentation::renderLayerDestroyed):
+ Plumbing for pseudo element created/destroyed events.
+
+ * style/StyleResolveTree.cpp:
+ (WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded):
+ This is the only place a pseudo element is created, inform the inspector.
+
+ * inspector/InspectorOverlay.cpp:
+ (WebCore::buildObjectForElementData):
+ Update the element data for the node highlight label to include the
+ host element's selector and the pseudo element selector.
+
+2015-12-01 Timothy Hatcher <timothy@apple.com>
+
</ins><span class="cx"> Merge r187249. rdar://problem/23221163
</span><span class="cx">
</span><span class="cx"> 2015-07-23 Devin Rousso <drousso@apple.com>
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoredomPseudoElementcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/dom/PseudoElement.cpp (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/dom/PseudoElement.cpp        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/dom/PseudoElement.cpp        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -67,7 +67,13 @@
</span><span class="cx"> PseudoElement::~PseudoElement()
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!m_hostElement);
</span><ins>+}
+
+void PseudoElement::clearHostElement()
+{
</ins><span class="cx"> InspectorInstrumentation::pseudoElementDestroyed(document().page(), *this);
</span><ins>+
+ m_hostElement = nullptr;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RefPtr<RenderStyle> PseudoElement::customStyleForRenderer(RenderStyle& parentStyle)
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoredomPseudoElementh"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/dom/PseudoElement.h (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/dom/PseudoElement.h        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/dom/PseudoElement.h        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx"> virtual ~PseudoElement();
</span><span class="cx">
</span><span class="cx"> Element* hostElement() const { return m_hostElement; }
</span><del>- void clearHostElement() { m_hostElement = nullptr; }
</del><ins>+ void clearHostElement();
</ins><span class="cx">
</span><span class="cx"> virtual RefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
</span><span class="cx"> virtual void didAttachRenderers() override;
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorCSSAgentcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include "NamedFlowCollection.h"
</span><span class="cx"> #include "Node.h"
</span><span class="cx"> #include "NodeList.h"
</span><ins>+#include "PseudoElement.h"
</ins><span class="cx"> #include "RenderNamedFlowFragment.h"
</span><span class="cx"> #include "SVGStyleElement.h"
</span><span class="cx"> #include "SelectorChecker.h"
</span><span class="lines">@@ -510,49 +511,60 @@
</span><span class="cx"> if (!element)
</span><span class="cx"> return;
</span><span class="cx">
</span><ins>+ Element* originalElement = element;
+ PseudoId elementPseudoId = element->pseudoId();
+ if (elementPseudoId) {
+ element = downcast<PseudoElement>(*element).hostElement();
+ if (!element) {
+ errorString = ASCIILiteral("Pseudo element has no parent");
+ return;
+ }
+ }
+
</ins><span class="cx"> // Matched rules.
</span><span class="cx"> StyleResolver& styleResolver = element->document().ensureStyleResolver();
</span><del>- auto matchedRules = styleResolver.styleRulesForElement(element, StyleResolver::AllCSSRules);
- matchedCSSRules = buildArrayForMatchedRuleList(matchedRules, styleResolver, element);
</del><ins>+ auto matchedRules = styleResolver.pseudoStyleRulesForElement(element, elementPseudoId, StyleResolver::AllCSSRules);
+ matchedCSSRules = buildArrayForMatchedRuleList(matchedRules, styleResolver, element, elementPseudoId);
</ins><span class="cx">
</span><del>- // Pseudo elements.
- if (!includePseudo || *includePseudo) {
- auto pseudoElements = Inspector::Protocol::Array<Inspector::Protocol::CSS::PseudoIdMatches>::create();
- for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
- auto matchedRules = styleResolver.pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
- if (!matchedRules.isEmpty()) {
- auto matches = Inspector::Protocol::CSS::PseudoIdMatches::create()
- .setPseudoId(static_cast<int>(pseudoId))
- .setMatches(buildArrayForMatchedRuleList(matchedRules, styleResolver, element))
- .release();
- pseudoElements->addItem(WTF::move(matches));
</del><ins>+ if (!originalElement->isPseudoElement()) {
+ // Pseudo elements.
+ if (!includePseudo || *includePseudo) {
+ auto pseudoElements = Inspector::Protocol::Array<Inspector::Protocol::CSS::PseudoIdMatches>::create();
+ for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
+ auto matchedRules = styleResolver.pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
+ if (!matchedRules.isEmpty()) {
+ auto matches = Inspector::Protocol::CSS::PseudoIdMatches::create()
+ .setPseudoId(static_cast<int>(pseudoId))
+ .setMatches(buildArrayForMatchedRuleList(matchedRules, styleResolver, element, pseudoId))
+ .release();
+ pseudoElements->addItem(WTF::move(matches));
+ }
</ins><span class="cx"> }
</span><ins>+
+ pseudoIdMatches = WTF::move(pseudoElements);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- pseudoIdMatches = WTF::move(pseudoElements);
- }
</del><ins>+ // Inherited styles.
+ if (!includeInherited || *includeInherited) {
+ auto entries = Inspector::Protocol::Array<Inspector::Protocol::CSS::InheritedStyleEntry>::create();
+ Element* parentElement = element->parentElement();
+ while (parentElement) {
+ StyleResolver& parentStyleResolver = parentElement->document().ensureStyleResolver();
+ auto parentMatchedRules = parentStyleResolver.styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
+ auto entry = Inspector::Protocol::CSS::InheritedStyleEntry::create()
+ .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules, styleResolver, parentElement, NOPSEUDO))
+ .release();
+ if (parentElement->style() && parentElement->style()->length()) {
+ if (InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement))
+ entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
+ }
</ins><span class="cx">
</span><del>- // Inherited styles.
- if (!includeInherited || *includeInherited) {
- auto entries = Inspector::Protocol::Array<Inspector::Protocol::CSS::InheritedStyleEntry>::create();
- Element* parentElement = element->parentElement();
- while (parentElement) {
- StyleResolver& parentStyleResolver = parentElement->document().ensureStyleResolver();
- auto parentMatchedRules = parentStyleResolver.styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
- auto entry = Inspector::Protocol::CSS::InheritedStyleEntry::create()
- .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules, styleResolver, parentElement))
- .release();
- if (parentElement->style() && parentElement->style()->length()) {
- InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
- if (styleSheet)
- entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
</del><ins>+ entries->addItem(WTF::move(entry));
+ parentElement = parentElement->parentElement();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- entries->addItem(WTF::move(entry));
- parentElement = parentElement->parentElement();
</del><ins>+ inheritedEntries = WTF::move(entries);
</ins><span class="cx"> }
</span><del>-
- inheritedEntries = WTF::move(entries);
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -924,11 +936,12 @@
</span><span class="cx"> return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(rule, nullptr) : nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::RuleMatch>> InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector<RefPtr<StyleRule>>& matchedRules, StyleResolver& styleResolver, Element* element)
</del><ins>+RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::RuleMatch>> InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector<RefPtr<StyleRule>>& matchedRules, StyleResolver& styleResolver, Element* element, PseudoId psuedoId)
</ins><span class="cx"> {
</span><span class="cx"> auto result = Inspector::Protocol::Array<Inspector::Protocol::CSS::RuleMatch>::create();
</span><span class="cx">
</span><span class="cx"> SelectorChecker::CheckingContext context(SelectorChecker::Mode::CollectingRules);
</span><ins>+ context.pseudoId = psuedoId ? psuedoId : element->pseudoId();
</ins><span class="cx"> SelectorChecker selectorChecker(element->document());
</span><span class="cx">
</span><span class="cx"> for (auto& matchedRule : matchedRules) {
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorCSSAgenth"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.h (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.h        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorCSSAgent.h        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -149,7 +149,7 @@
</span><span class="cx">
</span><span class="cx"> RefPtr<Inspector::Protocol::CSS::CSSRule> buildObjectForRule(StyleRule*, StyleResolver&, Element*);
</span><span class="cx"> RefPtr<Inspector::Protocol::CSS::CSSRule> buildObjectForRule(CSSStyleRule*);
</span><del>- RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::RuleMatch>> buildArrayForMatchedRuleList(const Vector<RefPtr<StyleRule>>&, StyleResolver&, Element*);
</del><ins>+ RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::RuleMatch>> buildArrayForMatchedRuleList(const Vector<RefPtr<StyleRule>>&, StyleResolver&, Element*, PseudoId);
</ins><span class="cx"> RefPtr<Inspector::Protocol::CSS::CSSStyle> buildObjectForAttributesStyle(Element*);
</span><span class="cx"> RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::Region>> buildArrayForRegions(ErrorString&, RefPtr<NodeList>&&, int documentNodeId);
</span><span class="cx"> RefPtr<Inspector::Protocol::CSS::NamedFlow> buildObjectForNamedFlow(ErrorString&, WebKitNamedFlow*, int documentNodeId);
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorDOMAgentcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -75,6 +75,7 @@
</span><span class="cx"> #include "NodeList.h"
</span><span class="cx"> #include "Page.h"
</span><span class="cx"> #include "Pasteboard.h"
</span><ins>+#include "PseudoElement.h"
</ins><span class="cx"> #include "RenderStyle.h"
</span><span class="cx"> #include "RenderStyleConstants.h"
</span><span class="cx"> #include "ScriptState.h"
</span><span class="lines">@@ -332,8 +333,13 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (is<Element>(*node)) {
</span><del>- if (ShadowRoot* root = downcast<Element>(*node).shadowRoot())
</del><ins>+ Element& element = downcast<Element>(*node);
+ if (ShadowRoot* root = element.shadowRoot())
</ins><span class="cx"> unbind(root, nodesMap);
</span><ins>+ if (PseudoElement* beforeElement = element.beforePseudoElement())
+ unbind(beforeElement, nodesMap);
+ if (PseudoElement* afterElement = element.afterPseudoElement())
+ unbind(afterElement, nodesMap);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> nodesMap->remove(node);
</span><span class="lines">@@ -392,9 +398,13 @@
</span><span class="cx"> if (!node)
</span><span class="cx"> return nullptr;
</span><span class="cx"> if (node->isInShadowTree()) {
</span><del>- errorString = ASCIILiteral("Can not edit nodes from shadow trees");
</del><ins>+ errorString = ASCIILiteral("Cannot edit nodes from shadow trees");
</ins><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><ins>+ if (node->isPseudoElement()) {
+ errorString = ASCIILiteral("Cannot edit pseudo elements");
+ return nullptr;
+ }
</ins><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -404,9 +414,13 @@
</span><span class="cx"> if (!element)
</span><span class="cx"> return nullptr;
</span><span class="cx"> if (element->isInShadowTree()) {
</span><del>- errorString = ASCIILiteral("Can not edit elements from shadow trees");
</del><ins>+ errorString = ASCIILiteral("Cannot edit elements from shadow trees");
</ins><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><ins>+ if (element->isPseudoElement()) {
+ errorString = ASCIILiteral("Cannot edit pseudo elements");
+ return nullptr;
+ }
</ins><span class="cx"> return element;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -698,7 +712,7 @@
</span><span class="cx">
</span><span class="cx"> ContainerNode* parentNode = node->parentNode();
</span><span class="cx"> if (!parentNode) {
</span><del>- errorString = ASCIILiteral("Can not remove detached node");
</del><ins>+ errorString = ASCIILiteral("Cannot remove detached node");
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1254,6 +1268,20 @@
</span><span class="cx"> return document->completeURL("").string();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static bool pseudoElementType(PseudoId pseudoId, Inspector::Protocol::DOM::PseudoType* type)
+{
+ switch (pseudoId) {
+ case BEFORE:
+ *type = Inspector::Protocol::DOM::PseudoType::Before;
+ return true;
+ case AFTER:
+ *type = Inspector::Protocol::DOM::PseudoType::After;
+ return true;
+ default:
+ return false;
+ }
+}
+
</ins><span class="cx"> Ref<Inspector::Protocol::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
</span><span class="cx"> {
</span><span class="cx"> int id = bind(node, nodesMap);
</span><span class="lines">@@ -1327,6 +1355,15 @@
</span><span class="cx"> value->setTemplateContent(buildObjectForNode(downcast<HTMLTemplateElement>(element).content(), 0, nodesMap));
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ if (element.pseudoId()) {
+ Inspector::Protocol::DOM::PseudoType pseudoType;
+ if (pseudoElementType(element.pseudoId(), &pseudoType))
+ value->setPseudoType(pseudoType);
+ } else {
+ if (auto pseudoElements = buildArrayForPseudoElements(element, nodesMap))
+ value->setPseudoElements(WTF::move(pseudoElements));
+ }
+
</ins><span class="cx"> } else if (is<Document>(*node)) {
</span><span class="cx"> Document& document = downcast<Document>(*node);
</span><span class="cx"> value->setFrameId(m_pageAgent->frameId(document.frame()));
</span><span class="lines">@@ -1394,6 +1431,21 @@
</span><span class="cx"> return WTF::move(children);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> InspectorDOMAgent::buildArrayForPseudoElements(const Element& element, NodeToIdMap* nodesMap)
+{
+ PseudoElement* beforeElement = element.beforePseudoElement();
+ PseudoElement* afterElement = element.afterPseudoElement();
+ if (!beforeElement && !afterElement)
+ return nullptr;
+
+ auto pseudoElements = Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>::create();
+ if (beforeElement)
+ pseudoElements->addItem(buildObjectForNode(beforeElement, 0, nodesMap));
+ if (afterElement)
+ pseudoElements->addItem(buildObjectForNode(afterElement, 0, nodesMap));
+ return WTF::move(pseudoElements);
+}
+
</ins><span class="cx"> Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<EventListener> eventListener = registeredEventListener.listener;
</span><span class="lines">@@ -1957,6 +2009,36 @@
</span><span class="cx"> setDocument(document);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void InspectorDOMAgent::pseudoElementCreated(PseudoElement& pseudoElement)
+{
+ Element* parent = pseudoElement.hostElement();
+ if (!parent)
+ return;
+
+ int parentId = m_documentNodeToIdMap.get(parent);
+ if (!parentId)
+ return;
+
+ pushChildNodesToFrontend(parentId, 1);
+ m_frontendDispatcher->pseudoElementAdded(parentId, buildObjectForNode(&pseudoElement, 0, &m_documentNodeToIdMap));
+}
+
+void InspectorDOMAgent::pseudoElementDestroyed(PseudoElement& pseudoElement)
+{
+ int pseudoElementId = m_documentNodeToIdMap.get(&pseudoElement);
+ if (!pseudoElementId)
+ return;
+
+ // If a PseudoElement is bound, its parent element must have been bound.
+ Element* parent = pseudoElement.hostElement();
+ ASSERT(parent);
+ int parentId = m_documentNodeToIdMap.get(parent);
+ ASSERT(parentId);
+
+ unbind(&pseudoElement, &m_documentNodeToIdMap);
+ m_frontendDispatcher->pseudoElementRemoved(parentId, pseudoElementId);
+}
+
</ins><span class="cx"> Node* InspectorDOMAgent::nodeForPath(const String& path)
</span><span class="cx"> {
</span><span class="cx"> // The path is of form "1,HTML,2,BODY,1,DIV"
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorDOMAgenth"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.h (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.h        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorDOMAgent.h        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -169,6 +169,8 @@
</span><span class="cx"> bool handleTouchEvent(Node&);
</span><span class="cx"> void didCommitLoad(Document*);
</span><span class="cx"> void frameDocumentUpdated(Frame*);
</span><ins>+ void pseudoElementCreated(PseudoElement&);
+ void pseudoElementDestroyed(PseudoElement&);
</ins><span class="cx">
</span><span class="cx"> // Callbacks that don't directly correspond to an instrumentation entry point.
</span><span class="cx"> void setDocument(Document*);
</span><span class="lines">@@ -233,6 +235,7 @@
</span><span class="cx"> Ref<Inspector::Protocol::DOM::Node> buildObjectForNode(Node*, int depth, NodeToIdMap*);
</span><span class="cx"> Ref<Inspector::Protocol::Array<String>> buildArrayForElementAttributes(Element*);
</span><span class="cx"> Ref<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap);
</span><ins>+ RefPtr<Inspector::Protocol::Array<Inspector::Protocol::DOM::Node>> buildArrayForPseudoElements(const Element&, NodeToIdMap* nodesMap);
</ins><span class="cx"> Ref<Inspector::Protocol::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, const AtomicString& eventType, Node*, const String* objectGroupId);
</span><span class="cx"> RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> buildObjectForAccessibilityProperties(Node*);
</span><span class="cx"> void processAccessibilityChildren(RefPtr<AccessibilityObject>&&, RefPtr<Inspector::Protocol::Array<int>>&&);
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorInstrumentationcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -208,6 +208,20 @@
</span><span class="cx"> domAgent->willPopShadowRoot(host, root);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void InspectorInstrumentation::pseudoElementCreatedImpl(InstrumentingAgents& instrumentingAgents, PseudoElement& pseudoElement)
+{
+ if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent())
+ domAgent->pseudoElementCreated(pseudoElement);
+}
+
+void InspectorInstrumentation::pseudoElementDestroyedImpl(InstrumentingAgents& instrumentingAgents, PseudoElement& pseudoElement)
+{
+ if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent())
+ domAgent->pseudoElementDestroyed(pseudoElement);
+ if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents.inspectorLayerTreeAgent())
+ layerTreeAgent->pseudoElementDestroyed(pseudoElement);
+}
+
</ins><span class="cx"> void InspectorInstrumentation::didCreateNamedFlowImpl(InstrumentingAgents& instrumentingAgents, Document* document, WebKitNamedFlow& namedFlow)
</span><span class="cx"> {
</span><span class="cx"> if (!document)
</span><span class="lines">@@ -1287,10 +1301,4 @@
</span><span class="cx"> layerTreeAgent->renderLayerDestroyed(renderLayer);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void InspectorInstrumentation::pseudoElementDestroyedImpl(InstrumentingAgents& instrumentingAgents, PseudoElement& pseudoElement)
-{
- if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents.inspectorLayerTreeAgent())
- layerTreeAgent->pseudoElementDestroyed(pseudoElement);
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorInstrumentationh"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.h (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.h        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorInstrumentation.h        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -75,9 +75,9 @@
</span><span class="cx"> class DOMWrapperWorld;
</span><span class="cx"> class Database;
</span><span class="cx"> class Document;
</span><del>-class Element;
</del><span class="cx"> class DocumentLoader;
</span><span class="cx"> class DocumentStyleSheetCollection;
</span><ins>+class Element;
</ins><span class="cx"> class GraphicsContext;
</span><span class="cx"> class HTTPHeaderMap;
</span><span class="cx"> class InspectorCSSAgent;
</span><span class="lines">@@ -85,7 +85,6 @@
</span><span class="cx"> class InspectorInstrumentation;
</span><span class="cx"> class InspectorTimelineAgent;
</span><span class="cx"> class InstrumentingAgents;
</span><del>-class URL;
</del><span class="cx"> class Node;
</span><span class="cx"> class PseudoElement;
</span><span class="cx"> class RenderLayer;
</span><span class="lines">@@ -100,6 +99,7 @@
</span><span class="cx"> class StyleResolver;
</span><span class="cx"> class StyleRule;
</span><span class="cx"> class ThreadableLoaderClient;
</span><ins>+class URL;
</ins><span class="cx"> class WorkerGlobalScope;
</span><span class="cx"> class WorkerGlobalScopeProxy;
</span><span class="cx"> class XMLHttpRequest;
</span><span class="lines">@@ -126,6 +126,8 @@
</span><span class="cx"> static void mediaQueryResultChanged(Document&);
</span><span class="cx"> static void didPushShadowRoot(Element& host, ShadowRoot&);
</span><span class="cx"> static void willPopShadowRoot(Element& host, ShadowRoot&);
</span><ins>+ static void pseudoElementCreated(Page*, PseudoElement&);
+ static void pseudoElementDestroyed(Page*, PseudoElement&);
</ins><span class="cx"> static void didCreateNamedFlow(Document*, WebKitNamedFlow&);
</span><span class="cx"> static void willRemoveNamedFlow(Document*, WebKitNamedFlow&);
</span><span class="cx"> static void didChangeRegionOverset(Document&, WebKitNamedFlow&);
</span><span class="lines">@@ -275,7 +277,6 @@
</span><span class="cx">
</span><span class="cx"> static void layerTreeDidChange(Page*);
</span><span class="cx"> static void renderLayerDestroyed(Page*, const RenderLayer&);
</span><del>- static void pseudoElementDestroyed(Page*, PseudoElement&);
</del><span class="cx">
</span><span class="cx"> static void frontendCreated() { s_frontendCounter += 1; }
</span><span class="cx"> static void frontendDeleted() { s_frontendCounter -= 1; }
</span><span class="lines">@@ -306,6 +307,8 @@
</span><span class="cx"> static void mediaQueryResultChangedImpl(InstrumentingAgents&);
</span><span class="cx"> static void didPushShadowRootImpl(InstrumentingAgents&, Element& host, ShadowRoot&);
</span><span class="cx"> static void willPopShadowRootImpl(InstrumentingAgents&, Element& host, ShadowRoot&);
</span><ins>+ static void pseudoElementCreatedImpl(InstrumentingAgents&, PseudoElement&);
+ static void pseudoElementDestroyedImpl(InstrumentingAgents&, PseudoElement&);
</ins><span class="cx"> static void didCreateNamedFlowImpl(InstrumentingAgents&, Document*, WebKitNamedFlow&);
</span><span class="cx"> static void willRemoveNamedFlowImpl(InstrumentingAgents&, Document*, WebKitNamedFlow&);
</span><span class="cx"> static void didChangeRegionOversetImpl(InstrumentingAgents&, Document&, WebKitNamedFlow&);
</span><span class="lines">@@ -449,7 +452,6 @@
</span><span class="cx">
</span><span class="cx"> static void layerTreeDidChangeImpl(InstrumentingAgents&);
</span><span class="cx"> static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&);
</span><del>- static void pseudoElementDestroyedImpl(InstrumentingAgents&, PseudoElement&);
</del><span class="cx">
</span><span class="cx"> static InstrumentingAgents* instrumentingAgentsForPage(Page&);
</span><span class="cx"> static InstrumentingAgents* instrumentingAgentsForFrame(Frame&);
</span><span class="lines">@@ -567,6 +569,20 @@
</span><span class="cx"> willPopShadowRootImpl(*instrumentingAgents, host, root);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline void InspectorInstrumentation::pseudoElementCreated(Page* page, PseudoElement& pseudoElement)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+ pseudoElementCreatedImpl(*instrumentingAgents, pseudoElement);
+}
+
+inline void InspectorInstrumentation::pseudoElementDestroyed(Page* page, PseudoElement& pseudoElement)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+ pseudoElementDestroyedImpl(*instrumentingAgents, pseudoElement);
+}
+
</ins><span class="cx"> inline void InspectorInstrumentation::didCreateNamedFlow(Document* document, WebKitNamedFlow& namedFlow)
</span><span class="cx"> {
</span><span class="cx"> FAST_RETURN_IF_NO_FRONTENDS(void());
</span><span class="lines">@@ -1308,22 +1324,18 @@
</span><span class="cx">
</span><span class="cx"> inline void InspectorInstrumentation::layerTreeDidChange(Page* page)
</span><span class="cx"> {
</span><ins>+ FAST_RETURN_IF_NO_FRONTENDS(void());
</ins><span class="cx"> if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
</span><span class="cx"> layerTreeDidChangeImpl(*instrumentingAgents);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const RenderLayer& renderLayer)
</span><span class="cx"> {
</span><ins>+ FAST_RETURN_IF_NO_FRONTENDS(void());
</ins><span class="cx"> if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
</span><span class="cx"> renderLayerDestroyedImpl(*instrumentingAgents, renderLayer);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline void InspectorInstrumentation::pseudoElementDestroyed(Page* page, PseudoElement& pseudoElement)
-{
- if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
- pseudoElementDestroyedImpl(*instrumentingAgents, pseudoElement);
-}
-
</del><span class="cx"> inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgentsForContext(ScriptExecutionContext* context)
</span><span class="cx"> {
</span><span class="cx"> if (!context)
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCoreinspectorInspectorOverlaycpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/inspector/InspectorOverlay.cpp (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/inspector/InspectorOverlay.cpp        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/inspector/InspectorOverlay.cpp        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include "Page.h"
</span><span class="cx"> #include "PageConfiguration.h"
</span><span class="cx"> #include "PolygonShape.h"
</span><ins>+#include "PseudoElement.h"
</ins><span class="cx"> #include "RectangleShape.h"
</span><span class="cx"> #include "RenderBoxModelObject.h"
</span><span class="cx"> #include "RenderElement.h"
</span><span class="lines">@@ -686,17 +687,24 @@
</span><span class="cx"> if (!is<Element>(node) || !node->document().frame())
</span><span class="cx"> return nullptr;
</span><span class="cx">
</span><del>- Element& element = downcast<Element>(*node);
</del><ins>+ Element* effectiveElement = downcast<Element>(node);
+ if (node->isPseudoElement()) {
+ Element* hostElement = downcast<PseudoElement>(*node).hostElement();
+ if (!hostElement)
+ return nullptr;
+ effectiveElement = hostElement;
+ }
+
+ Element& element = *effectiveElement;
</ins><span class="cx"> bool isXHTML = element.document().isXHTMLDocument();
</span><del>-
</del><span class="cx"> auto elementData = Inspector::Protocol::OverlayTypes::ElementData::create()
</span><span class="cx"> .setTagName(isXHTML ? element.nodeName() : element.nodeName().lower())
</span><span class="cx"> .setIdValue(element.getIdAttribute())
</span><span class="cx"> .release();
</span><span class="cx">
</span><del>- HashSet<AtomicString> usedClassNames;
</del><ins>+ StringBuilder classNames;
</ins><span class="cx"> if (element.hasClass() && is<StyledElement>(element)) {
</span><del>- StringBuilder classNames;
</del><ins>+ HashSet<AtomicString> usedClassNames;
</ins><span class="cx"> const SpaceSplitString& classNamesString = downcast<StyledElement>(element).classNames();
</span><span class="cx"> size_t classNameCount = classNamesString.size();
</span><span class="cx"> for (size_t i = 0; i < classNameCount; ++i) {
</span><span class="lines">@@ -707,8 +715,15 @@
</span><span class="cx"> classNames.append('.');
</span><span class="cx"> classNames.append(className);
</span><span class="cx"> }
</span><ins>+ }
+ if (node->isPseudoElement()) {
+ if (node->pseudoId() == BEFORE)
+ classNames.appendLiteral("::before");
+ else if (node->pseudoId() == AFTER)
+ classNames.appendLiteral("::after");
+ }
+ if (!classNames.isEmpty())
</ins><span class="cx"> elementData->setClassName(classNames.toString());
</span><del>- }
</del><span class="cx">
</span><span class="cx"> RenderElement* renderer = element.renderer();
</span><span class="cx"> if (!renderer)
</span></span></pre></div>
<a id="branchessafari601branchSourceWebCorestyleStyleResolveTreecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebCore/style/StyleResolveTree.cpp (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebCore/style/StyleResolveTree.cpp        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebCore/style/StyleResolveTree.cpp        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include "ElementRareData.h"
</span><span class="cx"> #include "FlowThreadController.h"
</span><span class="cx"> #include "InsertionPoint.h"
</span><ins>+#include "InspectorInstrumentation.h"
</ins><span class="cx"> #include "LoaderStrategy.h"
</span><span class="cx"> #include "MainFrame.h"
</span><span class="cx"> #include "NodeRenderStyle.h"
</span><span class="lines">@@ -464,6 +465,7 @@
</span><span class="cx"> if (!needsPseudoElement(current, pseudoId))
</span><span class="cx"> return;
</span><span class="cx"> Ref<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
</span><ins>+ InspectorInstrumentation::pseudoElementCreated(pseudoElement->document().page(), pseudoElement.get());
</ins><span class="cx"> setBeforeOrAfterPseudoElement(current, pseudoElement.copyRef(), pseudoId);
</span><span class="cx"> attachRenderTree(pseudoElement.get(), *current.renderStyle(), renderTreePosition, nullptr);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/ChangeLog (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/ChangeLog        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/ChangeLog        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -1,5 +1,91 @@
</span><span class="cx"> 2015-12-01 Timothy Hatcher <timothy@apple.com>
</span><span class="cx">
</span><ins>+ Merge r187496. rdar://problem/23221163
+
+ 2015-07-28 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Show Pseudo Elements in DOM Tree
+ https://bugs.webkit.org/show_bug.cgi?id=139612
+
+ Reviewed by Timothy Hatcher.
+
+ * UserInterface/Controllers/DOMTreeManager.js:
+ (WebInspector.DOMTreeManager.prototype._pseudoElementAdded):
+ Hook up the new pseudo element DOMNode to the parent.
+
+ (WebInspector.DOMTreeManager.prototype._pseudoElementRemoved):
+ Unhook the pseudo element from its parent.
+
+ (WebInspector.DOMTreeManager.prototype._unbind):
+ When unbinding, unbind any pseudo element children we may have had.
+
+ * UserInterface/Models/DOMNode.js:
+ (WebInspector.DOMNode.prototype.isPseudoElement):
+ (WebInspector.DOMNode.prototype.pseudoType):
+ (WebInspector.DOMNode.prototype.hasPseudoElements):
+ (WebInspector.DOMNode.prototype.pseudoElements):
+ New state of a DOMNode may include pseudo elements.
+
+ (WebInspector.DOMNode.prototype.appropriateSelectorFor):
+ A selector for this node includes the selector for the node above it.
+
+ * UserInterface/Protocol/DOMObserver.js:
+ (WebInspector.DOMObserver.prototype.pseudoElementAdded):
+ (WebInspector.DOMObserver.prototype.pseudoElementRemoved):
+ Pass the message on to DOMTreeManager.
+
+ * UserInterface/Views/DOMTreeElement.js:
+ (WebInspector.DOMTreeElement.prototype.get editable):
+ Pseudo element nodes are not editable.
+
+ (WebInspector.DOMTreeElement.prototype.showChildNode):
+ (WebInspector.DOMTreeElement.prototype.onpopulate):
+ (WebInspector.DOMTreeElement.prototype.updateChildren):
+ (WebInspector.DOMTreeElement.prototype._nodeTitleInfo):
+ (WebInspector.DOMTreeElement.prototype._singleTextChild):
+ (WebInspector.DOMTreeElement.prototype._hasVisibleChildren):
+ (WebInspector.DOMTreeElement.prototype._visibleChildren):
+ (WebInspector.DOMTreeElement.prototype._updateChildren):
+ (WebInspector.DOMTreeElement.prototype.adjustCollapsedRange):
+ (WebInspector.DOMTreeElement.prototype.handleLoadAllChildren):
+ A DOMTreeElement's children are no longer 1-to-1 to DOMNode's children.
+ Instead a DOMNode may have a before/after pseudo element child that
+ are not included in the children list. Update parts of DOMTreeElement
+ to respect this list of visible children.
+
+ * UserInterface/Views/DOMTreeElementPathComponent.js:
+ (WebInspector.DOMTreeElementPathComponent):
+ * UserInterface/Views/PathComponentIcons.css:
+ (.dom-pseudo-element-icon .icon):
+ Styling for the path component when a pseudo element is selected.
+
+ * UserInterface/Views/DOMTreeOutline.css:
+ (.dom-tree-outline .html-pseudo-element):
+ (.dom-tree-outline .html-fragment.shadow):
+ (.webkit-html-fragment.shadow): Deleted.
+ Styles for pseudo elements in the DOM tree.
+
+ * UserInterface/Views/DOMTreeOutline.js:
+ (WebInspector.DOMTreeOutline.prototype._hideElement):
+ Make the hide element selector hide the host element.
+
+ * UserInterface/Views/CSSStyleDetailsSidebarPanel.js:
+ (WebInspector.CSSStyleDetailsSidebarPanel.prototype.addEventListeners):
+ (WebInspector.CSSStyleDetailsSidebarPanel.prototype.removeEventListeners):
+ (WebInspector.CSSStyleDetailsSidebarPanel.prototype._forcedPseudoClassCheckboxChanged):
+ (WebInspector.CSSStyleDetailsSidebarPanel.prototype._updatePseudoClassCheckboxes):
+ Pseudo class changes won't happen on pseudo elements, but will
+ happen on their host element, so listen to and make pseudo class
+ changes to the host element.
+
+ * UserInterface/Views/RulesStyleDetailsPanel.css:
+ (.sidebar > .panel.details.css-style .rules > *:first-child:matches(.new-rule)):
+ Since a pseudo element does not have a style attribute,
+ give some margin in the style sidebar above the "New Rule"
+ button so it looks better.
+
+2015-12-01 Timothy Hatcher <timothy@apple.com>
+
</ins><span class="cx"> Merge r187480. rdar://problem/23221163
</span><span class="cx">
</span><span class="cx"> 2015-07-27 Matt Baker <mattbaker@apple.com>
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceControllersDOMTreeManagerjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -246,16 +246,55 @@
</span><span class="cx"> var node = this._idToDOMNode[nodeId];
</span><span class="cx"> parent._removeChild(node);
</span><span class="cx"> this._unbind(node);
</span><del>- this.dispatchEventToListeners(WebInspector.DOMTreeManager.Event.NodeRemoved, {node:node, parent});
</del><ins>+ this.dispatchEventToListeners(WebInspector.DOMTreeManager.Event.NodeRemoved, {node, parent});
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ _pseudoElementAdded(parentId, pseudoElement)
+ {
+ var parent = this._idToDOMNode[parentId];
+ if (!parent)
+ return;
+
+ var node = new WebInspector.DOMNode(this, parent.ownerDocument, false, pseudoElement);
+ node.parentNode = parent;
+ this._idToDOMNode[node.id] = node;
+ console.assert(!parent.pseudoElements().get(node.pseudoType()));
+ parent.pseudoElements().set(node.pseudoType(), node);
+ this.dispatchEventToListeners(WebInspector.DOMTreeManager.Event.NodeInserted, {node, parent});
+ }
+
+ _pseudoElementRemoved(parentId, pseudoElementId)
+ {
+ var pseudoElement = this._idToDOMNode[pseudoElementId];
+ if (!pseudoElement)
+ return;
+
+ var parent = pseudoElement.parentNode;
+ console.assert(parent);
+ console.assert(parent.id === parentId);
+ if (!parent)
+ return;
+
+ parent._removeChild(pseudoElement);
+ this._unbind(pseudoElement);
+ this.dispatchEventToListeners(WebInspector.DOMTreeManager.Event.NodeRemoved, {node: pseudoElement, parent});
+ }
+
</ins><span class="cx"> _unbind(node)
</span><span class="cx"> {
</span><span class="cx"> this._removeContentNodeFromFlowIfNeeded(node);
</span><span class="cx">
</span><span class="cx"> delete this._idToDOMNode[node.id];
</span><ins>+
</ins><span class="cx"> for (var i = 0; node.children && i < node.children.length; ++i)
</span><span class="cx"> this._unbind(node.children[i]);
</span><ins>+
+ var pseudoElements = node.pseudoElements();
+ for (var pseudoElement of pseudoElements)
+ this._unbind(pseudoElement);
+
+ // FIXME: Handle shadow roots.
+ // FIXME: Handle template content.
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> get restoreSelectedNodeIsAllowed()
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceModelsDOMNodejs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> this._nodeName = payload.nodeName;
</span><span class="cx"> this._localName = payload.localName;
</span><span class="cx"> this._nodeValue = payload.nodeValue;
</span><ins>+ this._pseudoType = payload.pseudoType;
</ins><span class="cx"> this._computedRole = payload.role;
</span><span class="cx">
</span><span class="cx"> if (this._nodeType === Node.DOCUMENT_NODE)
</span><span class="lines">@@ -78,9 +79,20 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ // FIXME: Handle templateContent.
+
</ins><span class="cx"> if (payload.children)
</span><span class="cx"> this._setChildrenPayload(payload.children);
</span><span class="cx">
</span><ins>+ this._pseudoElements = new Map;
+ if (payload.pseudoElements) {
+ for (var i = 0; i < payload.pseudoElements.length; ++i) {
+ var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, payload.pseudoElements[i]);
+ node.parentNode = this;
+ this._pseudoElements.set(node.pseudoType(), node);
+ }
+ }
+
</ins><span class="cx"> if (payload.contentDocument) {
</span><span class="cx"> this._contentDocument = new WebInspector.DOMNode(domAgent, null, false, payload.contentDocument);
</span><span class="cx"> this._children = [this._contentDocument];
</span><span class="lines">@@ -221,6 +233,11 @@
</span><span class="cx"> return this._isInShadowTree;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ isPseudoElement()
+ {
+ return this._pseudoType !== undefined;
+ }
+
</ins><span class="cx"> nodeType()
</span><span class="cx"> {
</span><span class="cx"> return this._nodeType;
</span><span class="lines">@@ -246,6 +263,31 @@
</span><span class="cx"> return this._localName;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ pseudoType()
+ {
+ return this._pseudoType;
+ }
+
+ hasPseudoElements()
+ {
+ return this._pseudoElements.size > 0;
+ }
+
+ pseudoElements()
+ {
+ return this._pseudoElements;
+ }
+
+ beforePseudoElement()
+ {
+ return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementType.Before) || null;
+ }
+
+ afterPseudoElement()
+ {
+ return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementType.After) || null;
+ }
+
</ins><span class="cx"> nodeValue()
</span><span class="cx"> {
</span><span class="cx"> return this._nodeValue;
</span><span class="lines">@@ -407,6 +449,9 @@
</span><span class="cx">
</span><span class="cx"> appropriateSelectorFor(justSelector)
</span><span class="cx"> {
</span><ins>+ if (this.isPseudoElement())
+ return this.parentNode.appropriateSelectorFor() + "::" + this._pseudoType;
+
</ins><span class="cx"> var lowerCaseName = this.localName() || this.nodeName().toLowerCase();
</span><span class="cx">
</span><span class="cx"> var id = this.getAttribute("id");
</span><span class="lines">@@ -475,7 +520,12 @@
</span><span class="cx">
</span><span class="cx"> _removeChild(node)
</span><span class="cx"> {
</span><del>- this._children.splice(this._children.indexOf(node), 1);
</del><ins>+ // FIXME: Handle removal if this is a shadow root.
+ if (node.isPseudoElement())
+ this._pseudoElements.delete(node.pseudoType());
+ else
+ this._children.splice(this._children.indexOf(node), 1);
+
</ins><span class="cx"> node.parentNode = null;
</span><span class="cx"> this._renumber();
</span><span class="cx"> }
</span><span class="lines">@@ -488,8 +538,7 @@
</span><span class="cx">
</span><span class="cx"> this._children = this._shadowRoots.slice();
</span><span class="cx"> for (var i = 0; i < payloads.length; ++i) {
</span><del>- var payload = payloads[i];
- var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, payload);
</del><ins>+ var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, payloads[i]);
</ins><span class="cx"> this._children.push(node);
</span><span class="cx"> }
</span><span class="cx"> this._renumber();
</span><span class="lines">@@ -597,3 +646,8 @@
</span><span class="cx"> AttributeModified: "dom-node-attribute-modified",
</span><span class="cx"> AttributeRemoved: "dom-node-attribute-removed"
</span><span class="cx"> };
</span><ins>+
+WebInspector.DOMNode.PseudoElementType = {
+ Before: "before",
+ After: "after",
+};
</ins></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceProtocolDOMObserverjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -81,4 +81,14 @@
</span><span class="cx"> {
</span><span class="cx"> WebInspector.domTreeManager._childNodeRemoved(parentNodeId, nodeId);
</span><span class="cx"> }
</span><ins>+
+ pseudoElementAdded(parentNodeId, pseudoElement)
+ {
+ WebInspector.domTreeManager._pseudoElementAdded(parentNodeId, pseudoElement);
+ }
+
+ pseudoElementRemoved(parentNodeId, pseudoElementId)
+ {
+ WebInspector.domTreeManager._pseudoElementRemoved(parentNodeId, pseudoElementId);
+ }
</ins><span class="cx"> };
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsCSSStyleDetailsSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -157,12 +157,20 @@
</span><span class="cx">
</span><span class="cx"> addEventListeners()
</span><span class="cx"> {
</span><del>- this.domNode.addEventListener(WebInspector.DOMNode.Event.EnabledPseudoClassesChanged, this._updatePseudoClassCheckboxes, this);
</del><ins>+ var effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;
+ if (!effectiveDOMNode)
+ return;
+
+ effectiveDOMNode.addEventListener(WebInspector.DOMNode.Event.EnabledPseudoClassesChanged, this._updatePseudoClassCheckboxes, this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> removeEventListeners()
</span><span class="cx"> {
</span><del>- this.domNode.removeEventListener(null, null, this);
</del><ins>+ var effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;
+ if (!effectiveDOMNode)
+ return;
+
+ effectiveDOMNode.removeEventListener(null, null, this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Private
</span><span class="lines">@@ -235,7 +243,9 @@
</span><span class="cx"> if (!this.domNode)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- this.domNode.setPseudoClassEnabled(pseudoClass, event.target.checked);
</del><ins>+ var effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;
+
+ effectiveDOMNode.setPseudoClassEnabled(pseudoClass, event.target.checked);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> _updatePseudoClassCheckboxes()
</span><span class="lines">@@ -243,8 +253,10 @@
</span><span class="cx"> if (!this.domNode)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- var enabledPseudoClasses = this.domNode.enabledPseudoClasses;
</del><ins>+ var effectiveDOMNode = this.domNode.isPseudoElement() ? this.domNode.parentNode : this.domNode;
</ins><span class="cx">
</span><ins>+ var enabledPseudoClasses = effectiveDOMNode.enabledPseudoClasses;
+
</ins><span class="cx"> for (var pseudoClass in this._forcedPseudoClassCheckboxes) {
</span><span class="cx"> var checkboxElement = this._forcedPseudoClassCheckboxes[pseudoClass];
</span><span class="cx"> checkboxElement.checked = enabledPseudoClasses.includes(pseudoClass);
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> super("", node);
</span><span class="cx">
</span><span class="cx"> this._elementCloseTag = elementCloseTag;
</span><del>- this.hasChildren = !elementCloseTag && node.hasChildNodes() && !this._showInlineText(node);
</del><ins>+ this.hasChildren = !elementCloseTag && this._hasVisibleChildren();
</ins><span class="cx">
</span><span class="cx"> if (this.representedObject.nodeType() === Node.ELEMENT_NODE && !elementCloseTag)
</span><span class="cx"> this._canAddAttributes = true;
</span><span class="lines">@@ -158,8 +158,11 @@
</span><span class="cx">
</span><span class="cx"> get editable()
</span><span class="cx"> {
</span><del>- if (this.representedObject.isInShadowTree())
</del><ins>+ var node = this.representedObject;
+ if (node.isInShadowTree())
</ins><span class="cx"> return false;
</span><ins>+ if (node.isPseudoElement())
+ return false;
</ins><span class="cx">
</span><span class="cx"> return this.treeOutline.editable;
</span><span class="cx"> }
</span><span class="lines">@@ -189,19 +192,22 @@
</span><span class="cx"> return count;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- showChild(index)
</del><ins>+ showChildNode(node)
</ins><span class="cx"> {
</span><span class="cx"> console.assert(!this._elementCloseTag);
</span><span class="cx"> if (this._elementCloseTag)
</span><del>- return false;
</del><ins>+ return null;
</ins><span class="cx">
</span><ins>+ var index = this._visibleChildren().indexOf(node);
+ if (index === -1)
+ return null;
+
</ins><span class="cx"> if (index >= this.expandedChildrenLimit) {
</span><span class="cx"> this._expandedChildrenLimit = index + 1;
</span><span class="cx"> this._updateChildren(true);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // Whether index-th child is visible in the children tree
- return this.expandedChildCount > index;
</del><ins>+ return this.children[index];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> _createTooltipForNode()
</span><span class="lines">@@ -284,7 +290,7 @@
</span><span class="cx">
</span><span class="cx"> onpopulate()
</span><span class="cx"> {
</span><del>- if (this.children.length || this._showInlineText(this.representedObject) || this._elementCloseTag)
</del><ins>+ if (this.children.length || !this._hasVisibleChildren() || this._elementCloseTag)
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> this.updateChildren();
</span><span class="lines">@@ -299,6 +305,7 @@
</span><span class="cx"> {
</span><span class="cx"> if (this._elementCloseTag)
</span><span class="cx"> return;
</span><ins>+
</ins><span class="cx"> this.representedObject.getChildNodes(this._updateChildren.bind(this, fullRefresh));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -325,78 +332,85 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> this._updateChildrenInProgress = true;
</span><ins>+
+ var node = this.representedObject;
</ins><span class="cx"> var selectedNode = this.treeOutline.selectedDOMNode();
</span><span class="cx"> var originalScrollTop = 0;
</span><del>- if (fullRefresh) {
</del><ins>+
+ var hasVisibleChildren = this._hasVisibleChildren();
+
+ if (fullRefresh || !hasVisibleChildren) {
</ins><span class="cx"> var treeOutlineContainerElement = this.treeOutline.element.parentNode;
</span><span class="cx"> originalScrollTop = treeOutlineContainerElement.scrollTop;
</span><span class="cx"> var selectedTreeElement = this.treeOutline.selectedTreeElement;
</span><span class="cx"> if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
</span><span class="cx"> this.select();
</span><span class="cx"> this.removeChildren();
</span><del>- }
</del><span class="cx">
</span><del>- var treeElement = this;
- var treeChildIndex = 0;
- var elementToSelect;
-
- function updateChildrenOfNode(node)
- {
- var treeOutline = treeElement.treeOutline;
- var child = node.firstChild;
- while (child) {
- var currentTreeElement = treeElement.children[treeChildIndex];
- if (!currentTreeElement || currentTreeElement.representedObject !== child) {
- // Find any existing element that is later in the children list.
- var existingTreeElement = null;
- for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) {
- if (treeElement.children[i].representedObject === child) {
- existingTreeElement = treeElement.children[i];
- break;
- }
- }
-
- if (existingTreeElement && existingTreeElement.parent === treeElement) {
- // If an existing element was found and it has the same parent, just move it.
- treeElement.moveChild(existingTreeElement, treeChildIndex);
- } else {
- // No existing element found, insert a new element.
- if (treeChildIndex < treeElement.expandedChildrenLimit) {
- var newElement = treeElement.insertChildElement(child, treeChildIndex);
- if (child === selectedNode)
- elementToSelect = newElement;
- if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit)
- treeElement.expandedChildrenLimit++;
- }
- }
- }
-
- child = child.nextSibling;
- ++treeChildIndex;
</del><ins>+ // No longer have children.
+ if (!hasVisibleChildren) {
+ this.hasChildren = false;
+ this.updateTitle();
+ this._updateChildrenInProgress = false;
+ return;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ // We now have children.
+ if (!this.hasChildren) {
+ this.hasChildren = true;
+ this.updateTitle();
+ }
+
</ins><span class="cx"> // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent.
</span><ins>+ // Keep a list of existing tree elements for nodes that we can use later.
+ var existingChildTreeElements = new Map;
</ins><span class="cx"> for (var i = (this.children.length - 1); i >= 0; --i) {
</span><del>- var currentChild = this.children[i];
- var currentNode = currentChild.representedObject;
</del><ins>+ var currentChildTreeElement = this.children[i];
+ var currentNode = currentChildTreeElement.representedObject;
</ins><span class="cx"> var currentParentNode = currentNode.parentNode;
</span><del>-
- if (currentParentNode === this.representedObject)
</del><ins>+ if (currentParentNode === node) {
+ existingChildTreeElements.set(currentNode, currentChildTreeElement);
</ins><span class="cx"> continue;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> var selectedTreeElement = this.treeOutline.selectedTreeElement;
</span><del>- if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
</del><ins>+ if (selectedTreeElement && (selectedTreeElement === currentChildTreeElement || selectedTreeElement.hasAncestor(currentChildTreeElement)))
</ins><span class="cx"> this.select();
</span><span class="cx">
</span><span class="cx"> this.removeChildAtIndex(i);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- updateChildrenOfNode(this.representedObject);
</del><ins>+ // Move / create TreeElements for our visible children.
+ var childIndex = 0;
+ var elementToSelect = null;
+ var visibleChildren = this._visibleChildren();
+ for (var i = 0; i < visibleChildren.length && i < this.expandedChildrenLimit; ++i) {
+ var childNode = visibleChildren[i];
+
+ // Already have a tree element for this child, just move it.
+ var existingChildTreeElement = existingChildTreeElements.get(childNode);
+ if (existingChildTreeElement) {
+ this.moveChild(existingChildTreeElement, i);
+ continue;
+ }
+
+ // No existing tree element for this child. Insert a new element.
+ var newChildTreeElement = this.insertChildElement(childNode, i);
+
+ // Update state.
+ if (childNode === selectedNode)
+ elementToSelect = newChildTreeElement;
+ if (this.expandedChildCount > this.expandedChildrenLimit)
+ this.expandedChildrenLimit++;
+ }
+
+ // Update expand all children button.
</ins><span class="cx"> this.adjustCollapsedRange();
</span><span class="cx">
</span><ins>+ // Insert closing tag tree element.
</ins><span class="cx"> var lastChild = this.children.lastValue;
</span><del>- if (this.representedObject.nodeType() === Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag))
</del><ins>+ if (node.nodeType() === Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag))
</ins><span class="cx"> this.insertChildElement(this.representedObject, this.children.length, true);
</span><span class="cx">
</span><span class="cx"> // We want to restore the original selection and tree scroll position after a full refresh, if possible.
</span><span class="lines">@@ -417,16 +431,18 @@
</span><span class="cx"> this.removeChild(this.expandAllButtonElement.__treeElement);
</span><span class="cx">
</span><span class="cx"> var node = this.representedObject;
</span><del>- if (!node.children)
</del><ins>+ if (!this._hasVisibleChildren())
</ins><span class="cx"> return;
</span><del>- var childNodeCount = node.children.length;
</del><span class="cx">
</span><ins>+ var visibleChildren = this._visibleChildren();
+ var totalChildrenCount = visibleChildren.length;
+
</ins><span class="cx"> // In case some nodes from the expanded range were removed, pull some nodes from the collapsed range into the expanded range at the bottom.
</span><del>- for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i)
- this.insertChildElement(node.children[i], i);
</del><ins>+ for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, totalChildrenCount); i < limit; ++i)
+ this.insertChildElement(totalChildrenCount[i], i);
</ins><span class="cx">
</span><span class="cx"> var expandedChildCount = this.expandedChildCount;
</span><del>- if (childNodeCount > this.expandedChildCount) {
</del><ins>+ if (totalChildrenCount > this.expandedChildCount) {
</ins><span class="cx"> var targetButtonIndex = expandedChildCount;
</span><span class="cx"> if (!this.expandAllButtonElement) {
</span><span class="cx"> var button = document.createElement("button");
</span><span class="lines">@@ -444,14 +460,16 @@
</span><span class="cx"> } else if (!this.expandAllButtonElement.__treeElement.parent)
</span><span class="cx"> this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex);
</span><span class="cx">
</span><del>- this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)").format(childNodeCount - expandedChildCount);
</del><ins>+ this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)").format(totalChildrenCount - expandedChildCount);
</ins><span class="cx"> } else if (this.expandAllButtonElement)
</span><span class="cx"> this.expandAllButtonElement = null;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> handleLoadAllChildren()
</span><span class="cx"> {
</span><del>- this.expandedChildrenLimit = Math.max(this.representedObject.childNodeCount, this.expandedChildrenLimit + WebInspector.DOMTreeElement.InitialChildrenLimit);
</del><ins>+ var visibleChildren = this._visibleChildren();
+ var totalChildrenCount = visibleChildren.length;
+ this.expandedChildrenLimit = Math.max(visibleChildren.length, this.expandedChildrenLimit + WebInspector.DOMTreeElement.InitialChildrenLimit);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> onexpand()
</span><span class="lines">@@ -574,7 +592,7 @@
</span><span class="cx"> if (this.treeOutline.selectedDOMNode() !== this.representedObject)
</span><span class="cx"> return false;
</span><span class="cx">
</span><del>- if (this.representedObject.isInShadowTree())
</del><ins>+ if (this.representedObject.isInShadowTree() || this.representedObject.isPseudoElement())
</ins><span class="cx"> return false;
</span><span class="cx">
</span><span class="cx"> if (this.representedObject.nodeType() !== Node.ELEMENT_NODE && this.representedObject.nodeType() !== Node.TEXT_NODE)
</span><span class="lines">@@ -1113,7 +1131,7 @@
</span><span class="cx">
</span><span class="cx"> switch (node.nodeType()) {
</span><span class="cx"> case Node.DOCUMENT_FRAGMENT_NODE:
</span><del>- var fragmentElement = info.titleDOM.createChild("span", "webkit-html-fragment");
</del><ins>+ var fragmentElement = info.titleDOM.createChild("span", "html-fragment");
</ins><span class="cx"> if (node.isInShadowTree()) {
</span><span class="cx"> fragmentElement.textContent = WebInspector.UIString("Shadow Content");
</span><span class="cx"> fragmentElement.classList.add("shadow");
</span><span class="lines">@@ -1127,6 +1145,14 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case Node.ELEMENT_NODE:
</span><ins>+ if (node.isPseudoElement()) {
+ var pseudoElement = info.titleDOM.createChild("span", "html-pseudo-element");
+ pseudoElement.textContent = "::" + node.pseudoType();
+ info.titleDOM.appendChild(document.createTextNode("\u200B"));
+ info.hasChildren = false;
+ break;
+ }
+
</ins><span class="cx"> var tagName = node.nodeNameInCorrectCase();
</span><span class="cx"> if (this._elementCloseTag) {
</span><span class="cx"> this._buildTagDOM(info.titleDOM, tagName, true, true);
</span><span class="lines">@@ -1236,6 +1262,8 @@
</span><span class="cx">
</span><span class="cx"> if (node.hasShadowRoots())
</span><span class="cx"> return null;
</span><ins>+ if (node.hasPseudoElements())
+ return null;
</ins><span class="cx">
</span><span class="cx"> var sibling = firstChild.nextSibling;
</span><span class="cx"> return sibling ? null : firstChild;
</span><span class="lines">@@ -1251,6 +1279,41 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _hasVisibleChildren()
+ {
+ var node = this.representedObject;
+
+ if (this._showInlineText(node))
+ return false;
+
+ if (node.hasChildNodes())
+ return true;
+ if (node.hasPseudoElements())
+ return true;
+
+ return false;
+ }
+
+ _visibleChildren()
+ {
+ var node = this.representedObject;
+
+ var visibleChildren = [];
+
+ var beforePseudoElement = node.beforePseudoElement();
+ if (beforePseudoElement)
+ visibleChildren.push(beforePseudoElement);
+
+ if (node.childNodeCount)
+ visibleChildren = visibleChildren.concat(node.children);
+
+ var afterPseudoElement = node.afterPseudoElement();
+ if (afterPseudoElement)
+ visibleChildren.push(afterPseudoElement);
+
+ return visibleChildren;
+ }
+
</ins><span class="cx"> remove()
</span><span class="cx"> {
</span><span class="cx"> var parentElement = this.parent;
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementPathComponentjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -34,8 +34,13 @@
</span><span class="cx">
</span><span class="cx"> switch (node.nodeType()) {
</span><span class="cx"> case Node.ELEMENT_NODE:
</span><del>- className = WebInspector.DOMTreeElementPathComponent.DOMElementIconStyleClassName;
- title = WebInspector.displayNameForNode(node);
</del><ins>+ if (node.isPseudoElement()) {
+ className = WebInspector.DOMTreeElementPathComponent.DOMPseudoElementIconStyleClassName;
+ title = "::" + node.pseudoType();
+ } else {
+ className = WebInspector.DOMTreeElementPathComponent.DOMElementIconStyleClassName;
+ title = WebInspector.displayNameForNode(node);
+ }
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case Node.TEXT_NODE:
</span><span class="lines">@@ -129,6 +134,7 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMElementIconStyleClassName = "dom-element-icon";
</span><ins>+WebInspector.DOMTreeElementPathComponent.DOMPseudoElementIconStyleClassName = "dom-pseudo-element-icon";
</ins><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMTextNodeIconStyleClassName = "dom-text-node-icon";
</span><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMCommentIconStyleClassName = "dom-comment-icon";
</span><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMDocumentTypeIconStyleClassName = "dom-document-type-icon";
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinecss"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -156,12 +156,16 @@
</span><span class="cx"> white-space: pre-wrap;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+.dom-tree-outline .html-pseudo-element {
+ color: hsl(0, 59%, 41%);
+}
+
+.dom-tree-outline .html-fragment.shadow {
+ opacity: 0.6;
+}
+
</ins><span class="cx"> .showing-find-banner .dom-tree-outline .search-highlight {
</span><span class="cx"> color: black;
</span><span class="cx"> background-color: hsla(53, 83%, 53%, 0.2);
</span><span class="cx"> border-bottom: 1px solid hsl(47, 82%, 60%);
</span><span class="cx"> }
</span><del>-
-.webkit-html-fragment.shadow {
- opacity: 0.6;
-}
</del></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinejs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -228,14 +228,15 @@
</span><span class="cx"> var treeElement = this.findTreeElement(node);
</span><span class="cx"> if (treeElement)
</span><span class="cx"> return treeElement;
</span><ins>+
</ins><span class="cx"> if (!node.parentNode)
</span><span class="cx"> return null;
</span><span class="cx">
</span><span class="cx"> treeElement = this.createTreeElementFor(node.parentNode);
</span><del>- if (treeElement && treeElement.showChild(node.index))
- return treeElement.children[node.index];
</del><ins>+ if (!treeElement)
+ return null;
</ins><span class="cx">
</span><del>- return null;
</del><ins>+ return treeElement.showChildNode(node);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> set suppressRevealAndSelect(x)
</span><span class="lines">@@ -548,12 +549,19 @@
</span><span class="cx">
</span><span class="cx"> event.preventDefault();
</span><span class="cx">
</span><del>- var selectedNode = this.selectedTreeElement.representedObject;
- console.assert(selectedNode);
- if (!selectedNode)
</del><ins>+ var effectiveNode = this.selectedTreeElement.representedObject;
+ console.assert(effectiveNode);
+ if (!effectiveNode)
</ins><span class="cx"> return;
</span><span class="cx">
</span><del>- if (selectedNode.nodeType() !== Node.ELEMENT_NODE)
</del><ins>+ if (effectiveNode.isPseudoElement()) {
+ effectiveNode = effectiveNode.parentNode;
+ console.assert(effectiveNode);
+ if (!effectiveNode)
+ return;
+ }
+
+ if (effectiveNode.nodeType() !== Node.ELEMENT_NODE)
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> function resolvedNode(object)
</span><span class="lines">@@ -579,7 +587,7 @@
</span><span class="cx"> object.release();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- WebInspector.RemoteObject.resolveNode(selectedNode, "", resolvedNode);
</del><ins>+ WebInspector.RemoteObject.resolveNode(effectiveNode, "", resolvedNode);
</ins><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsPathComponentIconscss"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -35,6 +35,10 @@
</span><span class="cx"> content: url(../Images/DOMElement.svg);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+.dom-pseudo-element-icon .icon {
+ content: url(../Images/PseudoElement.svg);
+}
+
</ins><span class="cx"> .dom-text-node-icon .icon {
</span><span class="cx"> content: url(../Images/DOMTextNode.svg);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceViewsRulesStyleDetailsPanelcss"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css (193028 => 193029)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css        2015-12-03 18:33:00 UTC (rev 193028)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css        2015-12-03 18:33:18 UTC (rev 193029)
</span><span class="lines">@@ -52,6 +52,10 @@
</span><span class="cx"> opacity: 0.5;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+.sidebar > .panel.details.css-style .rules > *:first-child:matches(.new-rule) {
+ margin-top: 8px;
+}
+
</ins><span class="cx"> .sidebar > .panel.details.css-style > .content.filter-in-progress .label {
</span><span class="cx"> padding-top: 15px;
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>