[css-conditional] assigning to conditionText and calling CSS.supports()

[All double-quoted strings in this email are to be interpreted as JS 
strings.]

I think the spec needs to be clearer about when the assignment of a 
string to CSSSupportsRule.conditionText should be successful and when 
the assignment should be ignored.  Currently the spec says:

   If the given value matches the grammar of the appropriate condition
   production for the given rule, replace the associated CSS condition
   with the given value.

Is this matching done strictly according to the grammar, or should the 
normal CSS parsing rules be applied?  For example with:

   supportsRule.conditionText = "(color: green";

the string does not strictly match the grammar, but if we think of it as 
passing the string to the CSS parser, we could invoke the special EOF 
handling behaviour that would imply the closing ")".

My interpretation of CSS.supports() is that it does invoke this 
behaviour, since it talks about the string being "parsed and evaluated 
as a supports_condition".

It might be strange if the conditionText attribute and CSS.supports() 
parsed condition expressions differently.


Assuming that CSS parser EOF behaviour is meant to be invoked for 
conditionText, then we have to be careful that if we serialize the rule 
as a whole with CSSSupportsRule.cssText that you can then reparse the 
string and get the same condition.  If you do:

   supportsRule.conditionText = "(color: green) /*";

then you don't want supportsRule.cssText to be:

   "@supports (color: green) /* {\n}"

so you might need to require that the conditionText be augmented with 
whatever characters are required to have it parse the same -- in this 
case, by appending "*/".

You'd need to do similar things for unclosed strings, unclosed url 
tokens, and for a trailing backslash that is not inside a string or url 
token.

More difficult is what to do with a bad-string or bad-url token that is 
bad because of a trailing backslash.  For example:

   supportsRule.conditionText = "(color: green) or (before: '\\";

IIUC this should be the following sequence of tokens:

   (
   ident "color"
   colon
   whitespace
   ident "green"
   )
   whitespace
   ident "or"
   whitespace
   (
   ident "before"
   colon
   whitespace
   bad-string

I don't think there's actually a way to preserve that exact sequence of 
tokens in the cssText of the rule.  The only way to create a bad-string 
without creating another token after it is to use EOF.


What we could do is distinguish between the "parse error" cases and the 
"valid because it's at the EOF" cases.  An unclosed comment is a parse 
error according to css-syntax, so doing

   supportsRule.conditionText = "(color: green) /*";

would be ignored.  But an unclosed string would be OK.  (Maybe that is 
already the intent of the spec text.)


So overall I think there are two sane options:

1. Have CSS.supports() and CSSSupportsRule.conditionText require strict 
matching against the grammar, and thus reject for example "(color: green".

2. Have CSS.supports() and CSSSupportsRule.conditionText allow the usual 
EOF handling, including closing strings, balancing brackets, etc.  Any 
parse error causes the condition expression to fail to parse, making 
CSS.supports() return false and the assignment to conditionText be 
ignored.  The spec would require the conditionText assignment to be 
augmented with any characters implied by the EOF that would result in it 
parsing the same when in the context of the rule's cssText.  I think 
this involves first looking at the tokenizer's state to determine how to 
properly finish the token:

   double-quote-string
     add "\""
   single-quote-string
     add "'"
   URL-double-quote
     add "\")"
   URL-single-quote
     add "')"
   URL-end
     add ")"
   URL-unquoted
     add ")"

and then to add as many ")"s as needed to balance supports_condition.


Also, and I'm not sure if this a problem, the first step of the 
conditionText assignment says to strip white space from the string, and 
that this can cause a change of meaning with:

   supportsRule.conditionText = "(counter-increment: a\\ ";

if we assume that we go with option 2 above.  If we strip the white 
space, this is a parse error, as we'll encounter "\\" in the ident 
state, switch to the data state since it's followed by EOF, then flag it 
as a parse error.  If we don't strip the white space, we'll have a valid 
ident whose value is "a\\".

Received on Wednesday, 3 April 2013 06:12:20 UTC