W3C home > Mailing lists > Public > public-webapps@w3.org > October to December 2011

Re: QSA, the problem with ":scope", and naming

From: Yehuda Katz <wycats@gmail.com>
Date: Tue, 18 Oct 2011 13:20:05 -0700
Message-ID: <CAMFeDTUHjcyeMYH77-w5J5RTTB0E4Pad=xyFYoNjHX6i+0fSrw@mail.gmail.com>
To: Alex Russell <slightlyoff@google.com>
Cc: Webapps WG <public-webapps@w3.org>, John Resig <jeresig@gmail.com>, Paul Irish <paulirish@google.com>, Lachlan Hunt <lachlan.hunt@lachy.id.au>
I agree entirely.

I have asked a number of practitioner friends about this scenario:

  <div id="parent">
    <p id="child"><span id="inline">Content</span></p>
  </div>

  document.getElementById("child").querySelectorAll("div span"); // returns
#inline

In 100% of cases, people consider this behavior *broken*. Not just
"interesting, I wouldn't have expected that", but "who came up with that!?".
In all cases involving JavaScript practitioners, people expect
querySelectorAll to operate on the element as though the element was the
root of a new document, and where combinators are relative to the element.

We already knew this was true since all JavaScript libraries that implement
selectors implemented them in this way.

I also agree that the name querySelectorAll (like getElement(s)By*,
requestAnimationFrame, addEventListener, and most other DOM APIs), are
simply too long to use in day-to-day usage. This results in the need to use
libraries for day-to-day browser development simply to reduce this
borderline-comical verbosity.

I like find and findAll, as jQuery has a `find` which invokes the selector
engine. As to whether jQuery would benefit from the improvements, the
existing jQuery implementation (Sizzle) of the selector engine when qSA is
available is at:
https://github.com/jquery/sizzle/blob/master/sizzle.js#L1150-1233

There are a few categories of extensions:

   - Speeding up certain operations like `#foo` and `body`. There is *no
   excuse* for it being possible to implement userland hacks that improve on
   the performance of querySelectorAll. This may be the result of browsers
   failing to cache the result of parsing selectors or something else, but the
   fact remains that qSA can be noticably slower than the old DOM methods, even
   when Sizzle needs to parse the selector to look for fast-paths.
   - Fixing the implementation mistake in qSA that we're discussing here.
   - Bugs in specific browsers.

jQuery also handles certain custom pseudoselectors, and it might be nice if
it was possible to register JavaScript functions that qSA would use if it
found an unknown pseudo (this would make it possible to implement most of
jQuery's selector engine in terms of qSA), but that's a discussion for
another day.

Yehuda Katz
(ph) 718.877.1325


On Tue, Oct 18, 2011 at 9:42 AM, Alex Russell <slightlyoff@google.com>wrote:

> Lachlan and I have been having an...um...*spirited* twitter discussion
> regarding querySelectorAll, the (deceased?) queryScopedSelectorAll,
> and ":scope". He asked me to continue here, so I'll try to keep it
> short:
>
> The rooted forms of "querySelector" and "querySelectorAll" are
> mis-designed.
>
> Discussions about a Scoped variant or ":scope" pseudo tacitly
> acknowledge this, and the JS libraries are proof in their own right:
> no major JS library exposes the QSA semantic, instead choosing to
> implement a rooted search.
>
> Related and equally important, that querySelector and querySelectorAll
> are often referred to by the abbreviation "QSA" suggests that its name
> is bloated and improved versions should have shorter names. APIs gain
> use both through naming and through use. On today's internet -- the
> one where 50% of all websites include jQuery -- you could even go with
> element.$("selector") and everyone would know what you mean: it's
> clearly a search rooted at the element on the left-hand side of the
> dot.
>
> Ceteris peribus, shorter is better. When there's a tie that needs to
> be broken, the more frequently used the API, the shorter the name it
> deserves -- i.e., the larger the component of its meaning it will gain
> through use and repetition and not naming and documentation.
>
> I know some on this list might disagree, but all of the above is
> incredibly non-controversial today. Even if there may have been
> debates about scoping or naming when QSA was originally designed,
> history has settled them. And QSA lost on both counts.
>
> I therefore believe that this group's current design for scoped
> selection could be improved significantly. If I understand the latest
> draft (http://www.w3.org/TR/selectors-api2/#the-scope-pseudo-class)
> correctly, a scoped search for multiple elements would be written as:
>
>   element.querySelectorAll(":scope > div > .thinger");
>
> Both then name and the need to specify ":scope" are punitive to
> readers and writers of this code. The selector is *obviously*
> happening in relationship to "element" somehow. The only sane
> relationship (from a modern JS hacker's perspective) is that it's
> where our selector starts from. I'd like to instead propose that we
> shorten all of this up and kill both stones by introducing a new API
> pair, "find" and "findAll", that are rooted as JS devs expect. The
> above becomes:
>
>   element.findAll("> div > .thinger");
>
> Out come the knives! You can't start a selector with a combinator!
>
> Ah, but we don't need to care what CSS thinks of our DOM-only API. We
> can live and let live by building on ":scope" and specifying find* as
> syntactic sugar, defined as:
>
>  HTMLDocument.prototype.find =
>  HTMLElement.prototype.find = function(rootedSelector) {
>     return this.querySelector(":scope " + rootedSelector);
>   }
>
>   HTMLDocument.prototype.findAll =
>   HTMLElement.prototype.findAll = function(rootedSelector) {
>     return this.querySelectorAll(":scope " + rootedSelector);
>   }
>
> Of course, ":scope" in this case is just a special case of the ID
> rooting hack, but if we're going to have it, we can kill both birds
> with it.
>
> Obvious follow up questions:
>
> Q.) Why do we need this at all? Don't the toolkits already just do
> this internally?
> A.) Are you saying everyone, everywhere, all the time should need to
> use a toolkit to get sane behavior from the DOM? If so, what are we
> doing here, exactly?
>
> Q.) Shorter names? Those are for weaklings!
> A.) And humans. Who still constitute most of our developers. Won't
> someone please think of the humans?
>
> Q.) You're just duplicating things!
> A.) If you ignore all of the things that are different, then that's
> true. If not, well, then no. This is a change. And a good one for the
> reasons listed above.
>
> Thoughts?
>
Received on Tuesday, 18 October 2011 20:21:03 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:48 GMT