Re: [selectors-api] Return an Array instead of a static NodeList

2011-10-24 Thread Cameron McCormack

On 30/08/11 4:19 PM, Jonas Sicking wrote:

Indeed! I think it's already been decided that all non-mutating
functions should be added to NodeLists and other list-like DOM
objects. I believe Cameron is still working on the specifics of that.


Shortly before the LC#2 was published, I added an [ArrayClass] extended 
attribute that you can put on interfaces that are not defined to inherit 
from another.  That causes that interface's [[Prototype]] to be 
Array.prototype instead of Object.prototype.  It's then up to the 
designer of the interface to ensure that length and array index 
properties behave usefully (by defining a length IDL attribute and using 
indexed properties) so that the Array.prototype methods will do nice things.


The other construct that uses Array.prototype is platform array objects. 
 They too have Array.prototype as their [[Prototype]].  Web IDL defines 
how array index properties and length are exposed on platform array 
objects so that they work with Array.prototype methods as best they can.




Re: [selectors-api] Return an Array instead of a static NodeList

2011-10-24 Thread Jonas Sicking
On Mon, Oct 24, 2011 at 11:17 AM, Cameron McCormack c...@mcc.id.au wrote:
 On 30/08/11 4:19 PM, Jonas Sicking wrote:

 Indeed! I think it's already been decided that all non-mutating
 functions should be added to NodeLists and other list-like DOM
 objects. I believe Cameron is still working on the specifics of that.

 Shortly before the LC#2 was published, I added an [ArrayClass] extended
 attribute that you can put on interfaces that are not defined to inherit
 from another.  That causes that interface's [[Prototype]] to be
 Array.prototype instead of Object.prototype.  It's then up to the designer
 of the interface to ensure that length and array index properties behave
 usefully (by defining a length IDL attribute and using indexed properties)
 so that the Array.prototype methods will do nice things.

 The other construct that uses Array.prototype is platform array objects.
  They too have Array.prototype as their [[Prototype]].  Web IDL defines how
 array index properties and length are exposed on platform array objects so
 that they work with Array.prototype methods as best they can.

I think we have three types of array-like objects:

1. Objects like the one returned from getElementsByTagName where
modifications to the array just doesn't make sense.
2. Objects like the one returned from HTMLInputElements.files where
modifications to the array could be allowed and where such
modifications affect the DOM (i.e. the submitted value would be
changed)
3. Object like the one returned from findAll where modifications don't
affect anything other than the mutated object.

It appears to me that [ArrayClass] helps with case 2.

For case 3 I think we should simply return an Array. No need for
anything more magic than that.

Case 1 appears to be unaddressed though. And I actually think that's
the most common case in the DOM right now. Or were we hoping that
[ArrayClass] would be used there too and all mutating functions would
throw?

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-10-24 Thread Cameron McCormack

On 24/10/11 11:51 AM, Jonas Sicking wrote:

I think we have three types of array-like objects:

1. Objects like the one returned from getElementsByTagName where
modifications to the array just doesn't make sense.
2. Objects like the one returned from HTMLInputElements.files where
modifications to the array could be allowed and where such
modifications affect the DOM (i.e. the submitted value would be
changed)
3. Object like the one returned from findAll where modifications don't
affect anything other than the mutated object.

It appears to me that [ArrayClass] helps with case 2.


Yes.


For case 3 I think we should simply return an Array. No need for
anything more magic than that.


Agreed.


Case 1 appears to be unaddressed though. And I actually think that's
the most common case in the DOM right now. Or were we hoping that
[ArrayClass] would be used there too and all mutating functions would
throw?


Yes that is the hope.  I should run through the mutation function 
definitions just to be sure. :)  It is at least well defined.


An alternative is to introduce a new prototype object in between 
Array.prototype and the mutable array-like object that has properties 
shadowing all of the mutating functions with a function that 
unconditionally throws.  I would prefer to avoid having to update the 
spec whenever new Array.prototype methods are introduced in the ES spec 
if possible, though.




Re: [selectors-api] Return an Array instead of a static NodeList

2011-10-24 Thread Jonas Sicking
On Mon, Oct 24, 2011 at 11:57 AM, Cameron McCormack c...@mcc.id.au wrote:
 On 24/10/11 11:51 AM, Jonas Sicking wrote:

 I think we have three types of array-like objects:

 1. Objects like the one returned from getElementsByTagName where
 modifications to the array just doesn't make sense.
 2. Objects like the one returned from HTMLInputElements.files where
 modifications to the array could be allowed and where such
 modifications affect the DOM (i.e. the submitted value would be
 changed)
 3. Object like the one returned from findAll where modifications don't
 affect anything other than the mutated object.

 It appears to me that [ArrayClass] helps with case 2.

 Yes.

 For case 3 I think we should simply return an Array. No need for
 anything more magic than that.

 Agreed.

 Case 1 appears to be unaddressed though. And I actually think that's
 the most common case in the DOM right now. Or were we hoping that
 [ArrayClass] would be used there too and all mutating functions would
 throw?

 Yes that is the hope.  I should run through the mutation function
 definitions just to be sure. :)  It is at least well defined.

 An alternative is to introduce a new prototype object in between
 Array.prototype and the mutable array-like object that has properties
 shadowing all of the mutating functions with a function that unconditionally
 throws.  I would prefer to avoid having to update the spec whenever new
 Array.prototype methods are introduced in the ES spec if possible, though.

Based on my testing, many methods wouldn't throw for zero-size
array-like objects. Similarly, methods like .push(), .unshift() and
.slice() wouldn't throw if no entries were actually requested to be
added or removed. And .reverse() wouldn't throw for single-sized
array-like objects.

May or may not be a big deal though.

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-10-24 Thread Cameron McCormack

On 24/10/11 12:14 PM, Jonas Sicking wrote:

Based on my testing, many methods wouldn't throw for zero-size
array-like objects. Similarly, methods like .push(), .unshift() and
.slice() wouldn't throw if no entries were actually requested to be
added or removed. And .reverse() wouldn't throw for single-sized
array-like objects.

May or may not be a big deal though.


Yeah.  IMO it's not.

One thing that is difficult to reflect from the JS Array API to objects 
like HTMLInputElements.files which we might want to make mutable is that 
the former is designed to work with sparse arrays while we have 
typically considered DOM collection/list objects as dense.


  myFileInput.files.length;// let's say this is 1
  myFileInput.files[2] = ...;  // what does this mean?



Re: [selectors-api] Return an Array instead of a static NodeList

2011-10-24 Thread Jonas Sicking
On Mon, Oct 24, 2011 at 3:02 PM, Cameron McCormack c...@mcc.id.au wrote:
 On 24/10/11 12:14 PM, Jonas Sicking wrote:

 Based on my testing, many methods wouldn't throw for zero-size
 array-like objects. Similarly, methods like .push(), .unshift() and
 .slice() wouldn't throw if no entries were actually requested to be
 added or removed. And .reverse() wouldn't throw for single-sized
 array-like objects.

 May or may not be a big deal though.

 Yeah.  IMO it's not.

 One thing that is difficult to reflect from the JS Array API to objects like
 HTMLInputElements.files which we might want to make mutable is that the
 former is designed to work with sparse arrays while we have typically
 considered DOM collection/list objects as dense.

  myFileInput.files.length;    // let's say this is 1
  myFileInput.files[2] = ...;  // what does this mean?

Indeed. Though I think we can deal with having holes. We'd just have
to compact whenever the list was changed (in this case if the user
modified the list of files).

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-30 Thread Jonas Sicking
On Mon, Aug 29, 2011 at 9:40 AM, Aryeh Gregor a...@aryeh.name wrote:
 On Thu, Aug 25, 2011 at 7:17 PM, Jonas Sicking jo...@sicking.cc wrote:
 .push and .pop are generic and work on anything that looks like an
 Array. However they don't work on NodeList because NodeList isn't
 mutable.

 . . .

 None of these are *mutable* functions.

 Oh, right.  I misunderstood you.  Yes, obviously we wouldn't expose
 things like .push or .pop on NodeList, since they wouldn't make sense.
  But we should expose things like .forEach, etc.  Any reason not to?

My point was that it was a mistake for querySelectorAll to return a
NodeList. It should have returned an Array. Sounds like people agree
with that then?

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-30 Thread Julien Richard-Foy
On Aug 30, 2011, at 10:33 AM, Jonas Sicking wrote:
 My point was that it was a mistake for querySelectorAll to return a
 NodeList. It should have returned an Array. Sounds like people agree
 with that then?

I think it’s better to return an immutable object (mutable objects are source 
of programming errors). But this immutable object should have traversing method 
(forEach, map, filter, etc.).

Julien.


Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-30 Thread Jonas Sicking
On Tue, Aug 30, 2011 at 2:32 AM, Julien Richard-Foy
jul...@richard-foy.fr wrote:
 On Aug 30, 2011, at 10:33 AM, Jonas Sicking wrote:
 My point was that it was a mistake for querySelectorAll to return a
 NodeList. It should have returned an Array. Sounds like people agree
 with that then?

 I think it’s better to return an immutable object (mutable objects are source 
 of programming errors). But this immutable object should have traversing 
 method (forEach, map, filter, etc.).

Can you explain how mutable objects are a source of programming
errors. It seems that javascript made the choice a log time ago to use
mutable objects and settable variables, as opposed to for example
haskell.

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-30 Thread Julien Richard-Foy
On 30 août 2011, at 18:07, Jonas Sicking jo...@sicking.cc wrote:

 On Tue, Aug 30, 2011 at 2:32 AM, Julien Richard-Foy
 jul...@richard-foy.fr wrote:
 I think it’s better to return an immutable object (mutable objects are 
 source of programming errors). But this immutable object should have 
 traversing method (forEach, map, filter, etc.).
 
 Can you explain how mutable objects are a source of programming
 errors. It seems that javascript made the choice a log time ago to use
 mutable objects and settable variables, as opposed to for example
 haskell.

Sure, have a look to these links:
http://en.m.wikipedia.org/wiki/Immutable_object
http://ofps.oreilly.com/titles/9780596155957/FunctionalProgramming.html

But that's not so important. If you just add traversing methods to NodeList it 
would be a huge improvement.


Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-30 Thread Aryeh Gregor
On Tue, Aug 30, 2011 at 4:33 AM, Jonas Sicking jo...@sicking.cc wrote:
 My point was that it was a mistake for querySelectorAll to return a
 NodeList. It should have returned an Array. Sounds like people agree
 with that then?

I don't have a problem with that, if it can be changed safely.
However, some things do have to return NodeLists, at least if the
returned list is live.  In that case, it's still useful to have the
Array methods available.



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-30 Thread Jonas Sicking
On Tue, Aug 30, 2011 at 2:25 PM, Aryeh Gregor a...@aryeh.name wrote:
 On Tue, Aug 30, 2011 at 4:33 AM, Jonas Sicking jo...@sicking.cc wrote:
 My point was that it was a mistake for querySelectorAll to return a
 NodeList. It should have returned an Array. Sounds like people agree
 with that then?

 I don't have a problem with that, if it can be changed safely.
 However, some things do have to return NodeLists, at least if the
 returned list is live.

Indeed, Arrays can't be returned when live objects are returned.

 In that case, it's still useful to have the
 Array methods available.

Indeed! I think it's already been decided that all non-mutating
functions should be added to NodeLists and other list-like DOM
objects. I believe Cameron is still working on the specifics of that.

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-29 Thread Aryeh Gregor
On Thu, Aug 25, 2011 at 7:17 PM, Jonas Sicking jo...@sicking.cc wrote:
 .push and .pop are generic and work on anything that looks like an
 Array. However they don't work on NodeList because NodeList isn't
 mutable.

 . . .

 None of these are *mutable* functions.

Oh, right.  I misunderstood you.  Yes, obviously we wouldn't expose
things like .push or .pop on NodeList, since they wouldn't make sense.
 But we should expose things like .forEach, etc.  Any reason not to?



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-29 Thread Cameron McCormack

On 30/08/11 4:40 AM, Aryeh Gregor wrote:

Oh, right.  I misunderstood you.  Yes, obviously we wouldn't expose
things like .push or .pop on NodeList, since they wouldn't make sense.
  But we should expose things like .forEach, etc.  Any reason not to?


I should point out that on platform array objects (i.e., the JS objects 
you get from IDL T[] types, and not JS Array objects) can be designated 
as read only but they always have Array.prototype in their prototype 
chain.  push/pop/etc. will just fail or do nothing, depending on whether 
the caller is in strict mode.




Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-26 Thread Julien Richard-Foy
  That works, but what is the advantage? And .push/.pop or other
  mutating functions wouldn't work.
  
  All mutable functions will work (forEach, map, etc.) and bring a better
  expressiveness to the code.
 
 Not if he 'this' object is a NodeList.

Yes, sorry I meant all “immutable” functions will work.

Julien



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-25 Thread Jonas Sicking
On Wed, Aug 24, 2011 at 12:04 PM, Aryeh Gregor a...@aryeh.name wrote:
 On Wed, Aug 24, 2011 at 1:27 PM, Jonas Sicking jo...@sicking.cc wrote:
 I agree with this, but it might be too late to make this change.

 The problem is that if we returned an Array object, it would not have
 a .item function, which the currently returned NodeList has.

 I guess we could return a Array object and add a .item function to it.

 Or return a NodeList and add .forEach/.filter/etc. to it?

That works, but what is the advantage? And .push/.pop or other
mutating functions wouldn't work.

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-25 Thread Julien Richard-Foy

On 25 août 2011, at 08:33, Jonas Sicking jo...@sicking.cc wrote:

 On Wed, Aug 24, 2011 at 12:04 PM, Aryeh Gregor a...@aryeh.name wrote:
 On Wed, Aug 24, 2011 at 1:27 PM, Jonas Sicking jo...@sicking.cc wrote:
 I agree with this, but it might be too late to make this change.
 
 The problem is that if we returned an Array object, it would not have
 a .item function, which the currently returned NodeList has.
 
 I guess we could return a Array object and add a .item function to it.
 
 Or return a NodeList and add .forEach/.filter/etc. to it?
 
 That works, but what is the advantage? And .push/.pop or other
 mutating functions wouldn't work.

All mutable functions will work (forEach, map, etc.) and bring a better 
expressiveness to the code.
 



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-25 Thread Jonas Sicking
On Wed, Aug 24, 2011 at 11:47 PM, Julien Richard-Foy
jul...@richard-foy.fr wrote:

 On 25 août 2011, at 08:33, Jonas Sicking jo...@sicking.cc wrote:

 On Wed, Aug 24, 2011 at 12:04 PM, Aryeh Gregor a...@aryeh.name wrote:
 On Wed, Aug 24, 2011 at 1:27 PM, Jonas Sicking jo...@sicking.cc wrote:
 I agree with this, but it might be too late to make this change.

 The problem is that if we returned an Array object, it would not have
 a .item function, which the currently returned NodeList has.

 I guess we could return a Array object and add a .item function to it.

 Or return a NodeList and add .forEach/.filter/etc. to it?

 That works, but what is the advantage? And .push/.pop or other
 mutating functions wouldn't work.

 All mutable functions will work (forEach, map, etc.) and bring a better 
 expressiveness to the code.

Not if he 'this' object is a NodeList.

/ Jonas



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-25 Thread Aryeh Gregor
On Thu, Aug 25, 2011 at 2:33 AM, Jonas Sicking jo...@sicking.cc wrote:
 That works, but what is the advantage?

The same advantage as having those methods work for Array.  :)
They're useful for lots of stuff.

 And .push/.pop or other mutating functions wouldn't work.

Right.  I'm only talking about the methods that are already generic
and work with anything that looks like an Array: filter, forEach,
every, etc.

On Thu, Aug 25, 2011 at 3:03 AM, Jonas Sicking jo...@sicking.cc wrote:
 On Wed, Aug 24, 2011 at 11:47 PM, Julien Richard-Foy
 jul...@richard-foy.fr wrote:
 All mutable functions will work (forEach, map, etc.) and bring a better 
 expressiveness to the code.

 Not if he 'this' object is a NodeList.

This works fine right now:

alert(
  [].filter.call(document.querySelectorAll(*), function(elem) {
return elem.textContent.length  6 })
  .map(function(elem) { return elem.tagName })
  .join(, )
);

And I use that pattern a *lot*, but it's both verbose and extremely
unintuitive.  Why can't that be just this?

alert(
  document.querySelectorAll(*)
  .filter(function(elem) { return elem.textContent.length  6 })
  .map(function(elem) { return elem.tagName })
  .join(, )
);

Likewise for all Array-like types, but NodeList is the most common.



Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-24 Thread Jonas Sicking
I agree with this, but it might be too late to make this change.

The problem is that if we returned an Array object, it would not have
a .item function, which the currently returned NodeList has.

I guess we could return a Array object and add a .item function to it.

/ Jonas

On Sun, Aug 21, 2011 at 10:52 AM, Julien Richard-Foy
jul...@richard-foy.fr wrote:
 Since Javascript 1.6, a lot of useful collection functions are defined for
 Array [1]. Unfortunately, they can’t be used directly with results returned by
 .querySelectorAll, or even .getElementsByTagName since these functions return
 NodeLists.
 I understand the DOM API is defined without a language in mind, but these
 collection functions are really useful, easy to implement and already
 available in most mainstream languages. Therefore, why not create a base
 Traversable type which would be implemented by all collection types (like
 NodeList) and which would provide the so useful bunch of iteration methods?
 Are there some issues or drawbacks I did not think of?

 Regards,
 Julien

 [1]
 https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array#Iteration_methods






Re: [selectors-api] Return an Array instead of a static NodeList

2011-08-24 Thread Aryeh Gregor
On Sun, Aug 21, 2011 at 1:52 PM, Julien Richard-Foy
jul...@richard-foy.fr wrote:
 Since Javascript 1.6, a lot of useful collection functions are defined for
 Array [1]. Unfortunately, they can’t be used directly with results returned by
 .querySelectorAll, or even .getElementsByTagName since these functions return
 NodeLists.

You can already use these methods with .call() if you want, like:
[].forEach.call(nodeList, fn).  But this is a highly unintuitive hack
-- I don't see why nodeList.forEach(fn) shouldn't work.

 I understand the DOM API is defined without a language in mind, but these
 collection functions are really useful, easy to implement and already
 available in most mainstream languages. Therefore, why not create a base
 Traversable type which would be implemented by all collection types (like
 NodeList) and which would provide the so useful bunch of iteration methods?
 Are there some issues or drawbacks I did not think of?

This sounds like a good idea.  It's not what the subject of your
e-mail says, though (Return an Array instead of a static NodeList).
I think we should keep returning a NodeList, just make it have the
same iteration methods as an Array.

On Wed, Aug 24, 2011 at 1:27 PM, Jonas Sicking jo...@sicking.cc wrote:
 I agree with this, but it might be too late to make this change.

 The problem is that if we returned an Array object, it would not have
 a .item function, which the currently returned NodeList has.

 I guess we could return a Array object and add a .item function to it.

Or return a NodeList and add .forEach/.filter/etc. to it?



[selectors-api] Return an Array instead of a static NodeList

2011-08-23 Thread Julien Richard-Foy
Since Javascript 1.6, a lot of useful collection functions are defined for 
Array [1]. Unfortunately, they can’t be used directly with results returned by 
.querySelectorAll, or even .getElementsByTagName since these functions return 
NodeLists.
I understand the DOM API is defined without a language in mind, but these 
collection functions are really useful, easy to implement and already 
available in most mainstream languages. Therefore, why not create a base 
Traversable type which would be implemented by all collection types (like 
NodeList) and which would provide the so useful bunch of iteration methods? 
Are there some issues or drawbacks I did not think of?

Regards,
Julien

[1] 
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array#Iteration_methods