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/

Reply via email to