I think the best way to test UA features should to use (and improve)
document.implementation.hasFeature.
Current hasFeature signature :
======================
hasFeature (feature:String, version:Number) : Boolean
Proposed hasFeature signature :
===========================
hasFeature (feature:String, [version:Number]) : Boolean
hasFeature (mainFeature:String, subFeature:String, [version:Number]) :
Boolean
Samples :
=========
"hasFeature", 1 (current version of hasFeature)
"hasFeature", 2 (improved hasFeature version)
"CSS-Selector-", "+"
"CSS-Pseudo", ":hover", 1
"CSS-Pseudo", ":hover", 2
"CSS-Pseudo", ":after"
"CSS-Pseudo", "::after"
"CSS-Property", "border"
"CSS-Property", "content"
"CSS-Value", "border:initial"
"CSS-Value", "width:fit-content"
"HTML-Tag", "MARQUEE",
"HTML-Attribute", "[EMAIL PROTECTED]",
"..."
Fremy
In response to :
==================================
> The try-catch statement does carry overhead with it in terms of an
additional
> scope. If you're doing a bunch of queries and you need to surround
each of
> them with a try-catch, it can affect performance (see
> http://dev.opera.com/articles/view/efficient-javascript/?page=2).
What this is saying is that if you have to run the catch clause (that
is, an
exception was thrown) you get a small performance hit. If you don't
throw, no hit.
But in this case, that means that you're going to use a fallback
querySelector
implementation anyway, so you're getting a big performance hit no matter
what.
I'd be interested in how the overhead of the catch compares to that. My
gut
instinct is that it's pretty insignificant.
It might be that the article isn't quite clear, so there is a hit even
if
nothing is thrown. Again, hard data would be much appreciated. Safari
has a
querySelector implementation that could be used to test this, for
example.
Alternately, I have a Gecko with such support here and would be happy to
run a
timing test if you come up with one.
> Errors should be thrown only for things that aren't easily detectable
> beforehand.
I'm not sure I agree. There are plenty of DOM operations where it would
be easy
to add an API to check whether the operation is allowed before
performing it...
and they all throw if the operation is not allowed.
Given that querySelector would continue throwing on unsupported
selectors
whether the pre-check is added or not, how is this situation different?
> Not supporting a selector is not the same as a syntax error.
Sure it is, from the point of view of a UA. A CSS parser +
implementation
really can't tell the two apart.
> Again, you're focusing in on the specific solution.
No. I'm asking for two things:
1) Concrete use cases. I have yet to see a decent one suggested.
2) Proposed solutions to solve those use cases.
These are somewhat orthogonal. (1) is more important.
> The DOM has tons of different ways to determine what is
> implemented and possible to use.
Most of them highly unreliable. And as I said before, it also has
plenty of
cases where such things are not available and operations either succeed
or throw
and let the caller deal.
> An unsupported selector doesn't necessarily break CSS syntax. Consider
that
> :after and :hover match the same pattern.
The "CSS syntax" (as opposed to the grammar) is something that doesn't
exist.
There is a "CSS2.1 syntax", which is the set of all things allowed in
CSS 2.1.
There is the "Selectors syntax" which is the set of all things allowed
in the
Selectors CSS3 module. But a parser that only supports part of the
module
doesn't have any idea whether the other things are "syntax errors" or
just CSS
it happens to not support. Nor is introducing such a dichotomy really
desirable.
An example. Is "a::before:hover" a syntax error? Or an unsupported
selector?
How do you know?
> A support status page could be useful, but I'm thinking more
practical.
Yes, practical is good.
> How can a JavaScript library that currently supports CSS querying
determine if it
> should use its implementation or the browser one?
I'd be interested in some feedback from actual JavaScript library
authors on
what they would find useful here, for what it's worth.
> Again, writing a try-catch around every call adds performance overhead
As I said, I'd love data here, especially as compared to proposals to
query
selector support. For example, is it more overhead than parsing the
selector
twice on every call (once to test support, once to run the query)?
> With some way to detect
> the capabilities of the query engine, a JS library could determine up
front
> whether or not to use the browser-native version.
If it's only doing the detection once up front, it doesn't really matter
whether
the detection is expensive...
> var goodEnough = document.querySelectorSupport(":hover", ":not",
".a.b",
> "tagname", "#id");
>
> In this paradigm, you can pass in a string representing each selector
to
> test, with special ones for single class names (.a), multiple (.a.b,
.a.b.c,
> etc.), tag names (tagname), IDs (#id).
Maybe I'm missing something... how would this work in practice?
Wouldn't this
require the JS library to parse every selector it needs to query to see
whether
it's in its precomputed "safe" set? My gut feeling is that this is more
overhead than a try/catch. Of course actual data would be welcome.
I should note that your ":not" example above seems to fail my
":not(.a.b)" test,
by the way.
-Boris