w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.52k stars 673 forks source link

[selectors] Error handling is not exhaustive? #2352

Open annevk opened 6 years ago

annevk commented 6 years ago

I could be missing something, but it's not clear to me how https://drafts.csswg.org/selectors/#invalid applies to :not(1) or not(1px) or some such.

SelenIT commented 6 years ago

Isn't such string inside :not() parsed as a type selector which is invalid because it doesn't match the <ident-token> grammar?

annevk commented 6 years ago

As far as I can tell https://drafts.csswg.org/selectors/#typedef-pseudo-class-selector accepts any value for all functional pseudo-classes. It does seem like a more restrictive grammar is then applied and ends up rejecting the selector, but it's not clear to me how that is defined.

SelenIT commented 6 years ago

The definition of the :not() pseudo-class says that it takes a selector list as an argument. So I suppose that anything inside the brackets is parsed as a selector list (consisting of one invalid simple selector in this case). I guess this is one of the "more specific syntactic constraints" which the first note after the formal grammar description in the section 17 warns about.

tabatkins commented 6 years ago

Yeah, like individual properties, individual pseudo-classes and pseudo-elements define their grammars at the point of definition. The panoply of pseudo-class grammars is not captured in the generic selector grammar, just like the panoply of property grammars aren't captured in the Syntax spec.

annevk commented 6 years ago

Sure, but how does that follow from https://drafts.csswg.org/selectors/#invalid (or the "parse a selector" algorithm)? At some point you actually need to do a lookup of that specific grammar and apply it.

annevk commented 6 years ago

(Notes are non-normative so when you try to determine the requirements you have to pretend they're not there.)

tabatkins commented 6 years ago

It follows from the bullet point:

a selector containing an invalid simple selector, an invalid combinator or an invalid token is invalid.

Each simple selector defines its grammar.


(Notes are non-normative so when you try to determine the requirements you have to pretend they're not there.)

Indeed, that note is just a reminder of requirements elsewhere. It's not relevant to your question.

annevk commented 6 years ago

I see. Nothing in https://drafts.csswg.org/selectors/#negation states what makes that simple selector invalid though (nothing in the section on simple selectors or pseudo-classes does either). It all hangs rather loosely together, without much formal rigor.

fantasai commented 6 years ago

@annevk

The negation pseudo-class, :not(), is a functional pseudo-class taking a selector list as an argument.

A list of simple/compound/complex selectors is a comma-separated list of simple, compound, or complex selectors. This is also called just a selector list when the type is either unimportant or specified in the surrounding prose; if the type is important and unspecified, it defaults to meaning a list of complex selectors.

A complex selector is a sequence of one or more compound selectors separated by combinators.

A compound selector is a sequence of simple selectors that are not separated by a combinator

A simple selector is a single condition on an element. A type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class is a simple selector.

1 and 1px do not match the grammars for type selectors, universal selectors, attribute selectors, class selectors, ID selectors, or pseudo-classes. Therefore they are not valid simple selectors, therefore not valid compound selectors, therefore not valid complex selectors, therefore not a valid selector list, therefore not a valid argument to :not(), therefore it is a parsing error in that selector (being a token which is not allowed at that parsing point) and :not() is invalid and any selector containing it is also invalid.

fantasai commented 6 years ago

Tweaked the parenthetical wording in https://drafts.csswg.org/selectors-4/#invalid to not imply that the Grammar section is the only arbiter of validity.

@annevk Let me know if something remains unclear. Afaict, the spec defines the syntax with sufficient rigor, it just happens to be partly in English rather than completely subsumed into a grammar definition syntax.

annevk commented 6 years ago

Thanks for the help! I'm not a huge fan of this style of specifying things (as it requires the reader to do a lot of digging), but it does seem defined.

What remains unclear is why the note in that #invalid section has a normative requirement.

cdoublev commented 2 years ago

Also:

a selector list containing an invalid selector is invalid.

A forgiving selector list should remain valid when it becomes empty after invalid selectors are removed: this is explicitly defined for :is() (and implicitly for :where()) but not for :has() and :nth-*-child().

It would be clearer to define it once in the error handling list, imo.

EDIT: parsing of :has() and :nth-*-child() argument is now unforgiving but my suggestion remains.