-
Notifications
You must be signed in to change notification settings - Fork 673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-scoping] [selectors] :scope and DocumentFragment / ShadowRoot #7261
Comments
In my opinion, the Usually, the |
Then doing so in
|
Reading the Selectors4 spec, it looks to me that :scope always matches a true element, even if the scoping root can be a Document or a DocumentFragment/ShadowRoot? Am I reading it correctly? https://drafts.csswg.org/selectors-4/#the-scope-pseudo says afaict that :scope must match an element? If so, point 2. Document.querySelectorAll(":scope > *") should return body/head because the scoping root is not an Element, hence falling back to the document root element? |
Hmm, I guess you're right. In which case Gecko and WebKit are just right? |
That's what it looks like to me. |
@emilio can you give an update on what we should resolve on for this? |
It seems we all agree on the spec meaning, so I guess what's left here is landing some tests. |
There are tests with the wrong assumptions: https://wpt.fyi/results/css/selectors/scope-selector.html?label=experimental&label=master&aligned |
Those come from web-platform-tests/wpt#12252. @lilles I saw some movement in the Chromium bug, are you fixing these or do you want me to send a PR? |
I have not changed them yet, so feel free to send a PR. |
I won't have time to change them today, at least. |
As per discussion in w3c/csswg-drafts#7261
As per discussion in w3c/csswg-drafts#7261
Automatic update from web-platform-tests Clean-up and fix :scope test. As per discussion in w3c/csswg-drafts#7261 -- wpt-commits: 3bd0214afc4f254b13c65117074806bfeee0189f wpt-pr: 34032
Automatic update from web-platform-tests Clean-up and fix :scope test. As per discussion in w3c/csswg-drafts#7261 -- wpt-commits: 3bd0214afc4f254b13c65117074806bfeee0189f wpt-pr: 34032
@tabatkins seemingly made a ninja edit of the spec which is in conflict with the conclusion here. Reopening since, we probably need to change the spec or implementations. |
Not a ninja edit! I was applying the resolutions from #6399, as the commit message says! Further, I don't think my edits had any impact on this thread. Can you elaborate on what you think I changed that's relevant here? |
Was just wrong. :scope can match a virtual scoping root, like a DocumentFragment; my #6399 edits reworded the relevant text but maintained this fact. A virtual scoping root can't be the subject of a selector, but that just means that The relevant question for So following the specs as they are written today, (If we wanted |
OK, I may have been too quick to declare a ninja edit. [But hey, I got your attention :-)]. I did see the #6399 reference, but I couldn't immediately understand why some fix related to
OK, but to be fair, Emilio and me (I remember looking at the spec at the time as well) also read the old spec as ":scope matches ELEMENTS ONLY". But whatever, let's move on:
Yeah, that behavior makes sense. It's not what browsers implement though. But this is good, it resolves another question I had about Closing the issue again, hopefully we can change implementations rather than changing the spec. |
I wrote it in an edit, but note that I think the current browser behavior (where But for document fragments (like shadow roots) |
In my opinion, |
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4272396 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1108363}
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4272396 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1108363}
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4272396 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1108363}
Automatic update from web-platform-tests [@scope] Support @scope (:host) In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4272396 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1108363} -- wpt-commits: 37ffe7edc5b6400a16ba6511ba2fd392ab8be318 wpt-pr: 38610
In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4272396 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1108363}
Automatic update from web-platform-tests [@scope] Support @scope (:host) In CalculateActivations, we'd previously just call Element.parentElement up the ancestor chain, therefore never reach the host. Additionally, we did not propagate the original SelectorCheckerContext.scope which is needed for :host to match. This CL uses ParentOrShadowHostElement, and adds the concept of "activation ceiling" to deal with the fact that we need to look at one element *above* the current activation root when that root is a ShadowRoot. Note that :scope is supposed to be able to match "virtual" roots [1] (like a ShadowRoot), but Blink does not support this in general. This CL does not address this issue. [1] w3c/csswg-drafts#7261 Bug: 1280240 Change-Id: I2d0be103f4cd02ec576711b959e075a5118e694a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4272396 Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1108363} -- wpt-commits: 37ffe7edc5b6400a16ba6511ba2fd392ab8be318 wpt-pr: 38610
Actually, no, that does not make sense for shadow roots, because the shadow root itself does not exist for the purposes of selector matching (when matching in the context of that shadow tree): Scoping:
Also, to reinforce that:
This is aligned with the current behavior of all browsers as well. To visualize: If this matches: :host > div { ... } then this can't also match: :scope > div { ... } At least not as long as |
`el.shadowRoot.querySelector` uses a `ShadowRoot` as the root of the query, not an `Element` so we should support that. The behavior of `:scope` seems to be a little weird, but Chrome also returns `null` when used in a shadow root. This [csswg issue](w3c/csswg-drafts#7261) has some ambiguity, but it seems that because browsers don't see shadow roots as elements, `querySelector` can't return the `ShadowRoot`. I think the best behavior we can do is just type `null`.
This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107
This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6011808 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382339}
This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6011808 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382339}
This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6011808 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382339}
…atchForRelation, a=testonly Automatic update from web-platform-tests Remove special :scope matching code in MatchForRelation This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6011808 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382339} -- wpt-commits: 7b7e2451a431d0cc68e4e5a96d19a71675dd782d wpt-pr: 49150
…atchForRelation, a=testonly Automatic update from web-platform-tests Remove special :scope matching code in MatchForRelation This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6011808 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382339} -- wpt-commits: 7b7e2451a431d0cc68e4e5a96d19a71675dd782d wpt-pr: 49150
…atchForRelation, a=testonly Automatic update from web-platform-tests Remove special :scope matching code in MatchForRelation This special path causes :scope selectors to incorrectly match ':scope *' selectors in shadow roots, when it actually should match nothing [1]. The provided test scope-pseudo-in-shadow.html is passing in Firefox and Safari. The existing WPT scope-selector.html (all browsers currently passing) cover querySelector[All] cases well for shadow roots, document, and other DocumentFragments. There should be no behavior change there. Fixed: 378698644 [1] w3c/csswg-drafts#11188 [2] w3c/csswg-drafts#7261 Change-Id: I1efbf999864a766ad5dfaee1fd67527309e38107 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6011808 Reviewed-by: Rune Lillesveen <futhark@chromium.org> Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org> Cr-Commit-Position: refs/heads/main@{#1382339} -- wpt-commits: 7b7e2451a431d0cc68e4e5a96d19a71675dd782d wpt-pr: 49150
Relevant spec sections are:
If I read the specs correctly:
Element.querySelectorAll(":scope > *")
returns all the direct descendants of the given element. This is interoperable behavior and not ambiguous.Document.querySelectorAll(":scope > *")
ought to work and return only the root element (the scoping root would be theDocument
node, and it has only one child, which is the document element). Browsers are interoperable here but not following this reasoning. Instead,:scope
is the root element (so such a query returns the<head>
and<body>
elements, usually).DocumentFragment.querySelectorAll(":scope > *")
ought to work and return the children of the fragment, because the scoping root is the fragment, and is a virtual scoping root. This works in Blink, but not in Gecko and WebKit (:scope
is undefined, so it falls back to the root element of the document, so it never matches anything).:scope
is always the root element of the document, because there's no defined scoping node, and that's the fallback. That's Gecko and WebKit's behavior. Blink in shadow trees considers the shadow root a:scope
(https://crbug.com/1272434), but:scope
doesn't match the shadow host directly like:host
does.This is all very unfortunate and inconsistent. It's clear that the spec is wrong for the
Document.querySelector
case, IMO (though the spec doesn't defineDocument
as a potential "virtual" scoping root, it follows that if such should work forDocumentFragment
it ought to work forDocument
as well?).We should probably agree on the non-interoperable cases. If we wanted to make
:scope
behave consistently forDocument
andDocumentFragment
, we ought to probably either::scope
(rather than what the spec currently says / what Blink does), or.For the stylesheets case, I think WebKit and Gecko follow the spec and the spec is somewhat reasonable. We have
:host
for shadow trees, and even tho defining:scope
is possible, it might be a bit tricky, depending on how we define the above.Thoughts?
cc @tabatkins @lilles @anttijk
The text was updated successfully, but these errors were encountered: