Re: [selectors-api] Return an Array instead of a static NodeList
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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