- From: Lachlan Hunt <lachlan.hunt@lachy.id.au>
- Date: Sun, 10 Apr 2011 13:30:33 +0200
- To: Boris Zbarsky <bzbarsky@MIT.EDU>
- CC: public-webapps <public-webapps@w3.org>, Cameron McCormack <cam@mcc.id.au>
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