Bug 1488656 [wpt PR 12839] - Fix :scope selector matching in the case of DocumentFragment/ShadowRoot, a=testonly
authorMomoko Sumida <momon@google.com>
Thu, 13 Sep 2018 02:58:59 +0000
changeset 492328 40c8e72fa87d6667c83a6773373cd381f928d2f6
parent 492327 6c04289208fe54724adc85b1980cfd52a69c6aea
child 492329 3f769ef4c0b86898825b025ce433a4ea5272543c
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1488656, 12839, 1158445, 859692, 1203472, 590595
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1488656 [wpt PR 12839] - Fix :scope selector matching in the case of DocumentFragment/ShadowRoot, a=testonly Automatic update from web-platform-testsFix :scope selector matching in the case of DocumentFragment/ShadowRoot When used in querySelector and querySelectorAll, :scope should match the element or the DocumentFragment/ShadowRoot the querySelector is called on. However, WPT adeed in crrev.com/c/1158445 shows that :scope matches nothing when querySelector is called on shadow root, while it works fine when querySelector is called on true element. This CL fixes :scope selector matching process so that :scope itself matches DocumentFragment/ShadowRoot when querySelector is called on DocumentFragment/ShadowRoot. Tests for DocumentFragment are also added in this CL. Link to the spec: https://drafts.csswg.org/selectors-4/#the-scope-pseudo Link to related issue: https://github.com/w3c/csswg-drafts/issues/3016 Link to related CL: crrev.com/c/1158445 Bug: 859692 Change-Id: If20fc4b122d93a553dc478be0ee958958340a34f Reviewed-on: https://chromium-review.googlesource.com/1203472 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Reviewed-by: Rakina Zata Amni <rakina@chromium.org> Commit-Queue: Momoko Sumida <momon@google.com> Cr-Commit-Position: refs/heads/master@{#590595} -- wpt-commits: 40529833d147d79895ace6de923d126aae7631e8 wpt-pr: 12839
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/css/selectors/scope-selector.html
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -580682,17 +580682,17 @@
    "89de32fdb8a4e48b1320f40f5a75352773077cee",
    "support"
   ],
   "css/selectors/root-siblings.htm": [
    "99c0cb4c26294d1d8b655ed0a35d1f0eeb4a9ccb",
    "reftest"
   ],
   "css/selectors/scope-selector.html": [
-   "bda0aed602aa691bba4c4089f0a4827a9b836c9e",
+   "0340f25919f34aaad07d53d1550d5155f73fb26b",
    "testharness"
   ],
   "css/selectors/scope-without-scoping.html": [
    "2ee7619e8023923c7d484554fd78c8e042d4b6ad",
    "reftest"
   ],
   "css/selectors/selection-image-001-no-selection-noref.html": [
    "ad2104bef671991a802c1750e6a2a6be1a7144a1",
--- a/testing/web-platform/tests/css/selectors/scope-selector.html
+++ b/testing/web-platform/tests/css/selectors/scope-selector.html
@@ -1,34 +1,86 @@
 <!doctype html>
 <link rel='help' href='https://drafts.csswg.org/selectors-4/#the-scope-pseudo'>
-<meta name='description' content=':scope should match when context object is a shadow root'>
+<meta name='description' content=':scope should match when context object is a ShadowRoot or a DocumentFragment'>
 <script src='/resources/testharness.js'></script>
 <script src='/resources/testharnessreport.js'></script>
 <div id='shadowHost'></div>
 <script>
 'use strict'
-  const shadowRoot = shadowHost.attachShadow({mode:'open'})
-  shadowRoot.innerHTML = '<div class="div" id="external_div">Shadow Element<div id="nesteddiv">nested</div></div>';
+const shadowRoot = shadowHost.attachShadow({mode:'open'})
+const externalDiv = document.createElement('div');
+externalDiv.setAttribute('id', 'external');
+const nestedDiv = document.createElement('div');
+nestedDiv.setAttribute('id', 'nested');
+shadowRoot.appendChild(externalDiv);
+externalDiv.appendChild(nestedDiv);
 
-test(() => {
-  assert_equals(shadowRoot.firstChild.querySelectorAll(':scope >  div').length, 1, 'should get the number of direct children of external_div');
-  assert_equals(shadowRoot.firstChild.querySelector(':scope > div'), shadowRoot.getElementById("nesteddiv"), 'should get the first direct child of external_div');
-  assert_equals(shadowRoot.firstChild.querySelector(':scope > div').innerHTML, 'nested', 'should get the text in nesteddiv');
+const nestedShadowRoot = nestedDiv.attachShadow({mode:'open'})
+const shadowExternalDiv = document.createElement('div');
+shadowExternalDiv.setAttribute('id', 'shadow_external');
+const shadowNestedDiv = document.createElement('div');
+shadowNestedDiv.setAttribute('id', 'shadow_nested');
+nestedShadowRoot.appendChild(shadowExternalDiv);
+shadowExternalDiv.appendChild(shadowNestedDiv);
+
+test (() => {
+  assert_equals(shadowRoot.firstChild.querySelectorAll(':scope > div').length, 1, 'should get the number of direct children of externalDiv');
+  assert_equals(shadowRoot.firstChild.querySelector(':scope > div'), shadowRoot.getElementById('nested'), 'should get the first direct child of externalDiv');
+  assert_equals(shadowRoot.firstChild.querySelector(':scope > div'), shadowRoot.getElementById('nested'), 'should get nestedDiv');
 }, 'scope selector works in shadowRoot.firstChild')
 
-test(() => {
-  assert_equals(shadowRoot.querySelector(':scope > div'), shadowRoot.getElementById('external_div'), 'should get the direct child of shadowRoot');
+test (() => {
+  assert_equals(shadowRoot.querySelector(':scope > div'), shadowRoot.getElementById('external'), 'should get the direct child of shadowRoot');
   assert_equals(shadowRoot.querySelectorAll(':scope > div').length, 1, 'should get the number of direct div children of shadowRoot');
 }, 'Selecting direct child of shadow root with :scope should work')
 
+test (() => {
+  assert_equals(shadowRoot.querySelector(':scope div'), shadowRoot.getElementById('external'), 'should get the first div descendant of shadowRoot');
+  assert_equals(shadowRoot.querySelectorAll(':scope div').length, 2, 'should get the number of the div descendants of shadowRoot, :scope div should not match for nestedShadow');
+}, 'Selecting descendants of shadow root with :scope should work')
+
+test (() => {
+  assert_equals(nestedShadowRoot.querySelector(':scope > div'), nestedShadowRoot.getElementById('shadow_external'), 'should get the direct child of nestedShadowRoot');
+  assert_equals(nestedShadowRoot.querySelectorAll(':scope > div').length, 1, 'should get the number of direct div children of nestedShadowRoot');
+}, 'Selecting direct child of nested shadow root with :scope should work')
+
+test (() => {
+  assert_equals(nestedShadowRoot.querySelector(':scope div'), nestedShadowRoot.getElementById('shadow_external'), 'should get the first div descendant of nestedShadowRoot');
+  assert_equals(nestedShadowRoot.querySelectorAll(':scope div').length, 2, 'should get the number of the div descendants of nestedShadowRoot');
+}, 'Selecting descendants of nested shadow root with :scope should work')
+
+const documentFragment = document.createDocumentFragment();
+const external_div = document.createElement('div');
+external_div.setAttribute('id', 'external_div');
+const nested_div = document.createElement('div');
+nested_div.setAttribute('id', 'nested_div');
+documentFragment.appendChild(external_div);
+external_div.appendChild(nested_div);
+
 test(() => {
-  assert_equals(shadowRoot.querySelector(':scope div'), shadowRoot.getElementById('external_div'), 'should get the first div descendant of shadowRoot');
-  assert_equals(shadowRoot.querySelectorAll(':scope div').length, 2, 'should get the number of the div descendants of shadowRoot');
-}, 'Selecting descendants of shadow root with :scope should work')
+  assert_equals(documentFragment.firstChild.querySelectorAll(':scope > div').length, 1, 'should get the number of direct children of external_div');
+  assert_equals(documentFragment.firstChild.querySelector(':scope > div'), documentFragment.getElementById('nested_div'), 'should get the first direct child of external_div');
+  assert_equals(documentFragment.firstChild.querySelector(':scope > div'), documentFragment.getElementById('nested_div'), 'should get the text in nesteddiv');
+}, 'scope selector works in documentFragment.firstChild')
+
+test(() => {
+  assert_equals(documentFragment.querySelector(':scope > div'), documentFragment.getElementById('external_div'), 'should get the direct child of DocumentFragment');
+  assert_equals(documentFragment.querySelectorAll(':scope > div').length, 1, 'should get the number of direct div children of DocumentFragment');
+}, 'Selecting direct child of document fragment with :scope should work')
+
+test(() => {
+  assert_equals(documentFragment.querySelector(':scope div'), documentFragment.getElementById('external_div'), 'should get the first div descendant of DocumentFragment');
+  assert_equals(documentFragment.querySelectorAll(':scope div').length, 2, 'should get the number of the div descendants of DocumentFragment');
+}, 'Selecting descendants of document fragment with :scope should work')
 
 test(() => {
   assert_equals(shadowRoot.firstChild.querySelector(':scope'), null, 'should return null');
+  assert_equals(shadowRoot.firstChild.querySelectorAll(':scope').length, 0, 'should return 0');
+
   assert_equals(shadowRoot.querySelector(':scope'), null, 'should return null');
   assert_equals(shadowRoot.querySelectorAll(':scope').length, 0, 'should return 0');
-}, 'querySelector() with ":scope" should return null, whether the context object is an element or a shadow root')
 
+  assert_equals(documentFragment.querySelector(':scope'), null, 'should return null');
+  assert_equals(documentFragment.querySelectorAll(':scope').length, 0, 'should return 0');
+
+}, 'querySelector() with ":scope" should return null, whether the context object is an element, a shadow root or a document fragment')
 </script>