Skip to content

Commit f6337dd

Browse files
committed
[selectors-4] Untangle 'scoped' from 'relative'. #6399
1 parent 617c50c commit f6337dd

File tree

1 file changed

+74
-134
lines changed

1 file changed

+74
-134
lines changed

selectors-4/Overview.bs

+74-134
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ Selectors Overview</h2>
151151
<tr>
152152
<td><code>E:has(<var>rs1</var>, <var>rs2</var>, &hellip;)</code>
153153
<td>an E element,
154-
if either of the <a>relative selectors</a> <var>rs1</var> or <var>rs2</var>,
155-
when evaluated with E as the <a>:scope elements</a>,
156-
match an element
154+
if there exists an element that matches
155+
either of the <a>relative selectors</a> <var>rs1</var> or <var>rs2</var>,
156+
when evaluated with E as the <a>anchor elements</a>
157157
<td>[[#relational]]
158158
<td>4
159159
<tbody>
@@ -272,7 +272,7 @@ Selectors Overview</h2>
272272
<td>4
273273
<tr>
274274
<td><code>E:scope</code>
275-
<td>an E element being a designated reference element
275+
<td>an E element being a [=scoping root=]
276276
<td>[[#the-scope-pseudo]]
277277
<td>4
278278
<tbody>
@@ -502,7 +502,7 @@ Structure and Terminology</h3>
502502
a particular pattern of element(s) in a tree structure.
503503
The term <a>selector</a> can refer to a <a>simple selector</a>,
504504
<a>compound selector</a>, <a>complex selector</a>, or <a>selector list</a>.
505-
The <dfn export for=selector lt="subject|subject of a selector">subject of a selector</dfn> is
505+
The <dfn export for=selector lt="subject|subject of a selector|subject of the selector">subject of a selector</dfn> is
506506
any element that selector is defined to be about;
507507
that is, any element <dfn export lt="match">matching</dfn> that <a>selector</a>.
508508

@@ -636,10 +636,8 @@ Data Model</h3>
636636
Scoped Selectors</h3>
637637

638638
Some host applications may choose to <dfn export lt="scoped selector" local-lt="scope">scope</dfn> selectors
639-
to a particular subtree or fragment of the document.
640-
The root of the scoping subtree is called the <dfn export>scoping root</dfn>,
641-
and may be either a true element (the <dfn export>scoping element</dfn>)
642-
or a <dfn export lt="virtual scoping root">virtual</dfn> one (such as a <a interface>DocumentFragment</a>).
639+
to a particular subtree or fragment of the document,
640+
The root of the scoping subtree is called the <dfn export>scoping root</dfn>.
643641

644642
When a selector is <a>scoped</a>,
645643
it matches an element only if the element is a descendant of the <a>scoping root</a>.
@@ -648,83 +646,31 @@ Scoped Selectors</h3>
648646

649647
<div class='example'>
650648
For example,
651-
the <code>element.querySelector()</code> function defined in [[DOM]]
649+
the {{Element/querySelector()}} method defined in [[DOM]]
652650
allows the author to evaluate a <a>scoped</a> selector
653-
relative to the <code>element</code> it's called on.
651+
relative to the element it's called on.
654652

655653
A call like <code highlight=js>widget.querySelector("a")</code>
656654
will thus only find <{a}> elements inside of the <code>widget</code> element,
657655
ignoring any other <{a}>s that might be scattered throughout the document.
658656
</div>
659657

660-
Note: If the context does not explicitly define any <a>:scope elements</a> for the selector,
661-
the <a>scoping root</a> is the <a>:scope element</a>.
662658

663659
<h3 id="relative">
664660
Relative Selectors</h3>
665661

666-
Certain contexts may accept <dfn lt="relative selector | relative | scope-relative" export>relative selectors</dfn>,
667-
which are a shorthand for selectors that represent elements relative to a <a>:scope element</a>
668-
(i.e. an element that matches '':scope'').
669-
In a <a>relative selector</a>,
670-
“:scope ” (the '':scope'' pseudo-class followed by a space)
671-
is implied at the beginning of each <a>complex selector</a>
672-
that does not already contain the '':scope'' pseudo-class.
673-
This allows the selector to begin syntactically with a <a>combinator</a>.
674-
However, it must be <a href="#absolutize">absolutized</a> before matching.
662+
Certain contexts may accept <dfn lt="relative selector" local-lt="relative" export>relative selectors</dfn>,
663+
which are a shorthand for selectors that represent elements relative to one or more
664+
<dfn export local-lt="anchor element">relative selector anchor elements</dfn>.
665+
Relative selectors begin with a <a>combinator</a>,
666+
with a selector representing the [=anchor element=]
667+
implied at the start of the selector.
668+
(If no combinator is present,
669+
the [=descendant combinator=] is implied.)
675670

676-
Relative selectors, once absolutized,
677-
can additionally be <a>scoped</a>.
671+
Relative selectors are represented by <<relative-selector>> in the selectors <a href="#grammar">grammar</a>,
672+
and lists of them by <<relative-selector-list>>.
678673

679-
Relative selectors are represented by <<relative-selector>> in the selectors <a href="#grammar">grammar</a>.
680-
681-
<h4 id='absolutizing'>
682-
Absolutizing a Relative Selector</h4>
683-
684-
To <dfn id='absolutize' export>absolutize a relative selector</dfn>:
685-
686-
If there are no <a>:scope elements</a>
687-
and the selector is <a>scoped</a> to a <a>virtual scoping root</a>:
688-
689-
ISSUE: <a href="https://github.com/w3c/csswg-drafts/issues/2199">This needs a sane definition.</a>
690-
691-
<!--
692-
<ol>
693-
<li>
694-
If the selector starts with a <a>child combinator</a>,
695-
remove the child combinator.
696-
The selector is now absolute,
697-
with the additional constraint that the first compound selector in the selector
698-
only matches elements without a parent.
699-
700-
<li>
701-
Otherwise, if the selector starts with any combinator other than the white space form of the <a>descendant combinator</a>,
702-
change the selector to '':not(*)''.
703-
<span class='note'>This is the shortest selector that is valid, but guaranteed to match nothing.</span>
704-
705-
<li>
706-
Otherwise, the selector is already absolute.
707-
</ol>
708-
-->
709-
710-
Otherwise:
711-
712-
<ol>
713-
<li>
714-
If the selector starts with a <a>combinator</a> other than the white space form of the <a>descendant combinator</a>,
715-
prepend '':scope'' as the initial <a>compound selector</a>.
716-
717-
<li>
718-
Otherwise, if the selector does not contain any instance of the '':scope'' pseudo-class
719-
(either at the top-level or as an argument to a functional pseudo-class),
720-
prepend '':scope'' followed by the white space form of the <a>descendant combinator</a>.
721-
722-
<li>
723-
Otherwise, the selector is already absolute.
724-
</ol>
725-
726-
To <dfn id='absolutize-list' export>absolutize a relative selector list</dfn>,
727-
absolutize each relative selector in the list.
728674

729675

730676
<h3 id="pseudo-classes">
@@ -1244,10 +1190,9 @@ The Relational Pseudo-class: '':has()''</h3>
12441190

12451191
The relational pseudo-class, <dfn id='has-pseudo'>:has()</dfn>,
12461192
is a functional pseudo-class taking a <<forgiving-relative-selector-list>> as an argument.
1247-
It represents an element if any of the <a>relative selectors</a>,
1248-
when <a href="#absolutize">absolutized</a>
1249-
and evaluated with the element as the <a>:scope elements</a>,
1250-
would match at least one element.
1193+
It represents an element if any of the <a>relative selectors</a>
1194+
would match at least one element
1195+
when [=anchor element|anchored against=] this element.
12511196

12521197
<div class='example'>
12531198
For example, the following selector matches only
@@ -1274,8 +1219,6 @@ The Relational Pseudo-class: '':has()''</h3>
12741219
which contains anything that's not a heading element.
12751220
</div>
12761221

1277-
Supporting the '':has()'' pseudo-class is not required to conform to this specification.
1278-
12791222

12801223
<h2 id="elemental-selectors">
12811224
Elemental selectors</h2>
@@ -2159,20 +2102,37 @@ The Target Container Pseudo-class: '':target-within''</h3>
21592102
<h3 id="the-scope-pseudo">
21602103
The Reference Element Pseudo-class: '':scope''</h3>
21612104

2162-
In some contexts, selectors can be matched with an explicit set of <dfn dfn export lt=":scope element">:scope elements</dfn>.
2163-
This is a (potentially empty) set of elements
2164-
that provide a reference point for selectors to match against,
2165-
such as that specified by the <code>querySelector()</code> call in [[DOM]].
2105+
In some contexts, selectors are matched
2106+
with respect to one or more [=scoping roots=],
2107+
such as when calling the {{Element/querySelector()}} method in [[DOM]].
2108+
The <dfn id='scope-pseudo'>:scope</dfn> pseudo-class represents
2109+
this [=scoping root=],
2110+
and may be either a true element
2111+
or a virtual one (such as a {{DocumentFragment}}).
21662112

2167-
The <dfn id='scope-pseudo'>:scope</dfn> pseudo-class represents any element that is a <a>:scope element</a>.
2168-
If the <a>:scope elements</a> are not explicitly specified,
2169-
but the selector is <a>scoped</a> and the <a>scoping root</a> is an element,
2170-
then '':scope'' represents the <a>scoping root</a>;
2171-
otherwise, it represents the root of the document
2113+
If there is no [=scoping root=]
2114+
then '':scope'' represents the root of the document
21722115
(equivalent to '':root'').
21732116
Specifications intending for this pseudo-class to match specific elements
21742117
rather than the document's root element
2175-
must define either a <a>scoping root</a> (if using <a>scoped selectors</a>) or an explicit set of <a>:scope elements</a>.
2118+
must define their [=scoping root|scoping root(s)=].
2119+
2120+
A virtual [=scoping root=] is some object representing the root of a document fragment,
2121+
and can be used in selector patterns to represent other elements’ relationships
2122+
to this [=scoping root=],
2123+
acting as the parent of any root elements in the document fragment it represents.
2124+
A virtual [=scoping root=] is [=featureless=]
2125+
and cannot be the [=subject of the selector=].
2126+
2127+
<div class=example>
2128+
For example, if you have a {{DocumentFragment}} <code>df</code>,
2129+
then <code highlight=js>df.querySelectorAll(":scope > .foo")</code>
2130+
matches all the ''.foo'' elements that are "top-level" in the document fragment
2131+
(those that have the document fragment as their {{Node/parentNode}}).
2132+
2133+
However, <code highlight=js>df.querySelector(":scope")</code> will not match anything,
2134+
as the document fragment itself can't be the [=subject of the selector=].
2135+
</div>
21762136

21772137
<h2 id="useraction-pseudos">
21782138
User Action Pseudo-classes</h2>
@@ -3678,30 +3638,25 @@ Parse A Selector</h3>
36783638
<h3 id='parse-relative-selector' algorithm>
36793639
Parse A Relative Selector</h3>
36803640

3681-
This section defines how to <dfn export>parse a relative selector</dfn> from a string <var>source</var>,
3682-
against <a>:scope elements</a> <var>refs</var>.
3641+
This section defines how to <dfn export>parse a relative selector</dfn> from a string <var>source</var>.
36833642
It returns either a complex selector list,
36843643
or failure.
36853644

36863645
<ol>
36873646
<li>
36883647
Let <var>selector</var> be the result of [=CSS/parsing=] <var>source</var> as a <<relative-selector-list>>.
3689-
If this return failure,
3648+
If this returns failure,
3649+
it's an [=invalid selector=];
36903650
return failure.
36913651

36923652
<li>
3693-
Otherwise,
3694-
if any simple selectors in <var>selector</var> are not recognized by the user agent,
3695-
or <var>selector</var> is otherwise invalid in some way
3653+
If |selector| is an [=invalid selector=] for any other reason
36963654
(such as, for example, containing an undeclared namespace prefix),
36973655
return failure.
36983656

36993657
<li>
37003658
Otherwise,
3701-
<a lt="absolutize a relative selector list">absolutize <var>selector</var></a> with <var>refs</var> as the <a>:scope elements</a>.
3702-
3703-
<li>
3704-
Return <var>selector</var>.
3659+
return <var>selector</var>.
37053660
</ol>
37063661

37073662
<h3 id='match-against-element' algorithm>
@@ -3715,16 +3670,8 @@ Match a Selector Against an Element</h3>
37153670

37163671
<ul>
37173672
<li>
3718-
a set of <a>:scope elements</a>,
3673+
one or more [=scoping roots=],
37193674
for resolving the '':scope'' pseudo-class against.
3720-
If not specified,
3721-
the set defaults to being empty.
3722-
3723-
Issue: Should it instead default to the root element,
3724-
to match the definition of '':scope''?
3725-
3726-
If the selector is a <a>relative selector</a>,
3727-
the set of <a>:scope elements</a> must not be empty.
37283675
</ul>
37293676

37303677
This algorithm returns either success or failure.
@@ -3794,47 +3741,28 @@ Match a Selector Against a Tree</h3>
37943741

37953742
APIs using this algorithm must provide a selector,
37963743
and one or more <var>root elements</var>
3797-
indicating the <a>trees</a> that will be searched by the selector.
3798-
All of the <var>root elements</var> must share the same <a for=tree>root</a>,
3744+
indicating the [=tree|subtrees=] that will be searched by the selector.
3745+
All of the <var>root elements</var> must share the same [=tree/root=],
37993746
or else calling this algorithm is invalid.
38003747

38013748
They may optionally provide:
38023749

38033750
<ul>
38043751
<li>
3805-
A <a>scoping root</a>
3752+
One or more <a>scoping roots</a>
38063753
indicating the selector is <a>scoped</a>.
3807-
If not specified,
3808-
the <var>selector</var> defaults to being unscoped.
3809-
3810-
Issue: This is now redundant with the <var>root elements</var>.
3811-
3812-
<li>
3813-
A set of <a>:scope elements</a>,
3814-
which will match the '':scope'' pseudo-class.
3815-
If not specified,
3816-
then if the selector is a <a>scoped selector</a>,
3817-
the set of <a>:scope elements</a> default to the <a>scoping root</a>;
3818-
otherwise,
3819-
it defaults to the <var>root elements</var>.
3820-
3821-
Note: Note that if the selector is scoped,
3822-
the scoping root is automatically taken as the <a>:scope element</a>,
3823-
so it doesn't have to be provided explicitly
3824-
unless a different result is desired.
38253754

38263755
<li>
3827-
Which <a>pseudo-elements</a> are allowed to show up in the match list.
3756+
A list of <a>pseudo-elements</a> that are allowed to show up in the match list.
38283757
If not specified, this defaults to allowing all pseudo-elements.
38293758

3830-
Issue: Only the ''::before'' and ''::after'' pseudo-elements are really
3759+
Issue: Only the [=tree-abiding pseudo-elements=] are really
38313760
handled in any way remotely like this.
38323761
</ul>
38333762

38343763
This algorithm returns a (possibly empty) list of elements.
38353764

38363765
<ol>
3837-
38383766
<li>
38393767
Start with a list of <var>candidate elements</var>,
38403768
which are the <var>root elements</var>
@@ -3843,10 +3771,10 @@ Match a Selector Against a Tree</h3>
38433771
unless otherwise specified.
38443772

38453773
<li>
3846-
If an optional scoping root was provided,
3774+
If [=scoping root=] were provided,
38473775
then remove from the <var>candidate elements</var>
38483776
any elements that are not
3849-
<a>descendants</a> of the <a>scoping root</a>.
3777+
<a>descendants</a> of at least one <a>scoping root</a>.
38503778

38513779
<li>
38523780
Initialize the <var>selector match list</var> to empty.
@@ -4057,6 +3985,18 @@ Appendix B: Obsolete but Required Parsing Quirks for Web Compat</h2>
40573985

40583986
<h2 id="changes">
40593987
Changes</h2>
3988+
3989+
<h3 id="changes-2022-05">
3990+
Changes since the 7 May 2022 Working Draft</h3>
3991+
3992+
Significant changes since the <a href="https://www.w3.org/TR/2022/WD-selectors-4-20220507/">7 May 2022 Working Draft</a>:
3993+
3994+
* Untangled the concepts of "scoped" and "relative" selectors completely.
3995+
(<a href="https://github.com/w3c/csswg-drafts/issues/6399">Issue 6399</a>)
3996+
* Removed "absolutize a selector" as well,
3997+
and just defined relative selector matching
3998+
in terms of the anchoring element.
3999+
40604000
<h3 id="changes-2018-11">
40614001
Changes since the 21 November 2018 Working Draft</h3>
40624002

0 commit comments

Comments
 (0)