<!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>[200285] trunk</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/200285">200285</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-04-29 21:19:00 -0700 (Fri, 29 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Rename getAssignedNodes to assignedNodes and support flattened option
https://bugs.webkit.org/show_bug.cgi?id=157225

Reviewed by Antti Koivisto.

Source/WebCore:

Renamed getAssignedNodes and added the the support for {flattened: true/false} as spec'ed at
http://w3c.github.io/webcomponents/spec/shadow/#widl-HTMLSlotElement-assignedNodes-sequence-Node--AssignedNodesOptions-options

Test: fast/shadow-dom/HTMLSlotElement-interface.html

* html/HTMLSlotElement.cpp:
(WebCore::flattenAssignedNodes): Added.
(WebCore::HTMLSlotElement::assignedNodesForBindings): Added.
* html/HTMLSlotElement.h:
* html/HTMLSlotElement.idl:

LayoutTests:

* fast/shadow-dom/HTMLSlotElement-interface-expected.txt:
* fast/shadow-dom/HTMLSlotElement-interface.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomHTMLSlotElementinterfaceexpectedtxt">trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomHTMLSlotElementinterfacehtml">trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLSlotElementcpp">trunk/Source/WebCore/html/HTMLSlotElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLSlotElementh">trunk/Source/WebCore/html/HTMLSlotElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLSlotElementidl">trunk/Source/WebCore/html/HTMLSlotElement.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/LayoutTests/ChangeLog        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-04-29  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Rename getAssignedNodes to assignedNodes and support flattened option
+        https://bugs.webkit.org/show_bug.cgi?id=157225
+
+        Reviewed by Antti Koivisto.
+
+        * fast/shadow-dom/HTMLSlotElement-interface-expected.txt:
+        * fast/shadow-dom/HTMLSlotElement-interface.html:
+
</ins><span class="cx"> 2016-04-29  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Blur filter escapes an enclosing overflow:hidden
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomHTMLSlotElementinterfaceexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface-expected.txt (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface-expected.txt        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface-expected.txt        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -1,8 +1,20 @@
</span><span class="cx"> 
</span><span class="cx"> PASS HTMLSlotElement must be defined on window 
</span><span class="cx"> PASS &quot;name&quot; attribute on HTMLSlotElement must reflect &quot;name&quot; attribute 
</span><del>-PASS getAssignedNodes method on HTMLSlotElement must return the list of distributed nodes 
-PASS getAssignedNodes must update when slot and name attributes are modified 
-PASS getAssignedNodes must update when a default slot is introduced dynamically by a slot rename 
-PASS getAssignedNodes must update when slot elements are inserted or removed 
</del><ins>+PASS assignedNodes() on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree 
+PASS assignedNodes({&quot;flattened&quot;:false}) on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree 
+PASS assignedNodes({&quot;flattened&quot;:true}) on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree 
+PASS assignedNodes() must return the list of assigned nodes when none of the assigned nodes themselves are slots 
+PASS assignedNodes({&quot;flattened&quot;:false}) must return the list of assigned nodes when none of the assigned nodes themselves are slots 
+PASS assignedNodes({&quot;flattened&quot;:true}) must return the list of assigned nodes when none of the assigned nodes themselves are slots 
+PASS assignedNodes() must update when slot and name attributes are modified 
+PASS assignedNodes({&quot;flattened&quot;:false}) must update when slot and name attributes are modified 
+PASS assignedNodes({&quot;flattened&quot;:true}) must update when slot and name attributes are modified 
+PASS assignedNodes must update when a default slot is introduced dynamically by a slot rename 
+PASS assignedNodes({&quot;flattened&quot;:false}) must update when slot and name attributes are modified 
+PASS assignedNodes({&quot;flattened&quot;:true}) must update when slot and name attributes are modified 
+PASS assignedNodes must update when slot elements are inserted or removed 
+PASS assignedNodes must update when slot elements are inserted or removed 
+PASS assignedNodes must update when slot elements are inserted or removed 
+PASS assignedNodes({flatten: true}) must return the distributed nodes, and assignedNodes() and assignedNodes({flatten: false}) must returned the assigned nodes 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomHTMLSlotElementinterfacehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface.html (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface.html        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/LayoutTests/fast/shadow-dom/HTMLSlotElement-interface.html        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -34,126 +34,237 @@
</span><span class="cx">     assert_equals(slotElement.getAttribute('name'), 'bar', '&quot;name&quot; attribute must update the &quot;name&quot; content attribute');
</span><span class="cx"> }, '&quot;name&quot; attribute on HTMLSlotElement must reflect &quot;name&quot; attribute');
</span><span class="cx"> 
</span><del>-test(function () {
-    assert_true('getAssignedNodes' in HTMLSlotElement.prototype, '&quot;getAssignedNodes&quot; method must be defined on HTMLSlotElement.prototype');
</del><ins>+function testSlotOutsideShadowTree(options)
+{
+    test(function () {
+        assert_true('assignedNodes' in HTMLSlotElement.prototype, '&quot;assignedNodes&quot; method must be defined on HTMLSlotElement.prototype');
</ins><span class="cx"> 
</span><del>-    var shadowHost = document.createElement('div');
-    var child = document.createElement('p');
</del><ins>+        var slotElement = document.createElement('slot');
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() must return an empty array when the slot element is not in any tree');
</ins><span class="cx"> 
</span><del>-    var shadowRoot = shadowHost.attachShadow({mode: 'open'});
-    var slotElement = document.createElement('slot');
-    shadowRoot.appendChild(slotElement);
</del><ins>+        document.body.appendChild(slotElement);
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() must return an empty array when the slot element is in a document tree');
</ins><span class="cx"> 
</span><del>-    assert_array_equals(slotElement.getAssignedNodes(), [], 'getAssignedNodes must return an empty array when there are no nodes in the shadow tree');
</del><ins>+    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '')
+        + ') on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree');
+}
</ins><span class="cx"> 
</span><del>-    shadowHost.appendChild(child);
-    assert_array_equals(slotElement.getAssignedNodes(), [child], 'getAssignedNodes on a default slot must return an element without slot element');
</del><ins>+testSlotOutsideShadowTree(null);
+testSlotOutsideShadowTree({flattened: false});
+testSlotOutsideShadowTree({flattened: true});
</ins><span class="cx"> 
</span><del>-    child.setAttribute('slot', 'foo');
-    assert_array_equals(slotElement.getAssignedNodes(), [], 'getAssignedNodes on a default slot must not return an element with non-empty slot attribute');
</del><ins>+function testSingleLevelOfSlotting(options)
+{
+    test(function () {
+        assert_true('assignedNodes' in HTMLSlotElement.prototype, '&quot;assignedNodes&quot; method must be defined on HTMLSlotElement.prototype');
</ins><span class="cx"> 
</span><del>-    child.setAttribute('slot', '');
-    assert_array_equals(slotElement.getAssignedNodes(), [child], 'getAssignedNodes on a default slot must return an element with empty slot attribute');
</del><ins>+        var shadowHost = document.createElement('div');
+        var child = document.createElement('p');
</ins><span class="cx"> 
</span><del>-    slotElement.setAttribute('name', 'bar');
-    assert_array_equals(slotElement.getAssignedNodes(), [], 'getAssignedNodes on a named slot must not return an element with empty slot attribute');
</del><ins>+        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
+        var slotElement = document.createElement('slot');
+        shadowRoot.appendChild(slotElement);
</ins><span class="cx"> 
</span><del>-    slotElement.setAttribute('name', '');
-    assert_array_equals(slotElement.getAssignedNodes(), [child], 'getAssignedNodes on an empty name slot must return an element with empty slot attribute');
</del><ins>+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() must return an empty array when there are no nodes in the shadow tree');
</ins><span class="cx"> 
</span><del>-}, 'getAssignedNodes method on HTMLSlotElement must return the list of distributed nodes');
</del><ins>+        shadowHost.appendChild(child);
+        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes() on a default slot must return an element without slot element');
</ins><span class="cx"> 
</span><del>-test(function () {
-    var shadowHost = document.createElement('div');
-    var p = document.createElement('p');
-    var b = document.createElement('b');
-    shadowHost.appendChild(p);
-    shadowHost.appendChild(b);
</del><ins>+        child.setAttribute('slot', 'foo');
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() on a default slot must not return an element with non-empty slot attribute');
</ins><span class="cx"> 
</span><del>-    var shadowRoot = shadowHost.attachShadow({mode: 'open'});
-    var slotElement = document.createElement('slot');
-    shadowRoot.appendChild(slotElement);
</del><ins>+        child.setAttribute('slot', '');
+        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes() on a default slot must return an element with empty slot attribute');
</ins><span class="cx"> 
</span><del>-    assert_array_equals(slotElement.getAssignedNodes(), [p, b], 'getAssignedNodes must return the distributed nodes');
</del><ins>+        slotElement.setAttribute('name', 'bar');
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() on a named slot must not return an element with empty slot attribute');
</ins><span class="cx"> 
</span><del>-    slotElement.name = 'foo';
-    assert_array_equals(slotElement.getAssignedNodes(), [], 'getAssignedNodes must be empty when there are no matching elements for the slot name');
</del><ins>+        slotElement.setAttribute('name', '');
+        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes() on an empty name slot must return an element with empty slot attribute');
</ins><span class="cx"> 
</span><del>-    b.slot = 'foo';
-    assert_array_equals(slotElement.getAssignedNodes(), [b], 'getAssignedNodes must return the nodes with the matching slot name');
</del><ins>+    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '') + ') must return the list of assigned nodes when none of the assigned nodes themselves are slots');
+}
</ins><span class="cx"> 
</span><del>-    p.slot = 'foo';
-    assert_array_equals(slotElement.getAssignedNodes(), [p, b], 'getAssignedNodes must return the nodes with the matching slot name in the tree order');
</del><ins>+testSingleLevelOfSlotting(null);
+testSingleLevelOfSlotting({flattened: false});
+testSingleLevelOfSlotting({flattened: true});
</ins><span class="cx"> 
</span><del>-    slotElement.removeAttribute('name');
-    assert_array_equals(slotElement.getAssignedNodes(), [], 'getAssignedNodes must be empty for a default slot when all elements have &quot;slot&quot; attributes specified');
</del><ins>+function testMutatingSlottedContents(options)
+{
+    test(function () {
+        var shadowHost = document.createElement('div');
+        var p = document.createElement('p');
+        var b = document.createElement('b');
+        shadowHost.appendChild(p);
+        shadowHost.appendChild(b);
</ins><span class="cx"> 
</span><del>-}, 'getAssignedNodes must update when slot and name attributes are modified');
</del><ins>+        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
+        var slotElement = document.createElement('slot');
+        shadowRoot.appendChild(slotElement);
</ins><span class="cx"> 
</span><del>-test(function () {
-    var shadowHost = document.createElement('div');
-    var child = document.createElement('span');
-    shadowHost.appendChild(child);
</del><ins>+        assert_array_equals(slotElement.assignedNodes(options), [p, b], 'assignedNodes must return the distributed nodes');
</ins><span class="cx"> 
</span><del>-    var shadowRoot = shadowHost.attachShadow({mode: 'open'});
-    var slotElement = document.createElement('slot');
-    slotElement.name = 'foo';
-    shadowRoot.appendChild(slotElement);
</del><ins>+        slotElement.name = 'foo';
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes must be empty when there are no matching elements for the slot name');
</ins><span class="cx"> 
</span><del>-    assert_array_equals(slotElement.getAssignedNodes(), [], 'getAssignedNodes must be empty when there are no matching elements for the slot name');
</del><ins>+        b.slot = 'foo';
+        assert_array_equals(slotElement.assignedNodes(options), [b], 'assignedNodes must return the nodes with the matching slot name');
</ins><span class="cx"> 
</span><del>-    slotElement.removeAttribute('name');
-    assert_array_equals(slotElement.getAssignedNodes(), [child], 'getAssignedNodes must be empty when there are no matching elements for the slot name');
</del><ins>+        p.slot = 'foo';
+        assert_array_equals(slotElement.assignedNodes(options), [p, b], 'assignedNodes must return the nodes with the matching slot name in the tree order');
</ins><span class="cx"> 
</span><del>-}, 'getAssignedNodes must update when a default slot is introduced dynamically by a slot rename');
</del><ins>+        slotElement.removeAttribute('name');
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes must be empty for a default slot when all elements have &quot;slot&quot; attributes specified');
</ins><span class="cx"> 
</span><ins>+    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '') + ') must update when slot and name attributes are modified');
+}
+
+testMutatingSlottedContents(null);
+testMutatingSlottedContents({flattened: false});
+testMutatingSlottedContents({flattened: true});
+
+function testMutatingSlotName(options)
+{
+    test(function () {
+        var shadowHost = document.createElement('div');
+        var child = document.createElement('span');
+        shadowHost.appendChild(child);
+
+        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
+        var slotElement = document.createElement('slot');
+        slotElement.name = 'foo';
+        shadowRoot.appendChild(slotElement);
+
+        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes must be empty when there are no matching elements for the slot name');
+
+        slotElement.removeAttribute('name');
+        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes must be empty when there are no matching elements for the slot name');
+
+    }, 'assignedNodes must update when a default slot is introduced dynamically by a slot rename');
+}
+
+testMutatingSlotName(null);
+testMutatingSlottedContents({flattened: false});
+testMutatingSlottedContents({flattened: true});
+
+function testInsertingAndRemovingSlots(options)
+{
+    test(function () {
+        var shadowHost = document.createElement('div');
+        var p = document.createElement('p');
+        var text = document.createTextNode('');
+        var comment = document.createComment('');
+        var processingInstruction = document.createProcessingInstruction('target', 'data');
+        var b = document.createElement('b');
+        shadowHost.appendChild(p);
+        shadowHost.appendChild(text);
+        shadowHost.appendChild(comment);
+        shadowHost.appendChild(processingInstruction);
+        shadowHost.appendChild(b);
+
+        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
+
+        var firstSlotElement = document.createElement('slot');
+        shadowRoot.appendChild(firstSlotElement);
+
+        var secondSlotElement = document.createElement('slot');
+        shadowRoot.appendChild(secondSlotElement);
+
+        assert_array_equals(firstSlotElement.assignedNodes(options), [p, text, b],
+            'assignedNodes on a default slot must return the elements without slot attributes and text nodes');
+        assert_array_equals(secondSlotElement.assignedNodes(options), [],
+            'assignedNodes on the second unnamed slot element must return an empty array');
+
+        shadowRoot.removeChild(firstSlotElement);
+        assert_array_equals(firstSlotElement.assignedNodes(options), [],
+            'assignedNodes on a detached formerly-default slot must return an empty array');
+        assert_array_equals(secondSlotElement.assignedNodes(options), [p, text, b],
+            'assignedNodes on the second unnamed slot element after removing the first must return the elements without slot attributes and text nodes');
+
+        shadowRoot.removeChild(secondSlotElement);
+        shadowRoot.appendChild(secondSlotElement);
+        assert_array_equals(firstSlotElement.assignedNodes(options), [],
+            'Removing and re-inserting a default slot must not change the result of assignedNodes on a detached slot');
+        assert_array_equals(secondSlotElement.assignedNodes(options), [p, text, b],
+            'Removing and re-inserting a default slot must not change the result of assignedNodes');
+
+        shadowRoot.insertBefore(firstSlotElement, secondSlotElement);
+        assert_array_equals(firstSlotElement.assignedNodes(options), [p, text, b],
+            'assignedNodes on a newly inserted unnamed slot element must return the elements without slot attributes and text nodes');
+        assert_array_equals(secondSlotElement.assignedNodes(options), [],
+            'assignedNodes on formerly-first but now second unnamed slot element must return an empty array');
+
+    }, 'assignedNodes must update when slot elements are inserted or removed');
+}
+
+testInsertingAndRemovingSlots(null);
+testInsertingAndRemovingSlots({flattened: false});
+testInsertingAndRemovingSlots({flattened: true});
+
</ins><span class="cx"> test(function () {
</span><del>-    var shadowHost = document.createElement('div');
-    var p = document.createElement('p');
-    var text = document.createTextNode('');
-    var comment = document.createComment('');
-    var processingInstruction = document.createProcessingInstruction('target', 'data');
-    var b = document.createElement('b');
-    shadowHost.appendChild(p);
-    shadowHost.appendChild(text);
-    shadowHost.appendChild(comment);
-    shadowHost.appendChild(processingInstruction);
-    shadowHost.appendChild(b);
</del><ins>+    var outerHost = document.createElement('div');
+    var outerChild = document.createElement('span');
+    outerHost.appendChild(outerChild);
</ins><span class="cx"> 
</span><del>-    var shadowRoot = shadowHost.attachShadow({mode: 'open'});
</del><ins>+    var outerShadow = outerHost.attachShadow({mode: 'closed'});
+    var innerHost = document.createElement('div');
+    var outerSlot = document.createElement('slot');
+    var innerChild = document.createElement('b');
+    outerShadow.appendChild(innerHost);
+    innerHost.appendChild(outerSlot);
+    innerHost.appendChild(innerChild);
</ins><span class="cx"> 
</span><del>-    var firstSlotElement = document.createElement('slot');
-    shadowRoot.appendChild(firstSlotElement);
</del><ins>+    var innerShadow = innerHost.attachShadow({mode: 'closed'});
+    var innerSlot = document.createElement('slot');
+    innerShadow.appendChild(innerSlot);
</ins><span class="cx"> 
</span><del>-    var secondSlotElement = document.createElement('slot');
-    shadowRoot.appendChild(secondSlotElement);
</del><ins>+    assert_array_equals(outerSlot.assignedNodes(), [outerChild], 'assignedNodes() on a default slot must return the assigned nodes');
+    assert_array_equals(outerSlot.assignedNodes({flatten: false}), [outerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
+    assert_array_equals(outerSlot.assignedNodes({flatten: true}), [outerChild], 'assignedNodes({flatten: true}) on a default slot must return the assigned nodes if they are not themselves slots');
</ins><span class="cx"> 
</span><del>-    assert_array_equals(firstSlotElement.getAssignedNodes(), [p, text, b],
-        'getAssignedNodes on a default slot must return the elements without slot attributes and text nodes');
-    assert_array_equals(secondSlotElement.getAssignedNodes(), [],
-        'getAssignedNodes on the second unnamed slot element must return an empty array');
</del><ins>+    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
</ins><span class="cx"> 
</span><del>-    shadowRoot.removeChild(firstSlotElement);
-    assert_array_equals(firstSlotElement.getAssignedNodes(), [],
-        'getAssignedNodes on a detached formerly-default slot must return an empty array');
-    assert_array_equals(secondSlotElement.getAssignedNodes(), [p, text, b],
-        'getAssignedNodes on the second unnamed slot element after removing the first must return the elements without slot attributes and text nodes');
</del><ins>+    outerSlot.name = 'foo';
+    assert_array_equals(outerSlot.assignedNodes(), [], 'assignedNodes() on a named slot must return an empty array if there are no matching elements');
+    assert_array_equals(outerSlot.assignedNodes({flatten: false}), [], 'assignedNodes({flatten: false}) on a named slot must return an empty array if there are no matching elements');
+    assert_array_equals(outerSlot.assignedNodes({flatten: true}), [], 'assignedNodes({flatten: true}) on a named slot must return an empty array if there are no matching elements');
</ins><span class="cx"> 
</span><del>-    shadowRoot.removeChild(secondSlotElement);
-    shadowRoot.appendChild(secondSlotElement);
-    assert_array_equals(firstSlotElement.getAssignedNodes(), [],
-        'Removing and re-inserting a default slot must not change the result of getAssignedNodes on a detached slot');
-    assert_array_equals(secondSlotElement.getAssignedNodes(), [p, text, b],
-        'Removing and re-inserting a default slot must not change the result of getAssignedNodes');
</del><ins>+    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
</ins><span class="cx"> 
</span><del>-    shadowRoot.insertBefore(firstSlotElement, secondSlotElement);
-    assert_array_equals(firstSlotElement.getAssignedNodes(), [p, text, b],
-        'getAssignedNodes on a newly inserted unnamed slot element must return the elements without slot attributes and text nodes');
-    assert_array_equals(secondSlotElement.getAssignedNodes(), [],
-        'getAssignedNodes on formerly-first but now second unnamed slot element must return an empty array');
</del><ins>+    outerChild.slot = 'foo';
+    assert_array_equals(outerSlot.assignedNodes(), [outerChild], 'assignedNodes() on a named slot must return matching elements');
+    assert_array_equals(outerSlot.assignedNodes({flatten: false}), [outerChild], 'assignedNodes({flatten: false}) on a named slot must return matching elements');
+    assert_array_equals(outerSlot.assignedNodes({flatten: true}), [outerChild], 'assignedNodes({flatten: true}) on a named slot must return matching elements');
</ins><span class="cx"> 
</span><del>-}, 'getAssignedNodes must update when slot elements are inserted or removed');
</del><ins>+    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
</ins><span class="cx"> 
</span><ins>+    var newInnerSlot = document.createElement('slot');
+    innerShadow.insertBefore(newInnerSlot, innerSlot);
+    assert_array_equals(newInnerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
+    assert_array_equals(newInnerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
+    assert_array_equals(newInnerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
+
+    assert_array_equals(innerSlot.assignedNodes(), [], 'assignedNodes() on a nameless slot element which appears after a default slot must return an empty array');
+    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [], 'assignedNodes({flatten: false}) on a nameless slot element which appears after a default slot must return an empty array');
+    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [], 'assignedNodes({flatten: true}) on a nameless slot element which appears after a default slot must return an empty array');
+
+    innerShadow.removeChild(newInnerSlot);
+    assert_array_equals(newInnerSlot.assignedNodes(), [], 'assignedNodes() must return an empty array when the slot element is not in any tree');
+    assert_array_equals(newInnerSlot.assignedNodes({flatten: false}), [], 'assignedNodes({flatten: false}) must return an empty array when the slot element is not in any tree');
+    assert_array_equals(newInnerSlot.assignedNodes({flatten: true}), [], 'assignedNodes({flatten: true}) must return an empty array when the slot element is not in any tree');
+
+    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
+    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
+
+}, 'assignedNodes({flatten: true}) must return the distributed nodes, and assignedNodes() and assignedNodes({flatten: false}) must returned the assigned nodes');
+
</ins><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/Source/WebCore/ChangeLog        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2016-04-29  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Rename getAssignedNodes to assignedNodes and support flattened option
+        https://bugs.webkit.org/show_bug.cgi?id=157225
+
+        Reviewed by Antti Koivisto.
+
+        Renamed getAssignedNodes and added the the support for {flattened: true/false} as spec'ed at
+        http://w3c.github.io/webcomponents/spec/shadow/#widl-HTMLSlotElement-assignedNodes-sequence-Node--AssignedNodesOptions-options
+
+        Test: fast/shadow-dom/HTMLSlotElement-interface.html
+
+        * html/HTMLSlotElement.cpp:
+        (WebCore::flattenAssignedNodes): Added.
+        (WebCore::HTMLSlotElement::assignedNodesForBindings): Added.
+        * html/HTMLSlotElement.h:
+        * html/HTMLSlotElement.idl:
+
</ins><span class="cx"> 2016-04-29  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Make clipToRect() and restoreClip() have similar signatures
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLSlotElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLSlotElement.cpp (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLSlotElement.cpp        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/Source/WebCore/html/HTMLSlotElement.cpp        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
</span><span class="cx"> 
</span><ins>+#include &quot;Dictionary.h&quot;
</ins><span class="cx"> #include &quot;ElementChildIterator.h&quot;
</span><span class="cx"> #include &quot;Event.h&quot;
</span><span class="cx"> #include &quot;EventNames.h&quot;
</span><span class="lines">@@ -99,6 +100,36 @@
</span><span class="cx">     return shadowRoot-&gt;assignedNodesForSlot(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void flattenAssignedNodes(Vector&lt;Node*&gt;&amp; nodes, const Vector&lt;Node*&gt;&amp; assignedNodes)
+{
+    for (Node* node : assignedNodes) {
+        if (is&lt;HTMLSlotElement&gt;(*node)) {
+            if (auto* innerAssignedNodes = downcast&lt;HTMLSlotElement&gt;(*node).assignedNodes())
+                flattenAssignedNodes(nodes, *innerAssignedNodes);
+            continue;
+        }
+        nodes.append(node);
+    }
+}
+
+const Vector&lt;Node*&gt; HTMLSlotElement::assignedNodesForBindings(const Dictionary&amp; options) const
+{
+    bool shouldFlatten = false;
+    options.get(&quot;flatten&quot;, shouldFlatten);
+
+    Vector&lt;Node*&gt; nodes;
+    auto* assignedNodes = this-&gt;assignedNodes();
+    if (!assignedNodes)
+        return nodes;
+
+    if (shouldFlatten)
+        flattenAssignedNodes(nodes, *assignedNodes);
+    else
+        nodes = *assignedNodes;
+
+    return nodes;
+}
+
</ins><span class="cx"> void HTMLSlotElement::enqueueSlotChangeEvent()
</span><span class="cx"> {
</span><span class="cx">     if (m_hasEnqueuedSlotChangeEvent)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLSlotElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLSlotElement.h (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLSlotElement.h        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/Source/WebCore/html/HTMLSlotElement.h        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx">     static Ref&lt;HTMLSlotElement&gt; create(const QualifiedName&amp;, Document&amp;);
</span><span class="cx"> 
</span><span class="cx">     const Vector&lt;Node*&gt;* assignedNodes() const;
</span><ins>+    const Vector&lt;Node*&gt; assignedNodesForBindings(const Dictionary&amp; options) const;
</ins><span class="cx"> 
</span><span class="cx">     void enqueueSlotChangeEvent();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLSlotElementidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLSlotElement.idl (200284 => 200285)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLSlotElement.idl        2016-04-30 04:13:22 UTC (rev 200284)
+++ trunk/Source/WebCore/html/HTMLSlotElement.idl        2016-04-30 04:19:00 UTC (rev 200285)
</span><span class="lines">@@ -31,6 +31,6 @@
</span><span class="cx"> ] interface HTMLSlotElement : HTMLElement {
</span><span class="cx"> 
</span><span class="cx">     [Reflect] attribute DOMString name;
</span><del>-    [ImplementedAs=assignedNodes] sequence&lt;Node&gt; getAssignedNodes();
</del><ins>+    [ImplementedAs=assignedNodesForBindings] sequence&lt;Node&gt; assignedNodes(optional Dictionary options);
</ins><span class="cx"> 
</span><span class="cx"> };
</span></span></pre>
</div>
</div>

</body>
</html>