Re: What type should .findAll return

2011-11-14 Thread Allen Wirfs-Brock

On Nov 12, 2011, at 12:07 PM, Yehuda Katz wrote:

 
 Yehuda Katz
 (ph) 718.877.1325
 
 
 On Sat, Nov 12, 2011 at 11:51 AM, Allen Wirfs-Brock al...@wirfs-brock.com 
 wrote:
 
 On Nov 12, 2011, at 10:27 AM, Boris Zbarsky wrote:
 
  On 11/13/11 6:10 AM, Allen Wirfs-Brock wrote:
 
 
  I think you're drawing a distinction between language level semantics and 
  library routine behavior which is for practical purposes irrelevant to 
  everyone outside the ES5 committee...
 
 It's relevant to this discussion because you have to decide what web 
 developers actually mean when they say Array.  The starting point was that 
 you want NodeArray to be something more than just an Array.  So you have do 
 look at all aspects of Array behavior and decide which you care about.  The 
 language semantic vs library behavior is relevant because it is often much 
 easer for engine implementers to change or extend library behavior then it is 
 to extend language semantics.
 
 
  In practice, at the moment, if you want something that needs to act like an 
  array as far as a web developer is concerned, it's [[Class]] better be 
  Array.  In the future, as you note, that might change.
 
 The most important point is that [[Class]] is neither the only nor the most 
 important distinguishing characteristic of ECMAScript built-in Arrays.  If 
 you are just arguing about [[Class]] you are missing the point.
 
 I think it's worth noting that [[Class]] is actually used by jQuery and other 
 implementations to identify whether an object is a real Array. It may be 
 the case that we could revisit some of those cases, but the technique of 
 using [[Class]] to get a less buggy picture of what an object is (compared to 
 typeof etc.) is pretty common. We use it in SproutCore as well.
 
 The jQuery.type function:
 https://github.com/jquery/jquery/blob/master/src/core.js#L491-495
 
 The class2type map:
 https://github.com/jquery/jquery/blob/master/src/core.js#L877-879
 
 toString in that function is declared above as Object.prototype.toString.
 
 That said, of course other aspects of the observed behavior, such as its 
 exposed methods, matter as well.

Those functions are not using [[Class]].  They are using the standard 
built-in Object.prototype.toString method.  Now, it so happens that the 
specification of toString makes use of [[Class]] but that is simply an artifact 
of the ES5.1 specification.  It is not a language features.  The technique that 
is used to specify toString can be changed without changing the actual behavior 
of the toString method.  All that is really required that existing ES code that 
depends upon the ES5.1 toString behavior will continue to work without 
modification  in future ES implementations that may use a different 
specification for toString.  However, it doesn'tconstrain future code that 
operates upon new kinds of objects that didn't exist in the ES5.1 specification.

BTW, when the ES5.1 spec. talks about objects whose [[Class]] has a specific 
value. it means precisely such objects as actually specified in the ES5.1 spec. 
[[Class]] is not an implementation extension point.  In particular, ES5.1 
clause 8.6.2 says: 
  The value of the [[Class]] internal property of a host object may be 
any String value except one of Arguments, Array,...

In other words, host object provides (such as a DOM implementation) are not 
allowed to define new kinds of objects whose [[Class]] is Array.

It's fine to want to define a new kind of host object that is behaviorally very 
similar (but slight different) from instances of the built-in Array 
constructor.  But characterizing such objects by saying they have 
[[Class]]==Array
 is a not meaningful from a ES5.1 specification perspective.

Allen

Re: What type should .findAll return

2011-11-14 Thread Rick Waldron

 [snip]



 ES5.1 clause 8.6.2 says:
The value of the [[Class]] internal property of a host object
 may be any String value except one of Arguments, Array,...
  In other words, host object provides (such as a DOM implementation) are
 not allowed to define new kinds of objects whose [[Class]] is Array.
  It's fine to want to define a new kind of host object that is
 behaviorally very similar (but slight different) from instances of the
 built-in Array constructor.  But characterizing such objects by saying they
 have [[Class]]==Array
   is a not meaningful from a ES5.1 specification perspective.

 I'm fine with any formulation, as long as it gives the correct behaviour
 in cases like Array.prototype.concat and Array.isArray.


ES 5.1 15.4.3.2 Array.isArray()
...
2. If the value of the [[Class]] internal property of arg is Array, then
return true.
...

Considering Allen's previous comment, this is not going to be allowed.

Rick



 Do you have suggestions for what to write?

 / Jonas


Re: What type should .findAll return

2011-11-14 Thread Yehuda Katz
It seems as though the spec intends to disallow host objects (i.e. DOM)
from fully acting like an Array, which is clearly the intent here. Perhaps
this is a time for willful disobedience and a correction in ES6?

Yehuda Katz
(ph) 718.877.1325


On Mon, Nov 14, 2011 at 10:46 AM, Rick Waldron waldron.r...@gmail.comwrote:

 [snip]



 ES5.1 clause 8.6.2 says:
The value of the [[Class]] internal property of a host
 object may be any String value except one of Arguments, Array,...
  In other words, host object provides (such as a DOM implementation) are
 not allowed to define new kinds of objects whose [[Class]] is Array.
  It's fine to want to define a new kind of host object that is
 behaviorally very similar (but slight different) from instances of the
 built-in Array constructor.  But characterizing such objects by saying they
 have [[Class]]==Array
   is a not meaningful from a ES5.1 specification perspective.

 I'm fine with any formulation, as long as it gives the correct behaviour
 in cases like Array.prototype.concat and Array.isArray.


 ES 5.1 15.4.3.2 Array.isArray()
 ...
 2. If the value of the [[Class]] internal property of arg is Array, then
 return true.
 ...

  Considering Allen's previous comment, this is not going to be allowed.

 Rick



 Do you have suggestions for what to write?

 / Jonas





Re: What type should .findAll return

2011-11-14 Thread Brendan Eich
On Nov 14, 2011, at 3:13 PM, Yehuda Katz wrote:

 It seems as though the spec intends to disallow host objects (i.e. DOM) from 
 fully acting like an Array, which is clearly the intent here. Perhaps this is 
 a time for willful disobedience and a correction in ES6?

Calm down -- this confrontational style is unjustified.

The spec cannot deal in non-observables. DOM host objects in most 
implementations are full of methods, which really are native function objects. 
But it's always possible to implement a work-alike. So long as a host array 
follows the contract in every observable way, no problem.

What's at issue is the abuse of internal methods defined only for spec-internal 
purposes as arbitrary plugin APIs by other specs. That's where negotiation 
and future-proofing are needed.

/be

 
 Yehuda Katz
 (ph) 718.877.1325
 
 
 On Mon, Nov 14, 2011 at 10:46 AM, Rick Waldron waldron.r...@gmail.com wrote:
 [snip]
  
 ES5.1 clause 8.6.2 says: 
The value of the [[Class]] internal property of a host object 
  may be any String value except one of Arguments, Array,...
  In other words, host object provides (such as a DOM implementation) are not 
  allowed to define new kinds of objects whose [[Class]] is Array.
  It's fine to want to define a new kind of host object that is behaviorally 
  very similar (but slight different) from instances of the built-in Array 
  constructor.  But characterizing such objects by saying they have 
  [[Class]]==Array
   is a not meaningful from a ES5.1 specification perspective.
 
 I'm fine with any formulation, as long as it gives the correct behaviour in 
 cases like Array.prototype.concat and Array.isArray.
 
 ES 5.1 15.4.3.2 Array.isArray()  
 ...
 2. If the value of the [[Class]] internal property of arg is Array, then 
 return true.
 ...
 
 Considering Allen's previous comment, this is not going to be allowed.
 
 Rick
  
 
 Do you have suggestions for what to write?
 
 / Jonas
 
 



Re: What type should .findAll return

2011-11-14 Thread Yehuda Katz
Sorry,

I was making a joke (referencing 1.5.2 of the HTML5 spec), not intending to
be confrontational.

The underlying issue here is just making it possible for Array.isArray to
return true for an Array of DOM nodes that is also enhanced with extra
features. Jonas had specifically said that he wanted isArray to work. Rick
then pointed out that the spec seems to disallow host objects from claiming
that their [[Class]] is Array, and that isArray specifically requires that
[[Class]] be Array.

I apologize again for my in-jest comment.

Yehuda Katz
(ph) 718.877.1325


On Mon, Nov 14, 2011 at 3:23 PM, Brendan Eich bren...@mozilla.org wrote:

 On Nov 14, 2011, at 3:13 PM, Yehuda Katz wrote:

 It seems as though the spec intends to disallow host objects (i.e. DOM)
 from fully acting like an Array, which is clearly the intent here. Perhaps
 this is a time for willful disobedience and a correction in ES6?


 Calm down -- this confrontational style is unjustified.

 The spec cannot deal in non-observables. DOM host objects in most
 implementations are full of methods, which really are native function
 objects. But it's always possible to implement a work-alike. So long as a
 host array follows the contract in every observable way, no problem.

 What's at issue is the abuse of internal methods defined only for
 spec-internal purposes as arbitrary plugin APIs by other specs. That's
 where negotiation and future-proofing are needed.

 /be


 Yehuda Katz
 (ph) 718.877.1325


 On Mon, Nov 14, 2011 at 10:46 AM, Rick Waldron waldron.r...@gmail.comwrote:

 [snip]



 ES5.1 clause 8.6.2 says:
The value of the [[Class]] internal property of a host
 object may be any String value except one of Arguments, Array,...
  In other words, host object provides (such as a DOM implementation)
 are not allowed to define new kinds of objects whose [[Class]] is Array.
  It's fine to want to define a new kind of host object that is
 behaviorally very similar (but slight different) from instances of the
 built-in Array constructor.  But characterizing such objects by saying they
 have [[Class]]==Array
   is a not meaningful from a ES5.1 specification perspective.

 I'm fine with any formulation, as long as it gives the correct behaviour
 in cases like Array.prototype.concat and Array.isArray.


 ES 5.1 15.4.3.2 Array.isArray()
 ...
 2. If the value of the [[Class]] internal property of arg is Array,
 then return true.
 ...

  Considering Allen's previous comment, this is not going to be allowed.

 Rick



 Do you have suggestions for what to write?

 / Jonas







Re: What type should .findAll return

2011-11-14 Thread Brendan Eich
On Nov 14, 2011, at 3:32 PM, Yehuda Katz wrote:

 Sorry,
 
 I was making a joke (referencing 1.5.2 of the HTML5 spec), not intending to 
 be confrontational.

Ah, I get it -- indeed such deviations were one of the reasons for creating 
public-script-coord.

SO I get it but I didn't lul. :-|


 The underlying issue here is just making it possible for Array.isArray to 
 return true for an Array of DOM nodes that is also enhanced with extra 
 features. Jonas had specifically said that he wanted isArray to work. Rick 
 then pointed out that the spec seems to disallow host objects from claiming 
 that their [[Class]] is Array, and that isArray specifically requires that 
 [[Class]] be Array.

We need to get this right in the future. It's a tricky issue. But even now I 
would say that if there's no observable difference, there is no problem. Allen 
should weigh in.

/be


 
 I apologize again for my in-jest comment.
 
 Yehuda Katz
 (ph) 718.877.1325
 
 
 On Mon, Nov 14, 2011 at 3:23 PM, Brendan Eich bren...@mozilla.org wrote:
 On Nov 14, 2011, at 3:13 PM, Yehuda Katz wrote:
 
 It seems as though the spec intends to disallow host objects (i.e. DOM) from 
 fully acting like an Array, which is clearly the intent here. Perhaps this 
 is a time for willful disobedience and a correction in ES6?
 
 Calm down -- this confrontational style is unjustified.
 
 The spec cannot deal in non-observables. DOM host objects in most 
 implementations are full of methods, which really are native function 
 objects. But it's always possible to implement a work-alike. So long as a 
 host array follows the contract in every observable way, no problem.
 
 What's at issue is the abuse of internal methods defined only for 
 spec-internal purposes as arbitrary plugin APIs by other specs. That's 
 where negotiation and future-proofing are needed.
 
 /be
 
 
 Yehuda Katz
 (ph) 718.877.1325
 
 
 On Mon, Nov 14, 2011 at 10:46 AM, Rick Waldron waldron.r...@gmail.com 
 wrote:
 [snip]
  
 ES5.1 clause 8.6.2 says: 
The value of the [[Class]] internal property of a host object 
  may be any String value except one of Arguments, Array,...
  In other words, host object provides (such as a DOM implementation) are 
  not allowed to define new kinds of objects whose [[Class]] is Array.
  It's fine to want to define a new kind of host object that is behaviorally 
  very similar (but slight different) from instances of the built-in Array 
  constructor.  But characterizing such objects by saying they have 
  [[Class]]==Array
   is a not meaningful from a ES5.1 specification perspective.
 
 I'm fine with any formulation, as long as it gives the correct behaviour in 
 cases like Array.prototype.concat and Array.isArray.
 
 ES 5.1 15.4.3.2 Array.isArray()  
 ...
 2. If the value of the [[Class]] internal property of arg is Array, then 
 return true.
 ...
 
 Considering Allen's previous comment, this is not going to be allowed.
 
 Rick
  
 
 Do you have suggestions for what to write?
 
 / Jonas
 
 
 
 



Re: What type should .findAll return

2011-11-14 Thread Yehuda Katz
Yehuda Katz
(ph) 718.877.1325


On Mon, Nov 14, 2011 at 3:49 PM, Brendan Eich bren...@mozilla.org wrote:

 On Nov 14, 2011, at 3:32 PM, Yehuda Katz wrote:

 Sorry,

 I was making a joke (referencing 1.5.2 of the HTML5 spec), not intending
 to be confrontational.


 Ah, I get it -- indeed such deviations were one of the reasons for
 creating public-script-coord.

 SO I get it but I didn't lul. :-|


 The underlying issue here is just making it possible for Array.isArray to
 return true for an Array of DOM nodes that is also enhanced with extra
 features. Jonas had specifically said that he wanted isArray to work. Rick
 then pointed out that the spec seems to disallow host objects from claiming
 that their [[Class]] is Array, and that isArray specifically requires that
 [[Class]] be Array.


 We need to get this right in the future. It's a tricky issue. But even now
 I would say that if there's no observable difference, there is no problem.
 Allen should weigh in.


One observable difference between this object and an Array (at least under
Jonas' proposal) would be that:

Object.getPrototypeOf(Object.getPrototypeOf(arrayOfNodes)) would be the
inserted DOM list prototype, while
Object.getPrototypeOf(Object.getPrototypeOf(regularArray)) would be
Object.prototype

It would be possible to mask this behavior, but masking it and also making
it possible to extend the DOM list prototype would be weird, no?


 /be



 I apologize again for my in-jest comment.

 Yehuda Katz
 (ph) 718.877.1325


 On Mon, Nov 14, 2011 at 3:23 PM, Brendan Eich bren...@mozilla.org wrote:

 On Nov 14, 2011, at 3:13 PM, Yehuda Katz wrote:

 It seems as though the spec intends to disallow host objects (i.e. DOM)
 from fully acting like an Array, which is clearly the intent here. Perhaps
 this is a time for willful disobedience and a correction in ES6?


 Calm down -- this confrontational style is unjustified.

 The spec cannot deal in non-observables. DOM host objects in most
 implementations are full of methods, which really are native function
 objects. But it's always possible to implement a work-alike. So long as a
 host array follows the contract in every observable way, no problem.

 What's at issue is the abuse of internal methods defined only for
 spec-internal purposes as arbitrary plugin APIs by other specs. That's
 where negotiation and future-proofing are needed.

 /be


 Yehuda Katz
 (ph) 718.877.1325


 On Mon, Nov 14, 2011 at 10:46 AM, Rick Waldron waldron.r...@gmail.comwrote:

 [snip]



 ES5.1 clause 8.6.2 says:
The value of the [[Class]] internal property of a host
 object may be any String value except one of Arguments, Array,...
  In other words, host object provides (such as a DOM implementation)
 are not allowed to define new kinds of objects whose [[Class]] is Array.
  It's fine to want to define a new kind of host object that is
 behaviorally very similar (but slight different) from instances of the
 built-in Array constructor.  But characterizing such objects by saying they
 have [[Class]]==Array
   is a not meaningful from a ES5.1 specification perspective.

 I'm fine with any formulation, as long as it gives the correct
 behaviour in cases like Array.prototype.concat and Array.isArray.


 ES 5.1 15.4.3.2 Array.isArray()
 ...
 2. If the value of the [[Class]] internal property of arg is Array,
 then return true.
 ...

  Considering Allen's previous comment, this is not going to be allowed.

 Rick



 Do you have suggestions for what to write?

 / Jonas









Re: What type should .findAll return

2011-11-14 Thread Allen Wirfs-Brock

On Nov 14, 2011, at 3:32 PM, Yehuda Katz wrote:

 Sorry,
 
 I was making a joke (referencing 1.5.2 of the HTML5 spec), not intending to 
 be confrontational.
 
 The underlying issue here is just making it possible for Array.isArray to 
 return true for an Array of DOM nodes that is also enhanced with extra 
 features. Jonas had specifically said that he wanted isArray to work. Rick 
 then pointed out that the spec seems to disallow host objects from claiming 
 that their [[Class]] is Array, and that isArray specifically requires that 
 [[Class]] be Array.

Ultimate you have to decide what it is you are asking for.  It been stated that 
you (DOM API designers) want this kind of object to be a real ECMAScript Array. 
 But you also want to deviate from some aspects of what it currently means to 
be an a real ECMAScript array.  A real ECMAscript Array has a specific 
[[Prototype]] value.  It also has specific behaviors for methods like concat 
and filter and other specific distinguishing behavioral characteristics all of 
which are defined in the ES5.1 spec.   If you change any of those for some 
object,  it is something other than a real ECMAScript Array.

Array.isArray was introduced into ES5 to provide an API for testing whether or 
not an object actually was a real ECMAScript Array as defined by section 15.4 
of the ES5 spec.  If Array.isArray starts answering  true for objects that 
aren't described by 15.4 then it ls no longer useful for its intended purpose.  

The language in 8.6.2 limiting host object use of certain class values is to 
ensure that host objects can't define things that violate important invariant 
about the inner workings of ECMAScript.  

Nobody is saying that it isn't useful to define new objects (host or otherwise) 
that share some (but not all) of the characteristics of ECMAScript Arrays.  
However, such object's aren't just  ECMAScript array as defined by 15.4 so 
don't expect Array.isArray to work for them.  Perhaps other discriminators are 
needed but we will all need to decide which specific subset of Array 
characteristics we want to discriminate. 

TC39 recognizes that ES needs better support for defining collections, 
including variants of Array.  This includes supporting both better collections 
defined in ES code and via host objects   (in general, TC39 don't like 
designs that depend uopn a host object being able to do something that can't be 
done only using ES code). We have features to support better collection 
definition in advanced stages of design for ES6.   Some of these features 
might be accelerated into implementation ahead of the completion of ES6.  
However, I'm not sure you would want to normatively specify a DOM feature that 
depended upon them. Maybe you could...

For right now, there are two ways you could quickly go that don't conflict with 
ES5.1 at all:

1) you can specify that .findAll returns a plain vanilla ECMAScript Array 
object.
2) you can define a new kind of host object that is a close approximation of a 
real ECMAScript Array object.  Such an object could indirectly inherit from 
Array.prototype, over-ride some inherited methods (such as concat and filter), 
and define additional DOM related methods.  However, its [[Class]] may not be 
Array and anything in the ES spec that requires [[Class]]===Array (such as 
Array.isArray) won't recognize it as an anything special.

We can work together on something between these two extremes but the further 
away from them we go the more we get into the land of ES6 features and the 
problem of how to advance them into current engines.

Allen


RE: What type should .findAll return

2011-11-14 Thread Travis Leithead
From: Allen Wirfs-Brock [mailto:al...@wirfs-brock.com] 
Sent: Monday, November 14, 2011 6:12 PM
 For right now, there are two ways you could quickly go that don't conflict 
 with ES5.1 at all:
 
 1) you can specify that .findAll returns a plain vanilla ECMAScript Array 
 object.
 2) you can define a new kind of host object that is a close approximation of 
 a real ECMAScript Array object.  Such an object could indirectly inherit from 
 Array.prototype, over-ride some inherited methods (such as concat and 
 filter), and define additional DOM related methods.  However, its [[Class]] 
 may not be Array and anything in the ES spec that requires 
 [[Class]]===Array (such as Array.isArray) won't recognize it as an anything 
 special.


This might be my simplified view of things, but have we just circled back 
around to the two definitions that Cameron already has in WebIDL [1]?
* 3.9.18 Sequences - sequenceT are the corollary of #1 above (plain-old JS 
arrays)
* 3.9.19 Arrays - T[] are the corollary of #2 above; array-like and even are 
participate in the Array.prototype chain. 

In section 4.2.20, the following note outlines the difference between the 
so-called platform array object and a vanilla JS array:

Note
Platform array objects differ from Array objects in the following ways: 
 - they are never sparse
 - their elements are always data properties
 - an ECMAScript-to-IDL value conversion is always performed when storing an 
element
 - their internal [[Class]] property value is different
 - their internal [[Extensible]] property value is always true

Can we pick one of these as a starting point for .find()/.findAll()? For 
consistency with other DOM APIs, I personally see the platform array object as 
the way forward.

[1] http://dev.w3.org/2006/webapi/WebIDL/#idl-sequence




Re: What type should .findAll return

2011-11-12 Thread Yehuda Katz
I'd like to see this thing smell like a normal Array, plus useful node
methods:

1. It should have at least all of the non-mutating Array methods on
 it. Possibly the mutating methods too if we allow the returned object
 to be mutable.


Agreed.


 2. It should have a object on the prototype chain where we can insert
 functions that are specifically useful for lists of nodes. Examples
 include .find/.findAll/.matchesSelector/.remove/.addEventListener


It would be nice if it also had getElementsBy*. This object (ElementList?)
could be a beachhead allowing us to add more useful functionality to lists
of elements in the browser over time.

Since this is a totally new API, we're also not bound by the API for
individual nodes, so we could use shorter names, like .is() for
matchesSelector() and .on() for addEventListener.


 3. It would be good if it had the Array prototype object on it's
 prototype chain so that if Array.prototype was extended, it would
 affect this object too.


Absolutely.


 4. The object will *not* be live since live results from selector
 matching is slow.


Agreed.

Yehuda Katz
(ph) 718.877.1325


On Fri, Nov 11, 2011 at 6:04 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Fri, Nov 11, 2011 at 5:59 PM, Tab Atkins Jr. jackalm...@gmail.com
 wrote:
  On Fri, Nov 11, 2011 at 5:52 PM, Rick Waldron waldron.r...@gmail.com
 wrote:
  Right, but I'm saying: why create yet more stuff in the DOM?
 
   findAll will return a NodeArray while querySelectorAll and friends
 return static and live NodeLists? No thanks.
 
  I'm not sure what you would prefer.  Make findAll return an Array? (We
  miss out on a *lot* of cool and useful stuff we could do.)  Make
  findAll return immutable live NodeLists? (Ditto, but for different
  reasons.)  Change qSA to return a NodeArray or Array? (Would be nice,
  but probably not doable for compat reasons.)

 Actually, if we add .item to NodeArray then it's entirely possible
 that we can make qSA return a NodeArray. I'm not entirely convinced
 that's worth it though.

 / Jonas




Re: What type should .findAll return

2011-11-12 Thread Boris Zbarsky

On 11/12/11 10:22 AM, Allen Wirfs-Brock wrote:

Note that the only specialness of Array instances relates to what happens when you add 
new array elements or dynamically change the value of the length property.


1)  In ES5 this is just not true; there are various parts of the spec 
that check [[Class]].  Yes, I know we're working on getting rid of them, 
but we haven't gotten to that future world yet.


2)  In implementations the above may or may not be true.


So, if you want the objects to be an immutable, array-like object that inherits 
from array.prototype through an intermediate prototype there really is no 
problem.  A JS programmer could express this today in ES5:

var DOMFindResultProto = Object.create(Array.prototype);  //make it inherit 
from Object.prototype
DOMFondResultProto.someMethod = function O() { ...};
//other prototype methods
//...

function FindResultFactory(nodes) {
var obj = Object.create(DOMFindResultProto);
for (var i=0; inodes.length;++i) obj[i]=nodes[i];
return Object.freeze(obj);
}


The result will not have the same performance characteristics as an 
actual array in many of today's JITs, for what it's worth.  You can 
consider this a bug in those JITs, of course.


-Boris



Re: What type should .findAll return

2011-11-12 Thread Allen Wirfs-Brock

On Nov 12, 2011, at 1:29 AM, Boris Zbarsky wrote:

 On 11/12/11 10:22 AM, Allen Wirfs-Brock wrote:
 Note that the only specialness of Array instances relates to what happens 
 when you add new array elements or dynamically change the value of the 
 length property.
 
 1)  In ES5 this is just not true; there are various parts of the spec that 
 check [[Class]].  Yes, I know we're working on getting rid of them, but we 
 haven't gotten to that future world yet.

Class related distinctions are covered in the document I reference: 
https://docs.google.com/document/d/1sSUtri6joyOOh23nVDfMbs1wDS7iDMDUFVVeHeRdSIw/edit?authkey=CI-FopgC
 and are generally secondary issues related to various library routines.  For 
example, whether JSON outputs the properties of an object using [ ] or { }. 
Notation. The only language level semantic specialness of Array is related to 
the length invarian
 
 2)  In implementations the above may or may not be true.

If it isn't the implementation are out of conformance with the standard that 
applies to them.  That means they are buggy and should be fixed.

 
 So, if you want the objects to be an immutable, array-like object that 
 inherits from array.prototype through an intermediate prototype there really 
 is no problem.  A JS programmer could express this today in ES5:
 
 var DOMFindResultProto = Object.create(Array.prototype);  //make it inherit 
 from Object.prototype
 DOMFondResultProto.someMethod = function O() { ...};
 //other prototype methods
 //...
 
 function FindResultFactory(nodes) {
var obj = Object.create(DOMFindResultProto);
for (var i=0; inodes.length;++i) obj[i]=nodes[i];
return Object.freeze(obj);
 }
 
 The result will not have the same performance characteristics as an actual 
 array in many of today's JITs, for what it's worth.  You can consider this a 
 bug in those JITs, of course.

It's an expected variance on optimization strategies that I don't think is 
particularly relevent to this discussion.  BTW, an equally valid statement 
would be: the result will have the same performance characteristics as an 
actual array in many of todays JITs that optimize all integer-indexed 
properties, regardless of whether or not an object is an actual Array instance.

Allen




Re: What type should .findAll return

2011-11-12 Thread Boris Zbarsky

On 11/13/11 6:10 AM, Allen Wirfs-Brock wrote:

Class related distinctions are covered in the document I reference:
https://docs.google.com/document/d/1sSUtri6joyOOh23nVDfMbs1wDS7iDMDUFVVeHeRdSIw/edit?authkey=CI-FopgC
and are generally secondary issues related to various library routines.


Yes, I'm well aware.


For example, whether JSON outputs the properties of an object using [ ]
or { }. Notation. The only language level semantic specialness of Array
is related to the length invarian


I think you're drawing a distinction between language level semantics 
and library routine behavior which is for practical purposes 
irrelevant to everyone outside the ES5 committee...


In practice, at the moment, if you want something that needs to act like 
an array as far as a web developer is concerned, it's [[Class]] better 
be Array.  In the future, as you note, that might change.



If it isn't the implementation are out of conformance with the standard
that applies to them. That means they are buggy and should be fixed.


The standard does not specify many aspects of implementation behavior, 
including but not limited to performance characteristics.  However, to 
language _consumers_ (e.g. web developers) those 
not-specified-in-the-standard aspects are still part of what it means to 
be an array.


It seems to me that there is a serious disconnect here between the way 
people are thinking about the standard for arrays and the simple it 
needs to act just like an array in all observable ways request from web 
developers.


For purposes of the ES spec, all that matters is the precise 
specification of arrays.  For purposes of web developers and web specs 
trying to return array-like objects, these things the standard doesn't 
care about matter.



It's an expected variance on optimization strategies that I don't think
is particularly relevent to this discussion.


See above.  It's 100% relevant to the public-webapps aspects of this 
discussion.



BTW, an equally valid
statement would be: the result will have the same performance
characteristics as an actual array in many of todays JITs that optimize
all integer-indexed properties, regardless of whether or not an object
is an actual Array instance.


Sure.  So?

-Boris





Re: What type should .findAll return

2011-11-12 Thread Allen Wirfs-Brock

On Nov 12, 2011, at 10:27 AM, Boris Zbarsky wrote:

 On 11/13/11 6:10 AM, Allen Wirfs-Brock wrote:
 
 
 I think you're drawing a distinction between language level semantics and 
 library routine behavior which is for practical purposes irrelevant to 
 everyone outside the ES5 committee...

It's relevant to this discussion because you have to decide what web 
developers actually mean when they say Array.  The starting point was that 
you want NodeArray to be something more than just an Array.  So you have do 
look at all aspects of Array behavior and decide which you care about.  The 
language semantic vs library behavior is relevant because it is often much 
easer for engine implementers to change or extend library behavior then it is 
to extend language semantics.

 
 In practice, at the moment, if you want something that needs to act like an 
 array as far as a web developer is concerned, it's [[Class]] better be 
 Array.  In the future, as you note, that might change.

The most important point is that [[Class]] is neither the only nor the most 
important distinguishing characteristic of ECMAScript built-in Arrays.  If you 
are just arguing about [[Class]] you are missing the point.
 
 If it isn't the implementation are out of conformance with the standard
 that applies to them. That means they are buggy and should be fixed.
 
 The standard does not specify many aspects of implementation behavior, 
 including but not limited to performance characteristics.

Such as??  While there are still non-performance aspects  of implementation 
that are not yet fully specified we are working hard to eliminate (or at least 
minimize them).  WRT Array, other than performance (including space efficiency) 
and some aspects of the sort function, what do you think isn't fully specified 
in ES5.1?  I want to know so I can fix that in ES6

 However, to language _consumers_ (e.g. web developers) those 
 not-specified-in-the-standard aspects are still part of what it means to be 
 an array.

What are they? Really TC39 doesn't want to have such aspects.

 
 It seems to me that there is a serious disconnect here between the way people 
 are thinking about the standard for arrays and the simple it needs to act 
 just like an array in all observable ways request from web developers.

all observable ways means no methods that aren't already on Array.prototype.  
I might think if would be fine for .findAll to just return an actual Array 
instance.  But others seem to want to augment that behavior so all observable 
ways does not seem to apply.

 
 For purposes of the ES spec, all that matters is the precise specification of 
 arrays.  For purposes of web developers and web specs trying to return 
 array-like objects, these things the standard doesn't care about matter.

I have to say that I think you are totally mischaracterizing the ES spec and 
the position of TC39.  I don't understand why?
 
 
 It's an expected variance on optimization strategies that I don't think
 is particularly relevent to this discussion.
 
 See above.  It's 100% relevant to the public-webapps aspects of this 
 discussion.

Still not clear,  are you saying that all implementation are expect to apply 
the same optimizations?  That clearly isn't the case today.

 
 BTW, an equally valid
 statement would be: the result will have the same performance
 characteristics as an actual array in many of todays JITs that optimize
 all integer-indexed properties, regardless of whether or not an object
 is an actual Array instance.
 
 Sure.  So? 

You bought of this implementation specific performance point, for some reason.  
I'm just pointing out that your argument goes both ways.  Personally, it sounds 
to me like design by premature optimization.

Allen


Re: What type should .findAll return

2011-11-12 Thread Yehuda Katz
Yehuda Katz
(ph) 718.877.1325


On Sat, Nov 12, 2011 at 11:51 AM, Allen Wirfs-Brock
al...@wirfs-brock.comwrote:


 On Nov 12, 2011, at 10:27 AM, Boris Zbarsky wrote:

  On 11/13/11 6:10 AM, Allen Wirfs-Brock wrote:
 
 
  I think you're drawing a distinction between language level semantics
 and library routine behavior which is for practical purposes irrelevant
 to everyone outside the ES5 committee...

 It's relevant to this discussion because you have to decide what web
 developers actually mean when they say Array.  The starting point was
 that you want NodeArray to be something more than just an Array.  So you
 have do look at all aspects of Array behavior and decide which you care
 about.  The language semantic vs library behavior is relevant because it is
 often much easer for engine implementers to change or extend library
 behavior then it is to extend language semantics.

 
  In practice, at the moment, if you want something that needs to act like
 an array as far as a web developer is concerned, it's [[Class]] better be
 Array.  In the future, as you note, that might change.

 The most important point is that [[Class]] is neither the only nor the
 most important distinguishing characteristic of ECMAScript built-in Arrays.
  If you are just arguing about [[Class]] you are missing the point.


I think it's worth noting that [[Class]] is actually used by jQuery and
other implementations to identify whether an object is a real Array. It
may be the case that we could revisit some of those cases, but the
technique of using [[Class]] to get a less buggy picture of what an object
is (compared to typeof etc.) is pretty common. We use it in SproutCore as
well.

The jQuery.type function:
https://github.com/jquery/jquery/blob/master/src/core.js#L491-495

The class2type map:
https://github.com/jquery/jquery/blob/master/src/core.js#L877-879

toString in that function is declared above as Object.prototype.toString.

That said, of course other aspects of the observed behavior, such as its
exposed methods, matter as well.


  If it isn't the implementation are out of conformance with the standard
  that applies to them. That means they are buggy and should be fixed.
 
  The standard does not specify many aspects of implementation behavior,
 including but not limited to performance characteristics.

 Such as??  While there are still non-performance aspects  of
 implementation that are not yet fully specified we are working hard to
 eliminate (or at least minimize them).  WRT Array, other than performance
 (including space efficiency) and some aspects of the sort function, what do
 you think isn't fully specified in ES5.1?  I want to know so I can fix that
 in ES6

  However, to language _consumers_ (e.g. web developers) those
 not-specified-in-the-standard aspects are still part of what it means to
 be an array.

 What are they? Really TC39 doesn't want to have such aspects.

 
  It seems to me that there is a serious disconnect here between the way
 people are thinking about the standard for arrays and the simple it needs
 to act just like an array in all observable ways request from web
 developers.

 all observable ways means no methods that aren't already on
 Array.prototype.  I might think if would be fine for .findAll to just
 return an actual Array instance.  But others seem to want to augment that
 behavior so all observable ways does not seem to apply.

 
  For purposes of the ES spec, all that matters is the precise
 specification of arrays.  For purposes of web developers and web specs
 trying to return array-like objects, these things the standard doesn't care
 about matter.

 I have to say that I think you are totally mischaracterizing the ES spec
 and the position of TC39.  I don't understand why?
 
 
  It's an expected variance on optimization strategies that I don't think
  is particularly relevent to this discussion.
 
  See above.  It's 100% relevant to the public-webapps aspects of this
 discussion.

 Still not clear,  are you saying that all implementation are expect to
 apply the same optimizations?  That clearly isn't the case today.

 
  BTW, an equally valid
  statement would be: the result will have the same performance
  characteristics as an actual array in many of todays JITs that optimize
  all integer-indexed properties, regardless of whether or not an object
  is an actual Array instance.
 
  Sure.  So?

 You bought of this implementation specific performance point, for some
 reason.  I'm just pointing out that your argument goes both ways.
  Personally, it sounds to me like design by premature optimization.

 Allen



Re: What type should .findAll return

2011-11-12 Thread Boris Zbarsky

On 11/13/11 8:51 AM, Allen Wirfs-Brock wrote:

It's relevant to this discussion because you have to decide what web developers 
actually mean when they say Array.


Yes, agreed.


The most important point is that [[Class]] is neither the only nor the most 
important distinguishing characteristic of ECMAScript built-in Arrays.


Agreed on the former; I don't think it matters that much how important 
it is.  It's just a distinguishing characteristic, period.



The standard does not specify many aspects of implementation behavior, 
including but not limited to performance characteristics.


Such as??  While there are still non-performance aspects  of implementation 
that are not yet fully specified we are working hard to eliminate (or at least 
minimize them).  WRT Array, other than performance (including space efficiency) 
and some aspects of the sort function, what do you think isn't fully specified 
in ES5.1?


For arrays specifically, I believe performance and space are the only 
issues off the top of my head, other than the sort thing you mention.



It seems to me that there is a serious disconnect here between the way people are 
thinking about the standard for arrays and the simple it needs to act just like an 
array in all observable ways request from web developers.


all observable ways means no methods that aren't already on Array.prototype.  I might 
think if would be fine for .findAll to just return an actual Array instance.  But others seem to 
want to augment that behavior so all observable ways does not seem to apply.


Yeah, different people have different definitions of all observable 
ways too... ;)



For purposes of the ES spec, all that matters is the precise specification of 
arrays.  For purposes of web developers and web specs trying to return 
array-like objects, these things the standard doesn't care about matter.


I have to say that I think you are totally mischaracterizing the ES spec and 
the position of TC39.


Unless the ES spec starts mandating something about array performance, I 
don't think I am.  Note that I don't think this is a problem for ES per 
se.  I do think that for the nodelists we're considering here mandating 
that they should perform like arrays do would not be an unreasonable 
requirement on the DOM side.



See above.  It's 100% relevant to the public-webapps aspects of this discussion.


Still not clear,  are you saying that all implementation are expect to apply 
the same optimizations?


I think expecting implementations to apply the same optimizations to 
these lists as to things created with |new Array| would not be 
unreasonable.  These optimizations may differ in different 
implementations, of course.


-Boris




What type should .findAll return

2011-11-11 Thread Jonas Sicking
Hi All,

So, we've debated a lot the exact syntax for .find/.findAll. However I
intentionally requested that we split out the discussions about return
type for .findAll to a separate thread. So I'm starting that thread
here.

There are a few goals for the return'ed object that I've envisioned
based on discussions so far:

1. It should have at least all of the non-mutating Array methods on
it. Possibly the mutating methods too if we allow the returned object
to be mutable.
2. It should have a object on the prototype chain where we can insert
functions that are specifically useful for lists of nodes. Examples
include .find/.findAll/.matchesSelector/.remove/.addEventListener
3. It would be good if it had the Array prototype object on it's
prototype chain so that if Array.prototype was extended, it would
affect this object too.
4. The object will *not* be live since live results from selector
matching is slow.

Since the returned object won't be live, I don't see a reason to make
it immutable. Hence it seems like we could put Array.prototype on the
prototype chain which would immediately make all non-mutating as well
as mutating functions available on the object.

We should also insert a new prototype object in the prototype chain.
Hence we end up with something like:

object - [some type].prototype - Array.prototype - Object.prototype.

And to ensure that the object acts as much as possible as an array it
should also have it's [[Class]] set to that of an array. This has
subtle effects on a number of functions. For example it affects what
Object.toString() and Array.isArray returns, it affects how
Array.concat behaves, and it affects the JSON serializer.

I'm not sure if setting the [[Class]] to that of an array also gives
the object the magical .length property, but if it doesn't, we need to
also define that the returned object has such a property. Note that
for Arrays, .length doesn't live on the prototype chain, but is rather
a special property on the object itself.

In other words, the returned object is exactly what you'd get if you did:

a = new Array;
a.__proto__ = [some type].prototype;
[some type].prototype.__proto__ = Array.prototype;

and then filled a with the set of nodes which matched the selector
passed to .findAll.


So the remaining question is, what should we use for [some type]. One
option is to use NodeList. However this would result in NodeLists
having Array.prototype on it's prototype chain. Including all mutating
functions. This is iffy in general since NodeLists are returned from
several APIs which return objects which represent a live result of a
query. For example .getElementsByTagName, .getElementsByClassName and
.childNodes.

An additional source of iffiness with this idea is that several of the
mutating methods on Array.prototype don't throw if called on a
immutable objects. For example .pop, .shift, .sort and .reverse all
would not throw if called on an empty immutable list.

Hence I propose that we add a new type. I don't care much for naming
things so I'll just suggest NodeArray for now and let others fight it
out over the name.

For now we can leave NodeArray as empty and just let it be an
extension point for page authors. We can discuss separately if
.findAll/.matchesSelector should be added to NodeArray, and if so how
they should behave.

However, we should probably use NodeArray to fix one of the problems
with some of the functions on Array.prototype. For example
Array.prototype.filter always returns a new Array object. This would
mean that:

elem.findAll(...).filter(function(node) { ... });

will return a plain Array and not a NodeArray. However we could make
NodeArray override all such functions and keep their behavior
identical except that they return NodeArrays.

Another way to fix this problem would be to change the definition of
Array.prototype.filter, but I have no idea if that's doable, or how
that would be done.


What do people think?

/ Jonas



Re: What type should .findAll return

2011-11-11 Thread Jake Verbaten
As a web developer, having DOM methods which return real arrays so we no
longer have to call `toArray(nodeList)` or `[].slice.call(nodeList)` would
be awesome.

On Fri, Nov 11, 2011 at 9:05 AM, Jonas Sicking jo...@sicking.cc wrote:

 Hi All,

 So, we've debated a lot the exact syntax for .find/.findAll. However I
 intentionally requested that we split out the discussions about return
 type for .findAll to a separate thread. So I'm starting that thread
 here.

 There are a few goals for the return'ed object that I've envisioned
 based on discussions so far:

 1. It should have at least all of the non-mutating Array methods on
 it. Possibly the mutating methods too if we allow the returned object
 to be mutable.
 2. It should have a object on the prototype chain where we can insert
 functions that are specifically useful for lists of nodes. Examples
 include .find/.findAll/.matchesSelector/.remove/.addEventListener
 3. It would be good if it had the Array prototype object on it's
 prototype chain so that if Array.prototype was extended, it would
 affect this object too.
 4. The object will *not* be live since live results from selector
 matching is slow.

 Since the returned object won't be live, I don't see a reason to make
 it immutable. Hence it seems like we could put Array.prototype on the
 prototype chain which would immediately make all non-mutating as well
 as mutating functions available on the object.

 We should also insert a new prototype object in the prototype chain.
 Hence we end up with something like:

 object - [some type].prototype - Array.prototype - Object.prototype.

 And to ensure that the object acts as much as possible as an array it
 should also have it's [[Class]] set to that of an array. This has
 subtle effects on a number of functions. For example it affects what
 Object.toString() and Array.isArray returns, it affects how
 Array.concat behaves, and it affects the JSON serializer.

 I'm not sure if setting the [[Class]] to that of an array also gives
 the object the magical .length property, but if it doesn't, we need to
 also define that the returned object has such a property. Note that
 for Arrays, .length doesn't live on the prototype chain, but is rather
 a special property on the object itself.

 In other words, the returned object is exactly what you'd get if you did:

 a = new Array;
 a.__proto__ = [some type].prototype;
 [some type].prototype.__proto__ = Array.prototype;

 and then filled a with the set of nodes which matched the selector
 passed to .findAll.


 So the remaining question is, what should we use for [some type]. One
 option is to use NodeList. However this would result in NodeLists
 having Array.prototype on it's prototype chain. Including all mutating
 functions. This is iffy in general since NodeLists are returned from
 several APIs which return objects which represent a live result of a
 query. For example .getElementsByTagName, .getElementsByClassName and
 .childNodes.


Not to mention, that there must be a ton of code out there that assumes a
nodeList is not an array (mediocre feature detection code).



 An additional source of iffiness with this idea is that several of the
 mutating methods on Array.prototype don't throw if called on a
 immutable objects. For example .pop, .shift, .sort and .reverse all
 would not throw if called on an empty immutable list.

 Hence I propose that we add a new type. I don't care much for naming
 things so I'll just suggest NodeArray for now and let others fight it
 out over the name.

 For now we can leave NodeArray as empty and just let it be an
 extension point for page authors. We can discuss separately if
 .findAll/.matchesSelector should be added to NodeArray, and if so how
 they should behave.

 However, we should probably use NodeArray to fix one of the problems
 with some of the functions on Array.prototype. For example
 Array.prototype.filter always returns a new Array object. This would
 mean that:

 elem.findAll(...).filter(function(node) { ... });

 will return a plain Array and not a NodeArray. However we could make
 NodeArray override all such functions and keep their behavior
 identical except that they return NodeArrays.

 Another way to fix this problem would be to change the definition of
 Array.prototype.filter, but I have no idea if that's doable, or how
 that would be done.


That would involve hackling with es-discuss. I send an email to their
mailing list
https://mail.mozilla.org/pipermail/es-discuss/2011-November/018242.html



 What do people think?


overall it's a great idea. It is however a shame we duplicate functionality
with querySelectorAll



 / Jonas




Re: What type should .findAll return

2011-11-11 Thread Tab Atkins Jr.
On Fri, Nov 11, 2011 at 1:05 AM, Jonas Sicking jo...@sicking.cc wrote:
 And to ensure that the object acts as much as possible as an array it
 should also have it's [[Class]] set to that of an array. This has
 subtle effects on a number of functions. For example it affects what
 Object.toString() and Array.isArray returns, it affects how
 Array.concat behaves, and it affects the JSON serializer.

Could you point me to an explanation of what [[Class]] represents in
ecmascript?  It's a little hard to search for.


 Another way to fix this problem would be to change the definition of
 Array.prototype.filter, but I have no idea if that's doable, or how
 that would be done.

I prefer this if possible.


 What do people think?

+1

~TJ



Re: What type should .findAll return

2011-11-11 Thread Bjoern Hoehrmann
* Tab Atkins Jr. wrote:
Could you point me to an explanation of what [[Class]] represents in
ecmascript?  It's a little hard to search for.

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Section 8.6.2. for instance.
-- 
Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/ 



Re: What type should .findAll return

2011-11-11 Thread Jake Verbaten
On Fri, Nov 11, 2011 at 3:46 PM, Tab Atkins Jr. jackalm...@gmail.comwrote:

 On Fri, Nov 11, 2011 at 1:05 AM, Jonas Sicking jo...@sicking.cc wrote:
  And to ensure that the object acts as much as possible as an array it
  should also have it's [[Class]] set to that of an array. This has
  subtle effects on a number of functions. For example it affects what
  Object.toString() and Array.isArray returns, it affects how
  Array.concat behaves, and it affects the JSON serializer.

 Could you point me to an explanation of what [[Class]] represents in
 ecmascript?  It's a little hard to search for.


[[Class]] is simply an internal property
http://es5.github.com/#x8.6.2containing a string like Array,
String, Object, etc. It's mainly
used throughout the ES specification to determine how internal methods
should behave to inputs.

For example JSON.parse http://es5.github.com/#x15.12.2 checks for the
[[Class]] of Array and adjusts the output accordingly. A quick string
search on Array will find you all occurrences of the internals relying on
[[Class]] being set to Array




  Another way to fix this problem would be to change the definition of
  Array.prototype.filter, but I have no idea if that's doable, or how
  that would be done.

 I prefer this if possible.


  What do people think?

 +1

 ~TJ




Re: What type should .findAll return

2011-11-11 Thread Brendan Eich
On Nov 11, 2011, at 1:05 AM, Jonas Sicking wrote:

 Hi All,
 
 So, we've debated a lot the exact syntax for .find/.findAll. However I
 intentionally requested that we split out the discussions about return
 type for .findAll to a separate thread. So I'm starting that thread
 here.
 
 There are a few goals for the return'ed object that I've envisioned
 based on discussions so far:
 
 1. It should have at least all of the non-mutating Array methods on
 it. Possibly the mutating methods too if we allow the returned object
 to be mutable.
 2. It should have a object on the prototype chain where we can insert
 functions that are specifically useful for lists of nodes. Examples
 include .find/.findAll/.matchesSelector/.remove/.addEventListener
 3. It would be good if it had the Array prototype object on it's
 prototype chain so that if Array.prototype was extended, it would
 affect this object too.
 4. The object will *not* be live since live results from selector
 matching is slow.
 
 Since the returned object won't be live, I don't see a reason to make
 it immutable. Hence it seems like we could put Array.prototype on the
 prototype chain which would immediately make all non-mutating as well
 as mutating functions available on the object.
 
 We should also insert a new prototype object in the prototype chain.
 Hence we end up with something like:
 
 object - [some type].prototype - Array.prototype - Object.prototype.
 
 And to ensure that the object acts as much as possible as an array it
 should also have it's [[Class]] set to that of an array.

This is not something to do lightly -- at least cross-post the first message to 
es-disc...@mozilla.org and set reply-to followups-to. Cc'ing Allen.

Note that [[Class]] is going away in ES.next.

The internal methods and properties of ECMA-262 are not arbitrary extension 
points for other specs to use without consultation.

/be


 This has
 subtle effects on a number of functions. For example it affects what
 Object.toString() and Array.isArray returns, it affects how
 Array.concat behaves, and it affects the JSON serializer.
 
 I'm not sure if setting the [[Class]] to that of an array also gives
 the object the magical .length property, but if it doesn't, we need to
 also define that the returned object has such a property. Note that
 for Arrays, .length doesn't live on the prototype chain, but is rather
 a special property on the object itself.
 
 In other words, the returned object is exactly what you'd get if you did:
 
 a = new Array;
 a.__proto__ = [some type].prototype;
 [some type].prototype.__proto__ = Array.prototype;
 
 and then filled a with the set of nodes which matched the selector
 passed to .findAll.
 
 
 So the remaining question is, what should we use for [some type]. One
 option is to use NodeList. However this would result in NodeLists
 having Array.prototype on it's prototype chain. Including all mutating
 functions. This is iffy in general since NodeLists are returned from
 several APIs which return objects which represent a live result of a
 query. For example .getElementsByTagName, .getElementsByClassName and
 .childNodes.
 
 An additional source of iffiness with this idea is that several of the
 mutating methods on Array.prototype don't throw if called on a
 immutable objects. For example .pop, .shift, .sort and .reverse all
 would not throw if called on an empty immutable list.
 
 Hence I propose that we add a new type. I don't care much for naming
 things so I'll just suggest NodeArray for now and let others fight it
 out over the name.
 
 For now we can leave NodeArray as empty and just let it be an
 extension point for page authors. We can discuss separately if
 .findAll/.matchesSelector should be added to NodeArray, and if so how
 they should behave.
 
 However, we should probably use NodeArray to fix one of the problems
 with some of the functions on Array.prototype. For example
 Array.prototype.filter always returns a new Array object. This would
 mean that:
 
 elem.findAll(...).filter(function(node) { ... });
 
 will return a plain Array and not a NodeArray. However we could make
 NodeArray override all such functions and keep their behavior
 identical except that they return NodeArrays.
 
 Another way to fix this problem would be to change the definition of
 Array.prototype.filter, but I have no idea if that's doable, or how
 that would be done.
 
 
 What do people think?
 
 / Jonas
 




Re: What type should .findAll return

2011-11-11 Thread Jonas Sicking
On Fri, Nov 11, 2011 at 10:06 AM, Brendan Eich bren...@mozilla.org wrote:
 On Nov 11, 2011, at 1:05 AM, Jonas Sicking wrote:

 Hi All,

 So, we've debated a lot the exact syntax for .find/.findAll. However I
 intentionally requested that we split out the discussions about return
 type for .findAll to a separate thread. So I'm starting that thread
 here.

 There are a few goals for the return'ed object that I've envisioned
 based on discussions so far:

 1. It should have at least all of the non-mutating Array methods on
 it. Possibly the mutating methods too if we allow the returned object
 to be mutable.
 2. It should have a object on the prototype chain where we can insert
 functions that are specifically useful for lists of nodes. Examples
 include .find/.findAll/.matchesSelector/.remove/.addEventListener
 3. It would be good if it had the Array prototype object on it's
 prototype chain so that if Array.prototype was extended, it would
 affect this object too.
 4. The object will *not* be live since live results from selector
 matching is slow.

 Since the returned object won't be live, I don't see a reason to make
 it immutable. Hence it seems like we could put Array.prototype on the
 prototype chain which would immediately make all non-mutating as well
 as mutating functions available on the object.

 We should also insert a new prototype object in the prototype chain.
 Hence we end up with something like:

 object - [some type].prototype - Array.prototype - Object.prototype.

 And to ensure that the object acts as much as possible as an array it
 should also have it's [[Class]] set to that of an array.

 This is not something to do lightly -- at least cross-post the first message 
 to es-disc...@mozilla.org and set reply-to followups-to. Cc'ing Allen.

 Note that [[Class]] is going away in ES.next.

 The internal methods and properties of ECMA-262 are not arbitrary extension 
 points for other specs to use without consultation.

Yup, that's why i cc'ed public-script-coord.

Note that what I'm suggesting in this thread is to create a real
normal Array. Just one with an extra object inserted in it's
prototype chain.

So if [[Class]] is going away in ES.next that shouldn't be a problem.
Whatever will happen to Arrays when that happens, should happen to
NodeArrays.

The separate issue of making .filter and friends work can be solved in
multiple ways. At least some of which require no changes to
Array.filter if that is preferable from a language point of view.

Granted, it would be nice if Array.filter(elem.findAll(...),
function(element) { ... }) worked too, and that *would* require
changes to ES.

/ Jonas



Re: What type should .findAll return

2011-11-11 Thread Boris Zbarsky

On 11/11/11 10:05 PM, Jonas Sicking wrote:

In other words, the returned object is exactly what you'd get if you did:

a = new Array;
a.__proto__ = [some type].prototype;
[some type].prototype.__proto__ = Array.prototype;


For what it's worth, at least some JITs deoptimize |a| if you do that. 
We'd probably need to do something to make sure that _doesn't_ happen in 
this case, right?


-Boris



Re: What type should .findAll return

2011-11-11 Thread Brendan Eich
On Nov 11, 2011, at 10:44 AM, Jonas Sicking wrote:

 On Fri, Nov 11, 2011 at 10:06 AM, Brendan Eich bren...@mozilla.org wrote:
 On Nov 11, 2011, at 1:05 AM, Jonas Sicking wrote:
 
 And to ensure that the object acts as much as possible as an array it
 should also have it's [[Class]] set to that of an array.
 
 This is not something to do lightly -- at least cross-post the first message 
 to es-disc...@mozilla.org and set reply-to followups-to. Cc'ing Allen.
 
 Note that [[Class]] is going away in ES.next.
 
 The internal methods and properties of ECMA-262 are not arbitrary extension 
 points for other specs to use without consultation.
 
 Yup, that's why i cc'ed public-script-coord.

That's why I'm asking you to cc: es-discuss. I expect Allen will catch up with 
this thread, but you may get more prompt responses from various people by using 
es-discuss for the initial message.


 Note that what I'm suggesting in this thread is to create a real
 normal Array. Just one with an extra object inserted in it's
 prototype chain.

That's not a real normal Array then. Boris mentioned one issue 
(optimization). Let's call it an extended array. ES.next should support 
user-extended arrays via the | operator, so this isn't something bad, but 
it's not exactly an array.


 So if [[Class]] is going away in ES.next that shouldn't be a problem.
 Whatever will happen to Arrays when that happens, should happen to
 NodeArrays.

Allen analyzed how [[Class]] is used in ES1-5, and broke down the cases. Some 
of these change to a different or more generic way of discriminating on 
class. Others still need an internal property. Notable among the latter is 
the string name disclosed by Object.prototype.toString.call(anArray).

The deeper issue for arrays is the custom [[DefineOwnProperty]] (ES5) or 
[[Put]] (ES1-3) that maintains length to be one greater than greatest index 
provided the index is  2^31 - 1.


 The separate issue of making .filter and friends work can be solved in
 multiple ways. At least some of which require no changes to
 Array.filter if that is preferable from a language point of view.

This sounds right.

/be


Re: What type should .findAll return

2011-11-11 Thread Allen Wirfs-Brock

On Nov 11, 2011, at 7:46 AM, Tab Atkins Jr. wrote:

 On Fri, Nov 11, 2011 at 1:05 AM, Jonas Sicking jo...@sicking.cc wrote:
 And to ensure that the object acts as much as possible as an array it
 should also have it's [[Class]] set to that of an array. This has
 subtle effects on a number of functions. For example it affects what
 Object.toString() and Array.isArray returns, it affects how
 Array.concat behaves, and it affects the JSON serializer.
 
 Could you point me to an explanation of what [[Class]] represents in
 ecmascript?  It's a little hard to search for.
 

this turns out to not be such a simple question see 
https://docs.google.com/document/d/1sSUtri6joyOOh23nVDfMbs1wDS7iDMDUFVVeHeRdSIw/edit?authkey=CI-FopgC
 

[[Class]] has been (mis-??)used for many things.  This is why we want to 
cleanup up for the future.

Allen 



Re: What type should .findAll return

2011-11-11 Thread Allen Wirfs-Brock
Note that the only specialness of Array instances relates to what happens when 
you add new array elements or dynamically change the value of the length 
property.

If the array instance is immutable you can't do any of those things so its 
specialness essentially disappears.

So, if you want the objects to be an immutable, array-like object that inherits 
from array.prototype through an intermediate prototype there really is no 
problem.  A JS programmer could express this today in ES5:

var DOMFindResultProto = Object.create(Array.prototype);  //make it inherit 
from Object.prototype
DOMFondResultProto.someMethod = function O() { ...};
//other prototype methods
//...

function FindResultFactory(nodes) {
   var obj = Object.create(DOMFindResultProto);
   for (var i=0; inodes.length;++i) obj[i]=nodes[i];
   return Object.freeze(obj);
}


However, if you want the object to be mutable and to act like a real array, 
then it has to have the array specialness.  The specialness comes, not from the 
[[Class]] property but from its alternative definitions of 
[[DefineOwnProperty]] (see ES5.1 spec. 15.4.5.1).

In ES.next a JS programmer will be able to easily define such an object.  But 
for ES5 it takes special implementation level intervention.Since this 
capability is going to ultimately be in ES.next I don't see why you couldn't do 
it now, assuming the the engine implementors are all willing to cooperate.

Basically, you would specify that the [[Prototype]] of the instances inherits 
from Array.prototype and that the instances use the [[DefineOwnProperty]] 
specification from ES5 section 15.4.5.1.

In either case, you would be specifying a new kind of ES native object rather 
than a host object'.

BTW, I think that either the immutable or mutable approach would work.  
However, since the collection is not live I don't see why you would really 
care whether or not a client mutated it.  If they want to process it by 
deleting elements after they are examined, so what?

Allen






On Nov 11, 2011, at 12:20 PM, Boris Zbarsky wrote:

 On 11/11/11 10:05 PM, Jonas Sicking wrote:
 In other words, the returned object is exactly what you'd get if you did:
 
 a = new Array;
 a.__proto__ = [some type].prototype;
 [some type].prototype.__proto__ = Array.prototype;
 
 For what it's worth, at least some JITs deoptimize |a| if you do that. We'd 
 probably need to do something to make sure that _doesn't_ happen in this 
 case, right?
 
 -Boris
 




Re: What type should .findAll return

2011-11-11 Thread Jonas Sicking
On Fri, Nov 11, 2011 at 1:22 PM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 However, if you want the object to be mutable and to act like a real array, 
 then it has to have the array specialness.  The specialness comes, not from 
 the [[Class]] property but from its alternative definitions of 
 [[DefineOwnProperty]] (see ES5.1 spec. 15.4.5.1).

The Array-like thing discussed in this thread is going to be mutable.

 In ES.next a JS programmer will be able to easily define such an object.  But 
 for ES5 it takes special implementation level intervention.    Since this 
 capability is going to ultimately be in ES.next I don't see why you couldn't 
 do it now, assuming the the engine implementors are all willing to cooperate.

 Basically, you would specify that the [[Prototype]] of the instances inherits 
 from Array.prototype and that the instances use the [[DefineOwnProperty]] 
 specification from ES5 section 15.4.5.1.

 In either case, you would be specifying a new kind of ES native object 
 rather than a host object'.

 BTW, I think that either the immutable or mutable approach would work.  
 However, since the collection is not live I don't see why you would really 
 care whether or not a client mutated it.  If they want to process it by 
 deleting elements after they are examined, so what?

Exactly, this is why I'm proposing that it should be mutable.

This does still leave the problem of making Array.filter(myNodeArray,
function(el) { ... }) work though. I.e. I think we'd like it to
return a NodeArray rather than a plain Array.

More importantly, we want myNodeArray.filter(function(el){ ... }) to
return a NodeArray. This would be doable by putting a special version
of filter on NodeArray.prototype which would shadow
Array.prototype.filter. This would make myNodeArray.filter work, but
not Array.filter.

I'm happy to start a separate thread on es-discuss about this, but I'm
worried that it'll fragment the current thread.

/ Jonas



Re: What type should .findAll return

2011-11-11 Thread Allen Wirfs-Brock

On Nov 11, 2011, at 2:16 PM, Jonas Sicking wrote:

 On Fri, Nov 11, 2011 at 1:22 PM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 
 BTW, I think that either the immutable or mutable approach would work.  
 However, since the collection is not live I don't see why you would really 
 care whether or not a client mutated it.  If they want to process it by 
 deleting elements after they are examined, so what?
 
 Exactly, this is why I'm proposing that it should be mutable.
 
 This does still leave the problem of making Array.filter(myNodeArray,
 function(el) { ... }) work though. I.e. I think we'd like it to
 return a NodeArray rather than a plain Array.

This is a problem for ES=5.  Filter and all the other similar Array.prototype 
functions are specified to produce an object created as if by calling: new 
Array();

I have a scheme that we can probably get in place for ES.next that would allow 
filter and friends to produce NodeArray's for you, but I don't see how that 
helps right now.

 
 More importantly, we want myNodeArray.filter(function(el){ ... }) to
 return a NodeArray. This would be doable by putting a special version
 of filter on NodeArray.prototype which would shadow
 Array.prototype.filter.


It isn't just filter that creates new instances that you would probably want to 
be NodeArrays. Also at least(I might have missed other when I just checkeds): 
concat, slice, splice, map

Over-riding them explicitly for NodeArray would be an immediate fix, but 
wouldn't solve the problem for future additions to Array.prototype.  However, 
if you assume that ES.next is going to provide the needed extension mechanism 
then you should also assume that it will use it for any new Array.prototype 
methods and they should pretty much just work.

 This would make myNodeArray.filter work, but
 not Array.filter.

An inherent problem with this approach. But if your NodeArrays supplies 
correctly working over-rides there is probably little reason somebody would try 
to use the Array.prototype versions  with NodeArrays.

I don't see a way around this short of modifying the specification of the 
Array.prototype methods.  That seems like a job for ES.next rather than a DOM 
spec.

 
 I'm happy to start a separate thread on es-discuss about this, but I'm
 worried that it'll fragment the current thread.

In theory, public-script-coord exists for exactly this sort of discussion and 
the ESdiscuss people who care should be subscripted. Rather than starting a new 
thread, perhaps should should just post to es-discuss a pointer to this thread.

Allen




Re: What type should .findAll return

2011-11-11 Thread Brendan Eich
On Nov 11, 2011, at 3:07 PM, Allen Wirfs-Brock wrote:

 I'm happy to start a separate thread on es-discuss about this, but I'm
 worried that it'll fragment the current thread.
 
 In theory, public-script-coord exists for exactly this sort of discussion and 
 the ESdiscuss people who care should be subscripted. Rather than starting a 
 new thread, perhaps should should just post to es-discuss a pointer to this 
 thread.
 

Turns out (thanks Jake!) we do have an es-discuss thread of interest:

https://mail.mozilla.org/pipermail/es-discuss/2011-November/018242.html

/be




Re: What type should .findAll return

2011-11-11 Thread Jonas Sicking
On Fri, Nov 11, 2011 at 3:07 PM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:

 On Nov 11, 2011, at 2:16 PM, Jonas Sicking wrote:

 On Fri, Nov 11, 2011 at 1:22 PM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:

 BTW, I think that either the immutable or mutable approach would work.  
 However, since the collection is not live I don't see why you would 
 really care whether or not a client mutated it.  If they want to process it 
 by deleting elements after they are examined, so what?

 Exactly, this is why I'm proposing that it should be mutable.

 This does still leave the problem of making Array.filter(myNodeArray,
 function(el) { ... }) work though. I.e. I think we'd like it to
 return a NodeArray rather than a plain Array.

 This is a problem for ES=5.  Filter and all the other similar 
 Array.prototype functions are specified to produce an object created as if by 
 calling: new Array();

 I have a scheme that we can probably get in place for ES.next that would 
 allow filter and friends to produce NodeArray's for you, but I don't see how 
 that helps right now.

Well, if we can get implementations to implement this new scheme for
the existing filter-like functions at the same time as they implement
.findAll, then we should be golden.

 More importantly, we want myNodeArray.filter(function(el){ ... }) to
 return a NodeArray. This would be doable by putting a special version
 of filter on NodeArray.prototype which would shadow
 Array.prototype.filter.


 It isn't just filter that creates new instances that you would probably want 
 to be NodeArrays. Also at least(I might have missed other when I just 
 checkeds): concat, slice, splice, map

Indeed, I was just using filter as an example.

 Over-riding them explicitly for NodeArray would be an immediate fix, but 
 wouldn't solve the problem for future additions to Array.prototype.  However, 
 if you assume that ES.next is going to provide the needed extension mechanism 
 then you should also assume that it will use it for any new Array.prototype 
 methods and they should pretty much just work.

Indeed. If we went down this path we would have to continuously update
the spec to make NodeArray override any filter-like methods that are
added to Array.

 This would make myNodeArray.filter work, but
 not Array.filter.

 An inherent problem with this approach. But if your NodeArrays supplies 
 correctly working over-rides there is probably little reason somebody would 
 try to use the Array.prototype versions  with NodeArrays.

Note that I was saying Array.filter and not Array.prototype.filter. My
assumption was that if people call Array.prototype with an Array as
the first argument, they would also do so with a NodeArray as first
argument.

 I don't see a way around this short of modifying the specification of the 
 Array.prototype methods.  That seems like a job for ES.next rather than a DOM 
 spec.

Definitely, hence the cc :)

 I'm happy to start a separate thread on es-discuss about this, but I'm
 worried that it'll fragment the current thread.

 In theory, public-script-coord exists for exactly this sort of discussion and 
 the ESdiscuss people who care should be subscripted. Rather than starting a 
 new thread, perhaps should should just post to es-discuss a pointer to this 
 thread.

Will do!

/ Jonas



Re: What type should .findAll return

2011-11-11 Thread Allen Wirfs-Brock

On Nov 11, 2011, at 3:57 PM, Jonas Sicking wrote:

 On Fri, Nov 11, 2011 at 3:07 PM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 
 ...
 
 This is a problem for ES=5.  Filter and all the other similar 
 Array.prototype functions are specified to produce an object created as if 
 by calling: new Array();
 
 I have a scheme that we can probably get in place for ES.next that would 
 allow filter and friends to produce NodeArray's for you, but I don't see how 
 that helps right now.
 
 Well, if we can get implementations to implement this new scheme for
 the existing filter-like functions at the same time as they implement
 .findAll, then we should be golden.

the scheme depends upon other Es.next features including private names. It 
isn't clear that if you start pulling that thread how far it extends. But 
perhaps, it might fly...


 ...
 
 This would make myNodeArray.filter work, but
 not Array.filter.
 
 An inherent problem with this approach. But if your NodeArrays supplies 
 correctly working over-rides there is probably little reason somebody would 
 try to use the Array.prototype versions  with NodeArrays.
 
 Note that I was saying Array.filter and not Array.prototype.filter. My
 assumption was that if people call Array.prototype with an Array as
 the first argument, they would also do so with a NodeArray as first
 argument.

Array.filter and friends (in contrast to Array.prototype.filter) are not in ES5 
and, so far, have not made the ES.next cut.  Personally, I'm not a bit fan of 
them for exactly this reason.  If you are building object-oriented class 
hierarchies you want to use methods, not global function that can't easily be 
virtually dispatched.  

Allen

Re: What type should .findAll return

2011-11-11 Thread Rick Waldron
Any DOM NodeList/NodeArray could be converted into a real array by passing 
to Array.from( array like )

http://wiki.ecmascript.org/doku.php?id=strawman:array_extras

Avoids creating yet another DOM NodeThing.

/Rick 

On Nov 11, 2011, at 6:57 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Fri, Nov 11, 2011 at 3:07 PM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 
 On Nov 11, 2011, at 2:16 PM, Jonas Sicking wrote:
 
 On Fri, Nov 11, 2011 at 1:22 PM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 
 BTW, I think that either the immutable or mutable approach would work.  
 However, since the collection is not live I don't see why you would 
 really care whether or not a client mutated it.  If they want to process 
 it by deleting elements after they are examined, so what?
 
 Exactly, this is why I'm proposing that it should be mutable.
 
 This does still leave the problem of making Array.filter(myNodeArray,
 function(el) { ... }) work though. I.e. I think we'd like it to
 return a NodeArray rather than a plain Array.
 
 This is a problem for ES=5.  Filter and all the other similar 
 Array.prototype functions are specified to produce an object created as if 
 by calling: new Array();
 
 I have a scheme that we can probably get in place for ES.next that would 
 allow filter and friends to produce NodeArray's for you, but I don't see how 
 that helps right now.
 
 Well, if we can get implementations to implement this new scheme for
 the existing filter-like functions at the same time as they implement
 .findAll, then we should be golden.
 
 More importantly, we want myNodeArray.filter(function(el){ ... }) to
 return a NodeArray. This would be doable by putting a special version
 of filter on NodeArray.prototype which would shadow
 Array.prototype.filter.
 
 
 It isn't just filter that creates new instances that you would probably want 
 to be NodeArrays. Also at least(I might have missed other when I just 
 checkeds): concat, slice, splice, map
 
 Indeed, I was just using filter as an example.
 
 Over-riding them explicitly for NodeArray would be an immediate fix, but 
 wouldn't solve the problem for future additions to Array.prototype.  
 However, if you assume that ES.next is going to provide the needed extension 
 mechanism then you should also assume that it will use it for any new 
 Array.prototype methods and they should pretty much just work.
 
 Indeed. If we went down this path we would have to continuously update
 the spec to make NodeArray override any filter-like methods that are
 added to Array.
 
 This would make myNodeArray.filter work, but
 not Array.filter.
 
 An inherent problem with this approach. But if your NodeArrays supplies 
 correctly working over-rides there is probably little reason somebody would 
 try to use the Array.prototype versions  with NodeArrays.
 
 Note that I was saying Array.filter and not Array.prototype.filter. My
 assumption was that if people call Array.prototype with an Array as
 the first argument, they would also do so with a NodeArray as first
 argument.
 
 I don't see a way around this short of modifying the specification of the 
 Array.prototype methods.  That seems like a job for ES.next rather than a 
 DOM spec.
 
 Definitely, hence the cc :)
 
 I'm happy to start a separate thread on es-discuss about this, but I'm
 worried that it'll fragment the current thread.
 
 In theory, public-script-coord exists for exactly this sort of discussion 
 and the ESdiscuss people who care should be subscripted. Rather than 
 starting a new thread, perhaps should should just post to es-discuss a 
 pointer to this thread.
 
 Will do!
 
 / Jonas
 



Re: What type should .findAll return

2011-11-11 Thread Tab Atkins Jr.
On Fri, Nov 11, 2011 at 5:35 PM, Rick Waldron waldron.r...@gmail.com wrote:
 Any DOM NodeList/NodeArray could be converted into a real array by 
 passing to Array.from( array like )

 http://wiki.ecmascript.org/doku.php?id=strawman:array_extras

 Avoids creating yet another DOM NodeThing.

Jonas explains very well why we don't want a real Array, but rather
something that just acts like an Array.

~TJ



Re: What type should .findAll return

2011-11-11 Thread Tab Atkins Jr.
On Fri, Nov 11, 2011 at 5:52 PM, Rick Waldron waldron.r...@gmail.com wrote:
 Right, but I'm saying: why create yet more stuff in the DOM?

  findAll will return a NodeArray while querySelectorAll and friends return 
 static and live NodeLists? No thanks.

I'm not sure what you would prefer.  Make findAll return an Array? (We
miss out on a *lot* of cool and useful stuff we could do.)  Make
findAll return immutable live NodeLists? (Ditto, but for different
reasons.)  Change qSA to return a NodeArray or Array? (Would be nice,
but probably not doable for compat reasons.)

~TJ



Re: What type should .findAll return

2011-11-11 Thread Jonas Sicking
On Fri, Nov 11, 2011 at 5:59 PM, Tab Atkins Jr. jackalm...@gmail.com wrote:
 On Fri, Nov 11, 2011 at 5:52 PM, Rick Waldron waldron.r...@gmail.com wrote:
 Right, but I'm saying: why create yet more stuff in the DOM?

  findAll will return a NodeArray while querySelectorAll and friends return 
 static and live NodeLists? No thanks.

 I'm not sure what you would prefer.  Make findAll return an Array? (We
 miss out on a *lot* of cool and useful stuff we could do.)  Make
 findAll return immutable live NodeLists? (Ditto, but for different
 reasons.)  Change qSA to return a NodeArray or Array? (Would be nice,
 but probably not doable for compat reasons.)

Actually, if we add .item to NodeArray then it's entirely possible
that we can make qSA return a NodeArray. I'm not entirely convinced
that's worth it though.

/ Jonas