Re: More questions about contextual reference nodes

2011-04-14 Thread Boris Zbarsky

On 4/13/11 5:43 AM, Lachlan Hunt wrote:

I didn't think so, but then perhaps I misunderstand what the spec means
by a native object. ECMAScript defines a native object as

object in an ECMAScript implementation whose semantics are fully
defined by this specification rather than by the host environment.

So that would include things like Array, String, etc.


Ineed.


I don't think NodeList fits that definition, since it's provided by the host
environment, not ECMAScript.


That's correct.


I also thought something like this would not be a native object either:

function init() {
...
}
var x = new init();


That's a native object; the behavior of that set of operations is 
completely defined by the ES spec.



JQuery more or less does that to create an object with custom
properties, and then basically uses Array.prototype.push.apply(x, elms)
to add the collection to that object.


Right; jquery's got native objects there.


It's nice so that cases where authors try to pass in an array of things
that aren't nodes are handled well. The other alternative is just to
accept a collection of anything, and iterate through it to find all the
Element nodes, ignoring everything else. I don't see any reason to
prefer the latter approach.


I would really prefer we not do the latter.

-Boris




Re: More questions about contextual reference nodes

2011-04-14 Thread Boris Zbarsky

On 4/13/11 6:20 AM, Lachlan Hunt wrote:

Which conversion algorithm applies here? Is it 4.1.15. object, or
4.1.16. Interface types?

http://dev.w3.org/2006/webapi/WebIDL/#es-object


The latter, since Node is an interface type.

-Boris



Re: More questions about contextual reference nodes

2011-04-14 Thread Cameron McCormack
Lachlan Hunt:
 However, with the way in which the IDL is overloaded, it's not clear
 to me which of the two overloaded methods gets invoked when the
 parameter is null.
 
 The IDL says:
   querySelector(in DOMString selectors, in optional Element refElement);
   querySelector(in DOMString selectors, in sequenceNode refNodes);
 
 When the author invokes:
 
   x.querySelector(a, null);
 
 Does it invoke the method with refElement or refNodes?

That is one of the unsatisfactory things about the way overloading is
currently handled in Web IDL.  In situations where null is a valid value
for more than one overload, it needs to be described in prose, but only
if it matters which of the two operations is considered to be invoked.

See the blue box just below this footnote:

  http://dev.w3.org/2006/webapi/WebIDL/#distinguishable-interface-note

Step 4 of the algorithm for the behaviour of Function objects that
correspond to IDL operations

  http://dev.w3.org/2006/webapi/WebIDL/#es-operations

says

  If S contains more than one entry, then the operation call is
  ambiguous. Remove all but one entry from S according to rules
  specified in the description of interface I, or arbitrarily if no such
  rules exist.


Note that it is ambiguous if you have, say

  querySelector(in DOMString selectors, in optional Element refElement);
  querySelector(in DOMString selectors, in Node[] refNodes);

since null is a valid value for both Element and Node[].  With

  querySelector(in DOMString selectors, in optional Element refElement);
  querySelector(in DOMString selectors, in sequenceNode refNodes);

null is not a valid value for sequenceNode, so passing null calls the
first of the two overloads.  That is because in the overload resolution
algorithm

  http://dev.w3.org/2006/webapi/WebIDL/#dfn-overload-resolution-algorithm

step 3.2.2 only considers object, interface types, nullable types and
array types when “null” is passed as an argument.

-- 
Cameron McCormack ≝ http://mcc.id.au/



Re: More questions about contextual reference nodes

2011-04-13 Thread Lachlan Hunt

On 2011-04-13 04:43, Cameron McCormack wrote:

Lachlan Hunt:

This seems to differ from the algorithm given for T[], which
requires that the object be either an array host object or a native
object, which would not handle the JQuery case.  The sequenceT
type seems more generic than that as the algorithm seems to be able
to support any object with a length and indexed properties.


Why wouldn’t it handle the JQuery case?  Isn’t it a native object?


I didn't think so, but then perhaps I misunderstand what the spec means 
by a native object.  ECMAScript defines a native object as


  object in an ECMAScript implementation whose semantics are fully
   defined by this specification rather than by the host environment.

So that would include things like Array, String, etc.  I don't think 
NodeList fits that definition, since it's provided by the host 
environment, not ECMAScript.


I also thought something like this would not be a native object either:

  function init() {
...
  }
  var x = new init();

JQuery more or less does that to create an object with custom 
properties, and then basically uses Array.prototype.push.apply(x, elms) 
to add the collection to that object.



The issue of whether you want to throw eagerly if passed an array with
elements of the wrong type to an operation taking a sequenceT  is an
interesting one, which probably still could bear some more discussion.
On the one hand, it helps ensure implementations don’t diverge based on
when during the course of running the method these elements from the
sequence are looked up.  I could mean a lot of useless checks, though.


It's nice so that cases where authors try to pass in an array of things 
that aren't nodes are handled well.  The other alternative is just to 
accept a collection of anything, and iterate through it to find all the 
Element nodes, ignoring everything else.  I don't see any reason to 
prefer the latter approach.


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



Re: More questions about contextual reference nodes

2011-04-13 Thread Lachlan Hunt

On 2011-04-13 06:32, Cameron McCormack wrote:

Lachlan Hunt:

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


... the only difference is that with Element[] you can distinguish
between null and an array of [length 0], while with sequenceElement  you
can’t.


I don't think it's necessary to distinguish between null and length 0 
here, since they both mean that there are no contextual reference elements.


However, with the way in which the IDL is overloaded, it's not clear to 
me which of the two overloaded methods gets invoked when the parameter 
is null.


The IDL says:
  querySelector(in DOMString selectors, in optional Element refElement);
  querySelector(in DOMString selectors, in sequenceNode refNodes);

When the author invokes:

  x.querySelector(a, null);

Does it invoke the method with refElement or refNodes?

(Although, in this case, it shouldn't matter, since the algorithm I 
wrote to determine contextual reference nodes ignores null in either case)



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.


This step can throw (as part of the conversion process defined for
converting to type T); seems like that would involve throwing from
the whole algorithm.


Yep.


Which conversion algorithm applies here?  Is it 4.1.15. object, or 
4.1.16. Interface types?


http://dev.w3.org/2006/webapi/WebIDL/#es-object

The former never throws, the latter will throw a TypeError. So am I 
right in assuming it's the latter?


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



Re: More questions about contextual reference nodes

2011-04-12 Thread Cameron McCormack
Lachlan Hunt:
 I reviewed WebIDL again, and I think I've started to understand the
 difference between sequenceT and T[] now.
 
 As I understand it, the algorithm to convert an ECMAScript object to
 an IDL sequence should work with any object that has a length
 property and indexed values containing Node objects.  That is true
 for an Array of Nodes, NodeList, HTMLCollection and the above JQuery
 case, they can all be handled in the same way.

Yes, that’s right.

 This seems to differ from the algorithm given for T[], which
 requires that the object be either an array host object or a native
 object, which would not handle the JQuery case.  The sequenceT
 type seems more generic than that as the algorithm seems to be able
 to support any object with a length and indexed properties.

Why wouldn’t it handle the JQuery case?  Isn’t it a native object?

 I've updated and simplified the spec to handle the above case using
 the parameter sequenceNode.  I still need to update the prose to
 say that while the collections may contain any Node, only Element
 nodes are added to the list of contextual reference elements.  But
 the following cases should all work.

Agreed, that works, according to Web IDL’s currenty definition of
overloading.

The issue of whether you want to throw eagerly if passed an array with
elements of the wrong type to an operation taking a sequenceT is an
interesting one, which probably still could bear some more discussion.
On the one hand, it helps ensure implementations don’t diverge based on
when during the course of running the method these elements from the
sequence are looked up.  I could mean a lot of useless checks, though.

-- 
Cameron McCormack ≝ http://mcc.id.au/



Re: More questions about contextual reference nodes

2011-04-12 Thread Boris Zbarsky

On 4/10/11 4:30 AM, Lachlan Hunt wrote:

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?


Looks like this already got answered, but yes, sequenceNode should 
make that work.



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


I'm not either.  That's why Cameron is cced.


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?


I think this is an edge case we shouldn't worry about.

Perhaps famous last words.


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.


This step can throw (as part of the conversion process defined for 
converting to type T); seems like that would involve throwing from the 
whole algorithm.


-Boris




Re: More questions about contextual reference nodes

2011-04-12 Thread Boris Zbarsky

On 4/10/11 12:02 PM, Lachlan Hunt wrote:

I've updated and simplified the spec to handle the above case using the
parameter sequenceNode. I still need to update the prose to say that
while the collections may contain any Node, only Element nodes are added
to the list of contextual reference elements.


Looks like you now made that change too.  The new text looks good to me. 
 Thanks!


What Firefox 5 will ship doesn't match this yet (because we don't 
actually have a sane webidl implementation yet), but that's why we're 
prefixing... ;)


-Boris



Re: More questions about contextual reference nodes

2011-04-12 Thread Cameron McCormack
Lachlan Hunt:
  OK. Then I'm not sure what the practical difference between the
  Element[] or sequenceElement would be then, nor which one to use.

Boris Zbarsky:
 I'm not either.  That's why Cameron is cced.

If you are choosing between those two for the type of an argument,
 and you don’t have any way of getting an actual array host object
 Element[] (so will be passing in a native Array, or a NodeList, or…),
 and hence the method cannot cause a reference to a passed-in Element[]
 object to be kept,
then the only difference is that with Element[] you can distinguish
between null and an array of length 1, while with sequenceElement you
can’t.

 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.
 
 This step can throw (as part of the conversion process defined for
 converting to type T); seems like that would involve throwing from
 the whole algorithm.

Yep.

-- 
Cameron McCormack ≝ http://mcc.id.au/



Re: More questions about contextual reference nodes

2011-04-12 Thread Cameron McCormack
Cameron McCormack:
 then the only difference is that with Element[] you can distinguish
 between null and an array of length 1, while with sequenceElement you
 can’t.

Length 0, not 1.

-- 
Cameron McCormack ≝ http://mcc.id.au/



Re: More questions about contextual reference nodes

2011-04-10 Thread Lachlan Hunt

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:

pspan/span
pspan/span
pspan/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(:scopea, p)

This would instead require scripts to do this:

  a[0].matchesSelector(:scopea, 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(:scopea, 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 sequenceElement 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[100] = 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 101 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 101 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/



Re: More questions about contextual reference nodes

2011-04-10 Thread Lachlan Hunt

On 2011-04-10 13:30, Lachlan Hunt wrote:

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...

var p = $(p.foo)
Var a = $(a);
a[0].matchesSelector(:scopea, p)
...
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(:scopea, x);


I reviewed WebIDL again, and I think I've started to understand the 
difference between sequenceT and T[] now.


As I understand it, the algorithm to convert an ECMAScript object to an 
IDL sequence should work with any object that has a length property and 
indexed values containing Node objects.  That is true for an Array of 
Nodes, NodeList, HTMLCollection and the above JQuery case, they can all 
be handled in the same way.


This seems to differ from the algorithm given for T[], which requires 
that the object be either an array host object or a native object, which 
would not handle the JQuery case.  The sequenceT type seems more 
generic than that as the algorithm seems to be able to support any 
object with a length and indexed properties.


I've updated and simplified the spec to handle the above case using the 
parameter sequenceNode.  I still need to update the prose to say that 
while the collections may contain any Node, only Element nodes are added 
to the list of contextual reference elements.  But the following cases 
should all work.



1. Array of Elements

  document.querySelector(:scopea, [el1, el2, el3]);

2. NodeList

  document.querySelector(:scopea, el.childNodes);

3. NodeList converted to an array

  document.querySelector(:scopea,
   Array.prototype.slice.call(el.childNodes, 0));
  // Conversion to an array is unnecessary here, but just showing that
  // it will work anyway.

4. HTMLCollection

  s.matchesSelector(:scope~a, document.images);

5. Objects with indexed properties, including JQuery

  var x = {}
  x[0] = el1;
  x[1] = el2;
  x[2] = el3;
  x.length = 3;
  document.querySelector(:scopea, x);

  x = $(.foo, .bar);
  a.matchesSelector(:scopea, x);

  a.matchesSelector(:scopea, x.toArray());
  // Unnecessary converstion to array here

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



Re: More questions about contextual reference nodes

2011-04-10 Thread Ms2ger

On 04/09/2011 07:14 PM, Boris Zbarsky wrote:

On 4/9/11 6:27 AM, Lachlan Hunt wrote:

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


If people are willing to implement that, certainly.

--
Ms2ger



More questions about contextual reference nodes

2011-04-09 Thread Boris Zbarsky
I have two questions about 
http://www.w3.org/TR/selectors-api2/#determine-contextual-reference-nodes


1)  What are the use cases for supplying more than one contextual 
reference node, exactly?  It seems weird to allow more than one node to 
match :scope.


2)  If we do want to allow the multiple node thing, can we please do it 
in IDL instead of the (currently pretty vague) prose?  Something like:


  Element querySelector(in DOMString selectors,
in optional Element refElement);
  Element querySelector(in DOMString selectors,
in optional NodeList refElements);
  Element querySelector(in DOMString selectors,
in optional sequenceElement refElements);

or some such?  It's not quite clear to me whether we want a 
sequenceElement or a T[]; that's worth checking.  In either case, 
the prose will need to define what happens with the NodeList or 
sequence/array cases, but there will be no ambiguity about how one gets 
Elements out of what's passed in.  The one difference is that in the 
array case if non-elements are present in the array an exception will be 
thrown.  I think that's fine, myself.


-Boris



Re: More questions about contextual reference nodes

2011-04-09 Thread Lachlan Hunt

On 2011-04-09 10:12, Boris Zbarsky wrote:

I have two questions about
http://www.w3.org/TR/selectors-api2/#determine-contextual-reference-nodes

1) What are the use cases for supplying more than one contextual
reference node, exactly? It seems weird to allow more than one node to
match :scope.


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.



2) If we do want to allow the multiple node thing, can we please do it
in IDL instead of the (currently pretty vague) prose? Something like:


I know the draft is quite poorly written with regards to how to deal 
with collections right now.



Element querySelector(in DOMString selectors,
in optional Element refElement);
Element querySelector(in DOMString selectors,
in optional NodeList refElements);
Element querySelector(in DOMString selectors,
in optional sequenceElement refElements);


I also have to include one for HTMLCollection, which doesn't inherit 
from NodeList.  But if that would be better, then yes, we can do that. 
It just makes the IDL 4 times longer, as that has to be repeated for 
each method of the 3 methods.  Ive made this change now.


I also dropped queryScopedSelector at the same time, since it wasn't 
able meet the original requirements that it was being designed for and 
so not worth keeping.



or some such? It's not quite clear to me whether we want a
sequenceElement or a T[]; that's worth checking.


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.



In either case, the prose will need to define what happens with the
NodeList or sequence/array cases, but there will be no ambiguity
about how one gets Elements out of what's passed in. The one
difference is that in the array case if non-elements are present in
the array an exception will be thrown. I think that's fine, myself.


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[100] = el2;

That will contain almost a million empty cells. Will iterating through 
that cause any unwanted performance issues?  Should we require arrays to 
contain contiguous Elements and only iterate up to the first empty or 
non-Element cell, ignoring anything beyond 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?


For NodeLists, should it accept any NodeList and only use the Element 
nodes?  e.g. element.childNodes may contain text or comment nodes.


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



Re: More questions about contextual reference nodes

2011-04-09 Thread Boris Zbarsky

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.

But is jquery's collection a JS Array?


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



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.



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[100] = 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 101 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 101 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.



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.


For NodeLists, should it accept any NodeList and only use the Element
nodes? e.g. element.childNodes may contain text or comment nodes.


I think that's the right thing to do, yes.

-Boris