Re: More questions about contextual reference nodes

On 2011-04-09 19:14, Boris Zbarsky wrote:
> On 4/9/11 6:27 AM, Lachlan Hunt wrote:
>> There were cases in JQuery where the script wanted to iteratively run a
>> selector on all nodes in a collection, and return elements that are
>> descendants of those elements. This allows :scope to be used in those
>> cases by passing the collection as the refNodes. There was previous
>> discussion of this somewhere in the public-webapps archive.
>
> Hmm... ok.

As a simple example of that, this works in JQuery:

<p><span></span>
<p><span></span>
<p><span></span>

<script>
alert($("p").find(">span").length)
</script>

> But is jquery's collection a JS Array?

The object returned by the $() function isn't an array.  It's a custom 
object that mimics the functionality of an array.  This means that as 
currently defined, refElements could not accept a JQuery object as the 
parameter like so:

   var p = $("p.foo")
   Var a = $("a");
   a[0].matchesSelector(":scope>a", p)

This would instead require scripts to do this:

   a[0].matchesSelector(":scope>a", p.toArray())

JQuery effectively defines .toArray() as a function that returns:

   Array.prototype.slice.call( this, 0 );

Would it be useful, and is it possible to define the refElements 
parameter to accept any object that contains a .length and indexed 
properties, just like a JQuery object?  i.e. Can we make this work?

   var x = {}
   x[0] = el1;
   x[1] = el2;
   x[2] = el3;
   x.length = 3;

   a.matchesSelector(":scope>a", x);

>> I also have to include one for HTMLCollection, which doesn't inherit
>> from NodeList.
>
> Yeah, that's broken... I wonder whether we can just fix that in Web DOM
> Core or something....

Yes, I'd like to fix it somehow.  I'm not yet sure how.

>> WebIDL says sequences are passed by value and arrays are passed by
>> reference. So I suspect using an array is better here so that it doesn't
>> have to create a copy.
>
> The by reference thing only happens for array host objects, which a JS
> Array is not. So the copy would effectively happen in either case, I
> believe, for JS Array.

OK. Then I'm not sure what the practical difference between the 
Element[] or sequence<Element> would be then, nor which one to use.

>> Yes, I would like feedback about the best way to define this,
>> particularly for Arrays. In particular, how to address the following
>> cases.
>>
>> var ref = [];
>> ref[0] = el1;
>> ref[1000000] = el2;
>>
>> That will contain almost a million empty cells. Will iterating through
>> that cause any unwanted performance issues?
>
> I believe my current Gecko implementation (using our existing variant
> facilities, since that's all we have to deal with overloads for the
> moment) will allocate a C array with 1000001 entries, then ignore it
> because not everything in the array is an Element.
>
> A DOM binding implementation using WebIDL arrays or sequences would
> allocate a C++ array with 1000001 entries, all of which except for the
> first and last are null. Then the actual implementation of the selectors
> API will walk this array and add only the first and last entry to the
> set of scope elements. I think. I'm pretty sure this is true for Array;
> the behavior for sequence is less clear to me. And maybe this can all be
> optimized in implementations, somehow... Ccing Cameron for his input.
>
>> Should we require arrays to contain contiguous Elements and only
>> iterate up to the first empty or non-Element cell, ignoring
>> anything beyond that?
>
> If using webidl array/sequence types, that would help with the
> iteration, but not the large allocation.

OK, does that mean it's not really worth defining like that?

>> ref[1] = "string";
>>
>> Should passing this now throw an exception, or should it just accept
>> that ref[0] was an element and use that?
>
> Webidl array/sequence would throw in this case, I think.

Yes, I just checked and I think you may be right. The WebIDL algorithm 
to convert an ECMAScript array to an IDL value of type T[] iterates the 
array and says:

   While i < n:

     Let x be the result of calling [[Get]] on V with property name 
ToString(i).
     Set Ei to be the result of converting x to an IDL value of type T.
     Set i to i + 1.

I think the second step in the loop should throw a TypeError if the 
object can't be converted to the correct type (Element, in this case). 
But WebIDL doesn't seems very clear about this, so I may be wrong.

-- 
Lachlan Hunt - Opera Software
http://lachy.id.au/
http://www.opera.com/

Received on Sunday, 10 April 2011 11:31:08 UTC