<!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>[193441] branches/safari-601.1.46-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/193441">193441</a></dd>
<dt>Author</dt> <dd>timothy@apple.com</dd>
<dt>Date</dt> <dd>2015-12-04 12:51:49 -0800 (Fri, 04 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/187496">r187496</a>. rdar://problem/23581597</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601146branchLayoutTestsChangeLog">branches/safari-601.1.46-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari601146branchSourceJavaScriptCoreChangeLog">branches/safari-601.1.46-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari601146branchSourceJavaScriptCoreinspectorprotocolDOMjson">branches/safari-601.1.46-branch/Source/JavaScriptCore/inspector/protocol/DOM.json</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreChangeLog">branches/safari-601.1.46-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari601146branchSourceWebCoredomPseudoElementcpp">branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.cpp</a></li>
<li><a href="#branchessafari601146branchSourceWebCoredomPseudoElementh">branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.h</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorCSSAgentcpp">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorCSSAgenth">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.h</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorDOMAgentcpp">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorDOMAgenth">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.h</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorInstrumentationcpp">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorInstrumentationh">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.h</a></li>
<li><a href="#branchessafari601146branchSourceWebCoreinspectorInspectorOverlaycpp">branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorOverlay.cpp</a></li>
<li><a href="#branchessafari601146branchSourceWebCorestyleStyleResolveTreecpp">branches/safari-601.1.46-branch/Source/WebCore/style/StyleResolveTree.cpp</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIChangeLog">branches/safari-601.1.46-branch/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceControllersDOMTreeManagerjs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceModelsDOMNodejs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceProtocolDOMObserverjs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsCSSStyleDetailsSidebarPaneljs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementjs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementPathComponentjs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinecss">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinejs">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsPathComponentIconscss">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css</a></li>
<li><a href="#branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsRulesStyleDetailsPanelcss">branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari601146branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodeexpectedtxt">branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt</a></li>
<li><a href="#branchessafari601146branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodehtml">branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html</a></li>
<li><a href="#branchessafari601146branchLayoutTestsinspectordompseudoelementdynamicexpectedtxt">branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt</a></li>
<li><a href="#branchessafari601146branchLayoutTestsinspectordompseudoelementdynamichtml">branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html</a></li>
<li><a href="#branchessafari601146branchLayoutTestsinspectordompseudoelementstaticexpectedtxt">branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt</a></li>
<li><a href="#branchessafari601146branchLayoutTestsinspectordompseudoelementstatichtml">branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601146branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/LayoutTests/ChangeLog (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/ChangeLog        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/LayoutTests/ChangeLog        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2015-12-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r187496. rdar://problem/23581597
+
+    2015-07-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            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-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r187249. rdar://problem/23581597
</span><span class="cx"> 
</span><span class="cx">     2015-07-23  Devin Rousso  &lt;drousso@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601146branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodeexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt (0 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node-expected.txt        2015-12-04 20:51:49 UTC (rev 193441)
</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="branchessafari601146branchLayoutTestsinspectorcsspseudoelementmatchesforpseudoelementnodehtml"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html (0 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/inspector/css/pseudo-element-matches-for-pseudo-element-node.html        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test() {
+    var nodeStyles = null;
+
+    function validateStyles() {
+        InspectorTest.log(&quot;&quot;);
+
+        InspectorTest.expectThat(!nodeStyles.inlineStyle, &quot;No Inline Styles&quot;);
+        InspectorTest.expectThat(!nodeStyles.attributesStyle, &quot;No Attribute Styles&quot;);
+        InspectorTest.expectThat(!nodeStyles.inheritedRules.length, &quot;No Inherited Styles&quot;);
+        InspectorTest.expectThat(!Object.keys(nodeStyles.pseudoElements).length, &quot;No Pseudo Element Styles&quot;);
+
+        InspectorTest.expectThat(nodeStyles.computedStyle, &quot;Has Computed Styles&quot;);
+        InspectorTest.log(&quot;PROPERTY: &quot; + nodeStyles.computedStyle.propertyForName(&quot;content&quot;).text);
+        InspectorTest.log(&quot;PROPERTY: &quot; + nodeStyles.computedStyle.propertyForName(&quot;color&quot;).text);
+
+        for (var rule of nodeStyles.matchedRules) {
+            InspectorTest.log(&quot;MATCHED RULE:&quot;);
+            for (var i = 0; i &lt; rule.selectors.length; ++i) {
+                var selector = rule.selectors[i];
+                var matched = rule.matchedSelectorIndices.includes(i);
+                InspectorTest.log(&quot;  SELECTOR: &quot; + selector.text + (matched ? &quot; [matched]&quot; : &quot;&quot;));
+            }
+        }
+
+        InspectorTest.completeTest();                
+    }
+
+    WebInspector.domTreeManager.requestDocument(function(documentNode) {
+        WebInspector.domTreeManager.querySelector(documentNode.id, &quot;#x&quot;, function(contentNodeId) {
+            var domNode = WebInspector.domTreeManager.nodeForId(contentNodeId);
+            InspectorTest.assert(domNode);
+            var beforePseudoElementDOMNode = domNode.beforePseudoElement();
+            InspectorTest.expectThat(beforePseudoElementDOMNode, &quot;Got ::before pseudo element for #x&quot;);
+            InspectorTest.log(&quot;Refreshing styles for ::before pseudo element&quot;);
+            nodeStyles = WebInspector.cssStyleManager.stylesForNode(beforePseudoElementDOMNode);
+            nodeStyles.addEventListener(WebInspector.DOMNodeStyles.Event.Refreshed, validateStyles);
+            nodeStyles.refresh();
+        });
+    });
+
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Testing that we can get computed and matched rules for pseudo element nodes.&lt;/p&gt;
+
+    &lt;style&gt;
+    input:before, #x:before, div { content: &quot;before&quot;; color: blue; }
+    &lt;/style&gt;
+
+    &lt;div id=&quot;x&quot;&gt;TEST ELEMENT: Has Before Pseudo Element&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="branchessafari601146branchLayoutTestsinspectordompseudoelementdynamicexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt (0 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic-expected.txt        2015-12-04 20:51:49 UTC (rev 193441)
</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="branchessafari601146branchLayoutTestsinspectordompseudoelementdynamichtml"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html (0 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-dynamic.html        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -0,0 +1,156 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test() {
+
+    var testDOMNode = null;
+    var insertedOrRemovedDOMNode = null;
+    var previousInsertedDOMNode = null;
+
+    var steps = [
+        {
+            name: &quot;Add :before&quot;,
+            action: function() {
+                InspectorTest.evaluateInPage(&quot;document.getElementById('x').classList.add('b')&quot;);
+            }
+        },
+        {
+            name: &quot;Verify :before was added&quot;,
+            action: function() {
+                InspectorTest.expectThat(testDOMNode.hasPseudoElements(), &quot;#x DOMNode has pseudo elements&quot;);
+                InspectorTest.expectThat(testDOMNode.pseudoElements().size === 1, &quot;DOMNode has 1 pseudo elements&quot;);
+                InspectorTest.expectThat(testDOMNode.beforePseudoElement(), &quot;DOMNode has a before pseudo element&quot;);
+                InspectorTest.expectThat(!testDOMNode.afterPseudoElement(), &quot;DOMNode does not have an after pseudo element&quot;);
+
+                InspectorTest.expectThat(insertedOrRemovedDOMNode === testDOMNode.beforePseudoElement(), &quot;New DOMNode is the beforePseudoElement&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === testDOMNode, &quot;New DOMNode is a child of #x&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, &quot;New DOMNode is a before pseudo element&quot;);
+
+                previousInsertedDOMNode = insertedOrRemovedDOMNode;
+                next();
+            }
+        },
+        {
+            name: &quot;Remove :before&quot;,
+            action: function() {
+                InspectorTest.evaluateInPage(&quot;document.getElementById('x').classList.remove('b')&quot;);
+            }
+        },
+        {
+            name: &quot;Verify :before was removed&quot;,
+            action: function() {
+                InspectorTest.expectThat(!testDOMNode.hasPseudoElements(), &quot;#x DOMNode has no pseudo elements&quot;);
+                InspectorTest.assert(testDOMNode.pseudoElements().size === 0);
+                InspectorTest.assert(!testDOMNode.beforePseudoElement());
+                InspectorTest.assert(!testDOMNode.afterPseudoElement());
+
+                InspectorTest.expectThat(insertedOrRemovedDOMNode === previousInsertedDOMNode, &quot;Removed DOMNode was the before pseudo element&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === null, &quot;Removed DOMNode has no parent&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, &quot;Removed DOMNode was a before pseudo element&quot;);
+
+                previousInsertedDOMNode = null;
+                next();
+            }
+        },
+        {
+            name: &quot;Add :after&quot;,
+            action: function() {
+                InspectorTest.evaluateInPage(&quot;document.getElementById('x').classList.add('a')&quot;);
+            }
+        },
+        {
+            name: &quot;Verify :after was added&quot;,
+            action: function() {
+                InspectorTest.expectThat(testDOMNode.hasPseudoElements(), &quot;#x DOMNode has pseudo elements&quot;);
+                InspectorTest.expectThat(testDOMNode.pseudoElements().size === 1, &quot;DOMNode has 1 pseudo elements&quot;);
+                InspectorTest.expectThat(!testDOMNode.beforePseudoElement(), &quot;DOMNode does not have a before pseudo element&quot;);
+                InspectorTest.expectThat(testDOMNode.afterPseudoElement(), &quot;DOMNode has an after pseudo element&quot;);
+
+                InspectorTest.expectThat(insertedOrRemovedDOMNode === testDOMNode.afterPseudoElement(), &quot;New DOMNode is the afterPseudoElement&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === testDOMNode, &quot;New DOMNode is a child of #x&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.After, &quot;New DOMNode is an after pseudo element&quot;);
+
+                previousInsertedDOMNode = insertedOrRemovedDOMNode;
+                next();
+            }
+        },
+        {
+            name: &quot;Remove :after&quot;,
+            action: function() {
+                InspectorTest.evaluateInPage(&quot;document.getElementById('x').classList.remove('a')&quot;);
+            }
+        },
+        {
+            name: &quot;Verify :after was removed&quot;,
+            action: function() {
+                InspectorTest.expectThat(!testDOMNode.hasPseudoElements(), &quot;#x DOMNode has no pseudo elements&quot;);
+                InspectorTest.assert(testDOMNode.pseudoElements().size === 0);
+                InspectorTest.assert(!testDOMNode.beforePseudoElement());
+                InspectorTest.assert(!testDOMNode.afterPseudoElement());
+
+                InspectorTest.expectThat(insertedOrRemovedDOMNode === previousInsertedDOMNode, &quot;Removed DOMNode was the after pseudo element&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.parentNode === null, &quot;Removed DOMNode has no parent&quot;);
+                InspectorTest.expectThat(insertedOrRemovedDOMNode.pseudoType() === WebInspector.DOMNode.PseudoElementType.After, &quot;Removed DOMNode was an after pseudo element&quot;);
+
+                previousInsertedDOMNode = null;
+                next();
+            }
+        },
+    ];
+
+    function next()
+    {
+        var step = steps.shift();
+        if (step) {
+            InspectorTest.log(&quot;&quot;);
+            InspectorTest.log(step.name);
+            step.action();
+            return;
+        }
+        InspectorTest.completeTest();
+    }
+
+    WebInspector.domTreeManager.requestDocument(function(documentNode) {
+        WebInspector.domTreeManager.querySelector(documentNode.id, &quot;#x&quot;, function(nodeId) {
+            testDOMNode = WebInspector.domTreeManager.nodeForId(nodeId);
+            InspectorTest.log(&quot;&quot;);
+            InspectorTest.expectThat(testDOMNode, &quot;Got DOMNode for #x&quot;);
+            InspectorTest.assert(!testDOMNode.pseudoType());
+            InspectorTest.expectThat(!testDOMNode.hasPseudoElements(), &quot;DOMNode has no pseudo elements&quot;);
+            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(&quot;EVENT: NodeInserted&quot;);
+        insertedOrRemovedDOMNode = event.data.node;
+        next();
+    });
+
+    WebInspector.domTreeManager.addEventListener(WebInspector.DOMTreeManager.Event.NodeRemoved, function(event) {
+        InspectorTest.log(&quot;EVENT: NodeRemoved&quot;);
+        insertedOrRemovedDOMNode = event.data.node;
+        next();
+    });
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Test for dynamic DOMNode pseudo element support, pseudo elements getting added and removed dynamically.&lt;/p&gt;
+
+    &lt;style&gt;
+    .b:before { content: &quot;before&quot;; }
+    .a:after { content: &quot;after&quot;; }
+    &lt;/style&gt;
+
+    &lt;div id=&quot;x&quot;&gt;TEST ELEMENT&lt;/div&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="branchessafari601146branchLayoutTestsinspectordompseudoelementstaticexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt (0 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static-expected.txt        2015-12-04 20:51:49 UTC (rev 193441)
</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="branchessafari601146branchLayoutTestsinspectordompseudoelementstatichtml"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static.html (0 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static.html                                (rev 0)
+++ branches/safari-601.1.46-branch/LayoutTests/inspector/dom/pseudo-element-static.html        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test() {
+    WebInspector.domTreeManager.requestDocument(function(documentNode) {
+        WebInspector.domTreeManager.querySelector(documentNode.id, &quot;#none&quot;, function(nodeId) {
+            var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+            InspectorTest.log(&quot;&quot;);
+            InspectorTest.expectThat(domNode, &quot;Got DOMNode for #none&quot;);
+            InspectorTest.assert(!domNode.pseudoType());
+            InspectorTest.expectThat(!domNode.hasPseudoElements(), &quot;DOMNode has no pseudo elements&quot;);
+            InspectorTest.assert(domNode.pseudoElements().size === 0);
+            InspectorTest.assert(!domNode.beforePseudoElement());
+            InspectorTest.assert(!domNode.afterPseudoElement());
+        });
+
+        WebInspector.domTreeManager.querySelector(documentNode.id, &quot;#b&quot;, function(nodeId) {
+            var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+            InspectorTest.log(&quot;&quot;);
+            InspectorTest.expectThat(domNode, &quot;Got DOMNode for #b&quot;);
+            InspectorTest.assert(!domNode.pseudoType());
+            InspectorTest.expectThat(domNode.hasPseudoElements(), &quot;DOMNode has pseudo elements&quot;);
+            InspectorTest.expectThat(domNode.pseudoElements().size === 1, &quot;DOMNode has 1 pseudo elements&quot;);
+            InspectorTest.expectThat(domNode.beforePseudoElement(), &quot;DOMNode has a before pseudo element&quot;);
+            InspectorTest.expectThat(!domNode.afterPseudoElement(), &quot;DOMNode does not have an after pseudo element&quot;);
+            InspectorTest.expectThat(domNode.beforePseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, &quot;DOMNode for before pseudo element has the right type&quot;);
+        });
+
+        WebInspector.domTreeManager.querySelector(documentNode.id, &quot;#a&quot;, function(nodeId) {
+            var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+            InspectorTest.log(&quot;&quot;);
+            InspectorTest.expectThat(domNode, &quot;Got DOMNode for #a&quot;);
+            InspectorTest.assert(!domNode.pseudoType());
+            InspectorTest.expectThat(domNode.hasPseudoElements(), &quot;DOMNode has pseudo elements&quot;);
+            InspectorTest.expectThat(domNode.pseudoElements().size === 1, &quot;DOMNode has 1 pseudo elements&quot;);
+            InspectorTest.expectThat(!domNode.beforePseudoElement(), &quot;DOMNode does not have a before pseudo element&quot;);
+            InspectorTest.expectThat(domNode.afterPseudoElement(), &quot;DOMNode has an after pseudo element&quot;);
+            InspectorTest.expectThat(domNode.afterPseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.After, &quot;DOMNode for after pseudo element has the right type&quot;);
+        });
+
+        WebInspector.domTreeManager.querySelector(documentNode.id, &quot;#x&quot;, function(nodeId) {
+            var domNode = WebInspector.domTreeManager.nodeForId(nodeId);
+            InspectorTest.log(&quot;&quot;);
+            InspectorTest.expectThat(domNode, &quot;Got DOMNode for #x&quot;);
+            InspectorTest.assert(!domNode.pseudoType());
+            InspectorTest.expectThat(domNode.hasPseudoElements(), &quot;DOMNode has pseudo elements&quot;);
+            InspectorTest.expectThat(domNode.pseudoElements().size === 2, &quot;DOMNode has 2 pseudo elements&quot;);
+            InspectorTest.expectThat(domNode.beforePseudoElement(), &quot;DOMNode has a before pseudo element&quot;);
+            InspectorTest.expectThat(domNode.afterPseudoElement(), &quot;DOMNode has an after pseudo element&quot;);
+            InspectorTest.expectThat(domNode.beforePseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.Before, &quot;DOMNode for before pseudo element has the right type&quot;);
+            InspectorTest.expectThat(domNode.afterPseudoElement().pseudoType() === WebInspector.DOMNode.PseudoElementType.After, &quot;DOMNode for after pseudo element has the right type&quot;);
+            InspectorTest.completeTest();
+        });
+    });
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Test for basic DOMNode pseudo element support.&lt;/p&gt;
+
+    &lt;style&gt;
+    #x:before, #b:before { content: &quot;before&quot;; }
+    #x:after, #a:after { content: &quot;after&quot;; }
+    &lt;/style&gt;
+
+    &lt;div id=&quot;none&quot;&gt;TEST ELEMENT: No Pseudo Elements&lt;/div&gt;
+    &lt;div id=&quot;b&quot;&gt;TEST ELEMENT: Has Before Pseudo Element&lt;/div&gt;
+    &lt;div id=&quot;a&quot;&gt;TEST ELEMENT: Has After Pseudo Element&lt;/div&gt;
+    &lt;div id=&quot;x&quot;&gt;TEST ELEMENT: Has Before and After Pseudo Elements&lt;/div&gt;
+
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="branchessafari601146branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/JavaScriptCore/ChangeLog (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/JavaScriptCore/ChangeLog        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/JavaScriptCore/ChangeLog        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -1,5 +1,21 @@
</span><span class="cx"> 2015-12-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r187496. rdar://problem/23581597
+
+    2015-07-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            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-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r187249. rdar://problem/23581597
</span><span class="cx"> 
</span><span class="cx">     2015-07-23  Devin Rousso  &lt;drousso@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601146branchSourceJavaScriptCoreinspectorprotocolDOMjson"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/JavaScriptCore/inspector/protocol/DOM.json (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/JavaScriptCore/inspector/protocol/DOM.json        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/JavaScriptCore/inspector/protocol/DOM.json        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -14,6 +14,12 @@
</span><span class="cx">             &quot;description&quot;: &quot;Unique DOM node identifier used to reference a node that may not have been pushed to the front-end.&quot;
</span><span class="cx">         },
</span><span class="cx">         {
</span><ins>+            &quot;id&quot;: &quot;PseudoType&quot;,
+            &quot;type&quot;: &quot;string&quot;,
+            &quot;enum&quot;: [&quot;before&quot;, &quot;after&quot;],
+            &quot;description&quot;: &quot;Pseudo element type.&quot;
+        },
+        {
</ins><span class="cx">             &quot;id&quot;: &quot;LiveRegionRelevant&quot;,
</span><span class="cx">             &quot;type&quot;: &quot;string&quot;,
</span><span class="cx">             &quot;enum&quot;: [&quot;additions&quot;, &quot;removals&quot;, &quot;text&quot;],
</span><span class="lines">@@ -39,10 +45,12 @@
</span><span class="cx">                 { &quot;name&quot;: &quot;xmlVersion&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;&lt;code&gt;Document&lt;/code&gt;'s XML version in case of XML documents.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;name&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;&lt;code&gt;Attr&lt;/code&gt;'s name.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;value&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;&lt;code&gt;Attr&lt;/code&gt;'s value.&quot; },
</span><ins>+                { &quot;name&quot;: &quot;pseudoType&quot;, &quot;$ref&quot;: &quot;PseudoType&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Pseudo element type for this node.&quot; },
</ins><span class="cx">                 { &quot;name&quot;: &quot;frameId&quot;, &quot;$ref&quot;: &quot;Network.FrameId&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Frame ID for frame owner elements.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;contentDocument&quot;, &quot;$ref&quot;: &quot;Node&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Content document for frame owner elements.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;shadowRoots&quot;, &quot;type&quot;: &quot;array&quot;, &quot;optional&quot;: true, &quot;items&quot;: { &quot;$ref&quot;: &quot;Node&quot; }, &quot;description&quot;: &quot;Shadow root list for given element host.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;templateContent&quot;, &quot;$ref&quot;: &quot;Node&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Content document fragment for template elements&quot; },
</span><ins>+                { &quot;name&quot;: &quot;pseudoElements&quot;, &quot;type&quot;: &quot;array&quot;, &quot;items&quot;: { &quot;$ref&quot;: &quot;Node&quot; }, &quot;optional&quot;: true, &quot;description&quot;: &quot;Pseudo elements associated with this node.&quot; },
</ins><span class="cx">                 { &quot;name&quot;: &quot;role&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Computed value for first recognized role token, default role per element, or overridden role.&quot; }
</span><span class="cx">             ],
</span><span class="cx">             &quot;description&quot;: &quot;DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type.&quot;
</span><span class="lines">@@ -526,6 +534,22 @@
</span><span class="cx">                 { &quot;name&quot;: &quot;rootId&quot;, &quot;$ref&quot;: &quot;NodeId&quot;, &quot;description&quot;: &quot;Shadow root id.&quot; }
</span><span class="cx">             ],
</span><span class="cx">             &quot;description&quot;: &quot;Called when shadow root is popped from the element.&quot;
</span><ins>+        },
+        {
+            &quot;name&quot;: &quot;pseudoElementAdded&quot;,
+            &quot;parameters&quot;: [
+                { &quot;name&quot;: &quot;parentId&quot;, &quot;$ref&quot;: &quot;NodeId&quot;, &quot;description&quot;: &quot;Pseudo element's parent element id.&quot; },
+                { &quot;name&quot;: &quot;pseudoElement&quot;, &quot;$ref&quot;: &quot;Node&quot;, &quot;description&quot;: &quot;The added pseudo element.&quot; }
+            ],
+            &quot;description&quot;: &quot;Called when a pseudo element is added to an element.&quot;
+        },
+        {
+            &quot;name&quot;: &quot;pseudoElementRemoved&quot;,
+            &quot;parameters&quot;: [
+                { &quot;name&quot;: &quot;parentId&quot;, &quot;$ref&quot;: &quot;NodeId&quot;, &quot;description&quot;: &quot;Pseudo element's parent element id.&quot; },
+                { &quot;name&quot;: &quot;pseudoElementId&quot;, &quot;$ref&quot;: &quot;NodeId&quot;, &quot;description&quot;: &quot;The removed pseudo element id.&quot; }
+            ],
+            &quot;description&quot;: &quot;Called when a pseudo element is removed from an element.&quot;
</ins><span class="cx">         }
</span><span class="cx">     ]
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/ChangeLog (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/ChangeLog        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/ChangeLog        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -1,5 +1,84 @@
</span><span class="cx"> 2015-12-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r187496. rdar://problem/23581597
+
+    2015-07-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            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-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r188227. rdar://problem/23581597
</span><span class="cx"> 
</span><span class="cx">     2015-08-10  Devin Rousso  &lt;drousso@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoredomPseudoElementcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.cpp (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.cpp        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.cpp        2015-12-04 20:51:49 UTC (rev 193441)
</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&lt;RenderStyle&gt; PseudoElement::customStyleForRenderer(RenderStyle&amp; parentStyle)
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoredomPseudoElementh"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.h (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.h        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/dom/PseudoElement.h        2015-12-04 20:51:49 UTC (rev 193441)
</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&lt;RenderStyle&gt; customStyleForRenderer(RenderStyle&amp; parentStyle) override;
</span><span class="cx">     virtual void didAttachRenderers() override;
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreinspectorInspectorCSSAgentcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.cpp        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;NamedFlowCollection.h&quot;
</span><span class="cx"> #include &quot;Node.h&quot;
</span><span class="cx"> #include &quot;NodeList.h&quot;
</span><ins>+#include &quot;PseudoElement.h&quot;
</ins><span class="cx"> #include &quot;RenderNamedFlowFragment.h&quot;
</span><span class="cx"> #include &quot;SVGStyleElement.h&quot;
</span><span class="cx"> #include &quot;SelectorChecker.h&quot;
</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-&gt;pseudoId();
+    if (elementPseudoId) {
+        element = downcast&lt;PseudoElement&gt;(*element).hostElement();
+        if (!element) {
+            errorString = ASCIILiteral(&quot;Pseudo element has no parent&quot;);
+            return;
+        }
+    }
+
</ins><span class="cx">     // Matched rules.
</span><span class="cx">     StyleResolver&amp; styleResolver = element-&gt;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&lt;Inspector::Protocol::CSS::PseudoIdMatches&gt;::create();
-        for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId &lt; AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast&lt;PseudoId&gt;(pseudoId + 1)) {
-            auto matchedRules = styleResolver.pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
-            if (!matchedRules.isEmpty()) {
-                auto matches = Inspector::Protocol::CSS::PseudoIdMatches::create()
-                    .setPseudoId(static_cast&lt;int&gt;(pseudoId))
-                    .setMatches(buildArrayForMatchedRuleList(matchedRules, styleResolver, element))
-                    .release();
-                pseudoElements-&gt;addItem(WTF::move(matches));
</del><ins>+    if (!originalElement-&gt;isPseudoElement()) {
+        // Pseudo elements.
+        if (!includePseudo || *includePseudo) {
+            auto pseudoElements = Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::PseudoIdMatches&gt;::create();
+            for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId &lt; AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast&lt;PseudoId&gt;(pseudoId + 1)) {
+                auto matchedRules = styleResolver.pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
+                if (!matchedRules.isEmpty()) {
+                    auto matches = Inspector::Protocol::CSS::PseudoIdMatches::create()
+                        .setPseudoId(static_cast&lt;int&gt;(pseudoId))
+                        .setMatches(buildArrayForMatchedRuleList(matchedRules, styleResolver, element, pseudoId))
+                        .release();
+                    pseudoElements-&gt;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&lt;Inspector::Protocol::CSS::InheritedStyleEntry&gt;::create();
+            Element* parentElement = element-&gt;parentElement();
+            while (parentElement) {
+                StyleResolver&amp; parentStyleResolver = parentElement-&gt;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-&gt;style() &amp;&amp; parentElement-&gt;style()-&gt;length()) {
+                    if (InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement))
+                        entry-&gt;setInlineStyle(styleSheet-&gt;buildObjectForStyle(styleSheet-&gt;styleForId(InspectorCSSId(styleSheet-&gt;id(), 0))));
+                }
</ins><span class="cx"> 
</span><del>-    // Inherited styles.
-    if (!includeInherited || *includeInherited) {
-        auto entries = Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::InheritedStyleEntry&gt;::create();
-        Element* parentElement = element-&gt;parentElement();
-        while (parentElement) {
-            StyleResolver&amp; parentStyleResolver = parentElement-&gt;document().ensureStyleResolver();
-            auto parentMatchedRules = parentStyleResolver.styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
-            auto entry = Inspector::Protocol::CSS::InheritedStyleEntry::create()
-                .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules, styleResolver, parentElement))
-                .release();
-            if (parentElement-&gt;style() &amp;&amp; parentElement-&gt;style()-&gt;length()) {
-                InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
-                if (styleSheet)
-                    entry-&gt;setInlineStyle(styleSheet-&gt;buildObjectForStyle(styleSheet-&gt;styleForId(InspectorCSSId(styleSheet-&gt;id(), 0))));
</del><ins>+                entries-&gt;addItem(WTF::move(entry));
+                parentElement = parentElement-&gt;parentElement();
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            entries-&gt;addItem(WTF::move(entry));
-            parentElement = parentElement-&gt;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-&gt;buildObjectForRule(rule, nullptr) : nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::RuleMatch&gt;&gt; InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector&lt;RefPtr&lt;StyleRule&gt;&gt;&amp; matchedRules, StyleResolver&amp; styleResolver, Element* element)
</del><ins>+RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::RuleMatch&gt;&gt; InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector&lt;RefPtr&lt;StyleRule&gt;&gt;&amp; matchedRules, StyleResolver&amp; styleResolver, Element* element, PseudoId psuedoId)
</ins><span class="cx"> {
</span><span class="cx">     auto result = Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::RuleMatch&gt;::create();
</span><span class="cx"> 
</span><span class="cx">     SelectorChecker::CheckingContext context(SelectorChecker::Mode::CollectingRules);
</span><ins>+    context.pseudoId = psuedoId ? psuedoId : element-&gt;pseudoId();
</ins><span class="cx">     SelectorChecker selectorChecker(element-&gt;document());
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; matchedRule : matchedRules) {
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreinspectorInspectorCSSAgenth"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.h (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.h        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorCSSAgent.h        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -149,7 +149,7 @@
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Inspector::Protocol::CSS::CSSRule&gt; buildObjectForRule(StyleRule*, StyleResolver&amp;, Element*);
</span><span class="cx">     RefPtr&lt;Inspector::Protocol::CSS::CSSRule&gt; buildObjectForRule(CSSStyleRule*);
</span><del>-    RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::RuleMatch&gt;&gt; buildArrayForMatchedRuleList(const Vector&lt;RefPtr&lt;StyleRule&gt;&gt;&amp;, StyleResolver&amp;, Element*);
</del><ins>+    RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::RuleMatch&gt;&gt; buildArrayForMatchedRuleList(const Vector&lt;RefPtr&lt;StyleRule&gt;&gt;&amp;, StyleResolver&amp;, Element*, PseudoId);
</ins><span class="cx">     RefPtr&lt;Inspector::Protocol::CSS::CSSStyle&gt; buildObjectForAttributesStyle(Element*);
</span><span class="cx">     RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::CSS::Region&gt;&gt; buildArrayForRegions(ErrorString&amp;, RefPtr&lt;NodeList&gt;&amp;&amp;, int documentNodeId);
</span><span class="cx">     RefPtr&lt;Inspector::Protocol::CSS::NamedFlow&gt; buildObjectForNamedFlow(ErrorString&amp;, WebKitNamedFlow*, int documentNodeId);
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreinspectorInspectorDOMAgentcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.cpp        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -75,6 +75,7 @@
</span><span class="cx"> #include &quot;NodeList.h&quot;
</span><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;Pasteboard.h&quot;
</span><ins>+#include &quot;PseudoElement.h&quot;
</ins><span class="cx"> #include &quot;RenderStyle.h&quot;
</span><span class="cx"> #include &quot;RenderStyleConstants.h&quot;
</span><span class="cx"> #include &quot;ScriptState.h&quot;
</span><span class="lines">@@ -332,8 +333,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (is&lt;Element&gt;(*node)) {
</span><del>-        if (ShadowRoot* root = downcast&lt;Element&gt;(*node).shadowRoot())
</del><ins>+        Element&amp; element = downcast&lt;Element&gt;(*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-&gt;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-&gt;isInShadowTree()) {
</span><del>-        errorString = ASCIILiteral(&quot;Can not edit nodes from shadow trees&quot;);
</del><ins>+        errorString = ASCIILiteral(&quot;Cannot edit nodes from shadow trees&quot;);
</ins><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><ins>+    if (node-&gt;isPseudoElement()) {
+        errorString = ASCIILiteral(&quot;Cannot edit pseudo elements&quot;);
+        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-&gt;isInShadowTree()) {
</span><del>-        errorString = ASCIILiteral(&quot;Can not edit elements from shadow trees&quot;);
</del><ins>+        errorString = ASCIILiteral(&quot;Cannot edit elements from shadow trees&quot;);
</ins><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><ins>+    if (element-&gt;isPseudoElement()) {
+        errorString = ASCIILiteral(&quot;Cannot edit pseudo elements&quot;);
+        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-&gt;parentNode();
</span><span class="cx">     if (!parentNode) {
</span><del>-        errorString = ASCIILiteral(&quot;Can not remove detached node&quot;);
</del><ins>+        errorString = ASCIILiteral(&quot;Cannot remove detached node&quot;);
</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-&gt;completeURL(&quot;&quot;).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&lt;Inspector::Protocol::DOM::Node&gt; 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-&gt;setTemplateContent(buildObjectForNode(downcast&lt;HTMLTemplateElement&gt;(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(), &amp;pseudoType))
+                value-&gt;setPseudoType(pseudoType);
+        } else {
+            if (auto pseudoElements = buildArrayForPseudoElements(element, nodesMap))
+                value-&gt;setPseudoElements(WTF::move(pseudoElements));
+        }
+
</ins><span class="cx">     } else if (is&lt;Document&gt;(*node)) {
</span><span class="cx">         Document&amp; document = downcast&lt;Document&gt;(*node);
</span><span class="cx">         value-&gt;setFrameId(m_pageAgent-&gt;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&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::DOM::Node&gt;&gt; InspectorDOMAgent::buildArrayForPseudoElements(const Element&amp; element, NodeToIdMap* nodesMap)
+{
+    PseudoElement* beforeElement = element.beforePseudoElement();
+    PseudoElement* afterElement = element.afterPseudoElement();
+    if (!beforeElement &amp;&amp; !afterElement)
+        return nullptr;
+
+    auto pseudoElements = Inspector::Protocol::Array&lt;Inspector::Protocol::DOM::Node&gt;::create();
+    if (beforeElement)
+        pseudoElements-&gt;addItem(buildObjectForNode(beforeElement, 0, nodesMap));
+    if (afterElement)
+        pseudoElements-&gt;addItem(buildObjectForNode(afterElement, 0, nodesMap));
+    return WTF::move(pseudoElements);
+}
+
</ins><span class="cx"> Ref&lt;Inspector::Protocol::DOM::EventListener&gt; InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener&amp; registeredEventListener, const AtomicString&amp; eventType, Node* node, const String* objectGroupId)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;EventListener&gt; 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&amp; pseudoElement)
+{
+    Element* parent = pseudoElement.hostElement();
+    if (!parent)
+        return;
+
+    int parentId = m_documentNodeToIdMap.get(parent);
+    if (!parentId)
+        return;
+
+    pushChildNodesToFrontend(parentId, 1);
+    m_frontendDispatcher-&gt;pseudoElementAdded(parentId, buildObjectForNode(&amp;pseudoElement, 0, &amp;m_documentNodeToIdMap));
+}
+
+void InspectorDOMAgent::pseudoElementDestroyed(PseudoElement&amp; pseudoElement)
+{
+    int pseudoElementId = m_documentNodeToIdMap.get(&amp;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(&amp;pseudoElement, &amp;m_documentNodeToIdMap);
+    m_frontendDispatcher-&gt;pseudoElementRemoved(parentId, pseudoElementId);
+}
+
</ins><span class="cx"> Node* InspectorDOMAgent::nodeForPath(const String&amp; path)
</span><span class="cx"> {
</span><span class="cx">     // The path is of form &quot;1,HTML,2,BODY,1,DIV&quot;
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreinspectorInspectorDOMAgenth"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.h (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.h        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorDOMAgent.h        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -169,6 +169,8 @@
</span><span class="cx">     bool handleTouchEvent(Node&amp;);
</span><span class="cx">     void didCommitLoad(Document*);
</span><span class="cx">     void frameDocumentUpdated(Frame*);
</span><ins>+    void pseudoElementCreated(PseudoElement&amp;);
+    void pseudoElementDestroyed(PseudoElement&amp;);
</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&lt;Inspector::Protocol::DOM::Node&gt; buildObjectForNode(Node*, int depth, NodeToIdMap*);
</span><span class="cx">     Ref&lt;Inspector::Protocol::Array&lt;String&gt;&gt; buildArrayForElementAttributes(Element*);
</span><span class="cx">     Ref&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::DOM::Node&gt;&gt; buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap);
</span><ins>+    RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::DOM::Node&gt;&gt; buildArrayForPseudoElements(const Element&amp;, NodeToIdMap* nodesMap);
</ins><span class="cx">     Ref&lt;Inspector::Protocol::DOM::EventListener&gt; buildObjectForEventListener(const RegisteredEventListener&amp;, const AtomicString&amp; eventType, Node*, const String* objectGroupId);
</span><span class="cx">     RefPtr&lt;Inspector::Protocol::DOM::AccessibilityProperties&gt; buildObjectForAccessibilityProperties(Node*);
</span><span class="cx">     void processAccessibilityChildren(RefPtr&lt;AccessibilityObject&gt;&amp;&amp;, RefPtr&lt;Inspector::Protocol::Array&lt;int&gt;&gt;&amp;&amp;);
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreinspectorInspectorInstrumentationcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.cpp        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -208,6 +208,20 @@
</span><span class="cx">         domAgent-&gt;willPopShadowRoot(host, root);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InspectorInstrumentation::pseudoElementCreatedImpl(InstrumentingAgents&amp; instrumentingAgents, PseudoElement&amp; pseudoElement)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent())
+        domAgent-&gt;pseudoElementCreated(pseudoElement);
+}
+
+void InspectorInstrumentation::pseudoElementDestroyedImpl(InstrumentingAgents&amp; instrumentingAgents, PseudoElement&amp; pseudoElement)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents.inspectorDOMAgent())
+        domAgent-&gt;pseudoElementDestroyed(pseudoElement);
+    if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents.inspectorLayerTreeAgent())
+        layerTreeAgent-&gt;pseudoElementDestroyed(pseudoElement);
+}
+
</ins><span class="cx"> void InspectorInstrumentation::didCreateNamedFlowImpl(InstrumentingAgents&amp; instrumentingAgents, Document* document, WebKitNamedFlow&amp; namedFlow)
</span><span class="cx"> {
</span><span class="cx">     if (!document)
</span><span class="lines">@@ -1287,10 +1301,4 @@
</span><span class="cx">         layerTreeAgent-&gt;renderLayerDestroyed(renderLayer);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InspectorInstrumentation::pseudoElementDestroyedImpl(InstrumentingAgents&amp; instrumentingAgents, PseudoElement&amp; pseudoElement)
-{
-    if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents.inspectorLayerTreeAgent())
-        layerTreeAgent-&gt;pseudoElementDestroyed(pseudoElement);
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebCoreinspectorInspectorInstrumentationh"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.h (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.h        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorInstrumentation.h        2015-12-04 20:51:49 UTC (rev 193441)
</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&amp;);
</span><span class="cx">     static void didPushShadowRoot(Element&amp; host, ShadowRoot&amp;);
</span><span class="cx">     static void willPopShadowRoot(Element&amp; host, ShadowRoot&amp;);
</span><ins>+    static void pseudoElementCreated(Page*, PseudoElement&amp;);
+    static void pseudoElementDestroyed(Page*, PseudoElement&amp;);
</ins><span class="cx">     static void didCreateNamedFlow(Document*, WebKitNamedFlow&amp;);
</span><span class="cx">     static void willRemoveNamedFlow(Document*, WebKitNamedFlow&amp;);
</span><span class="cx">     static void didChangeRegionOverset(Document&amp;, WebKitNamedFlow&amp;);
</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&amp;);
</span><del>-    static void pseudoElementDestroyed(Page*, PseudoElement&amp;);
</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&amp;);
</span><span class="cx">     static void didPushShadowRootImpl(InstrumentingAgents&amp;, Element&amp; host, ShadowRoot&amp;);
</span><span class="cx">     static void willPopShadowRootImpl(InstrumentingAgents&amp;, Element&amp; host, ShadowRoot&amp;);
</span><ins>+    static void pseudoElementCreatedImpl(InstrumentingAgents&amp;, PseudoElement&amp;);
+    static void pseudoElementDestroyedImpl(InstrumentingAgents&amp;, PseudoElement&amp;);
</ins><span class="cx">     static void didCreateNamedFlowImpl(InstrumentingAgents&amp;, Document*, WebKitNamedFlow&amp;);
</span><span class="cx">     static void willRemoveNamedFlowImpl(InstrumentingAgents&amp;, Document*, WebKitNamedFlow&amp;);
</span><span class="cx">     static void didChangeRegionOversetImpl(InstrumentingAgents&amp;, Document&amp;, WebKitNamedFlow&amp;);
</span><span class="lines">@@ -449,7 +452,6 @@
</span><span class="cx"> 
</span><span class="cx">     static void layerTreeDidChangeImpl(InstrumentingAgents&amp;);
</span><span class="cx">     static void renderLayerDestroyedImpl(InstrumentingAgents&amp;, const RenderLayer&amp;);
</span><del>-    static void pseudoElementDestroyedImpl(InstrumentingAgents&amp;, PseudoElement&amp;);
</del><span class="cx"> 
</span><span class="cx">     static InstrumentingAgents* instrumentingAgentsForPage(Page&amp;);
</span><span class="cx">     static InstrumentingAgents* instrumentingAgentsForFrame(Frame&amp;);
</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&amp; pseudoElement)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        pseudoElementCreatedImpl(*instrumentingAgents, pseudoElement);
+}
+
+inline void InspectorInstrumentation::pseudoElementDestroyed(Page* page, PseudoElement&amp; 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&amp; 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&amp; 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&amp; 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="branchessafari601146branchSourceWebCoreinspectorInspectorOverlaycpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorOverlay.cpp (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorOverlay.cpp        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/inspector/InspectorOverlay.cpp        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;PageConfiguration.h&quot;
</span><span class="cx"> #include &quot;PolygonShape.h&quot;
</span><ins>+#include &quot;PseudoElement.h&quot;
</ins><span class="cx"> #include &quot;RectangleShape.h&quot;
</span><span class="cx"> #include &quot;RenderBoxModelObject.h&quot;
</span><span class="cx"> #include &quot;RenderElement.h&quot;
</span><span class="lines">@@ -686,17 +687,24 @@
</span><span class="cx">     if (!is&lt;Element&gt;(node) || !node-&gt;document().frame())
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    Element&amp; element = downcast&lt;Element&gt;(*node);
</del><ins>+    Element* effectiveElement = downcast&lt;Element&gt;(node);
+    if (node-&gt;isPseudoElement()) {
+        Element* hostElement = downcast&lt;PseudoElement&gt;(*node).hostElement();
+        if (!hostElement)
+            return nullptr;
+        effectiveElement = hostElement;
+    }
+
+    Element&amp; 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&lt;AtomicString&gt; usedClassNames;
</del><ins>+    StringBuilder classNames;
</ins><span class="cx">     if (element.hasClass() &amp;&amp; is&lt;StyledElement&gt;(element)) {
</span><del>-        StringBuilder classNames;
</del><ins>+        HashSet&lt;AtomicString&gt; usedClassNames;
</ins><span class="cx">         const SpaceSplitString&amp; classNamesString = downcast&lt;StyledElement&gt;(element).classNames();
</span><span class="cx">         size_t classNameCount = classNamesString.size();
</span><span class="cx">         for (size_t i = 0; i &lt; 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-&gt;isPseudoElement()) {
+        if (node-&gt;pseudoId() == BEFORE)
+            classNames.appendLiteral(&quot;::before&quot;);
+        else if (node-&gt;pseudoId() == AFTER)
+            classNames.appendLiteral(&quot;::after&quot;);
+    }
+    if (!classNames.isEmpty())
</ins><span class="cx">         elementData-&gt;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="branchessafari601146branchSourceWebCorestyleStyleResolveTreecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebCore/style/StyleResolveTree.cpp (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebCore/style/StyleResolveTree.cpp        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebCore/style/StyleResolveTree.cpp        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;ElementRareData.h&quot;
</span><span class="cx"> #include &quot;FlowThreadController.h&quot;
</span><span class="cx"> #include &quot;InsertionPoint.h&quot;
</span><ins>+#include &quot;InspectorInstrumentation.h&quot;
</ins><span class="cx"> #include &quot;LoaderStrategy.h&quot;
</span><span class="cx"> #include &quot;MainFrame.h&quot;
</span><span class="cx"> #include &quot;NodeRenderStyle.h&quot;
</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&lt;PseudoElement&gt; pseudoElement = PseudoElement::create(current, pseudoId);
</span><ins>+    InspectorInstrumentation::pseudoElementCreated(pseudoElement-&gt;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="branchessafari601146branchSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/ChangeLog (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/ChangeLog        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/ChangeLog        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -1,5 +1,91 @@
</span><span class="cx"> 2015-12-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r187496. rdar://problem/23581597
+
+    2015-07-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            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 &gt; .panel.details.css-style .rules &gt; *:first-child:matches(.new-rule)):
+            Since a pseudo element does not have a style attribute,
+            give some margin in the style sidebar above the &quot;New Rule&quot;
+            button so it looks better.
+
+2015-12-04  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r187249. rdar://problem/23581597
</span><span class="cx"> 
</span><span class="cx">     2015-07-23  Devin Rousso  &lt;drousso@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebInspectorUIUserInterfaceControllersDOMTreeManagerjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js        2015-12-04 20:51:49 UTC (rev 193441)
</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 &amp;&amp; i &lt; 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="branchessafari601146branchSourceWebInspectorUIUserInterfaceModelsDOMNodejs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Models/DOMNode.js        2015-12-04 20:51:49 UTC (rev 193441)
</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 &lt; 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 &gt; 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() + &quot;::&quot; + 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(&quot;id&quot;);
</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 &lt; 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: &quot;dom-node-attribute-modified&quot;,
</span><span class="cx">     AttributeRemoved: &quot;dom-node-attribute-removed&quot;
</span><span class="cx"> };
</span><ins>+
+WebInspector.DOMNode.PseudoElementType = {
+    Before: &quot;before&quot;,
+    After: &quot;after&quot;,
+};
</ins></span></pre></div>
<a id="branchessafari601146branchSourceWebInspectorUIUserInterfaceProtocolDOMObserverjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Protocol/DOMObserver.js        2015-12-04 20:51:49 UTC (rev 193441)
</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="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsCSSStyleDetailsSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js        2015-12-04 20:51:49 UTC (rev 193441)
</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="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx">         super(&quot;&quot;, node);
</span><span class="cx"> 
</span><span class="cx">         this._elementCloseTag = elementCloseTag;
</span><del>-        this.hasChildren = !elementCloseTag &amp;&amp; node.hasChildNodes() &amp;&amp; !this._showInlineText(node);
</del><ins>+        this.hasChildren = !elementCloseTag &amp;&amp; this._hasVisibleChildren();
</ins><span class="cx"> 
</span><span class="cx">         if (this.representedObject.nodeType() === Node.ELEMENT_NODE &amp;&amp; !elementCloseTag)
</span><span class="cx">             this._canAddAttributes = true;
</span><span class="lines">@@ -159,8 +159,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">@@ -190,19 +193,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 &gt;= 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 &gt; index;
</del><ins>+        return this.children[index];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _createTooltipForNode()
</span><span class="lines">@@ -285,7 +291,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">@@ -300,6 +306,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">@@ -326,78 +333,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 &amp;&amp; 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 &lt; size; ++i) {
-                        if (treeElement.children[i].representedObject === child) {
-                            existingTreeElement = treeElement.children[i];
-                            break;
-                        }
-                    }
-
-                    if (existingTreeElement &amp;&amp; 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 &lt; treeElement.expandedChildrenLimit) {
-                            var newElement = treeElement.insertChildElement(child, treeChildIndex);
-                            if (child === selectedNode)
-                                elementToSelect = newElement;
-                            if (treeElement.expandedChildCount &gt; 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 &gt;= 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 &amp;&amp; (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
</del><ins>+            if (selectedTreeElement &amp;&amp; (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 &lt; visibleChildren.length &amp;&amp; i &lt; 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 &gt; 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 &amp;&amp; (!lastChild || !lastChild._elementCloseTag))
</del><ins>+        if (node.nodeType() === Node.ELEMENT_NODE &amp;&amp; (!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">@@ -418,16 +432,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 &lt; limit; ++i)
-            this.insertChildElement(node.children[i], i);
</del><ins>+        for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, totalChildrenCount); i &lt; limit; ++i)
+            this.insertChildElement(totalChildrenCount[i], i);
</ins><span class="cx"> 
</span><span class="cx">         var expandedChildCount = this.expandedChildCount;
</span><del>-        if (childNodeCount &gt; this.expandedChildCount) {
</del><ins>+        if (totalChildrenCount &gt; this.expandedChildCount) {
</ins><span class="cx">             var targetButtonIndex = expandedChildCount;
</span><span class="cx">             if (!this.expandAllButtonElement) {
</span><span class="cx">                 var button = document.createElement(&quot;button&quot;);
</span><span class="lines">@@ -445,14 +461,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(&quot;Show All Nodes (%d More)&quot;).format(childNodeCount - expandedChildCount);
</del><ins>+            this.expandAllButtonElement.textContent = WebInspector.UIString(&quot;Show All Nodes (%d More)&quot;).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">@@ -575,7 +593,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 &amp;&amp; this.representedObject.nodeType() !== Node.TEXT_NODE)
</span><span class="lines">@@ -1114,7 +1132,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(&quot;span&quot;, &quot;webkit-html-fragment&quot;);
</del><ins>+                var fragmentElement = info.titleDOM.createChild(&quot;span&quot;, &quot;html-fragment&quot;);
</ins><span class="cx">                 if (node.isInShadowTree()) {
</span><span class="cx">                     fragmentElement.textContent = WebInspector.UIString(&quot;Shadow Content&quot;);
</span><span class="cx">                     fragmentElement.classList.add(&quot;shadow&quot;);
</span><span class="lines">@@ -1128,6 +1146,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(&quot;span&quot;, &quot;html-pseudo-element&quot;);
+                    pseudoElement.textContent = &quot;::&quot; + node.pseudoType();
+                    info.titleDOM.appendChild(document.createTextNode(&quot;\u200B&quot;));
+                    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">@@ -1237,6 +1263,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">@@ -1252,6 +1280,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="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeElementPathComponentjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeElementPathComponent.js        2015-12-04 20:51:49 UTC (rev 193441)
</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 = &quot;::&quot; + 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 = &quot;dom-element-icon&quot;;
</span><ins>+WebInspector.DOMTreeElementPathComponent.DOMPseudoElementIconStyleClassName = &quot;dom-pseudo-element-icon&quot;;
</ins><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMTextNodeIconStyleClassName = &quot;dom-text-node-icon&quot;;
</span><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMCommentIconStyleClassName = &quot;dom-comment-icon&quot;;
</span><span class="cx"> WebInspector.DOMTreeElementPathComponent.DOMDocumentTypeIconStyleClassName = &quot;dom-document-type-icon&quot;;
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinecss"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css        2015-12-04 20:51:49 UTC (rev 193441)
</span><span class="lines">@@ -154,12 +154,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: rgba(235, 215, 38, 0.2);
</span><span class="cx">     border-bottom: 1px solid rgb(237, 202, 71);
</span><span class="cx"> }
</span><del>-
-.webkit-html-fragment.shadow {
-    opacity: 0.6;
-}
</del></span></pre></div>
<a id="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsDOMTreeOutlinejs"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js        2015-12-04 20:51:49 UTC (rev 193441)
</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 &amp;&amp; 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, &quot;&quot;, resolvedNode);
</del><ins>+        WebInspector.RemoteObject.resolveNode(effectiveNode, &quot;&quot;, resolvedNode);
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsPathComponentIconscss"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/PathComponentIcons.css        2015-12-04 20:51:49 UTC (rev 193441)
</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="branchessafari601146branchSourceWebInspectorUIUserInterfaceViewsRulesStyleDetailsPanelcss"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css (193440 => 193441)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css        2015-12-04 20:51:31 UTC (rev 193440)
+++ branches/safari-601.1.46-branch/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css        2015-12-04 20:51:49 UTC (rev 193441)
</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 &gt; .panel.details.css-style .rules &gt; *:first-child:matches(.new-rule) {
+    margin-top: 8px;
+}
+
</ins><span class="cx"> .sidebar &gt; .panel.details.css-style &gt; .content.filter-in-progress .label {
</span><span class="cx">     padding-top: 15px;
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>