<!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>[198056] 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/198056">198056</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-11 19:11:04 -0800 (Fri, 11 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add Event.deepPath() and Event.scoped
https://bugs.webkit.org/show_bug.cgi?id=153538
&lt;rdar://problem/24363836&gt;

Reviewed by Darin Adler.

Source/WebCore:

Added the support for deepPath(), scoped, and relatedTargetScoped on Event.prototype for shadow DOM:
http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-event-interface
and updated the EventPath class to respect scoped and relatedTargetScoped flags as specified at:
http://w3c.github.io/webcomponents/spec/shadow/#get-the-parent

Tests: fast/shadow-dom/Extensions-to-Event-Interface.html
       fast/shadow-dom/trusted-event-scoped-flags.html

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateConstructorDefinition): Added the support for Conditional for InitializedByEventConstructor.
* bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.cpp:
* bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.h:
* bindings/scripts/test/JS/JSTestEventConstructor.cpp:
* bindings/scripts/test/ObjC/DOMTestEventConstructor.h:
* bindings/scripts/test/ObjC/DOMTestEventConstructor.mm:
* bindings/scripts/test/TestEventConstructor.idl: Added a test case for using InitializedByEventConstructor
with Conditional.
* dom/Event.cpp:
(WebCore::Event::Event): Initialize m_scoped and m_relatedTargetScoped from EventInit dictionary.
(WebCore::Event::scoped): Added. Implements http://w3c.github.io/webcomponents/spec/shadow/#scoped-flag
(WebCore::Event::deepPath): Added.
* dom/Event.h:
(WebCore::Event::relatedTargetScoped): Added. Overridden by FocusEvent and MouseEvent to implement
http://w3c.github.io/webcomponents/spec/shadow/#relatedtargetscoped-flag
(WebCore::Event::setEventPath): Added.
(WebCore::Event::clearEventPath): Added.
* dom/Event.idl: Added scoped, relatedTargetScoped, and deepPath() conditionally enabled for shadow DOM.
* dom/EventContext.h:
(WebCore::EventContext::currentTarget):
* dom/EventDispatcher.cpp:
(WebCore::EventDispatcher::dispatchEvent): Set the event path while the event is being dispatched.
* dom/EventPath.cpp:
(WebCore::shouldEventCrossShadowBoundary): Check event.scoped flag instead of hard-coding a list of events here
which has been moved to Event::scoped. See above.
(WebCore::EventPath::setRelatedTarget): Check m_event.relatedTargetScoped() instead of hard-coding a list of
events here. relatedTargetScoped is overridden by FocusEvent and MouseEvent.
(WebCore::EventPath::hasEventListeners): Fixed the misleading variable name.
(WebCore::isUnclosedNodeOf): Added. Implements http://w3c.github.io/webcomponents/spec/shadow/#dfn-unclosed-node
(WebCore::EventPath::computePathDisclosedToTarget): Added. Implements the algorithm to filter event targets:
http://w3c.github.io/webcomponents/spec/shadow/#widl-Event-deepPath-sequence-EventTarget
* dom/EventPath.h:
* dom/FocusEvent.cpp:
(WebCore::FocusEvent::relatedTargetScoped): Returns true when this is a trusted event per:
http://w3c.github.io/webcomponents/spec/shadow/#relatedtargetscoped-flag
* dom/FocusEvent.h:
* dom/MouseEvent.cpp:
(WebCore::MouseEvent::relatedTargetScoped): Ditto.
* dom/MouseEvent.h:

LayoutTests:

Added a W3C style testharness.js tests for Event.prototype.scoped, Event.prototype.scopedRelatedTarget,
Event.prototype.deepPath() and a test that uses eventSender to verify the values of the scoped and
scopedRelatedTarget flags on trusted events.

* fast/shadow-dom/Extensions-to-Event-Interface-expected.txt: Added.
* fast/shadow-dom/Extensions-to-Event-Interface.html: Added.
* fast/shadow-dom/event-with-related-target.html:
* fast/shadow-dom/resources: Added.
* fast/shadow-dom/resources/event-path-test-helpers.js: Added. Extracted from event-with-related-target.html.
* fast/shadow-dom/trusted-event-scoped-flags-expected.txt: Added.
* fast/shadow-dom/trusted-event-scoped-flags.html: Added.
* fast/xmlhttprequest/xmlhttprequest-get-expected.txt:
* http/tests/workers/worker-importScriptsOnError-expected.txt:
* inspector/model/remote-object-get-properties-expected.txt:
* platform/ios-simulator/fast/shadow-dom/trusted-event-scoped-flags-expected.txt: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomeventwithrelatedtargethtml">trunk/LayoutTests/fast/shadow-dom/event-with-related-target.html</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomnegativetabindexonshadowhostexpectedtxt">trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomnegativetabindexonshadowhosthtml">trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host.html</a></li>
<li><a href="#trunkLayoutTestsfastxmlhttprequestxmlhttprequestgetexpectedtxt">trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsworkersworkerimportScriptsOnErrorexpectedtxt">trunk/LayoutTests/http/tests/workers/worker-importScriptsOnError-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectormodelremoteobjectgetpropertiesexpectedtxt">trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestGObjectWebKitDOMTestEventConstructorcpp">trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestGObjectWebKitDOMTestEventConstructorh">trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.h</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestJSJSTestEventConstructorcpp">trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestObjCDOMTestEventConstructorh">trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.h</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestObjCDOMTestEventConstructormm">trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.mm</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestTestEventConstructoridl">trunk/Source/WebCore/bindings/scripts/test/TestEventConstructor.idl</a></li>
<li><a href="#trunkSourceWebCoredomEventcpp">trunk/Source/WebCore/dom/Event.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventh">trunk/Source/WebCore/dom/Event.h</a></li>
<li><a href="#trunkSourceWebCoredomEventidl">trunk/Source/WebCore/dom/Event.idl</a></li>
<li><a href="#trunkSourceWebCoredomEventContexth">trunk/Source/WebCore/dom/EventContext.h</a></li>
<li><a href="#trunkSourceWebCoredomEventDispatchercpp">trunk/Source/WebCore/dom/EventDispatcher.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventPathcpp">trunk/Source/WebCore/dom/EventPath.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventPathh">trunk/Source/WebCore/dom/EventPath.h</a></li>
<li><a href="#trunkSourceWebCoredomFocusEventcpp">trunk/Source/WebCore/dom/FocusEvent.cpp</a></li>
<li><a href="#trunkSourceWebCoredomFocusEventh">trunk/Source/WebCore/dom/FocusEvent.h</a></li>
<li><a href="#trunkSourceWebCoredomMouseEventcpp">trunk/Source/WebCore/dom/MouseEvent.cpp</a></li>
<li><a href="#trunkSourceWebCoredomMouseEventh">trunk/Source/WebCore/dom/MouseEvent.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastshadowdomExtensionstoEventInterfaceexpectedtxt">trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomExtensionstoEventInterfacehtml">trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface.html</a></li>
<li>trunk/LayoutTests/fast/shadow-dom/resources/</li>
<li><a href="#trunkLayoutTestsfastshadowdomresourceseventpathtesthelpersjs">trunk/LayoutTests/fast/shadow-dom/resources/event-path-test-helpers.js</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomtrustedeventscopedflagsexpectedtxt">trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomtrustedeventscopedflagshtml">trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags.html</a></li>
<li>trunk/LayoutTests/platform/ios-simulator/fast/shadow-dom/</li>
<li><a href="#trunkLayoutTestsplatformiossimulatorfastshadowdomtrustedeventscopedflagsexpectedtxt">trunk/LayoutTests/platform/ios-simulator/fast/shadow-dom/trusted-event-scoped-flags-expected.txt</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/ChangeLog        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2016-03-11  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Add Event.deepPath() and Event.scoped
+        https://bugs.webkit.org/show_bug.cgi?id=153538
+        &lt;rdar://problem/24363836&gt;
+
+        Reviewed by Darin Adler.
+
+        Added a W3C style testharness.js tests for Event.prototype.scoped, Event.prototype.scopedRelatedTarget,
+        Event.prototype.deepPath() and a test that uses eventSender to verify the values of the scoped and
+        scopedRelatedTarget flags on trusted events.
+
+        * fast/shadow-dom/Extensions-to-Event-Interface-expected.txt: Added.
+        * fast/shadow-dom/Extensions-to-Event-Interface.html: Added.
+        * fast/shadow-dom/event-with-related-target.html:
+        * fast/shadow-dom/resources: Added.
+        * fast/shadow-dom/resources/event-path-test-helpers.js: Added. Extracted from event-with-related-target.html.
+        * fast/shadow-dom/trusted-event-scoped-flags-expected.txt: Added.
+        * fast/shadow-dom/trusted-event-scoped-flags.html: Added.
+        * fast/xmlhttprequest/xmlhttprequest-get-expected.txt:
+        * http/tests/workers/worker-importScriptsOnError-expected.txt:
+        * inspector/model/remote-object-get-properties-expected.txt:
+        * platform/ios-simulator/fast/shadow-dom/trusted-event-scoped-flags-expected.txt: Added.
+
</ins><span class="cx"> 2016-03-11  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebKit should not be redirected to an invalid URL
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomExtensionstoEventInterfaceexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface-expected.txt (0 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+
+PASS deepPath() must exist on Event 
+PASS deepPath() must return an empty array when the event has not been dispatched 
+PASS deepPath() must return an empty array when the event is no longer dispatched 
+PASS scoped must exist on Event 
+PASS scoped on EventInit must default to false 
+PASS scoped on EventInit must set the scoped flag 
+PASS relatedTargetScoped must exist on Event 
+PASS relatedTargetScoped on EventInit must default to false 
+PASS relatedTargetScoped on EventInit must set the scoped flag 
+PASS The event must propagate out of open mode shadow boundaries when the scoped flag is unset 
+PASS The event must propagate out of closed mode shadow boundaries when the scoped flag is unset 
+PASS The event must not propagate out of open mode shadow boundaries when the scoped flag is set 
+PASS The event must not propagate out of closed mode shadow boundaries when the scoped flag is set 
+PASS The event must propagate out of open mode shadow boundaries when the scoped flag is unset on an event with relatedTarget 
+PASS The event must propagate out of closed mode shadow boundaries when the scoped flag is unset on an event with relatedTarget 
+PASS The event must not propagate out of open mode shadow boundaries when the scoped flag is set on an event with relatedTarget 
+PASS The event must not propagate out of closed mode shadow boundaries when the scoped flag is set on an event with relatedTarget 
+PASS The event must not propagate out of open mode shadow tree of the target but must propagate out of inner shadow trees when the scoped flag is set 
+PASS The event must not propagate out of closed mode shadow tree of the target but must propagate out of inner shadow trees when the scoped flag is set 
+PASS The event must propagate out of open mode shadow tree in which the relative target and the relative related target are the same 
+PASS The event must propagate out of closed mode shadow tree in which the relative target and the relative related target are the same 
+PASS deepPath() must contain and only contain the unclosed nodes of target in open mode shadow trees 
+PASS deepPath() must contain and only contain the unclosed nodes of target in closed mode shadow trees 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomExtensionstoEventInterfacehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface.html (0 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface.html                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Extensions-to-Event-Interface.html        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -0,0 +1,285 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Shadow DOM: Extensions to Event Interface&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;Event interface must have deepPath() as a method&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-event-interface&quot;&gt;
+&lt;script src=&quot;../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/event-path-test-helpers.js&quot;&gt;&lt;/script&gt;
+&lt;link rel='stylesheet' href='../../resources/testharness.css'&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+test(function () {
+    assert_true('deepPath' in Event.prototype);
+    assert_true('deepPath' in new Event('my-event'));
+}, 'deepPath() must exist on Event');
+
+test(function () {
+    var event = new Event('my-event');
+    assert_array_equals(event.deepPath(), []);
+}, 'deepPath() must return an empty array when the event has not been dispatched');
+
+test(function () {
+    var event = new Event('my-event');
+    document.body.dispatchEvent(event);
+    assert_array_equals(event.deepPath(), []);
+}, 'deepPath() must return an empty array when the event is no longer dispatched');
+
+test(function () {
+    assert_true('scoped' in Event.prototype);
+    assert_true('scoped' in new Event('my-event'));
+}, 'scoped must exist on Event');
+
+test(function () {
+    var event = new Event('my-event');
+    assert_false(event.scoped);
+}, 'scoped on EventInit must default to false');
+
+test(function () {
+    var event = new Event('my-event', {scoped: true});
+    assert_true(event.scoped);
+
+    event = new Event('my-event', {scoped: false});
+    assert_false(event.scoped);
+}, 'scoped on EventInit must set the scoped flag');
+
+test(function () {
+    assert_true('relatedTargetScoped' in Event.prototype);
+    assert_true('relatedTargetScoped' in new Event('my-event'));
+}, 'relatedTargetScoped must exist on Event');
+
+test(function () {
+    var event = new Event('my-event');
+    assert_false(event.relatedTargetScoped);
+}, 'relatedTargetScoped on EventInit must default to false');
+
+test(function () {
+    var event = new Event('my-event', {relatedTargetScoped: true});
+    assert_true(event.relatedTargetScoped);
+
+    event = new Event('my-event', {relatedTargetScoped: false});
+    assert_false(event.relatedTargetScoped);
+}, 'relatedTargetScoped on EventInit must set the scoped flag');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  *: indicates start  digit: event path order
+A (4) --------------------------- A-SR (3)
++ B ------------ B-SR             + A1 (2) --- A1-SR (1)
+  + C            + B1 --- B1-SR   + A2-S       + A1a (*; 0)
+  + D --- D-SR     + B1a    + B1b --- B1b-SR
+          + D1              + B1c-S   + B1b1
+                                      + B1b2
+*/
+
+function testUnscopedEvent(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        var log = dispatchEventWithLog(nodes, nodes.A1a, new Event('my-event', {scoped: false, bubbles: true}));
+
+        var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR', 'A'];
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], expectedPath);
+        assert_array_equals(log.pathAtTargets[1], expectedPath);
+        assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : ['A1', 'A-SR', 'A'],
+            'deepPath must only contain unclosed nodes of the current target.');
+    }, 'The event must propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is unset');
+}
+
+testUnscopedEvent('open');
+testUnscopedEvent('closed');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  *: indicates start  digit: event path order
+A ------------------------------- A-SR
++ B ------------ B-SR             + A1 --- A1-SR (1)
+  + C            + B1 --- B1-SR   + A2-S   + A1a (*; 0)
+  + D --- D-SR     + B1a  + B1b --- B1b-SR
+          + D1            + B1c-S   + B1b1
+                                    + B1b2
+*/
+
+function testScopedEvent(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        var log = dispatchEventWithLog(nodes, nodes.A1a, new Event('my-event', {scoped: true, bubbles: true}));
+
+        var expectedPath = ['A1a', 'A1-SR'];
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], expectedPath);
+        assert_array_equals(log.pathAtTargets[1], expectedPath);
+    }, 'The event must not propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is set');
+}
+
+testScopedEvent('open');
+testScopedEvent('closed');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
+A (4) [4] ----------------------- A-SR (3)
++ B ------------ B-SR             + A1 (2) ------- A1-SR (1)
+  + C            + B1 --- B1-SR   + A2-S [*; 0-3]  + A1a (*; 0)
+  + D --- D-SR     + B1a  + B1b --- B1b-SR
+          + D1            + B1c-S   + B1b1
+                                    + B1b2
+*/
+
+function testUnscopedEventWithUnscopedRelatedTarget(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        var log = dispatchEventWithLog(nodes, nodes.A1a, new MouseEvent('foo', {scoped: false, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['A2-S']}));
+
+        var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR', 'A'];
+        var pathExposedToA1 = ['A1', 'A-SR', 'A'];
+        var pathExposedToA = ['A'];
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], expectedPath);
+        assert_array_equals(log.pathAtTargets[1], expectedPath);
+        assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToA1);
+        assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToA1);
+        assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToA);
+        assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S', 'A2-S', 'A2-S', 'A']);
+    }, 'The event must propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is unset on an event with relatedTarget');
+}
+
+testUnscopedEventWithUnscopedRelatedTarget('open');
+testUnscopedEventWithUnscopedRelatedTarget('closed');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
+A ------------------------------- A-SR
++ B ------------ B-SR             + A1 ----------- A1-SR (1)
+  + C            + B1 --- B1-SR   + A2-S [*; 0-1]  + A1a (*; 0)
+  + D --- D-SR     + B1a  + B1b --- B1b-SR
+          + D1            + B1c-S   + B1b1
+                                    + B1b2
+*/
+
+function testScopedEventWithUnscopedRelatedTarget(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        var log = dispatchEventWithLog(nodes, nodes.A1a, new MouseEvent('foo', {scoped: true, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['A2-S']}));
+
+        var expectedPath = ['A1a', 'A1-SR'];
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], expectedPath);
+        assert_array_equals(log.pathAtTargets[1], expectedPath);
+        assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S']);
+    }, 'The event must not propagate out of ' + mode + ' mode shadow boundaries when the scoped flag is set on an event with relatedTarget');
+}
+
+testScopedEventWithUnscopedRelatedTarget('open');
+testScopedEventWithUnscopedRelatedTarget('closed');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
+A ------------------------------------------------ A-SR
++ B ------------ B-SR (4)                          + A1 --- A1-SR
+  + C            + B1 (3) [0,3-4] --- B1-SR (2)    + A2-S   + A1a
+  + D --- D-SR     + B1a (*; 0)       + B1b [1-2] --- B1b-SR
+          + D1                        + B1c-S (1)     + B1b1
+                                                      + B1b2 [*]
+*/
+
+function testScopedEventWithUnscopedRelatedTargetThroughSlot(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        var log = dispatchEventWithLog(nodes, nodes.B1a, new MouseEvent('foo', {scoped: true, relatedTargetScoped: false, bubbles: true, relatedTarget: nodes['B1b2']}));
+
+        var expectedPath = ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR'];
+        var pathExposedToB1a = ['B1a', 'B1', 'B-SR'];
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], mode == 'open' ? expectedPath : pathExposedToB1a);
+        assert_array_equals(log.pathAtTargets[1], expectedPath);
+        assert_array_equals(log.pathAtTargets[2], expectedPath);
+        assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToB1a);
+        assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToB1a);
+        assert_array_equals(log.relatedTargets, ['B1', 'B1b', 'B1b', 'B1', 'B1']);
+    }, 'The event must not propagate out of ' + mode + ' mode shadow tree of the target but must propagate out of inner shadow trees when the scoped flag is set');
+}
+
+testScopedEventWithUnscopedRelatedTargetThroughSlot('open');
+testScopedEventWithUnscopedRelatedTargetThroughSlot('closed');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
+A ------------------------------- A-SR (3)
++ B ------------ B-SR             + A1 (2) ------- A1-SR (1)
+  + C            + B1 --- B1-SR   + A2-S [*; 0-3]  + A1a (*; 0)
+  + D --- D-SR     + B1a  + B1b --- B1b-SR
+          + D1            + B1c-S   + B1b1
+                                    + B1b2
+*/
+
+function testUnscopedEventWithScopedRelatedTarget(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        log = dispatchEventWithLog(nodes, nodes.A1a, new MouseEvent('foo', {scoped: false, relatedTargetScoped: true, bubbles: true, relatedTarget: nodes['A2-S']}));
+
+        var expectedPath = ['A1a', 'A1-SR', 'A1', 'A-SR'];
+        var pathExposedToA1 = ['A1', 'A-SR'];
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], expectedPath);
+        assert_array_equals(log.pathAtTargets[1], expectedPath);
+        assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToA1);
+        assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToA1);
+        assert_array_equals(log.relatedTargets, ['A2-S', 'A2-S', 'A2-S', 'A2-S']);
+    }, 'The event must propagate out of ' + mode + ' mode shadow tree in which the relative target and the relative related target are the same');
+}
+
+testUnscopedEventWithScopedRelatedTarget('open');
+testUnscopedEventWithScopedRelatedTarget('closed');
+
+/*
+-SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
+A (8) [0-5,8] ---------------------------------------- A-SR (7)
++ B (5)  ------- B-SR (4)                              + A1 [6,7] --- A1-SR
+  + C            + B1 (3) ------- B1-SR (2)            + A2-S (6)     + A1a [*]
+  + D --- D-SR     + B1a (*; 0)   + B1b ------- B1b-SR
+          + D1                    + B1c-S (1)   + B1b1
+                                                + B1b2
+*/
+
+function testUnscopedEventWithScopedRelatedTargetThroughSlot(mode) {
+    test(function () {
+        var nodes = createTestTree(mode);
+        log = dispatchEventWithLog(nodes, nodes.B1a, new MouseEvent('foo', {scoped: false, relatedTargetScoped: true, bubbles: true, relatedTarget: nodes.A1a}));
+
+        var expectedPath =          ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR', 'B', 'A2-S', 'A-SR', 'A'];
+        var expectedRelatedTarget = ['A',   'A',     'A',     'A',   'A',   'A', 'A1',   'A1',   'A'];
+        var pathExposedToB1a =      ['B1a',                   'B1', 'B-SR', 'B',                 'A'];
+        var pathExposedToB1cS =     ['B1a', 'B1c-S', 'B1-SR', 'B1', 'B-SR', 'B',                 'A'];
+        var pathExposedToB =        [                                       'B',                 'A'];
+        var pathExposedToA1 =       [                                       'B', 'A2-S', 'A-SR', 'A'];
+
+        assert_array_equals(log.eventPath, expectedPath);
+        assert_array_equals(log.eventPath.length, log.pathAtTargets.length);
+        assert_array_equals(log.pathAtTargets[0], mode == 'open' ? expectedPath : pathExposedToB1a);
+        assert_array_equals(log.pathAtTargets[1], mode == 'open' ? expectedPath : pathExposedToB1cS);
+        assert_array_equals(log.pathAtTargets[2], mode == 'open' ? expectedPath : pathExposedToB1cS);
+        assert_array_equals(log.pathAtTargets[3], mode == 'open' ? expectedPath : pathExposedToB1a);
+        assert_array_equals(log.pathAtTargets[4], mode == 'open' ? expectedPath : pathExposedToB1a);
+        assert_array_equals(log.pathAtTargets[5], mode == 'open' ? expectedPath : pathExposedToB);
+        assert_array_equals(log.pathAtTargets[6], mode == 'open' ? expectedPath : pathExposedToA1);
+        assert_array_equals(log.pathAtTargets[7], mode == 'open' ? expectedPath : pathExposedToA1);
+        assert_array_equals(log.pathAtTargets[8], mode == 'open' ? expectedPath : pathExposedToB);
+        assert_array_equals(log.relatedTargets, expectedRelatedTarget);
+    }, 'deepPath() must contain and only contain the unclosed nodes of target in ' + mode + ' mode shadow trees');
+}
+
+testUnscopedEventWithScopedRelatedTargetThroughSlot('open');
+testUnscopedEventWithScopedRelatedTargetThroughSlot('closed');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomeventwithrelatedtargethtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shadow-dom/event-with-related-target.html (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/event-with-related-target.html        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/fast/shadow-dom/event-with-related-target.html        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -7,100 +7,14 @@
</span><span class="cx">     &lt;link rel=&quot;help&quot; href=&quot;https://w3c.github.io/webcomponents/spec/shadow/#retargeting-relatedtarget&quot;&gt;
</span><span class="cx">     &lt;script src=&quot;../../resources/testharness.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;resources/event-path-test-helpers.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;link rel='stylesheet' href='../../resources/testharness.css'&gt;
</span><span class="cx"> &lt;/head&gt;
</span><span class="cx"> &lt;body&gt;
</span><span class="cx">     &lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
</span><span class="cx">     &lt;script&gt;
</span><span class="cx"> 
</span><del>-        function dispatchEventWithLog(shadow, target, event) {
-            var eventPath = [];
-            var relatedTargets = [];
-
-            var attachedNodes = [];
-            for (var nodeKey in shadow) {
-                var startingNode = shadow[nodeKey];
-                for (var node = startingNode; node; node = node.parentNode) {
-                    if (attachedNodes.indexOf(node) &gt;= 0)
-                        continue;
-                    attachedNodes.push(node);
-                    node.addEventListener(event.type, (function (event) {
-                        eventPath.push(this.label);
-                        relatedTargets.push(event.relatedTarget.label);
-                    }).bind(node));
-                }
-            }
-
-            target.dispatchEvent(event);
-
-            return {eventPath: eventPath, relatedTargets: relatedTargets};
-        }
-
</del><span class="cx">         /*
</span><del>-        -SR: ShadowRoot  -S: Slot
-        A ------------------------------- A-SR
-        + B ------------ B-SR             + A1 --- A1-SR
-          + C            + B1 --- B1-SR   + A2-S   + A1a
-          + D --- D-SR   + B1a    + B1b --- B1b-SR
-                  + D1            + B1c-S   + B1b1
-                                            + B1b2
-        */
-        function createTestTree(mode) {
-            var namedNodes = {};
-
-            function element(name) {
-                var element = document.createElement(name.indexOf('-S') &gt; 0 ? 'slot' : 'div');
-                element.label = name;
-                namedNodes[name] = element;
-                for (var i = 1; i &lt; arguments.length; i++) {
-                    var item = arguments[i];
-                    if (typeof(item) == 'function')
-                        item(element);
-                    else
-                        element.appendChild(item);
-                }
-                return element;
-            }
-
-            function shadow(name) {
-                var children = [];
-                for (var i = 1; i &lt; arguments.length; i++)
-                    children.push(arguments[i]);
-                return function (element) {
-                    var shadowRoot = element.attachShadow({mode: mode});
-                    shadowRoot.label = name;
-                    namedNodes[name] = shadowRoot;
-                    for (var child of children)
-                        shadowRoot.appendChild(child);
-                }
-            }
-
-            var host = element('A',
-                shadow('A-SR',
-                    element('A1',
-                        shadow('A1-SR',
-                            element('A1a'))),
-                    element('A2-S')
-                ),
-                element('B',
-                    shadow('B-SR',
-                        element('B1',
-                            shadow('B1-SR',
-                                element('B1b',
-                                    shadow('B1b-SR',
-                                        element('B1b1'),
-                                        element('B1b2'))),
-                                element('B1c-S')),
-                            element('B1a'))),
-                    element('C'),
-                    element('D',
-                        shadow('D-SR',
-                            element('D1')))));
-
-            return namedNodes;
-        }
-
-        /*
</del><span class="cx">         -SR: ShadowRoot  -S: Slot  target: (~)  relatedTarget: [~]  *: indicates start  digit: event path order
</span><span class="cx">         A (8) --------------------------------------------- A-SR (7)
</span><span class="cx">         + B (5) [5-8] --- B-SR (4)                          + A1 -------- A1-SR
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomnegativetabindexonshadowhostexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host-expected.txt (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host-expected.txt        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -2,9 +2,8 @@
</span><span class="cx"> To manually test, press tab key four times. It should traverse focusable elements in the increasing numerical order.
</span><span class="cx"> 
</span><span class="cx"> 1. First sequentially focusable element outside shadow trees
</span><del>-2. / 3.2. Shadow host with a positive tabindex
-3.1. Focusable element inside a shadow host with a positive tabindex
-2. / 3.2. Shadow host with a positive tabindex
</del><ins>+2. Shadow host with a positive tabindex
+3. Focusable element inside a shadow host with a positive tabindex
</ins><span class="cx"> 4.1. Focusable element inside a shadow host with no tabindex
</span><span class="cx"> 4.2. Shadow host with no tabindex
</span><span class="cx"> 5. Last sequentially focusable element outside shadow trees
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomnegativetabindexonshadowhosthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host.html (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host.html        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/fast/shadow-dom/negative-tabindex-on-shadow-host.html        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -7,7 +7,7 @@
</span><span class="cx"> &lt;div id=&quot;first&quot; tabindex=&quot;1&quot; onfocus=&quot;log(this)&quot;&gt;1. First sequentially focusable element outside shadow trees&lt;/div&gt;
</span><span class="cx"> &lt;div id=&quot;host-with-negative-tabindex&quot; tabindex=&quot;-1&quot; onfocus=&quot;log(this)&quot;&gt;Shadow host with a negative tabindex&lt;/div&gt;
</span><span class="cx"> &lt;div id=&quot;host-with-no-tabindex&quot; onfocus=&quot;log(this)&quot;&gt;4.2. Shadow host with no tabindex&lt;/div&gt;
</span><del>-&lt;div id=&quot;host-with-positive-tabindex&quot; tabindex=&quot;2&quot; onfocus=&quot;log(this)&quot;&gt;2. / 3.2. Shadow host with a positive tabindex&lt;/div&gt;
</del><ins>+&lt;div id=&quot;host-with-positive-tabindex&quot; tabindex=&quot;2&quot; onfocus=&quot;log(this)&quot;&gt;2. Shadow host with a positive tabindex&lt;/div&gt;
</ins><span class="cx"> &lt;div tabindex=&quot;0&quot; onfocus=&quot;log(this)&quot;&gt;5. Last sequentially focusable element outside shadow trees&lt;/div&gt;
</span><span class="cx"> &lt;/div&gt;
</span><span class="cx"> &lt;pre&gt;&lt;/pre&gt;
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx"> 
</span><span class="cx"> document.getElementById('host-with-positive-tabindex').attachShadow({mode: 'closed'}).innerHTML = `
</span><span class="cx">     &lt;slot&gt;&lt;/slot&gt;
</span><del>-    &lt;div tabindex=&quot;0&quot; onfocus=&quot;log(this)&quot;&gt;3.1. Focusable element inside a shadow host with a positive tabindex&lt;/div&gt;
</del><ins>+    &lt;div tabindex=&quot;0&quot; onfocus=&quot;log(this)&quot;&gt;3. Focusable element inside a shadow host with a positive tabindex&lt;/div&gt;
</ins><span class="cx"> `;
</span><span class="cx"> 
</span><span class="cx"> function log(element) {
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomresourceseventpathtesthelpersjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/resources/event-path-test-helpers.js (0 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/resources/event-path-test-helpers.js                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/resources/event-path-test-helpers.js        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+
+function dispatchEventWithLog(shadow, target, event) {
+    var eventPath = [];
+    var relatedTargets = [];
+    var pathAtTargets = [];
+
+    var attachedNodes = [];
+    for (var nodeKey in shadow) {
+        var startingNode = shadow[nodeKey];
+        for (var node = startingNode; node; node = node.parentNode) {
+            if (attachedNodes.indexOf(node) &gt;= 0)
+                continue;
+            attachedNodes.push(node);
+            node.addEventListener(event.type, (function (event) {
+                eventPath.push(this.label);
+                relatedTargets.push(event.relatedTarget ? event.relatedTarget.label : null);
+
+                if (!event.deepPath) // Don't fail all tests just for the lack of deepPath.
+                    return;
+
+                pathAtTargets.push(event.deepPath().map(function (node) { return node.label; }));
+            }).bind(node));
+        }
+    }
+
+    target.dispatchEvent(event);
+
+    return {eventPath: eventPath, relatedTargets: relatedTargets, pathAtTargets: pathAtTargets};
+}
+
+/*
+-SR: ShadowRoot  -S: Slot
+A ------------------------------- A-SR
++ B ------------ B-SR             + A1 --- A1-SR
+  + C            + B1 --- B1-SR   + A2-S   + A1a
+  + D --- D-SR     + B1a  + B1b --- B1b-SR
+          + D1            + B1c-S   + B1b1
+                                    + B1b2
+*/
+function createTestTree(mode) {
+    var namedNodes = {};
+
+    function element(name) {
+        var element = document.createElement(name.indexOf('-S') &gt; 0 ? 'slot' : 'div');
+        element.label = name;
+        namedNodes[name] = element;
+        for (var i = 1; i &lt; arguments.length; i++) {
+            var item = arguments[i];
+            if (typeof(item) == 'function')
+                item(element);
+            else
+                element.appendChild(item);
+        }
+        return element;
+    }
+
+    function shadow(name) {
+        var children = [];
+        for (var i = 1; i &lt; arguments.length; i++)
+            children.push(arguments[i]);
+        return function (element) {
+            var shadowRoot = element.attachShadow({mode: mode});
+            shadowRoot.label = name;
+            namedNodes[name] = shadowRoot;
+            for (var child of children)
+                shadowRoot.appendChild(child);
+        }
+    }
+
+    var host = element('A',
+        shadow('A-SR',
+            element('A1',
+                shadow('A1-SR',
+                    element('A1a'))),
+            element('A2-S')
+        ),
+        element('B',
+            shadow('B-SR',
+                element('B1',
+                    shadow('B1-SR',
+                        element('B1b',
+                            shadow('B1b-SR',
+                                element('B1b1'),
+                                element('B1b2'))),
+                        element('B1c-S')),
+                    element('B1a'))),
+            element('C'),
+            element('D',
+                shadow('D-SR',
+                    element('D1')))));
+
+    return namedNodes;
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomtrustedeventscopedflagsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags-expected.txt (0 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+
+world
+PASS input.type = &quot;radio&quot;; log(input, &quot;change&quot;); input.click(); eventType is &quot;change&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS log(form, &quot;reset&quot;); form.reset(); eventType is &quot;reset&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS form.focus(); log(input, &quot;focus&quot;); input.focus(); eventType is &quot;focus&quot;
+PASS scoped is false
+PASS relatedTargetScoped is true
+
+PASS log(input, &quot;blur&quot;); form.focus(); eventType is &quot;blur&quot;
+PASS scoped is false
+PASS relatedTargetScoped is true
+
+PASS input.type = &quot;text&quot;; log(input, &quot;mousemove&quot;); eventSender.mouseMoveTo(x, y); eventType is &quot;mousemove&quot;
+PASS scoped is false
+PASS relatedTargetScoped is false
+
+PASS log(input, &quot;mousedown&quot;); eventSender.mouseDown(); eventType is &quot;mousedown&quot;
+PASS scoped is false
+PASS relatedTargetScoped is false
+
+PASS log(input, &quot;mouseup&quot;); eventSender.mouseUp(); eventType is &quot;mouseup&quot;
+PASS scoped is false
+PASS relatedTargetScoped is false
+
+PASS log(input, &quot;mouseout&quot;); eventSender.mouseMoveTo(0, 0); eventType is &quot;mouseout&quot;
+PASS scoped is false
+PASS relatedTargetScoped is true
+
+PASS log(input, &quot;mouseover&quot;); eventSender.mouseMoveTo(x, y); eventType is &quot;mouseover&quot;
+PASS scoped is false
+PASS relatedTargetScoped is true
+
+input.value = &quot;hello&quot;; eventSender.mouseMoveTo(input.offsetLeft + 1, y); eventSender.mouseDown();
+PASS log(input, &quot;select&quot;); eventSender.mouseMoveTo(input.offsetLeft + input.offsetWidth - 2, y); eventSender.mouseUp(); eventType is &quot;select&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS log(editableElement, &quot;selectstart&quot;); eventSender.mouseMoveTo(editableElement.offsetLeft + 1, y); eventSender.mouseDown(); eventType is &quot;selectstart&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;load&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;error&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;scroll&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;resize&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomtrustedeventscopedflagshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags.html (0 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags.html                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/trusted-event-scoped-flags.html        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -0,0 +1,142 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;form&gt;&lt;input&gt;&lt;/form&gt;
+&lt;div id=&quot;editor&quot; contenteditable&gt;world&lt;/div&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+var eventType;
+var scoped;
+var relatedTargetScoped;
+
+function logEvent(event) {
+    eventType = event.type;
+    scoped = event.scoped;
+    relatedTargetScoped = event.relatedTargetScoped;
+}
+
+function checkFlags(code, expected) {
+    shouldBeEqualToString(code ? code + '; eventType' : 'eventType', expected.eventType);
+    shouldBe('scoped', expected.scoped.toString());
+    shouldBe('relatedTargetScoped', expected.relatedTargetScoped.toString());
+    debug('');
+}
+
+var lastTarget;
+var lastEventName;
+function log(target, eventName) {
+    eventType = undefined;
+    scoped = undefined;
+    relatedTargetScoped = undefined;
+    if (lastTarget)
+        lastTarget.removeEventListener(lastEventName, logEvent);
+    target.addEventListener(eventName, logEvent);
+    lastTarget = target;
+    lastEventName = eventName;
+}
+
+var input = document.querySelector('input');
+var form = document.querySelector('form');
+form.tabIndex = 0;
+
+checkFlags('input.type = &quot;radio&quot;; log(input, &quot;change&quot;); input.click()', {eventType: 'change', scoped: true, relatedTargetScoped: false});
+checkFlags('log(form, &quot;reset&quot;); form.reset()', {eventType: 'reset', scoped: true, relatedTargetScoped: false});
+
+checkFlags('form.focus(); log(input, &quot;focus&quot;); input.focus()', {eventType: 'focus', scoped: false, relatedTargetScoped: true});
+checkFlags('log(input, &quot;blur&quot;); form.focus()', {eventType: 'blur', scoped: false, relatedTargetScoped: true});
+
+if (!window.eventSender)
+    testFailed('This test requires eventSender');
+else {
+    testRunner.waitUntilDone();
+
+    eventSender.dragMode = false;
+
+    var x = input.offsetLeft + input.offsetWidth / 2;
+    var y = input.offsetTop + input.offsetHeight / 2;
+
+    checkFlags('input.type = &quot;text&quot;; log(input, &quot;mousemove&quot;); eventSender.mouseMoveTo(x, y)', {eventType: 'mousemove', scoped: false, relatedTargetScoped: false});
+    checkFlags('log(input, &quot;mousedown&quot;); eventSender.mouseDown()', {eventType: 'mousedown', scoped: false, relatedTargetScoped: false});
+    checkFlags('log(input, &quot;mouseup&quot;); eventSender.mouseUp()', {eventType: 'mouseup', scoped: false, relatedTargetScoped: false});
+    checkFlags('log(input, &quot;mouseout&quot;); eventSender.mouseMoveTo(0, 0)', {eventType: 'mouseout', scoped: false, relatedTargetScoped: true});
+    checkFlags('log(input, &quot;mouseover&quot;); eventSender.mouseMoveTo(x, y)', {eventType: 'mouseover', scoped: false, relatedTargetScoped: true});
+
+    evalAndLog('input.value = &quot;hello&quot;; eventSender.mouseMoveTo(input.offsetLeft + 1, y); eventSender.mouseDown();');
+    checkFlags('log(input, &quot;select&quot;); eventSender.mouseMoveTo(input.offsetLeft + input.offsetWidth - 2, y); eventSender.mouseUp()',
+        {eventType: 'select', scoped: true, relatedTargetScoped: false});
+
+    var editableElement = document.getElementById('editor');
+    y = editableElement.offsetTop + editableElement.offsetHeight / 2;
+    checkFlags('log(editableElement, &quot;selectstart&quot;); eventSender.mouseMoveTo(editableElement.offsetLeft + 1, y); eventSender.mouseDown()',
+        {eventType: 'selectstart', scoped: true, relatedTargetScoped: false});
+}
+
+function testLoadEvent() {
+    var scriptThatLoads = document.createElement('script');
+    scriptThatLoads.src = &quot;resources/event-path-test-helpers.js&quot;;
+    scriptThatLoads.onload = function (event) {
+        logEvent(event);
+        checkFlags('', {eventType: 'load', scoped: true, relatedTargetScoped: false});
+        testErrorEvent();
+    }
+    document.body.appendChild(scriptThatLoads);
+}
+
+function testErrorEvent() {
+    var scriptThatFailsToLoad = document.createElement('script');
+    scriptThatFailsToLoad.src = &quot;bad.js&quot;;
+    scriptThatFailsToLoad.onerror = function (event) {
+        logEvent(event);
+        checkFlags('', {eventType: 'error', scoped: true, relatedTargetScoped: false});
+        testScrollEvent();
+    }
+    document.body.appendChild(scriptThatFailsToLoad);
+}
+
+function testScrollEvent() {
+    document.body.style.marginBottom = '1000px';
+    log(window, 'scroll');
+    setTimeout(function () {
+        window.scrollTo(0, 1000);
+        setTimeout(function () {
+            checkFlags('', {eventType: 'scroll', scoped: true, relatedTargetScoped: false});
+            window.scrollTo(0, 0);
+            testResizeEvent();
+        }, 0);
+    }, 0);
+}
+
+function testResizeEvent() {
+    var iframe = document.createElement('iframe');
+    iframe.style.width = '100px';
+    iframe.style.height = '100px';
+
+    iframe.onload = function () {
+        iframe.contentDocument.body.getBoundingClientRect();
+        log(iframe.contentWindow, &quot;resize&quot;);
+        setTimeout(function () {
+            iframe.style.width = '200px';
+            iframe.style.height = '200px';
+            iframe.contentDocument.body.getBoundingClientRect();
+            setTimeout(function () {
+                checkFlags('', {eventType: 'resize', scoped: true, relatedTargetScoped: false});
+                finishJSTest();
+            }, 0);
+        }, 0);
+    }
+
+    document.body.appendChild(iframe);
+}
+
+testLoadEvent();
+
+// FIXME: Test abort and loadedmetadata events.
+
+jsTestIsAsync = true;
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastxmlhttprequestxmlhttprequestgetexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -48,6 +48,9 @@
</span><span class="cx"> cancelable : 'false'
</span><span class="cx"> clipboardData : 'undefined'
</span><span class="cx"> currentTarget : '[object XMLHttpRequest]'
</span><ins>+deepPath : 'function deepPath() {
+    [native code]
+}'
</ins><span class="cx"> defaultPrevented : 'false'
</span><span class="cx"> eventPhase : '2'
</span><span class="cx"> initEvent : 'function initEvent() {
</span><span class="lines">@@ -60,7 +63,9 @@
</span><span class="cx"> preventDefault : 'function preventDefault() {
</span><span class="cx">     [native code]
</span><span class="cx"> }'
</span><ins>+relatedTargetScoped : 'false'
</ins><span class="cx"> returnValue : 'true'
</span><ins>+scoped : 'true'
</ins><span class="cx"> srcElement : '[object XMLHttpRequest]'
</span><span class="cx"> stopImmediatePropagation : 'function stopImmediatePropagation() {
</span><span class="cx">     [native code]
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsworkersworkerimportScriptsOnErrorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/workers/worker-importScriptsOnError-expected.txt (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/workers/worker-importScriptsOnError-expected.txt        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/http/tests/workers/worker-importScriptsOnError-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> clipboardData: undefined,
</span><span class="cx"> colno: 14,
</span><span class="cx"> currentTarget: [object Worker],
</span><ins>+deepPath: function deepPath() { [native code] },
</ins><span class="cx"> defaultPrevented: false,
</span><span class="cx"> eventPhase: 2,
</span><span class="cx"> filename: http://127.0.0.1:8000/workers/resources/worker-importScripts-error.js,
</span><span class="lines">@@ -36,7 +37,9 @@
</span><span class="cx"> lineno: 2,
</span><span class="cx"> message: Error: Script error.,
</span><span class="cx"> preventDefault: function preventDefault() { [native code] },
</span><ins>+relatedTargetScoped: false,
</ins><span class="cx"> returnValue: true,
</span><ins>+scoped: true,
</ins><span class="cx"> srcElement: [object Worker],
</span><span class="cx"> stopImmediatePropagation: function stopImmediatePropagation() { [native code] },
</span><span class="cx"> stopPropagation: function stopPropagation() { [native code] },
</span></span></pre></div>
<a id="trunkLayoutTestsinspectormodelremoteobjectgetpropertiesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -48,6 +48,8 @@
</span><span class="cx">     eventPhase
</span><span class="cx">     bubbles
</span><span class="cx">     cancelable
</span><ins>+    scoped
+    relatedTargetScoped
</ins><span class="cx">     timeStamp
</span><span class="cx">     defaultPrevented
</span><span class="cx">     srcElement
</span><span class="lines">@@ -65,12 +67,15 @@
</span><span class="cx">     eventPhase
</span><span class="cx">     bubbles
</span><span class="cx">     cancelable
</span><ins>+    scoped
+    relatedTargetScoped
</ins><span class="cx">     timeStamp
</span><span class="cx">     defaultPrevented
</span><span class="cx">     srcElement
</span><span class="cx">     returnValue
</span><span class="cx">     cancelBubble
</span><span class="cx">     clipboardData
</span><ins>+    deepPath
</ins><span class="cx">     stopPropagation
</span><span class="cx">     preventDefault
</span><span class="cx">     initEvent
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorfastshadowdomtrustedeventscopedflagsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/ios-simulator/fast/shadow-dom/trusted-event-scoped-flags-expected.txt (0 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/fast/shadow-dom/trusted-event-scoped-flags-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator/fast/shadow-dom/trusted-event-scoped-flags-expected.txt        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+
+world
+PASS input.type = &quot;radio&quot;; log(input, &quot;change&quot;); input.click(); eventType is &quot;change&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS log(form, &quot;reset&quot;); form.reset(); eventType is &quot;reset&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS form.focus(); log(input, &quot;focus&quot;); input.focus(); eventType is &quot;focus&quot;
+PASS scoped is false
+PASS relatedTargetScoped is true
+
+PASS log(input, &quot;blur&quot;); form.focus(); eventType is &quot;blur&quot;
+PASS scoped is false
+PASS relatedTargetScoped is true
+
+FAIL input.type = &quot;text&quot;; log(input, &quot;mousemove&quot;); eventSender.mouseMoveTo(x, y); eventType should be mousemove (of type string). Was undefined (of type undefined).
+FAIL scoped should be false (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be false (of type boolean). Was undefined (of type undefined).
+
+FAIL log(input, &quot;mousedown&quot;); eventSender.mouseDown(); eventType should be mousedown (of type string). Was undefined (of type undefined).
+FAIL scoped should be false (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be false (of type boolean). Was undefined (of type undefined).
+
+FAIL log(input, &quot;mouseup&quot;); eventSender.mouseUp(); eventType should be mouseup (of type string). Was undefined (of type undefined).
+FAIL scoped should be false (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be false (of type boolean). Was undefined (of type undefined).
+
+FAIL log(input, &quot;mouseout&quot;); eventSender.mouseMoveTo(0, 0); eventType should be mouseout (of type string). Was undefined (of type undefined).
+FAIL scoped should be false (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be true (of type boolean). Was undefined (of type undefined).
+
+FAIL log(input, &quot;mouseover&quot;); eventSender.mouseMoveTo(x, y); eventType should be mouseover (of type string). Was undefined (of type undefined).
+FAIL scoped should be false (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be true (of type boolean). Was undefined (of type undefined).
+
+input.value = &quot;hello&quot;; eventSender.mouseMoveTo(input.offsetLeft + 1, y); eventSender.mouseDown();
+FAIL log(input, &quot;select&quot;); eventSender.mouseMoveTo(input.offsetLeft + input.offsetWidth - 2, y); eventSender.mouseUp(); eventType should be select (of type string). Was undefined (of type undefined).
+FAIL scoped should be true (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be false (of type boolean). Was undefined (of type undefined).
+
+FAIL log(editableElement, &quot;selectstart&quot;); eventSender.mouseMoveTo(editableElement.offsetLeft + 1, y); eventSender.mouseDown(); eventType should be selectstart (of type string). Was undefined (of type undefined).
+FAIL scoped should be true (of type boolean). Was undefined (of type undefined).
+FAIL relatedTargetScoped should be false (of type boolean). Was undefined (of type undefined).
+
+PASS eventType is &quot;load&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;error&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;scroll&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS eventType is &quot;resize&quot;
+PASS scoped is true
+PASS relatedTargetScoped is false
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/ChangeLog        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2016-03-11  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Add Event.deepPath() and Event.scoped
+        https://bugs.webkit.org/show_bug.cgi?id=153538
+        &lt;rdar://problem/24363836&gt;
+
+        Reviewed by Darin Adler.
+
+        Added the support for deepPath(), scoped, and relatedTargetScoped on Event.prototype for shadow DOM:
+        http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-event-interface
+        and updated the EventPath class to respect scoped and relatedTargetScoped flags as specified at:
+        http://w3c.github.io/webcomponents/spec/shadow/#get-the-parent
+
+        Tests: fast/shadow-dom/Extensions-to-Event-Interface.html
+               fast/shadow-dom/trusted-event-scoped-flags.html
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateConstructorDefinition): Added the support for Conditional for InitializedByEventConstructor.
+        * bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.cpp:
+        * bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.h:
+        * bindings/scripts/test/JS/JSTestEventConstructor.cpp:
+        * bindings/scripts/test/ObjC/DOMTestEventConstructor.h:
+        * bindings/scripts/test/ObjC/DOMTestEventConstructor.mm:
+        * bindings/scripts/test/TestEventConstructor.idl: Added a test case for using InitializedByEventConstructor
+        with Conditional.
+        * dom/Event.cpp:
+        (WebCore::Event::Event): Initialize m_scoped and m_relatedTargetScoped from EventInit dictionary.
+        (WebCore::Event::scoped): Added. Implements http://w3c.github.io/webcomponents/spec/shadow/#scoped-flag
+        (WebCore::Event::deepPath): Added.
+        * dom/Event.h:
+        (WebCore::Event::relatedTargetScoped): Added. Overridden by FocusEvent and MouseEvent to implement
+        http://w3c.github.io/webcomponents/spec/shadow/#relatedtargetscoped-flag
+        (WebCore::Event::setEventPath): Added.
+        (WebCore::Event::clearEventPath): Added.
+        * dom/Event.idl: Added scoped, relatedTargetScoped, and deepPath() conditionally enabled for shadow DOM.
+        * dom/EventContext.h:
+        (WebCore::EventContext::currentTarget):
+        * dom/EventDispatcher.cpp:
+        (WebCore::EventDispatcher::dispatchEvent): Set the event path while the event is being dispatched.
+        * dom/EventPath.cpp:
+        (WebCore::shouldEventCrossShadowBoundary): Check event.scoped flag instead of hard-coding a list of events here
+        which has been moved to Event::scoped. See above.
+        (WebCore::EventPath::setRelatedTarget): Check m_event.relatedTargetScoped() instead of hard-coding a list of
+        events here. relatedTargetScoped is overridden by FocusEvent and MouseEvent.
+        (WebCore::EventPath::hasEventListeners): Fixed the misleading variable name.
+        (WebCore::isUnclosedNodeOf): Added. Implements http://w3c.github.io/webcomponents/spec/shadow/#dfn-unclosed-node
+        (WebCore::EventPath::computePathDisclosedToTarget): Added. Implements the algorithm to filter event targets:
+        http://w3c.github.io/webcomponents/spec/shadow/#widl-Event-deepPath-sequence-EventTarget
+        * dom/EventPath.h:
+        * dom/FocusEvent.cpp:
+        (WebCore::FocusEvent::relatedTargetScoped): Returns true when this is a trusted event per:
+        http://w3c.github.io/webcomponents/spec/shadow/#relatedtargetscoped-flag
+        * dom/FocusEvent.h:
+        * dom/MouseEvent.cpp:
+        (WebCore::MouseEvent::relatedTargetScoped): Ditto.
+        * dom/MouseEvent.h:
+
</ins><span class="cx"> 2016-03-11  John Wilander  &lt;wilander@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move prevalent resource classifier from WebCore to WebKit.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -4856,10 +4856,16 @@
</span><span class="cx">                 if ($attribute-&gt;signature-&gt;extendedAttributes-&gt;{&quot;InitializedByEventConstructor&quot;}) {
</span><span class="cx">                     my $attributeName = $attribute-&gt;signature-&gt;name;
</span><span class="cx">                     my $attributeImplName = $attribute-&gt;signature-&gt;extendedAttributes-&gt;{&quot;ImplementedAs&quot;} || $attributeName;
</span><ins>+                    my $conditionalString = $codeGenerator-&gt;GenerateConditionalString($attribute-&gt;signature);
+
+                    push(@implContent, &quot;#if ${conditionalString}\n&quot;) if $conditionalString;
+
</ins><span class="cx">                     push(@implContent, &lt;&lt;END);
</span><span class="cx">     if (!dictionary.tryGetProperty(&quot;${attributeName}&quot;, eventInit.${attributeImplName}))
</span><span class="cx">         return false;
</span><span class="cx"> END
</span><ins>+                    push(@implContent, &quot;#endif\n&quot;) if $conditionalString;
+
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestGObjectWebKitDOMTestEventConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx">     PROP_0,
</span><span class="cx">     PROP_ATTR1,
</span><span class="cx">     PROP_ATTR2,
</span><ins>+    PROP_ATTR3,
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static void webkit_dom_test_event_constructor_finalize(GObject* object)
</span><span class="lines">@@ -94,6 +95,9 @@
</span><span class="cx">     case PROP_ATTR2:
</span><span class="cx">         g_value_take_string(value, webkit_dom_test_event_constructor_get_attr2(self));
</span><span class="cx">         break;
</span><ins>+    case PROP_ATTR3:
+        g_value_take_string(value, webkit_dom_test_event_constructor_get_attr3(self));
+        break;
</ins><span class="cx">     default:
</span><span class="cx">         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec);
</span><span class="cx">         break;
</span><span class="lines">@@ -139,6 +143,16 @@
</span><span class="cx">             &quot;&quot;,
</span><span class="cx">             WEBKIT_PARAM_READABLE));
</span><span class="cx"> 
</span><ins>+    g_object_class_install_property(
+        gobjectClass,
+        PROP_ATTR3,
+        g_param_spec_string(
+            &quot;attr3&quot;,
+            &quot;TestEventConstructor:attr3&quot;,
+            &quot;read-only gchar* TestEventConstructor:attr3&quot;,
+            &quot;&quot;,
+            WEBKIT_PARAM_READABLE));
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void webkit_dom_test_event_constructor_init(WebKitDOMTestEventConstructor* request)
</span><span class="lines">@@ -165,3 +179,18 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+gchar* webkit_dom_test_event_constructor_get_attr3(WebKitDOMTestEventConstructor* self)
+{
+#if ENABLE(SPECIAL_EVENT)
+    WebCore::JSMainThreadNullState state;
+    g_return_val_if_fail(WEBKIT_DOM_IS_TEST_EVENT_CONSTRUCTOR(self), 0);
+    WebCore::TestEventConstructor* item = WebKit::core(self);
+    gchar* result = convertToUTF8String(item-&gt;attr3());
+    return result;
+#else
+    UNUSED_PARAM(self);
+    WEBKIT_WARN_FEATURE_NOT_PRESENT(&quot;Special Event&quot;)
+    return 0;
+#endif /* ENABLE(SPECIAL_EVENT) */
+}
+
</ins></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestGObjectWebKitDOMTestEventConstructorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestEventConstructor.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -69,6 +69,17 @@
</span><span class="cx"> WEBKIT_API gchar*
</span><span class="cx"> webkit_dom_test_event_constructor_get_attr2(WebKitDOMTestEventConstructor* self);
</span><span class="cx"> 
</span><ins>+/**
+ * webkit_dom_test_event_constructor_get_attr3:
+ * @self: A #WebKitDOMTestEventConstructor
+ *
+ * Returns: A #gchar
+ *
+ * Stability: Unstable
+**/
+WEBKIT_API gchar*
+webkit_dom_test_event_constructor_get_attr3(WebKitDOMTestEventConstructor* self);
+
</ins><span class="cx"> G_END_DECLS
</span><span class="cx"> 
</span><span class="cx"> #endif /* WEBKIT_DOM_USE_UNSTABLE_API */
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestJSJSTestEventConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -38,6 +38,9 @@
</span><span class="cx"> 
</span><span class="cx"> JSC::EncodedJSValue jsTestEventConstructorAttr1(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><span class="cx"> JSC::EncodedJSValue jsTestEventConstructorAttr2(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><ins>+#if ENABLE(SPECIAL_EVENT)
+JSC::EncodedJSValue jsTestEventConstructorAttr3(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
+#endif
</ins><span class="cx"> JSC::EncodedJSValue jsTestEventConstructorConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><span class="cx"> bool setJSTestEventConstructorConstructor(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
</span><span class="cx"> 
</span><span class="lines">@@ -106,6 +109,10 @@
</span><span class="cx"> {
</span><span class="cx">     if (!dictionary.tryGetProperty(&quot;attr2&quot;, eventInit.attr2))
</span><span class="cx">         return false;
</span><ins>+#if ENABLE(SPECIAL_EVENT)
+    if (!dictionary.tryGetProperty(&quot;attr3&quot;, eventInit.attr3))
+        return false;
+#endif
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -131,6 +138,11 @@
</span><span class="cx">     { &quot;constructor&quot;, DontEnum, NoIntrinsic, { (intptr_t)static_cast&lt;PropertySlot::GetValueFunc&gt;(jsTestEventConstructorConstructor), (intptr_t) static_cast&lt;PutPropertySlot::PutValueFunc&gt;(setJSTestEventConstructorConstructor) } },
</span><span class="cx">     { &quot;attr1&quot;, ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast&lt;PropertySlot::GetValueFunc&gt;(jsTestEventConstructorAttr1), (intptr_t) static_cast&lt;PutPropertySlot::PutValueFunc&gt;(0) } },
</span><span class="cx">     { &quot;attr2&quot;, ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast&lt;PropertySlot::GetValueFunc&gt;(jsTestEventConstructorAttr2), (intptr_t) static_cast&lt;PutPropertySlot::PutValueFunc&gt;(0) } },
</span><ins>+#if ENABLE(SPECIAL_EVENT)
+    { &quot;attr3&quot;, ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast&lt;PropertySlot::GetValueFunc&gt;(jsTestEventConstructorAttr3), (intptr_t) static_cast&lt;PutPropertySlot::PutValueFunc&gt;(0) } },
+#else
+    { 0, 0, NoIntrinsic, { 0, 0 } },
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSTestEventConstructorPrototype::s_info = { &quot;TestEventConstructorPrototype&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSTestEventConstructorPrototype) };
</span><span class="lines">@@ -194,6 +206,23 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+#if ENABLE(SPECIAL_EVENT)
+EncodedJSValue jsTestEventConstructorAttr3(ExecState* state, EncodedJSValue thisValue, PropertyName)
+{
+    UNUSED_PARAM(state);
+    UNUSED_PARAM(thisValue);
+    JSValue decodedThisValue = JSValue::decode(thisValue);
+    auto* castedThis = jsDynamicCast&lt;JSTestEventConstructor*&gt;(decodedThisValue);
+    if (UNLIKELY(!castedThis)) {
+        return throwGetterTypeError(*state, &quot;TestEventConstructor&quot;, &quot;attr3&quot;);
+    }
+    auto&amp; impl = castedThis-&gt;wrapped();
+    JSValue result = jsStringWithCache(state, impl.attr3());
+    return JSValue::encode(result);
+}
+
+#endif
+
</ins><span class="cx"> EncodedJSValue jsTestEventConstructorConstructor(ExecState* state, EncodedJSValue thisValue, PropertyName)
</span><span class="cx"> {
</span><span class="cx">     JSTestEventConstructorPrototype* domObject = jsDynamicCast&lt;JSTestEventConstructorPrototype*&gt;(JSValue::decode(thisValue));
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestObjCDOMTestEventConstructorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -32,4 +32,5 @@
</span><span class="cx"> WEBCORE_EXPORT @interface DOMTestEventConstructor : DOMObject
</span><span class="cx"> @property (readonly, copy) NSString *attr1;
</span><span class="cx"> @property (readonly, copy) NSString *attr2;
</span><ins>+@property (readonly, copy) NSString *attr3;
</ins><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestObjCDOMTestEventConstructormm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.mm (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.mm        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/test/ObjC/DOMTestEventConstructor.mm        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -67,6 +67,14 @@
</span><span class="cx">     return IMPL-&gt;attr2();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(SPECIAL_EVENT)
+- (NSString *)attr3
+{
+    WebCore::JSMainThreadNullState state;
+    return IMPL-&gt;attr3();
+}
+#endif
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> WebCore::TestEventConstructor* core(DOMTestEventConstructor *wrapper)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestTestEventConstructoridl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/TestEventConstructor.idl (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/TestEventConstructor.idl        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/bindings/scripts/test/TestEventConstructor.idl        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -34,4 +34,5 @@
</span><span class="cx">     // Attributes
</span><span class="cx">     readonly attribute DOMString attr1;
</span><span class="cx">     [InitializedByEventConstructor] readonly attribute DOMString attr2;
</span><ins>+    [InitializedByEventConstructor, Conditional=SPECIAL_EVENT] readonly attribute DOMString attr3;
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Event.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Event.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/Event.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -23,6 +23,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;Event.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;EventPath.h&quot;
</ins><span class="cx"> #include &quot;EventTarget.h&quot;
</span><span class="cx"> #include &quot;UserGestureIndicator.h&quot;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><span class="lines">@@ -59,6 +60,8 @@
</span><span class="cx">     , m_type(eventType)
</span><span class="cx">     , m_canBubble(initializer.bubbles)
</span><span class="cx">     , m_cancelable(initializer.cancelable)
</span><ins>+    , m_scoped(initializer.scoped)
+    , m_relatedTargetScoped(initializer.relatedTargetScoped)
</ins><span class="cx">     , m_createTime(convertSecondsToDOMTimeStamp(currentTime()))
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -83,6 +86,26 @@
</span><span class="cx">     m_cancelable = cancelableArg;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Event::scoped() const
+{
+    if (m_scoped)
+        return true;
+
+    // http://w3c.github.io/webcomponents/spec/shadow/#scoped-flag
+    if (!isTrusted())
+        return false;
+
+    return m_type == eventNames().abortEvent
+        || m_type == eventNames().changeEvent
+        || m_type == eventNames().errorEvent
+        || m_type == eventNames().loadEvent
+        || m_type == eventNames().resetEvent
+        || m_type == eventNames().resizeEvent
+        || m_type == eventNames().scrollEvent
+        || m_type == eventNames().selectEvent
+        || m_type == eventNames().selectstartEvent;
+}
+
</ins><span class="cx"> EventInterface Event::eventInterface() const
</span><span class="cx"> {
</span><span class="cx">     return EventInterfaceType;
</span><span class="lines">@@ -163,6 +186,13 @@
</span><span class="cx">         receivedTarget();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Vector&lt;EventTarget*&gt; Event::deepPath() const
+{
+    if (!m_eventPath)
+        return Vector&lt;EventTarget*&gt;();
+    return m_eventPath-&gt;computePathDisclosedToTarget(*m_target);
+}
+
</ins><span class="cx"> void Event::receivedTarget()
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Event.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Event.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/Event.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -36,12 +36,15 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class DataTransfer;
</span><ins>+class EventPath;
</ins><span class="cx"> class EventTarget;
</span><span class="cx"> class HTMLIFrameElement;
</span><span class="cx"> 
</span><span class="cx"> struct EventInit {
</span><span class="cx">     bool bubbles { false };
</span><span class="cx">     bool cancelable { false };
</span><ins>+    bool scoped { false };
+    bool relatedTargetScoped { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> enum EventInterface {
</span><span class="lines">@@ -114,8 +117,15 @@
</span><span class="cx"> 
</span><span class="cx">     bool bubbles() const { return m_canBubble; }
</span><span class="cx">     bool cancelable() const { return m_cancelable; }
</span><ins>+    bool scoped() const;
+    virtual bool relatedTargetScoped() const { return m_relatedTargetScoped; }
+
</ins><span class="cx">     DOMTimeStamp timeStamp() const { return m_createTime; }
</span><span class="cx"> 
</span><ins>+    void setEventPath(const EventPath&amp; path) { m_eventPath = &amp;path; }
+    void clearEventPath() { m_eventPath = nullptr; }
+    Vector&lt;EventTarget*&gt; deepPath() const;
+
</ins><span class="cx">     void stopPropagation() { m_propagationStopped = true; }
</span><span class="cx">     void stopImmediatePropagation() { m_immediatePropagationStopped = true; }
</span><span class="cx"> 
</span><span class="lines">@@ -198,6 +208,8 @@
</span><span class="cx">     AtomicString m_type;
</span><span class="cx">     bool m_canBubble { false };
</span><span class="cx">     bool m_cancelable { false };
</span><ins>+    bool m_scoped { false };
+    bool m_relatedTargetScoped { false };
</ins><span class="cx"> 
</span><span class="cx">     bool m_propagationStopped { false };
</span><span class="cx">     bool m_immediatePropagationStopped { false };
</span><span class="lines">@@ -208,6 +220,7 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned short m_eventPhase { 0 };
</span><span class="cx">     EventTarget* m_currentTarget { nullptr };
</span><ins>+    const EventPath* m_eventPath { nullptr };
</ins><span class="cx">     RefPtr&lt;EventTarget&gt; m_target;
</span><span class="cx">     DOMTimeStamp m_createTime;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Event.idl (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Event.idl        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/Event.idl        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -57,8 +57,12 @@
</span><span class="cx">     readonly attribute unsigned short   eventPhase;
</span><span class="cx">     [InitializedByEventConstructor] readonly attribute boolean bubbles;
</span><span class="cx">     [InitializedByEventConstructor] readonly attribute boolean cancelable;
</span><ins>+    [InitializedByEventConstructor, Conditional=SHADOW_DOM, EnabledAtRuntime=ShadowDOM] readonly attribute boolean scoped;
+    [InitializedByEventConstructor, Conditional=SHADOW_DOM, EnabledAtRuntime=ShadowDOM] readonly attribute boolean relatedTargetScoped;
</ins><span class="cx">     readonly attribute DOMTimeStamp     timeStamp;
</span><span class="cx"> 
</span><ins>+    [Conditional=SHADOW_DOM, EnabledAtRuntime=ShadowDOM] sequence&lt;Node&gt; deepPath();
+
</ins><span class="cx">     void               stopPropagation();
</span><span class="cx">     void               preventDefault();
</span><span class="cx">     [ObjCLegacyUnnamedParameters] void initEvent([Default=Undefined] optional DOMString eventTypeArg, 
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventContext.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventContext.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/EventContext.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx">     virtual ~EventContext();
</span><span class="cx"> 
</span><span class="cx">     Node* node() const { return m_node.get(); }
</span><ins>+    EventTarget* currentTarget() const { return m_currentTarget.get(); }
</ins><span class="cx">     EventTarget* target() const { return m_target.get(); }
</span><span class="cx">     bool currentTargetSameAsTarget() const { return m_currentTarget.get() == m_target.get(); }
</span><span class="cx">     virtual void handleLocalEvents(Event&amp;) const;
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventDispatchercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventDispatcher.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -177,8 +177,11 @@
</span><span class="cx">     if (is&lt;HTMLInputElement&gt;(*node))
</span><span class="cx">         downcast&lt;HTMLInputElement&gt;(*node).willDispatchEvent(event, clickHandlingState);
</span><span class="cx"> 
</span><del>-    if (!event.propagationStopped() &amp;&amp; !eventPath.isEmpty())
</del><ins>+    if (!event.propagationStopped() &amp;&amp; !eventPath.isEmpty()) {
+        event.setEventPath(eventPath);
</ins><span class="cx">         dispatchEventInDOM(event, eventPath, windowEventContext);
</span><ins>+        event.clearEventPath();
+    }
</ins><span class="cx"> 
</span><span class="cx">     event.setTarget(EventPath::eventTargetRespectingTargetRules(*node));
</span><span class="cx">     event.setCurrentTarget(nullptr);
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventPathcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventPath.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventPath.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/EventPath.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -49,21 +49,8 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
-    // Changing this breaks existing sites.
-    // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
-    const AtomicString&amp; eventType = event.type();
</del><span class="cx">     bool targetIsInShadowRoot = targetNode &amp;&amp; &amp;targetNode-&gt;treeScope().rootNode() == &amp;shadowRoot;
</span><del>-    return !targetIsInShadowRoot
-        || !(eventType == eventNames().abortEvent
-        || eventType == eventNames().changeEvent
-        || eventType == eventNames().errorEvent
-        || eventType == eventNames().loadEvent
-        || eventType == eventNames().resetEvent
-        || eventType == eventNames().resizeEvent
-        || eventType == eventNames().scrollEvent
-        || eventType == eventNames().selectEvent
-        || eventType == eventNames().selectstartEvent);
</del><ins>+    return !targetIsInShadowRoot || !event.scoped();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static Node* nodeOrHostIfPseudoElement(Node* node)
</span><span class="lines">@@ -174,10 +161,7 @@
</span><span class="cx">     RelatedNodeRetargeter retargeter(*relatedNode, downcast&lt;MouseOrFocusEventContext&gt;(*m_path[0]).node()-&gt;treeScope());
</span><span class="cx"> 
</span><span class="cx">     bool originIsRelatedTarget = &amp;origin == relatedNode;
</span><del>-    // FIXME: We should add a new flag on Event instead.
-    bool shouldTrimEventPath = m_event.type() == eventNames().mouseoverEvent
-        || m_event.type() == eventNames().mousemoveEvent
-        || m_event.type() == eventNames().mouseoutEvent;
</del><ins>+    bool relatedTargetScoped = m_event.relatedTargetScoped();
</ins><span class="cx">     Node&amp; rootNodeInOriginTreeScope = origin.treeScope().rootNode();
</span><span class="cx">     TreeScope* previousTreeScope = nullptr;
</span><span class="cx">     size_t originalEventPathSize = m_path.size();
</span><span class="lines">@@ -189,14 +173,14 @@
</span><span class="cx">             retargeter.moveToNewTreeScope(previousTreeScope, currentTreeScope);
</span><span class="cx"> 
</span><span class="cx">         Node* currentRelatedNode = retargeter.currentNode(currentTreeScope);
</span><del>-        if (UNLIKELY(shouldTrimEventPath &amp;&amp; !originIsRelatedTarget &amp;&amp; context.target() == currentRelatedNode)) {
</del><ins>+        if (UNLIKELY(relatedTargetScoped &amp;&amp; !originIsRelatedTarget &amp;&amp; context.target() == currentRelatedNode)) {
</ins><span class="cx">             m_path.shrink(contextIndex);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         context.setRelatedTarget(currentRelatedNode);
</span><span class="cx"> 
</span><del>-        if (UNLIKELY(shouldTrimEventPath &amp;&amp; originIsRelatedTarget &amp;&amp; context.node() == &amp;rootNodeInOriginTreeScope)) {
</del><ins>+        if (UNLIKELY(relatedTargetScoped &amp;&amp; originIsRelatedTarget &amp;&amp; context.node() == &amp;rootNodeInOriginTreeScope)) {
</ins><span class="cx">             m_path.shrink(contextIndex + 1);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -251,14 +235,53 @@
</span><span class="cx"> 
</span><span class="cx"> bool EventPath::hasEventListeners(const AtomicString&amp; eventType) const
</span><span class="cx"> {
</span><del>-    for (auto&amp; eventPath : m_path) {
-        if (eventPath-&gt;node()-&gt;hasEventListeners(eventType))
</del><ins>+    for (auto&amp; context : m_path) {
+        if (context-&gt;node()-&gt;hasEventListeners(eventType))
</ins><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// http://w3c.github.io/webcomponents/spec/shadow/#dfn-unclosed-node
+static bool isUnclosedNodeOf(const Node&amp; a, const Node&amp; b)
+{
+    // Use Vector instead of HashSet since we expect the number of ancestor tree scopes to be small.
+    Vector&lt;TreeScope*, 8&gt; treeScopesOpenToB;
+
+    for (auto* scope = &amp;b.treeScope(); scope; scope = scope-&gt;parentTreeScope())
+        treeScopesOpenToB.append(scope);
+
+    for (auto* treeScopeThatCanAccessA = &amp;a.treeScope(); treeScopeThatCanAccessA; treeScopeThatCanAccessA = treeScopeThatCanAccessA-&gt;parentTreeScope()) {
+        for (auto* openToB : treeScopesOpenToB) {
+            if (openToB == treeScopeThatCanAccessA)
+                return true;
+        }
+        auto&amp; root = treeScopeThatCanAccessA-&gt;rootNode();
+        if (is&lt;ShadowRoot&gt;(root) &amp;&amp; downcast&lt;ShadowRoot&gt;(root).type() != ShadowRoot::Type::Open)
+            break;
+    }
+
+    return false;
+}
+
+Vector&lt;EventTarget*&gt; EventPath::computePathDisclosedToTarget(const EventTarget&amp; target) const
+{
+    Vector&lt;EventTarget*&gt; path;
+    const Node* targetNode = const_cast&lt;EventTarget&amp;&gt;(target).toNode();
+    if (!targetNode)
+        return path;
+
+    for (auto&amp; context : m_path) {
+        if (Node* nodeInPath = context-&gt;currentTarget()-&gt;toNode()) {
+            if (isUnclosedNodeOf(*nodeInPath, *targetNode))
+                path.append(context-&gt;currentTarget());
+        }
+    }
+
+    return path;
+}
+
</ins><span class="cx"> RelatedNodeRetargeter::RelatedNodeRetargeter(Node&amp; relatedNode, TreeScope&amp; targetTreeScope)
</span><span class="cx">     : m_relatedNode(relatedNode)
</span><span class="cx">     , m_retargetedRelatedNode(&amp;relatedNode)
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventPathh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventPath.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventPath.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/EventPath.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -48,6 +48,8 @@
</span><span class="cx"> 
</span><span class="cx">     EventContext* lastContextIfExists() { return m_path.isEmpty() ? nullptr : m_path.last().get(); }
</span><span class="cx"> 
</span><ins>+    Vector&lt;EventTarget*&gt; computePathDisclosedToTarget(const EventTarget&amp;) const;
+
</ins><span class="cx">     static EventTarget* eventTargetRespectingTargetRules(Node&amp; referenceNode)
</span><span class="cx">     {
</span><span class="cx">         if (is&lt;PseudoElement&gt;(referenceNode))
</span></span></pre></div>
<a id="trunkSourceWebCoredomFocusEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/FocusEvent.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/FocusEvent.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/FocusEvent.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -52,4 +52,9 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool FocusEvent::relatedTargetScoped() const
+{
+    return (isTrusted() &amp;&amp; m_relatedTarget) || UIEvent::relatedTargetScoped();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomFocusEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/FocusEvent.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/FocusEvent.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/FocusEvent.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -58,6 +58,8 @@
</span><span class="cx">     FocusEvent(const AtomicString&amp; type, bool canBubble, bool cancelable, AbstractView*, int, RefPtr&lt;EventTarget&gt;&amp;&amp;);
</span><span class="cx">     FocusEvent(const AtomicString&amp; type, const FocusEventInit&amp;);
</span><span class="cx"> 
</span><ins>+    bool relatedTargetScoped() const override;
+
</ins><span class="cx">     bool isFocusEvent() const override;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;EventTarget&gt; m_relatedTarget;
</span></span></pre></div>
<a id="trunkSourceWebCoredomMouseEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/MouseEvent.cpp (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/MouseEvent.cpp        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/MouseEvent.cpp        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -189,6 +189,11 @@
</span><span class="cx">     return event.type() == eventNames().clickEvent &amp;&amp; (!is&lt;MouseEvent&gt;(event) || downcast&lt;MouseEvent&gt;(event).button() != RightButton);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool MouseEvent::relatedTargetScoped() const
+{
+    return (isTrusted() &amp;&amp; m_relatedTarget) || UIEvent::relatedTargetScoped();
+}
+
</ins><span class="cx"> int MouseEvent::which() const
</span><span class="cx"> {
</span><span class="cx">     // For the DOM, the return values for left, middle and right mouse buttons are 0, 1, 2, respectively.
</span></span></pre></div>
<a id="trunkSourceWebCoredomMouseEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/MouseEvent.h (198055 => 198056)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/MouseEvent.h        2016-03-12 00:36:17 UTC (rev 198055)
+++ trunk/Source/WebCore/dom/MouseEvent.h        2016-03-12 03:11:04 UTC (rev 198056)
</span><span class="lines">@@ -121,6 +121,8 @@
</span><span class="cx"> 
</span><span class="cx">     MouseEvent();
</span><span class="cx"> 
</span><ins>+    bool relatedTargetScoped() const override;
+
</ins><span class="cx"> private:
</span><span class="cx">     unsigned short m_button;
</span><span class="cx">     bool m_buttonDown;
</span></span></pre>
</div>
</div>

</body>
</html>