- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Mon, 22 Oct 2012 17:28:09 -0700
- To: Simon Sapin <simon.sapin@kozea.fr>
- Cc: WWW Style <www-style@w3.org>
Okay, I did some basic testing. I was actually surprised - the
results were more varied than I had thought they would be.
All of these tests were done with the following HTML doc (external
stylesheet to avoid any possible complications with HTML
normalization):
<!doctype html>
<link rel=stylesheet href=test.css>
<p>foo!
<ul>
<li>bar
<li>baz
</ul>
<pre></pre>
<script>
var str = '';
window.onload = function() {
[].slice.call(document.styleSheets[0].cssRules).forEach(function(e) {
str += e.cssText+'\n';
});
document.querySelector('pre').textContent = str;
};
</script>
First, I tested putting a null inside of a stylesheet. I wrote up a
basic sheet applying styles to some of the elements in the HTML doc,
then reopened in hex mode and added a null byte. (Thanks, Sublime!)
* Firefox and Opera treats the null appear to just do normal
tokenization of the null as a DELIM token. If it appears in a
selector, they throw away the whole rule (I presume because it doesn't
match the grammar of Selectors). Elsewhere, they do normal
error-recovery.
* IE and WebKit truncate the stylesheet at the point they discover the
null. They literally just drop the rest of the file on the floor.
Next, I tested a hex-escaped null, written as \0. If you put the
escaped null in most places, it does the expected thing, triggering
normal error-recovery because it's not valid anywhere. The browsers
do weird things if you put it in a selector, though:
* WebKit treats it as an escaped null, no problem. Notably, it does
*not* throw away rules which contain it in their selector (though it
obviously doesn't match anything) - you can examine the cssText and
see the null, clear as day.
* Firefox forces "\0" to be interpreted as escaping a literal "0",
even if more digits follow it. (More testing shows that they simply
refuse to tokenize \0 as a hex escape, regardless of how many 0s there
are. This means that I was lied to - they have to do 6-char lookahead
when parsing stylesheets, not 3-char. ^_^)
* IE and Opera both do something weird - if it appears in a selector,
they keep the rule, but it doesn't match anything, and they return the
empty string for cssText and selectorText on it. The rule is
definitely kept, though - if you ask for one of the properties set in
it, it's properly returned.
Next, I tested an actual escaped null, that is, a \ followed by a null.
In a selector:
* IE does the same thing as \0.
* Chrome appears to truncate the sheet again, then *claims that the
stylesheet contains no rules*, despite clearly applying the
*preceding* rules to the page.
* Firefox appears to convert it into a \0, and then act normally.
* Opera claims that the selector is empty, but otherwise preserves the
rule. (It doesn't match anything.)
In a value:
* IE ignores the rest of the property's value, but appears to treat it
as *not a syntax error*, and keep the rule in the CSSOM (just missing
some of the value). Otherwise, acts as normal.
* Chrome acts the same as in a selector.
* Firefox treats it as an invalid value and drops the declaration.
Otherwise, acts as normal.
* Opera is doing something stupid that makes me think it's doing funny
cache stuff, so I can't trust it.
Here are my conclusions:
1. Browsers are remarkably divergent in behavior here, so I can
probably just spec something sane and be done with it.
2. Nobody does anything *useful* with nulls, so getting rid of them in
the input string is almost certainly just fine.
3. I'd like to know why Firefox refuses to allow a hex-escaped null.
If there's a good reason, I can disallow it.
My recommendations:
1. Go ahead and replace nulls in the input stream with U+FFFD. Most
browsers do stupid, stupid things with nulls, and the one good browser
(FF) should act the same with U+FFFD as it does with U+0000. Avoiding
the problem seems to be the easiest path to convergence.
2. Unless Firefox has a good reason to disallow \0 (like, the person
who authored their grammar was just overzealous), I'll allow \0 as a
valid hex escape.
~TJ
Received on Tuesday, 23 October 2012 00:28:57 UTC