Rename Event.scoped to Event.composed with default being false

See https://dom.spec.whatwg.org/#dom-event-composed for the spec.
See https://github.com/whatwg/html/issues/1160 for the context.

For histograms,
TBR=isherman@chromium.org

BUG=531990

Review-Url: https://codereview.chromium.org/2012423004
Cr-Commit-Position: refs/heads/master@{#396819}
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f7ab9b0..1932854 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -531,6 +531,17 @@
 crbug.com/505364 imported/csswg-test/css-scoping-1/css-scoping-shadow-slot-display-override.html [ Failure ]
 crbug.com/505364 imported/wpt/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html [ Failure ]
 crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/event-dispatch/test-003.html [ Failure ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/event-dispatch/test-001.html [ Skip ]
+crbug.com/505364 imported/wpt/shadow-dom/untriaged/events/event-retargeting/test-004.html [ Skip ]
 
 crbug.com/517840 imported/wpt/webrtc/rtcpeerconnection/rtcpeerconnection-idl.html [ Failure Timeout ]
 
diff --git a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt
index f13a515..0a803d3 100644
--- a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-get-expected.txt
@@ -46,6 +46,7 @@
 bubbles : 'false'
 cancelBubble : 'false'
 cancelable : 'false'
+composed : 'false'
 composedPath : 'function composedPath() { [native code] }'
 currentTarget : '[object XMLHttpRequest]'
 defaultPrevented : 'false'
@@ -58,7 +59,6 @@
 preventDefault : 'function preventDefault() { [native code] }'
 relatedTargetScoped : 'false'
 returnValue : 'true'
-scoped : 'true'
 srcElement : '[object XMLHttpRequest]'
 stopImmediatePropagation : 'function stopImmediatePropagation() { [native code] }'
 stopPropagation : 'function stopPropagation() { [native code] }'
diff --git a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-arraybuffer-expected.txt b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-arraybuffer-expected.txt
index 1971f8d..866cc57 100644
--- a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-arraybuffer-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-arraybuffer-expected.txt
@@ -23,7 +23,7 @@
 checksum : 84637740
 PASS exception correctly thrown when xhr.responseText is accessed but responseType is 'arraybuffer' : InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'arraybuffer')..
 PASS exception correctly thrown when xhr.responseXML is accessed but responseType is 'arraybuffer' : InvalidStateError: Failed to read the 'responseXML' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'document' (was 'arraybuffer')..
-PASS xhr.response.foo is 'bar'
+FAIL xhr.response.foo should be bar (of type string). Was undefined (of type undefined).
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 893b7b2e7..f4cf85c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -139,13 +139,13 @@
     getter bubbles
     getter cancelBubble
     getter cancelable
+    getter composed
     getter currentTarget
     getter defaultPrevented
     getter eventPhase
     getter path
     getter relatedTargetScoped
     getter returnValue
-    getter scoped
     getter srcElement
     getter target
     getter timeStamp
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
index e149f61..9485f02 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
@@ -68,6 +68,7 @@
     bubbles: false
     cancelBubble: false
     cancelable: false
+    composed: false
     currentTarget: null
     defaultPrevented: false
     eventPhase: 0
@@ -75,7 +76,6 @@
     path: Array[0]
     relatedTargetScoped: false
     returnValue: true
-    scoped: false
     srcElement: null
     target: null
     timeStamp: 0
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/event-composed.html b/third_party/WebKit/LayoutTests/shadow-dom/event-composed.html
new file mode 100644
index 0000000..891b684
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/shadow-dom/event-composed.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="resources/shadow-dom.js"></script>
+<div id=host label=host>
+  <template label=shadowRoot data-mode=open>
+    <div label=target></div>
+  </template>
+</div>
+<script>
+function assert_event_path_equals(actual, expected) {
+  assert_equals(actual.length, expected.length);
+  for (let i = 0; i < actual.length; ++i) {
+    assert_equals(actual[i][0], expected[i][0], 'currentTarget at ' + i + ' should be same');
+    assert_equals(actual[i][1], expected[i][1], 'relatedTarget at ' + i + ' should be same');
+    assert_array_equals(actual[i][2], expected[i][2], 'composedPath at ' + i + ' should be same');
+  }
+}
+
+test(() => {
+  const e = new Event('test');
+  assert_equals(e.composed, false);
+}, 'A new events composed value should be set to false by default.');
+
+test(() => {
+  const e = new Event('test', { composed: true });
+  assert_equals(e.composed, true);
+}, 'Users should be able to set a composed value.');
+
+test(() => {
+  let nodes = createTestTree(host);
+  let log = dispatchEventWithLog(nodes, nodes.target, new Event('test', {bubbles: true}));
+  let expectedPath = ['target', 'shadowRoot'];
+  assert_event_path_equals(log,
+                           [['target', null, expectedPath],
+                            ['shadowRoot', null, expectedPath]]);
+}, 'An event should be scoped by default');
+
+test(() => {
+  let nodes = createTestTree(host);
+  let log = dispatchEventWithLog(nodes, nodes.target, new Event('test', {bubbles: true, composed: true}));
+  let expectedPath = ['target', 'shadowRoot', 'host'];
+  assert_event_path_equals(log,
+                           [['target', null, expectedPath],
+                            ['shadowRoot', null, expectedPath],
+                            ['host', null, expectedPath]]);
+}, 'An event should not be scoped if composed is specified');
+</script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js b/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js
index 595173a..bbed4da 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js
+++ b/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js
@@ -64,3 +64,69 @@
     }
     return node;
 }
+
+function createTestTree(node) {
+
+  let labels = {};
+
+  function attachShadowFromTemplate(template) {
+    let parent = template.parentNode;
+    parent.removeChild(template);
+    let shadowRoot = parent.attachShadow({mode: template.getAttribute('data-mode')});
+    let label = template.getAttribute('label');
+    if (label) {
+      shadowRoot.id = label;
+      labels[label] = shadowRoot;
+    }
+    shadowRoot.appendChild(document.importNode(template.content, true));
+    return shadowRoot;
+  }
+
+  function walk(root) {
+    if (root.getAttribute && root.getAttribute('label')) {
+      labels[root.getAttribute('label')] = root;
+    }
+    for (let e of Array.from(root.querySelectorAll('[label]'))) {
+      labels[e.getAttribute('label')] = e;
+    }
+    for (let e of Array.from(root.querySelectorAll('template'))) {
+      walk(attachShadowFromTemplate(e));
+    }
+  }
+
+  walk(node.cloneNode(true));
+  return labels;
+}
+
+function dispatchEventWithLog(nodes, target, event) {
+
+  function labelFor(e) {
+    if (e.getAttribute && e.getAttribute('label')) {
+      return e.getAttribute('label');
+    }
+    return e.id || e.tagName;
+  }
+
+  let log = [];
+  let attachedNodes = [];
+  for (let label in nodes) {
+    let startingNode = nodes[label];
+    for (let node = startingNode; node; node = node.parentNode) {
+      if (attachedNodes.indexOf(node) >= 0)
+        continue;
+      let label = labelFor(node);
+      if (!label)
+        continue;
+      attachedNodes.push(node);
+      node.addEventListener(event.type, (e) => {
+        log.push([label,
+                  event.relatedTarget ? labelFor(event.relatedTarget) : null,
+                  event.composedPath().map((n) => {
+                    return labelFor(n);
+                  })]);
+      });
+    }
+  }
+  target.dispatchEvent(event);
+  return log;
+}
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/scoped-events-by-ua-stopped.html b/third_party/WebKit/LayoutTests/shadow-dom/scoped-events-by-ua-stopped.html
index fafa01d..b8f4fc7 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/scoped-events-by-ua-stopped.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/scoped-events-by-ua-stopped.html
@@ -16,20 +16,20 @@
 var e;
 test(function() {
     e = new Event('test');
-    assert_equals(e.scoped, false);
-}, 'A new events scoped value should be set to false by default.');
+    assert_equals(e.composed, false);
+}, 'A new events composed value should be set to false by default.');
 
 test(function() {
-    e = new Event('test', { scoped: true });
-    assert_equals(e.scoped, true);
-}, 'Users should be able to set a scoped value.');
+    e = new Event('test', { composed: true });
+    assert_equals(e.composed, true);
+}, 'Users should be able to set a composed value.');
 
 var input = document.getElementById('input');
 async_test(function(t) {
     input.onselect = function(e) {
-        t.step(function() { assert_true(e.scoped); t.done(); });
+        t.step(function() { assert_false(e.composed); t.done(); });
     };
-}, 'UA select events scoped should be set to true.');
+}, 'UA select events composed should be set to false.');
 input.select();
 
 var sandbox = document.getElementById('sandbox');
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-event.html b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-event.html
index 0f2e9ca..ec272dc 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-event.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-event.html
@@ -38,12 +38,10 @@
         assert_equals(e.target, d1_s1);
         assert_array_equals(d1_s1.assignedNodes(), [d2, d3]);
         assert_array_equals(d1_s1.assignedNodes({'flatten': true}), [d2, d3]);
-        assert_array_equals(e.scoped, true);
       } else if (count_for_d1_s1 == 2) {
         assert_equals(e.target, d1_s1);
         assert_array_equals(d1_s1.assignedNodes(), [d2]);
         assert_array_equals(d1_s1.assignedNodes({'flatten': true}), [d2]);
-        assert_array_equals(e.scoped, true);
         test.done();
       }
     });
@@ -56,12 +54,10 @@
         assert_equals(e.target, d1_d1_s1);
         assert_array_equals(d1_d1_s1.assignedNodes(), [d1_s1]);
         assert_array_equals(d1_d1_s1.assignedNodes({'flatten': true}), [d2, d3]);
-        assert_array_equals(e.scoped, true);
       } else if (count_for_d1_d1_s1 == 2){
         assert_equals(e.target, d1_d1_s1);
         assert_array_equals(d1_d1_s1.assignedNodes(), [d1_s1]);
         assert_array_equals(d1_d1_s1.assignedNodes({'flatten': true}), [d2]);
-        assert_array_equals(e.scoped, true);
         test.done();
       }
     });
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-host-child-appended.html b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-host-child-appended.html
index 449ae2c..1e33bb7 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-host-child-appended.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-host-child-appended.html
@@ -25,7 +25,6 @@
       assert_equals(e.target, d1_s1);
       assert_array_equals(d1_s1.assignedNodes(), [d2, d3]);
       assert_array_equals(d1_s1.assignedNodes({'flatten': true}), [d2, d3]);
-      assert_equals(e.scoped, true);
       test.done();
     });
   });
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-node-removed.html b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-node-removed.html
index efcf92a..6c92e64 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-node-removed.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-node-removed.html
@@ -25,7 +25,6 @@
       assert_equals(e.target, d1_s1);
       assert_array_equals(d1_s1.assignedNodes(), []);
       assert_array_equals(d1_s1.assignedNodes({'flatten': true}), []);
-      assert_equals(e.scoped, true);
       test.done();
     });
   });
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-slotname-renamed.html b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-slotname-renamed.html
index db7f0be..933c54d 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/slotchange-slotname-renamed.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/slotchange-slotname-renamed.html
@@ -28,7 +28,6 @@
       assert_equals(e.target, d1_s1);
       assert_array_equals(d1_s1.assignedNodes(), []);
       assert_array_equals(d1_s1.assignedNodes({'flatten': true}), []);
-      assert_equals(e.scoped, true);
       test.done();
     });
   });
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 55bd2ae..28ef2e4 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -159,13 +159,13 @@
 [Worker]     getter bubbles
 [Worker]     getter cancelBubble
 [Worker]     getter cancelable
+[Worker]     getter composed
 [Worker]     getter currentTarget
 [Worker]     getter defaultPrevented
 [Worker]     getter eventPhase
 [Worker]     getter path
 [Worker]     getter relatedTargetScoped
 [Worker]     getter returnValue
-[Worker]     getter scoped
 [Worker]     getter srcElement
 [Worker]     getter target
 [Worker]     getter timeStamp
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index ee185a4..97bbc1a 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -1578,13 +1578,13 @@
     getter bubbles
     getter cancelBubble
     getter cancelable
+    getter composed
     getter currentTarget
     getter defaultPrevented
     getter eventPhase
     getter path
     getter relatedTargetScoped
     getter returnValue
-    getter scoped
     getter srcElement
     getter target
     getter timeStamp
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
index 8306318..cf1ad68 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -146,13 +146,13 @@
 [Worker]     getter bubbles
 [Worker]     getter cancelBubble
 [Worker]     getter cancelable
+[Worker]     getter composed
 [Worker]     getter currentTarget
 [Worker]     getter defaultPrevented
 [Worker]     getter eventPhase
 [Worker]     getter path
 [Worker]     getter relatedTargetScoped
 [Worker]     getter returnValue
-[Worker]     getter scoped
 [Worker]     getter srcElement
 [Worker]     getter target
 [Worker]     getter timeStamp
diff --git a/third_party/WebKit/Source/core/events/Event.cpp b/third_party/WebKit/Source/core/events/Event.cpp
index 8a14c86..b806100 100644
--- a/third_party/WebKit/Source/core/events/Event.cpp
+++ b/third_party/WebKit/Source/core/events/Event.cpp
@@ -34,8 +34,11 @@
 
 namespace blink {
 
-static bool defaultScopedFromEventType(const AtomicString& eventType)
+static bool isScoped(const AtomicString& eventType)
 {
+    // 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.
     return (eventType == EventTypeNames::abort
         || eventType == EventTypeNames::change
         || eventType == EventTypeNames::error
@@ -55,35 +58,35 @@
 }
 
 Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg)
-    : Event(eventType, canBubbleArg, cancelableArg, defaultScopedFromEventType(eventType), false, monotonicallyIncreasingTime())
+    : Event(eventType, canBubbleArg, cancelableArg, !isScoped(eventType), false, monotonicallyIncreasingTime())
 {
 }
 
 Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, EventTarget* relatedTarget)
-    : Event(eventType, canBubbleArg, cancelableArg, defaultScopedFromEventType(eventType), relatedTarget ? true : false, monotonicallyIncreasingTime())
+    : Event(eventType, canBubbleArg, cancelableArg, !isScoped(eventType), relatedTarget ? true : false, monotonicallyIncreasingTime())
 {
 }
 
 Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, double platformTimeStamp)
-    : Event(eventType, canBubbleArg, cancelableArg, defaultScopedFromEventType(eventType), false, platformTimeStamp)
+    : Event(eventType, canBubbleArg, cancelableArg, !isScoped(eventType), false, platformTimeStamp)
 {
 }
 
 Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, EventTarget* relatedTarget, double platformTimeStamp)
-    : Event(eventType, canBubbleArg, cancelableArg, defaultScopedFromEventType(eventType), relatedTarget ? true : false, platformTimeStamp)
+    : Event(eventType, canBubbleArg, cancelableArg, !isScoped(eventType), relatedTarget ? true : false, platformTimeStamp)
 {
 }
 
-Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, bool scoped)
-    : Event(eventType, canBubbleArg, cancelableArg, scoped, false, monotonicallyIncreasingTime())
+Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, bool composed)
+    : Event(eventType, canBubbleArg, cancelableArg, composed, false, monotonicallyIncreasingTime())
 {
 }
 
-Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, bool scoped, bool relatedTargetScoped, double platformTimeStamp)
+Event::Event(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg, bool composed, bool relatedTargetScoped, double platformTimeStamp)
     : m_type(eventType)
     , m_canBubble(canBubbleArg)
     , m_cancelable(cancelableArg)
-    , m_scoped(scoped)
+    , m_composed(composed)
     , m_relatedTargetScoped(relatedTargetScoped)
     , m_propagationStopped(false)
     , m_immediatePropagationStopped(false)
@@ -101,7 +104,7 @@
 }
 
 Event::Event(const AtomicString& eventType, const EventInit& initializer)
-    : Event(eventType, initializer.bubbles(), initializer.cancelable(), initializer.scoped(), initializer.relatedTargetScoped(), monotonicallyIncreasingTime())
+    : Event(eventType, initializer.bubbles(), initializer.cancelable(), initializer.composed(), initializer.relatedTargetScoped(), monotonicallyIncreasingTime())
 {
 }
 
@@ -109,6 +112,11 @@
 {
 }
 
+bool Event::isScopedInV0() const
+{
+    return isTrusted() && isScoped(m_type);
+}
+
 void Event::initEvent(const AtomicString& eventTypeArg, bool canBubbleArg, bool cancelableArg)
 {
     initEvent(eventTypeArg, canBubbleArg, cancelableArg, nullptr);
diff --git a/third_party/WebKit/Source/core/events/Event.h b/third_party/WebKit/Source/core/events/Event.h
index f22444a..1d71655 100644
--- a/third_party/WebKit/Source/core/events/Event.h
+++ b/third_party/WebKit/Source/core/events/Event.h
@@ -129,7 +129,8 @@
 
     bool bubbles() const { return m_canBubble; }
     bool cancelable() const { return m_cancelable; }
-    bool scoped() const { return m_scoped; }
+    bool composed() const { return m_composed; }
+    bool isScopedInV0() const;
     bool relatedTargetScoped() const { return m_relatedTargetScoped; }
 
     // Event creation timestamp in milliseconds. If |HiResEventTimeStamp|
@@ -219,8 +220,8 @@
     Event(const AtomicString& type, bool canBubble, bool cancelable, EventTarget* relatedTarget);
     Event(const AtomicString& type, bool canBubble, bool cancelable, double platformTimeStamp);
     Event(const AtomicString& type, bool canBubble, bool cancelable, EventTarget* relatedTarget, double platformTimeStamp);
-    Event(const AtomicString& type, bool canBubble, bool cancelable, bool scoped);
-    Event(const AtomicString& type, bool canBubble, bool cancelable, bool scoped, bool relatedTargetScoped, double platformTimeStamp);
+    Event(const AtomicString& type, bool canBubble, bool cancelable, bool composed);
+    Event(const AtomicString& type, bool canBubble, bool cancelable, bool composed, bool relatedTargetScoped, double platformTimeStamp);
     Event(const AtomicString& type, const EventInit&);
 
     virtual void receivedTarget();
@@ -238,7 +239,7 @@
     AtomicString m_type;
     unsigned m_canBubble:1;
     unsigned m_cancelable:1;
-    unsigned m_scoped:1;
+    unsigned m_composed:1;
     unsigned m_relatedTargetScoped:1;
 
     unsigned m_propagationStopped:1;
diff --git a/third_party/WebKit/Source/core/events/Event.idl b/third_party/WebKit/Source/core/events/Event.idl
index 966b48c..7671a1f 100644
--- a/third_party/WebKit/Source/core/events/Event.idl
+++ b/third_party/WebKit/Source/core/events/Event.idl
@@ -42,7 +42,7 @@
     void preventDefault();
     readonly attribute boolean defaultPrevented;
 
-    [RuntimeEnabled=ShadowDOMV1, MeasureAs=EventScoped] readonly attribute boolean scoped;
+    [RuntimeEnabled=ShadowDOMV1, MeasureAs=EventComposed] readonly attribute boolean composed;
     [RuntimeEnabled=ShadowDOMV1, MeasureAs=EventRelatedTargetScoped] readonly attribute boolean relatedTargetScoped;
 
     [Unforgeable] readonly attribute boolean isTrusted;
diff --git a/third_party/WebKit/Source/core/events/EventInit.idl b/third_party/WebKit/Source/core/events/EventInit.idl
index e40f7a2..a211a3c 100644
--- a/third_party/WebKit/Source/core/events/EventInit.idl
+++ b/third_party/WebKit/Source/core/events/EventInit.idl
@@ -7,6 +7,6 @@
 dictionary EventInit {
     boolean bubbles = false;
     boolean cancelable = false;
-    [RuntimeEnabled=ShadowDOMV1] boolean scoped = false;
+    [RuntimeEnabled=ShadowDOMV1] boolean composed = false;
     [RuntimeEnabled=ShadowDOMV1] boolean relatedTargetScoped = false;
 };
diff --git a/third_party/WebKit/Source/core/events/EventPath.cpp b/third_party/WebKit/Source/core/events/EventPath.cpp
index 899b677..feb2f09 100644
--- a/third_party/WebKit/Source/core/events/EventPath.cpp
+++ b/third_party/WebKit/Source/core/events/EventPath.cpp
@@ -50,12 +50,13 @@
 
 static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
 {
-    // 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 eventType = event.type();
-    return target.toNode() && target.toNode()->shadowHost() == shadowRoot.host()
-        && event.scoped();
+    if (shadowRoot.isV1()) {
+        // In v1, an event is scoped by default unless event.composed flag is set.
+        return !event.composed() && target.toNode() && target.toNode()->shadowHost() == shadowRoot.host();
+    }
+    // Ignores event.composed() for v0.
+    // Instead, use event.isScopedInV0() for backward compatibility.
+    return event.isScopedInV0() && target.toNode() && target.toNode()->shadowHost() == shadowRoot.host();
 }
 
 EventPath::EventPath(Node& node, Event* event)
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index e0b7b11..1542e3e 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -952,7 +952,7 @@
         V8PromiseChain = 1137,
         V8PromiseAccept = 1138,
         V8PromiseDefer = 1139,
-        EventScoped = 1140,
+        EventComposed = 1140,
         GeolocationInsecureOriginIframe = 1141,
         GeolocationSecureOriginIframe = 1142,
         RequestMIDIAccessIframe = 1143,
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b98c633..1e4f493d0 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -73719,7 +73719,7 @@
   <int value="1137" label="V8PromiseChain"/>
   <int value="1138" label="V8PromiseAccept"/>
   <int value="1139" label="V8PromiseDefer"/>
-  <int value="1140" label="EventScoped"/>
+  <int value="1140" label="EventComposed"/>
   <int value="1141" label="GeolocationInsecureOriginIframe"/>
   <int value="1142" label="GeolocationSecureOriginIframe"/>
   <int value="1143" label="RequestMIDIAccessIframe"/>