ES3.1 Draft: Array generics
I know for a fact that not passing the thisObject as the third param in methods like map etc will break real world applications such as Gmail. If JScript does not follow the defacto standard, developers will have to add detection for this anormality. I think compatibility with other browser should be enough for ES3.1 to standardize that the thisObject should be passed as the third parameter.
Erik Arvidsson wrote:
I know for a fact that not passing the thisObject as the third param in methods like map etc will break real world applications such as Gmail. If JScript does not follow the defacto standard, developers will have to add detection for this anormality. I think compatibility with other browser should be enough for ES3.1 to standardize that the thisObject should be passed as the third parameter.
I disagree. Gmail can continue patching Array.prototype as it does now, so nothing breaks. But going forward, new applications should be using bind instead of a thisoObject.
On Tue, May 20, 2008 at 07:35, Douglas Crockford <douglas at crockford.com> wrote:
I disagree. Gmail can continue patching Array.prototype as it does now, so nothing breaks. But going forward, new applications should be using bind instead of a thisoObject.
Yes, Google can and will change it's usage if IE does it this way. It is a price I am willing to pay but this makes proposed ES3.1 incompatible with ES3+Reality. Something that will break the web.
On May 20, 2008, at 8:02 AM, Erik Arvidsson wrote:
On Tue, May 20, 2008 at 07:35, Douglas Crockford
<douglas at crockford.com> wrote:I disagree. Gmail can continue patching Array.prototype as it does
now, so nothing breaks. But going forward, new applications should be
using bind instead of a thisoObject.Yes, Google can and will change it's usage if IE does it this way. It is a price I am willing to pay but this makes proposed ES3.1 incompatible with ES3+Reality. Something that will break the web.
What's more, bind is not free -- it may require an extra object.
There is no necessary reason, given bind and map, to insist that map
not take an optional third argument obviating the need for bind in
conjunction with map. Factoring to the Nth degree is not mandated.
Minimalism is good, but it does not trump all usability and
efficiency considerations.
Anyway, existing implementations support the third parameter. If
ES3.1 has as a principle codifying existing practice, it ought to do
so here.
2008/5/19 Pratap Lakshman (VJ#SDK) <pratapl at microsoft.com>:
I have uploaded to the wiki a draft proposal (link) for Array generics. I have extracted the Array portion of the ES3 spec, added a rationale (with hyperlinks) at the beginning, and made relevant changes to the included section 15.4 text, with some comments added. I have tried to be mindful of compat.
"If Type(callbackfn) is not a function, throw a TypeError exception."
There is no function Type defined in ES 3.1. Are you incorporating the ES4 Type, or does callbackfn must implement [[Call]]?
It would be sufficient and more correct to say: "throw a TypeError" rather than "throw a TypeError exception"
As with my comment for ES4, there are many benefits to having the spec in HTML. It is easy to link directly to a fragment, it doesn't take a plugin, I don't get prompted to update Acrobat Reader, HTML is not slow to load as launching Reader is.
But most of all, it is easier for the rest of the world to link to and discuss (if that is desirable to the committee)
,
Garrett
On May 20, 2008, at 7:35 AM, Douglas Crockford wrote:
Erik Arvidsson wrote:
I know for a fact that not passing the thisObject as the third param in methods like map etc will break real world applications such as Gmail. If JScript does not follow the defacto standard, developers will have to add detection for this anormality. I think
compatibility with other browser should be enough for ES3.1 to standardize that the thisObject should be passed as the third parameter.I disagree. Gmail can continue patching Array.prototype as it does
now, so nothing breaks. But going forward, new applications should be using
bind instead of a thisoObject.
I've heard it mentioned that ES3.1 has a "3 out of 4 browsers" rule.
What exactly is the scope of this rule, and why does it not apply here?
, Maciej
[I'll take shot at replying (and Doug can clarify)]
A feature that is present in 3 out of 4 browsers makes it a candidate for inclusion into ES3.1. However, that does not guarantee that it will get included.
In the present case, here are a couple of data points: (1) It was felt that providing the thisObj could potentially introduce a security issue. (2) In ES3.1 we want to support Function.prototype.bind.
Taken together, this led us to propose codifying Array generics as called out in the proposal I sent out (i.e. without the thisObj parameter). As Doug mentiones below, apps could continue patching Array.prototype if they so desired, but going forward new apps should use bind instead of the thisObj.
Kris Zyp then made the observation that apps on ES3.1 that relied on feature-testing (before patching Array.prototype) would end up using the 'incompatible' implementation was present! At that point, we thought we would be better off not including the proposal for now.
pratap PS: I'll have this on the agenda for further discussion in our next conf. call.
On May 31, 2008, at 6:17 AM, Pratap Lakshman (VJ#SDK) wrote:
[I'll take shot at replying (and Doug can clarify)]
A feature that is present in 3 out of 4 browsers makes it a
candidate for inclusion into ES3.1. However, that does not guarantee
that it will get included.In the present case, here are a couple of data points: (1) It was felt that providing the thisObj could potentially
introduce a security issue. (2) In ES3.1 we want to support Function.prototype.bind.
To counter that, I would mention:
(1) The 3 out of 4 browsers that currently support the "thisObj"
parameter, and I do not expect they would remove it, so the spec will
be incompatible with 3 out of 4 implementations.
(2) Te proposed function.bind can be used to defend against this
rebinding, so the security issue can be avoided.
(3) Many existing ECMAScript functions can be used to perform this
rebinding, including Function.prototype.call,
Function.prototype.apply, and the ES3.1 proposed
Function.prototype.bind itself!
So, specifying map, filter, forEach etc as they are already
implemented in 3 out of 4 browsers does not create any consideration
that does not already exist, and the spec itself creates the means to
mitigate it.
Taken together, this led us to propose codifying Array generics as
called out in the proposal I sent out (i.e. without the thisObj
parameter). As Doug mentiones below, apps could continue patching
Array.prototype if they so desired, but going forward new apps
should use bind instead of the thisObj.
If apps can redefine Array.prototype.map to do what existing
implementations do, doesn't that by definition mean the same security
issue still exists? Security is based on what bad things you actually
can do, not which are condoned by the spec as acceptable or which are
common practice. I imagine the reason "this" rebinding is of concern
is for secure dialects trying to prevent malicious code from doing it,
not to protect against someone doing accidentally.
Thus, I can't see a sound reason to be incompatible with existing
practice.
, Maciej
Maciej Stachowiak wrote:
On May 31, 2008, at 6:17 AM, Pratap Lakshman (VJ#SDK) wrote:
[I'll take shot at replying (and Doug can clarify)]
A feature that is present in 3 out of 4 browsers makes it a candidate for inclusion into ES3.1. However, that does not guarantee that it will get included.
In the present case, here are a couple of data points: (1) It was felt that providing the thisObj could potentially introduce a security issue. (2) In ES3.1 we want to support Function.prototype.bind.
To counter that, I would mention:
(1) The 3 out of 4 browsers that currently support the "thisObj" parameter, and I do not expect they would remove it, so the spec will be incompatible with 3 out of 4 implementations. (2) Te proposed function.bind can be used to defend against this rebinding, so the security issue can be avoided. (3) Many existing ECMAScript functions can be used to perform this rebinding, including Function.prototype.call, Function.prototype.apply, and the ES3.1 proposed Function.prototype.bind itself!
So, specifying map, filter, forEach etc as they are already implemented in 3 out of 4 browsers does not create any consideration that does not already exist, and the spec itself creates the means to mitigate it.
Taken together, this led us to propose codifying Array generics as called out in the proposal I sent out (i.e. without the thisObj parameter). As Doug mentions below, apps could continue patching Array.prototype if they so desired, but going forward new apps should use bind instead of the thisObj.
If apps can redefine Array.prototype.map to do what existing implementations do, doesn't that by definition mean the same security issue still exists? Security is based on what bad things you actually can do, not which are condoned by the spec as acceptable or which are common practice. I imagine the reason "this" rebinding is of concern is for secure dialects trying to prevent malicious code from doing it, not to protect against someone doing accidentally.
Thus, I can't see a sound reason to be incompatible with existing practice.
I think we must implement the Array methods as currently understood, even with the regrettable thisObject parameter. The hazards of the misbinding of this are a particular problem for mashup platforms, so the use of the thisObject parameter will not be allowed in strict mode.
This will allow existing applications that use thisObject to continue to work, and it will also disable the thisObject pattern for new applications with more severe security requirements.
On May 31, 2008, at 3:37 PM, Douglas Crockford wrote:
The hazards of the misbinding of this are a particular problem for mashup platforms, so the use of the
thisObject parameter will not be allowed in strict mode.
So IIUC, in ES3.1 strict mode, given
var a = [1,2,3];
this is an error:
var b = a.map(function(e,i,a){print(e,i,a, this.z);return e}, {z: 42});
but this is not:
var b = a.map(function(e,i,a){print(e,i,a, this.z);return e}.bind ({z:42}));
Why is it ok to do something one (novel) way, but not another
(existing in 3 of 4 browsers) way?
That bind allocates an extra object may give the second way greater
integrity, but unless the function is stashed somewhere and called on
a different thisObject by other code, the above forms are equivalent.
The map implementation will only call the passed in function, and
only with the given or bound thisObject, once per existing (non-hole)
array element.
That bind require an extra (function) object to be allocated is
undesirable overhead, in the absence of threats.
fwd to list.
On Sat, May 31, 2008 at 1:44 AM, Garrett Smith <dhtmlkitchen at gmail.com> wrote:
2008/5/19 Pratap Lakshman (VJ#SDK) <pratapl at microsoft.com>:
It would be sufficient and more correct to say: "throw a TypeError" rather than "throw a TypeError exception"
So it should probably read one of:-
- If callbackfn does not implement [[Call]], throw a TypeError.
- If callbackfn is not a function, throw a TypeError
There is also an absence of top-level generics:-
Array.forEach
- This avoids having to write:-
[].forEach.call( nodeList, fun );
Note on host objects: Whether the forEach function can be applied successfully to a host object is implementation -dependent.
- support Array Generics for host object, for example, a DOM NodeList in abstract view.
[].sort.call( ul.getElementsByTagName("li"), byName );
Garrett
On Sat, May 31, 2008 at 3:37 PM, Douglas Crockford <douglas at crockford.com> wrote:
I think we must implement the Array methods as currently understood, even with the regrettable thisObject parameter. The hazards of the misbinding of this are a particular problem for mashup platforms, so the use of the thisObject parameter will not be allowed in strict mode.
This will allow existing applications that use thisObject to continue to work, and it will also disable the thisObject pattern for new applications with more severe security requirements.
Crock, I see no viable way to make this switchable on the strictness of the caller. We should try to avoid adding to the number of ways that built-in objects are magical -- able to do things that objects defined in JavaScript cannot. We have not proposed that a function/method be able to determine the strictness of its caller. I do not wish to propose that. Without it, I see no way to both introduce this API, but have it reject thisObject arguments only from strict callers.
My first choice is still to avoid adding any of this. When in doubt, leave it out. But, as others have argued, none of this is fatal to security. If we're going to add it, we should provide the existing behavior as is, independent of the strictness of the caller. It won't hurt ADsafe or Cajita, since they don't have "this" at all. It will be a pain for Caja, but nothing we can't cope with. This one isn't worth fighting.
Hello Pratap,
Were you genuinely interested in feedback?
Is Function described by Type in ES3.1?
Are top-level generics part of the spec (Array.forEach)?
You or one of your colleagues signed me up for the ES3.1 list, then, apparently, after I replied directly to you, decided to ignore the reply and unsubscribed me from the list. I can't be bothered to resubscribe myself. Posted to ES4 discuss.
Garrett
---------- Forwarded message ---------- From: <es3.x-discuss-owner at mozilla.org>
Date: Sat, May 31, 2008 at 6:27 PM Subject: Fwd: ES3.1 Draft: Array generics To: dhtmlkitchen at gmail.com
Messages from non-subscribers are automatically rejected. Please subscribe to the list first before attempting to post, or ensure that you are posting using the address you subscribed with.
---------- Forwarded message ---------- From: "Garrett Smith" <dhtmlkitchen at gmail.com>
To: "es3.x-discuss at mozilla.org" <es3.x-discuss at mozilla.org>, "es4-discuss at mozilla.org" <es4-discuss at mozilla.org>
Date: Sat, 31 May 2008 18:27:10 -0700 Subject: Fwd: ES3.1 Draft: Array generics fwd to list.
On Sat, May 31, 2008 at 1:44 AM, Garrett Smith <dhtmlkitchen at gmail.com> wrote:
2008/5/19 Pratap Lakshman (VJ#SDK) <pratapl at microsoft.com>:
It would be sufficient and more correct to say: "throw a TypeError" rather than "throw a TypeError exception"
So it should probably read one of:-
- If callbackfn does not implement [[Call]], throw a TypeError.
- If callbackfn is not a function, throw a TypeError
There is also an absence of top-level generics:-
Array.forEach
- This avoids having to write:-
[].forEach.call( nodeList, fun );
Note on host objects: Whether the forEach function can be applied successfully to a host object is implementation -dependent.
- support Array Generics for host object, for example, a DOM NodeList in abstract view.
[].sort.call( ul.getElementsByTagName("li"), byName );
Garrett
Garrett, I apologize. I was not ignoring you. Yes, I am interested in feedback!
The initial Array generics proposal did not include the thisObj param as it was felt that it could open the door to some security issues. We were even contemplating cutting Array generics from ES3.1 altogether. Later, based on feedback from many of us on the discuss lists, we are going back to specifying the Array Generics to include the "thisObj" param; these generics will be available on Array.prototype. I am currently revising the proposal, and it will include the following: Array.prototype.indexOf Array.prototype.lastIndexOf Array.prototype.every Array.prototype.some Array.prototype.forEach Array.prototype.map Array.prototype.filter
and also, Array.prototype.reduce Array.prototype.reduceRight
I am not sure how you got unsubscribed; there must be some mistake!
pratap
On Sun, Jun 8, 2008 at 2:50 PM, Pratap Lakshman (VJ#SDK) <pratapl at microsoft.com> wrote:
Garrett, I apologize. I was not ignoring you. Yes, I am interested in feedback!
The initial Array generics proposal did not include the thisObj param as it was felt that it could open the door to some security issues. We were even contemplating cutting Array generics from ES3.1 altogether. Later, based on feedback from many of us on the discuss lists, we are going back to specifying the Array Generics to include the "thisObj" param; these generics will be available on Array.prototype. I am currently revising the proposal, and it will include the following: Array.prototype.indexOf Array.prototype.lastIndexOf Array.prototype.every Array.prototype.some Array.prototype.forEach Array.prototype.map Array.prototype.filter
and also, Array.prototype.reduce Array.prototype.reduceRight
I meant the top-level generics:
Array.forEach(arrayLike, fn);
It was not my argument for:
Array.prototype.forEach(fn[, thisArg]);
The thisArg was what Erik had brought up.
The other question was regarding the: "If Type(callbackfn) is not a function, throw a TypeError exception."
ES 3.0 doesn't define "Function" as a Type. In fact, the spec often uses: If "x is a Function". There is: "if Type(x) is Number", but not "if Type(x) is Function". That is why I asked if ES 3.1 defines Function for Type(). Does it? ES 3.1: Type, section 8 bclary.com/2004/11/07/#a-8
If ES 3.0 had forEach, it would probably have read something along the lines of one of:
- If callbackfn does not implement [[Call]], throw a TypeError.
- If callbackfn is not a function, throw a TypeError.
I am not sure how you got unsubscribed; there must be some mistake!
I don't know either.
Garrett
pratap
[snip]
On Sun, Jun 8, 2008 at 2:50 PM, Pratap Lakshman (VJ#SDK) <pratapl at microsoft.com> wrote:
Garrett, I apologize. I was not ignoring you. Yes, I am interested in feedback!
OK, but you seem to have misunderstood me.
The initial Array generics proposal did not include the thisObj param as it was felt that it could open the door to some security issues. We were even contemplating cutting Array generics from ES3.1 altogether. Later, based on feedback from many of us on the discuss lists, we are going back to specifying the Array Generics to include the "thisObj" param; these generics will be available on Array.prototype. I am currently revising the proposal, and it will include the following: Array.prototype.indexOf Array.prototype.lastIndexOf Array.prototype.every Array.prototype.some Array.prototype.forEach Array.prototype.map Array.prototype.filter
and also, Array.prototype.reduce Array.prototype.reduceRight
I meant the top-level generics:
Array.forEach(arrayLike, fn);
It was not my argument for:
Array.prototype.forEach(fn[, thisArg]);
The thisArg was what Erik had brought up.
The other question was regarding the: "If Type(callbackfn) is not a function, throw a TypeError exception."
ES 3.0 doesn't define "Function" as a Type. In fact, the spec often uses: If "x is a Function". There is: "if Type(x) is Number", but not "if Type(x) is Function". That is why I asked if ES 3.1 defines Function for Type(). Does it? ES 3.1: Type, section 8 bclary.com/2004/11/07/#a-8
If ES 3.0 had forEach, it would probably have read something along the lines of one of:
- If callbackfn does not implement [[Call]], throw a TypeError.
- If callbackfn is not a function, throw a TypeError.
I am not sure how you got unsubscribed; there must be some mistake!
I don't know either. Is there a link to get back on?
Garrett
pratap
[snip]
I'll fix my usage of 'function' in the steps.
Presently, top-level generics are not there in ES3.1. I had brought this up when discussing String generics (refer the thread "ES3.1 Draft: String generics"); I am using the same rationale for not including top level Array generics too.
Use the following link to subscribe to the ES3.x discuss list: mail.mozilla.org/listinfo/es3.x-discuss
pratap
On Jun 9, 2008, at 6:25 PM, Pratap Lakshman (VJ#SDK) wrote:
I'll fix my usage of 'function' in the steps.
Presently, top-level generics are not there in ES3.1. I had brought
this up when discussing String generics (refer the thread "ES3.1
Draft: String generics"); I am using the same rationale for not
including top level Array generics too.
Hi Pratap,
I missed this rationale extension and wanted to point out that
there's a difference between String generics and Array generics that
is substantial: the String.prototype.slice, etc., methods all call
ToString on the value of "this", requiring conversion to string from
non-String object (ES3 sense) types. But the Array generics do not
convert. So it's possible and useful to call:
Array.prototype.slice.call(nodeList, begin, end)
for example. That's the motivation for the static-generic shorter
forms, e.g.:
Array.slice(nodeList, begin, end)
I have uploaded to the wiki a draft proposal (linkes3.1:es31_arrayobject.pdf) for Array generics.
I have extracted the Array portion of the ES3 spec, added a rationale (with hyperlinks) at the beginning, and made relevant changes to the included section 15.4 text, with some comments added. I have tried to be mindful of compat.
pratap