Re: Remaining Problems with Explicit :scope Switching in find/findAll (was: Re: [Selectors API 2] Is matchesSelector stable enough to unprefix in implementations?)

On Thu, Nov 24, 2011 at 12:50 AM, Lachlan Hunt <lachlan.hunt@lachy.id.au> wrote:
> On 2011-11-24 00:52, Yehuda Katz wrote:
>>
>> On Wed, Nov 23, 2011 at 2:38 PM, Sean Hogan<shogun70@westnet.com.au>
>>  wrote:
>>>
>>> The alternative option (find / findAll / matches can accept explicit
>>> :scope, but will otherwise imply :scope) seems to be where all the
>>> ambiguity lies.
>>
>> What exact cases are ambiguous with "find/findAll/matches can accept
>> explicit :scope, but will otherwise imply :scope"?
>
> The problems to be solved with automatically switching between implied and
> explicit :scope are basically in determining what exactly counts as an
> explicit :scope.  The answers to each of these has is trade off between
> complexity and functionality, with the simplest option being always implying
> :scope.
>
> * Is explicit :scope allowed at the beginning of each selector?
>
>  find(":scope>div");
>  find("body.foo :scope>div");

Anywhere within the selector.


> * Does :scope inside functional pseudo-classes count?
>
>  find(":not(:scope)");
>  find(":matches(:scope)");
>
> If yes, does the first match the whole document, only descendants, or
> descendants plus siblings?

Yes, I believe so.  The first matches the whole document except for
the scoping element.  The second matches only the scoping element.


> * If using an explicit :scope, can it match itself?
>
>  find(":scope") // Return null or the element itself?

Yes, because selectors with an explicit scope are evaluated against
the whole document.  (Selectors with an implicit scope are too,
theoretically, though implementations can optimize.)  That example
returns the element itself.


> * Is :scope always implied if it begins with an explicit combinator other
> than descendant, even if :scope is used elsewhere?
>  find(">div :scope");
>  find("+div :scope");
>  find("~div :scope");

Yes.


> * There's also the general issue, not related to :scope, about how the
> reference combinator affects the range of potential matches.
>  label.find("/for/ input")
>
> Based on the above issues, what happens in this case?
>
>  foo.find(">label /for/ input+:scope~span)

This is equivalent to prepending ":scope" to the selector, and
evaluating it against the whole document.  In other words, it finds a
span that is preceded by the scope which is immediately preceded by an
input which is referenced by a label which is a child of the scope.

So, the rules end up being very simple.  find always evaluates against
the whole document.  If one of the selectors starts with a combinator
or doesn't contain a ":scope" pseudoclass somewhere in it, ":scope" is
prepended to it.  That's it.  With this, we make the most common cases
(searching descendants/siblings) easy, while making the global case
*also* easy.  There's a bit of intent-guessing when :scope is used in
an indirect way, but I believe it's better to err on the side of
simplicity and consistency there.

~TJ

Received on Thursday, 24 November 2011 14:53:14 UTC