Skip to content

[css-nesting-1] Clearer definition of “nest-containing” #7972

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

Open
sesse opened this issue Oct 28, 2022 · 20 comments
Open

[css-nesting-1] Clearer definition of “nest-containing” #7972

sesse opened this issue Oct 28, 2022 · 20 comments

Comments

@sesse
Copy link
Contributor

sesse commented Oct 28, 2022

The spec currently reads: “If a selector in the does not start with a combinator but does contain the nesting selector, it is interpreted as a non-relative selector.”

But it doesn't really say what “contain” means. An example we discussed earlier was:

.foo { :is(.bar, !#&/) { … }}

Does this “contain” the nesting selector? It has a & in there, but it's thrown away due to parse error (and then forgiving parsing should kick in and retain only .bar.). (This is a contrived example, of course, but you could imagine something like :is(.bar, & >> .foo) for a hypothetical >> combinator. A newer browser would interpret it as selector-containing, an older that did not understand >> would not.)

I assume this doesn't contain the nesting selector:

.foo { :is(/*fluid&flexible*/.bar) { … }}

but it's difficult to distinguish from the previous case.

Finally, there's also

.foo { :is(& .bar, .bar) { …}}

where one side of the :is() contains a nesting selector, which I'd interpret as the entire selector doing so, but it's not 100% obvious.

The simplest thing for us would certainly be to let “contain” mean a properly parsed & somewhere, so the answers here would be no, no, yes, respectively. But if you changed the third case to “no” (requring all arms of the :is() to have & for the :is to be selector-containing), you would probably avoid differences in cases like the first one between old and new browsers.

@lilles lilles added the css-nesting-1 Current Work label Oct 28, 2022
@bradkemper
Copy link
Contributor

I think each complex selector in a selector list should be considered separately. So it one is garbage and is thrown out of a forgiving function, then it doesn't affect the other.

@sesse
Copy link
Contributor Author

sesse commented Oct 29, 2022

So is :is(.bar, &) to be interpreted as a relative selector or not?

@bradkemper
Copy link
Contributor

This is just my opinion, but I would say both. For the purposes of determining whether there is an implicit & (but still basing specificity on the most specific part), it would be as though that was divided into two rules, like this:

:is(.bar) {...}
:is(&) {...}

So then, this:

& :is(.bar) {...}
:is(&) {...}

@bradkemper
Copy link
Contributor

bradkemper commented Oct 29, 2022

So then, to bring back to a single selector list


:is(& .bar, &) {...}

Not sure if that works consistently or not; I probably haven't considered it enough.

@sesse
Copy link
Contributor Author

sesse commented Oct 29, 2022

So again, what about this? :is(.bar, &:thispseudodoesnotexist)

@bradkemper
Copy link
Contributor


:is(& .bar, &:thispseudodoesnotexist)

And since :is() is forgiving, then becomes this:


:is(& .bar)

which is equivalent to:


& .bar

@sesse
Copy link
Contributor Author

sesse commented Oct 29, 2022

I don't think this is going to work; just adding & everywhere is going to be increasingly strange and not very useful. (Also, the standard right now is defined in terms of relative selectors, which don't work like this at all.) For instance, :is(.a) > .is(.b) should then become :is(& .a) > :is(& .b)? Which means that :is(.a) > .is(.b) becomes something entirely different from .a > .b (which according to the standard should become & .a > .b)? Or that :is(:is(.a)) should become :is(& :is(& .a))?

@tabatkins
Copy link
Member

Proposal Part 1: Selector Lists

Split on top-level commas, and decide whether each selector is relative or not independently. (.foo { .bar, .baz & {...}} desugars to .foo .bar, .baz .foo {...}). (Doing anything else seems like it would give strange results, and result in worse editting hazards for authors.)

Proposal Part 2: Enclosed &

  • Option 1: Relativeness is decided based on only top-level &. An & inside any other construct (such as :is() or :nth-child()) is ignored for this purpose.
  • Option 2: Relativeness is decided based on & both at the top level and within functional syntaxes (such as :has() or :is()).
  • Option 3: Relativeness is decided based on & both at the top level and within only non-forgiving functional syntaxes (visible in :has() or :nth-child() but ignored in :is() or :where()).

Option 2 seems to be the most preferable to me, but it's unclear how :is(:unknown(&), .bar) should (or even can be) handled - once we're no longer looking at a valid selector, all bets are off on what that & might mean. It might be reasonable to assume we won't use & in a selector context in a way that doesn't represent the nesting selector, but :is() drops its invalid arguments when serialized, so reserializing could change the relative/non-relativeness of the selector which is bad.

Between Option 1 and Option 3, Option 1 has the advantage of being simpler to understand and explain. Both of these can potentially lead to selectors that simply cannot be written in a nested fashion (for example, .foo { :not(&) {...}}), but the solution is to just... not nest those. And the simpler and easier we make such situations to notice and understand, the better.

So, I propose we go with Option 1, and only recognize & at the top-level of a selector to determine whether the nested selector is relative or not.

@sesse
Copy link
Contributor Author

sesse commented Jan 11, 2023

Option 2 seems fine to me; I don't honestly think people will be writing :is(:unknown(&), .bar) too much in the first place (surely, :is(:unknown(&), & .bar) would be a more common case?). We have to give up something, and between handling forward-compatibility and distinguishing between & inside and and outside of parens, the latter seems more broadly useful to me. (“Just don't nest” is limiting the standard unneccessarily, I'd feel? As long as we've said nesting is something fundamentally different from @scope and more like a grouping handling similar to a macro, we should probably accept these cases as equally valid.)

@tabatkins
Copy link
Member

tabatkins commented Jan 13, 2023

Yeah, after discussing with @nex3 (the situation doesn't apply to Sass, since it doesn't have forgiving parsing anywhere), I do lean towards Option 2 as well. To handle the rare weird case where it will matter, I'll probably have to specify some sort of "guaranteed never-matching selector" that can be paired with &, and specify that an :is() has to insert that if it would drop an invalid selector that contains an & token and none of the remaining valid selectors have it, but that's a corner case we don't need to worry about imminently.

(That is, :is(:unknown(&), .bar) would serialize to :is(&:matches-nothing, .bar) instead, but :is(:unknown(&), & .bar) would just serialize to :is(& .bar) as normal.)

Natalie also expressed that she thought it was pretty important to be able to wrap an & in functions (:not(), specifically) and that :is() would also still be a reasonable use-case.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Clearer definition of "nest-containing", and agreed to the following:

  • RESOLVED: Relative-ness is decided based on & appearing *anywhere* in the selector, even nested inside anything else
  • RESOLVED: Option 2
The full IRC log of that discussion <fantasai> Subtopic: Clearer definition of "nest-containing"
<fantasai> github: https://github.com//issues/7972
<dbaron> Zoom for web is not working for me... I've tried multiple browsers at this point.
<dbaron> (doesn't work in either Chrome or Firefox)
<fantasai> TabAtkins: If a selector starts with a combinator, we assume relative selector
<fantasai> TabAtkins: insert & and interpret accordingly
<fantasai> TabAtkins: If no such combinator, we need to check if this should be relative selector or if there's an & deeper in
<fantasai> TabAtkins: Could have something like "foo &" or ":not(&) ..>"
<fantasai> TabAtkins: But spec is not super clear what it means by "contain" an &
<TabAtkins> :is(&:unknown, .foo)
<fantasai> TabAtkins: e.g. what happens if & is inside :is() within branch that's ignored by invalidity?
<fantasai> TabAtkins: is that &-containing or not?
<fantasai> TabAtkins: Depending on our answer, how does it affect serialization
<fantasai> TabAtkins: Listed a few options
<fantasai> TabAtkins: 1. Only look at top-level, not inside parens
<fantasai> TabAtkins: 2. Look everywhere except inside forgiving parsing list
<fantasai> TabAtkins: 3. Get deeper into parsing guts, say something about & inside even forgiving selector lists that might be invalid, and preserve that info across serialization even though normally drop such branches during reserialization
<fantasai> TabAtkins: fantasai and I thought #3 would be weird, because [missed]
<fantasai> TabAtkins: so initial suggestion was #1, simple suggestion
<fantasai> TabAtkins: after discussion with Natalie and Miriam, there were too many use cases for & deeper than top-level
<fantasai> TabAtkins: and having selector only in one branch and not others is weird and unusual, so not that important if behavior differs in branches
<dbaron> OK, given that the meeting link doesn't work for me in (a) Chrome/Mac (b) Firefox/Mac, and (c) Firefox/Linux, I'm going to give up for technical difficulties... see you at the regular call in 50 minutes.
<fantasai> TabAtkins: so suggestion is to look for & in every branch, invalid or not
<fantasai> TabAtkins: needs authors to be a little more careful
<fantasai> TabAtkins: but simple: if there's an & anywhere, it's got one
<fremy> q+
<fantasai> TabAtkins: Might need to tighten up parsing by having known-invalid selectors serialize as something particular
<fantasai> TabAtkins: So definition proposed is that it's containing an & if it contains an & anywhere
<fantasai> fremy: Tab mentioned that it's weird to have branches where some contain & but some do not
<fantasai> fremy: I agree, if you're doing that it's probably a mistake
<fantasai> fremy: But then why can't we make this a rule?
<fantasai> fremy: if you have a branching selector, have to have & in every branch
<dbaron> (ok, zoom started working when I clicked on the grayed-out "More ..." button at the bottom)
<fantasai> fremy: otherwise invalid
<fantasai> TabAtkins: Valid question, we could, but probably doesn't matter because unusual case
<fantasai> TabAtkins: so I don't think it's necessary
<fantasai> TabAtkins: but I could do either way
<Rossen_> ack fremy
<fantasai> fantasai asks for an example
<fantasai> TabAtkins: Consider the previous example, where only one branch of :is() has an &. Difference is we'd make that illegal
<TabAtkins> so `:is(&:unknown, .foo)` would be an invalid selector
<fantasai> TabAtkins: Also weird, it would be the only way for :is() to invalidate a selector
<lea> in case it helps, as an author, I'd expect .foo { :is(&, .bar) {} } to be interpreted as .foo, .foo .bar , not .foo, .bar
<fantasai> TabAtkins: another little bit of complexity that we could avoid for a corner case
<fantasai> fremy: Yes, I think I agree. It might not make much sense, but you might want it
<fantasai> TabAtkins: Lea posts a different suggestion, which is that you take different paths in deciding relative selector or not
<fantasai> TabAtkins: Problem is that doesn't map directly to :is() notation, so suspect it would complexify implementations
<chris> leaverou there was a question for you
<fantasai> fantasai: Do we have any comments from implementers on lea's question?
<lea> chris: what was it? I'm looking at the minutes but can't find it. I'm not on the call, as I'm on the TAG plenary
<fantasai> TabAtkins: I can't say for sure, but I think our implementation would find it difficult
<fantasai> s/sure/sure because our implementers aren't on the call/
<fantasai> emilio: Doing what Lea suggests would be fairly annoying
<fremy> @ lea, the question was whether TabAtkins's reply to you addressed your concern or not
<fantasai> emilio: and could have problems with selectors growing exponentially, which is not great
<fantasai> emilio: I think this is a problem Blink had when they initially implemented this
<fantasai> TabAtkins: When trying to do naive impleementation of :is(), it was a problem
<fremy> @ lea, and (I guess) whether this was something you felt strongly about
<lea> fremy: no, this is not something I feel strongly about
<fantasai> Rossen_: Current proposal is simply option 3 without any further modification (and by option 3 we mean option 3 in IRC, which is option 2 in the issue)
<TabAtkins> proposed resolution: Relative-ness is decided based on & appearing *anywhere* in the selector, including in (potentially-invalid) branches of a forgiving-selector-list
<fantasai> plinss: I presume it's only legal for one & in selector?
<fantasai> TabAtkins: no can have multiple
<fantasai> plinss: so I can say &.foo &.bar?
<lea> though I do find it fairly weird if you can "break" out of the nest by doing `:is(&, .bar)`. and if :is(.bar) matches different things than the .bar in :is(&, .bar)
<fantasai> TabAtkins: & represents elements matched by the parent selector
<fantasai> TabAtkins: would be two different elements that both happen to match the same parent
<fantasai> plinss: fair enough
<Rossen_> ack fantasai
<TabAtkins> fantasai: suggest we clarify that if I have any kind of selector garbage inside :is(), including an & nested deep inside of the garbage, that & is considered to be an & for these purposes?
<TabAtkins> TabAtkins: correct
<fantasai> :is(:unknown(&))
<fantasai> :is([something (&something else { } ) ])
<TabAtkins> :is([{(&)}]) has an ampersand in it, per the suggested resolution
<fantasai> TabAtkins: If during selector parsing you see an & delim token, mark the selector as having an & and continue normal parsing
<fantasai> Rossen_: any other feedback?
<fantasai> RESOLVED: Relative-ness is decided based on & appearing *anywhere* in the selector, even nested inside anything else
<fantasai> TabAtkins: Question is what to do about serialization
<fantasai> TabAtkins: Option 1: do nothing special. This might mean that an invalid branch is dropped, which changes selector interpretation
<fantasai> TabAtkins: Option 2: serialize any :is() branch that contains an & as-is
<fantasai> TabAtkins: Option 3: serialize any :is() branch that contains & as something guaranteed to be invalid, e.g. "&:not(&)" (which is guaranteed to not match but definitely contains an &)
<emeyer> q+
<fantasai> emilio: Only doing ????
<fantasai> TabAtkins: Option 4: do 2 or 3 if that's the only branch that contains an & (and thus the selector interpretation is dependent on that branch existing)
<Rossen_> ack emeyer
<fantasai> emeyer: wrt option 1, what are the concerns?
<fantasai> emilio: It's bad if something serializes and then whe you re-parse it it's interpreted differenly than the original
<fantasai> TabAtkins: So you can have a selector that's relative in new browsers and non-relative in older browesers, which is significant change
<fantasai> emilio: You lose the forgiveness ... which is annoying
<fantasai> [missed]
<dbaron> My preferences: definitely not option 1, weakly prefer option 3 (without the option 4 variant).
<fantasai> emilio: Implementationwise, it feels like it would be nice not to account for & in invalid branches, so you can compute the relativeness of a selector independently of the parsing process
<fantasai> <fantasai> +1 dbaron
<fantasai> emilio: ... but all the options are weird in their own way
<Rossen_> q?
<fremy> @ TabAtkins, for option 3 `&:not(&)` might be costly to compute, how about something truly invalid like `::-invalid-(&)`
<fantasai> [Tabatkins summarizes dbaron's comment into audio]
<fantasai> plinss: [asks about option 2]
<fantasai> emeyer: option 2 is consistent with media queries, where we preserve the CSS string for general enclosed
<fantasai> TabAtkins: fair
<emilio> s/emeyer/emilio
<fantasai> [Leaning towards 2 or 3]
<dbaron> I'm also fine with 2.
<fantasai> Straw Poll: Option 2 vs Option 3
<TabAtkins> abstain
<fantasai> abstain (defer to implementers)
<emilio> either wfm
<plinss> 2
<lea> 2 (based on the descriptions in the comment primarily, as I've missed a lot of the discussion due to being on another call)
<Rossen_> 3, 2
<fremy> abstain
<emeyer> abstain
<chris> abstain
<davidleininger> 2
<dbaron> abstain
<florian> abstain
<jensimmons> abstain
<fantasai> emilio: other issue of option 2 is that it changes behavior from today
<fantasai> TabAtkins: in theory, yes, if someone is putting & inside their invalid :is() selector, it will change serialization
<fantasai> emilio: We probalby want to do it for all invalid selectors, so that :unknown is reserialized as-is, regardless of &
<fantasai> TabAtkins: I suggest taking up separately
<fantasai> Proposed to go with option 2
<fantasai> and emilio to open issue about switching serialization for all selectors
<fantasai> plinss: In my mind, would want to be consistent for all selectors
<fantasai> TabAtkins: I agree in theory, don't care too much
<fantasai> RESOLVED: Option 2
<fantasai> TabAtkins: open separate issue for the rest, because it may have a compat risk
<fantasai> plinss: If the other one goes the other way, might want to revert this one
<fantasai> TabAtkins: currently don't have compat either way for & stuff
<fantasai> plinss: Yes, but I want us to note in the other issue to reconsider this one
<emilio> I can open the issue
<fantasai> ACTION: emilio to open new issue

@romainmenke
Copy link
Member

romainmenke commented Jan 25, 2023

:is(:unknown(&), .bar)

.foo {
  :is(:unknown(&), .bar) {}
  :is(& .any, .bar) {}
}

I might be overlooking this in the thread but what happens to the .bar branches?
The selector as a whole is not relative because it contains &.

I assume it is a valid but never matches anything?
I would be surprised if it matches any .bar in the document, regardless of elements having a .foo ancestor.

@tabatkins
Copy link
Member

It does indeed match any .bar element (that is, it's equivalent to .foo .any, .bar {...}). I agree it feels a little odd (since it's the only way to write such a selector in a nested context), but the behavior isn't totally off-base. After all, .foo { :not(&) {...}} selects all the elements on the page that aren't .foo, also with absolutely no regard to whether they're in a .foo ancestor or not. Nesting isn't @scope ^_^

@romainmenke
Copy link
Member

Actually happy it works this way :)
It is a bit odd indeed, but easy to understand if you don't overthink it.

@sesse
Copy link
Contributor Author

sesse commented Jan 27, 2023

We're adjusting the Blink implementation now, but be aware that this breaks round-tripping. :is(!&, .c) is nest-containing, but if you serialize it, it becomes :is(.c), which isn't.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Jan 27, 2023
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
@cdoublev
Copy link
Collaborator

& appearing *anywhere* in the selector

Sorry, but I am confused.

According to #8310 (comment), & must replace a <simple-selector>.

According to #7503 (comment), & can replace a sub-production of <simple-selector>.

According to the above comment, it can match anything? !& is not a valid <relative-selector>.

The selector of the nested style rule is nest-containing if it contains & even as part of an invalid <relative-selector>? And in a comment? Or escaped (thus matching <ident>, thus matching <type-selector>)?

@Loirooriol
Copy link
Contributor

From the minutes

TabAtkins: If during selector parsing you see an & delim token, mark the selector as having an & and continue normal parsing

So /* & */ or \& will not mark the selector as having an &.
!& is not a valid simple selector and thus won't be able to refer to the parent selector, but it will mark the selector as having a &.

@tabatkins
Copy link
Member

@sesse Note the second resolution in the minutes - if a forgiving-selector-list entry contains an &, we don't drop it when serializing. I'll be updating the spec with this text in a little bit.

Sorry, but I am confused.

Yup, Oriol got it. We look for delim tokens, and this doesn't change the existing definition of the nesting selector; it's something unrelated happening at an earlier stage of parsing.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Jan 30, 2023
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4200218
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1098520}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Jan 30, 2023
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4200218
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1098520}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Jan 30, 2023
See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
aarongable pushed a commit to chromium/chromium that referenced this issue Jan 31, 2023
See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4203527
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099231}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Jan 31, 2023
See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4203527
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099231}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Jan 31, 2023
See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4203527
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099231}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Feb 2, 2023
…ing forgiving parsing still count towards nest-containment., a=testonly

Automatic update from web-platform-tests
[css-nesting] Make selectors dropped during forgiving parsing still
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4200218
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1098520}

--

wpt-commits: 429a174f9169a9d5c4a9c0f1d7f8d3f560d01499
wpt-pr: 38217
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Feb 2, 2023
…id selectors within :is()., a=testonly

Automatic update from web-platform-tests
[css-nesting] Keep nest-containing invalid selectors within :is().

See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4203527
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099231}

--

wpt-commits: bbb24b5a2d4b3a1f959b12e6b1377758feb0a50e
wpt-pr: 38255
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Feb 3, 2023
…ing forgiving parsing still count towards nest-containment., a=testonly

Automatic update from web-platform-tests
[css-nesting] Make selectors dropped during forgiving parsing still
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4200218
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1098520}

--

wpt-commits: 429a174f9169a9d5c4a9c0f1d7f8d3f560d01499
wpt-pr: 38217
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Feb 3, 2023
…id selectors within :is()., a=testonly

Automatic update from web-platform-tests
[css-nesting] Keep nest-containing invalid selectors within :is().

See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4203527
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099231}

--

wpt-commits: bbb24b5a2d4b3a1f959b12e6b1377758feb0a50e
wpt-pr: 38255
tabatkins added a commit that referenced this issue Feb 15, 2023
…, and the CSSWG resolution to preserve forgiving selectors that are invalid but contain the nesting selector. #7972
@tabatkins
Copy link
Member

All right, edited in with the resolutions from above:

  • a selector "contains the nesting selector" if, during parsing, it encoutners a delim-token with the value "&" anywhere
  • a monkey-patch of the forgiving-selector-list behavior, where it must preserve list items that contain the nesting selector

marcoscaceres pushed a commit to web-platform-tests/wpt that referenced this issue Mar 28, 2023
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4200218
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1098520}
marcoscaceres pushed a commit to web-platform-tests/wpt that referenced this issue Mar 28, 2023
See w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: Ifebb6e8d2f4a2c0f627abaea4a432173a0993f01
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4203527
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099231}
@sircumferencee
Copy link
Contributor

@tabatkins Is there anything left for this issue?

i3roly pushed a commit to i3roly/firefox-dynasty that referenced this issue Jun 1, 2024
…ing forgiving parsing still count towards nest-containment., a=testonly

Automatic update from web-platform-tests
[css-nesting] Make selectors dropped during forgiving parsing still
count towards nest-containment.

Also add a test. We keep track of this using a simple boolean,
and since we make CSSParser from scratch every time we start parsing
a new top-level selector, we don't need to worry about resetting it.

In line with CSSWG resolution at
w3c/csswg-drafts#7972.

Bug: 1095675
Change-Id: I869e6859e32284167ef4e1e8c60b64e770b9e945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4200218
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1098520}

--

wpt-commits: 429a174f9169a9d5c4a9c0f1d7f8d3f560d01499
wpt-pr: 38217
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests