Array.prototype.slice web-compat issue?

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Array.prototype.slice web-compat issue?

André Bargull-2
This test case [1] from SpiderMonkey failed when I applied the latest
spec changes to my ES6 test implementation. Based on the bug report at
[2], this might be another web-compatibility issue - but is that really
the case? Any input appreciated!

Thanks,
André


[1]
https://github.com/mozilla/mozilla-central/blob/master/js/src/jit-test/tests/basic/bug683140.js
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=683140
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Allen Wirfs-Brock

On Aug 28, 2013, at 5:09 AM, André Bargull wrote:

This test case [1] from SpiderMonkey failed when I applied the latest spec changes to my ES6 test implementation. Based on the bug report at [2], this might be another web-compatibility issue - but is that really the case? Any input appreciated!

Thanks,
André


[1] https://github.com/mozilla/mozilla-central/blob/master/js/src/jit-test/tests/basic/bug683140.js
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=683140

Very interesting.  Here is one of the test cases André is talking about.

var g = newGlobal("new-compartment");  //or any non-standard mechanism to get a handle on another realm's global object
g.a = g.Array(10);
print(g.a instanceof Array);
g.a = Array.prototype.slice(g.a);
print(g.a instanceof Array);

--
Output ES<6: false, true
Output ES6:  false, false

Also note that if the instanceof tests above were replaced with Array.isArray(g.a) you would get all trues in both ES5 and ES6.  instanceof is not a reliable test for array-ness when objects flow between realms..

The problem is that in ES<6 slice always returned a new Array instance using the Array of the realm associated with the invoked slice function.  In ES6 slice returns an object that is determine based upon the actual this value passed to slice.  In the default case like above, this will be the a new Array instance using the Array of the realm associated with the this value.

The reason for this change is to enable slice to behave rationally for Array subclasses. For example:

class SubArray extends Array {
   get isSubArray() {return true}
}

let sa = new SubArray(10);
let sal = sa.slice(1);
print(sa.isSubArray);                   //true for Es6 slice, undefined for ES5 slice
print(sal instanceof SubArray); //true for ES6 slice spec. false for ES5 slice spec.
print(sal instanceof Array);        //true for ES6. true for ES5

The way that the result object creation works in the ES6 spec. is approximately:
 
 slice(start, end) {
     ...
     let result = new this.constructor();  //create an instance of the same "class" as the this value
     ...
}


Continuing to allow slice (and most other Array.prototype methods) to work as expected with subclasses and still preserving ES5 cross-realm instanceof compatability for these cases is at best hackish.  Something like: 

slice(start, end) {
     ...
     let resultConstructor = this.constructor; 
     if (realm(resultConstructor) !== thisFunctionsRealm) {
               if (isIntrinsicArrayConstrutorForAnyRealm(resultConstructor) then resultConstructor = thisFunctionsReam.intrinsics("Array");
     }
     let result = new resultConstructor();
     ...
 }

I guess I could put mechanism to support this into the spec...

However, do we actually understand what the real world use case that tripped over this in FF?  It'seasy to write a test case that detects this difference but that sort of instanceof test doesn't seem to make much sense for production code.

Allen 

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Kevin Reid-4
On Wed, Aug 28, 2013 at 10:19 AM, Allen Wirfs-Brock <[hidden email]> wrote:
The problem is that in ES<6 slice always returned a new Array instance using the Array of the realm associated with the invoked slice function.  In ES6 slice returns an object that is determine based upon the actual this value passed to slice.  In the default case like above, this will be the a new Array instance using the Array of the realm associated with the this value.

!

This is a hazardous change for SES-style security. For example, I've just taken a quick look at our (Caja) codebase and found a place where Array.prototype.slice.call(foo) is used to obtain a “no funny business” array (i.e. doesn't have side effects when you read it) and another where it's used to obtain an array which must be in the caller's realm. These would be easy enough to replace with a more explicit operation, but I wanted to point out that this is not a harmless change.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Allen Wirfs-Brock

On Aug 29, 2013, at 10:51 AM, Kevin Reid wrote:

On Wed, Aug 28, 2013 at 10:19 AM, Allen Wirfs-Brock <[hidden email]> wrote:
The problem is that in ES<6 slice always returned a new Array instance using the Array of the realm associated with the invoked slice function.  In ES6 slice returns an object that is determine based upon the actual this value passed to slice.  In the default case like above, this will be the a new Array instance using the Array of the realm associated with the this value.

!

This is a hazardous change for SES-style security. For example, I've just taken a quick look at our (Caja) codebase and found a place where Array.prototype.slice.call(foo) is used to obtain a “no funny business” array (i.e. doesn't have side effects when you read it) and another where it's used to obtain an array which must be in the caller's realm. These would be easy enough to replace with a more explicit operation, but I wanted to point out that this is not a harmless change.

In the Array.prototype.slice.call(foo) use case what is foo? Is it known to be an Array?  Are you saying this is how you clone an Array?

For you second use case, that sounds like it is contrary to what is implicitly assume by ES5.  For ES5, every built-in is assume to be associated with a realm when it is created and any references to built-ins by a built-in are assume to use the same realm as the referencing built-in.  So something like:
       var newArray = slice.call( [ ] );

in ES5, should return a new Array instances based upon the same Realm  as the slice function that was invoked.  It is not necessarily the same as the caller's realm.

Array literals are guaranteed to be create an array instance in the same realm as the code that evaluates the literal.

Allen








_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Kevin Reid-4
On Thu, Aug 29, 2013 at 12:56 PM, Allen Wirfs-Brock <[hidden email]> wrote:
On Aug 29, 2013, at 10:51 AM, Kevin Reid wrote:
This is a hazardous change for SES-style security. For example, I've just taken a quick look at our (Caja) codebase and found a place where Array.prototype.slice.call(foo) is used to obtain a “no funny business” array (i.e. doesn't have side effects when you read it) and another where it's used to obtain an array which must be in the caller's realm. These would be easy enough to replace with a more explicit operation, but I wanted to point out that this is not a harmless change.

In the Array.prototype.slice.call(foo) use case what is foo? Is it known to be an Array?  Are you saying this is how you clone an Array?

Sorry, both are of that form, if I was unclear. When we want to simply clone an existing array, belonging to a secured realm, I think we generally use slice as a method, and there is no security property there.

Of the two cases I refer to, one is a function (the trademarking stamp()) which takes a list of objects as a parameter and needs to ensure that successive stages of processing operate on exactly the same set of objects and do not trigger any side effects in the list's implementation. Here, realm is irrelevant but the list's implementation must be relied on, so in practice we want an Array from stamp()'s own realm.

The other case is one where it is a cross-frame protocol and we specifically want an object which belongs to 'our own' realm because its prototypes are frozen and specially extended, whereas the calling realm's prototypes notably are not frozen (it's outside of the shiny happy sandbox) and therefore constitute a risk to least-authority programming which we want to stop at the boundaries. (Note for MarkM: It's actually a little bit more complicated than this, but the details are irrelevant to the principle.)
 
For you second use case, that sounds like it is contrary to what is implicitly assume by ES5.  For ES5, every built-in is assume to be associated with a realm when it is created and any references to built-ins by a built-in are assume to use the same realm as the referencing built-in.  So something like:
       var newArray = slice.call( [ ] );

Sorry, when I said "the caller" I meant this particular caller, the function in our codebase which contains "Array.prototype.slice" in its source text and therefore does call the slice belonging to its own realm. I apologize for the particularly misleading phrasing.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Allen Wirfs-Brock

On Aug 29, 2013, at 1:39 PM, Kevin Reid wrote:

On Thu, Aug 29, 2013 at 12:56 PM, Allen Wirfs-Brock <[hidden email]> wrote:
On Aug 29, 2013, at 10:51 AM, Kevin Reid wrote:
This is a hazardous change for SES-style security. For example, I've just taken a quick look at our (Caja) codebase and found a place where Array.prototype.slice.call(foo) is used to obtain a “no funny business” array (i.e. doesn't have side effects when you read it) and another where it's used to obtain an array which must be in the caller's realm. These would be easy enough to replace with a more explicit operation, but I wanted to point out that this is not a harmless change.

In the Array.prototype.slice.call(foo) use case what is foo? Is it known to be an Array?  Are you saying this is how you clone an Array?

Sorry, both are of that form, if I was unclear. When we want to simply clone an existing array, belonging to a secured realm, I think we generally use slice as a method, and there is no security property there.

Of the two cases I refer to, one is a function (the trademarking stamp()) which takes a list of objects as a parameter and needs to ensure that successive stages of processing operate on exactly the same set of objects and do not trigger any side effects in the list's implementation. Here, realm is irrelevant but the list's implementation must be relied on, so in practice we want an Array from stamp()'s own realm.

The other case is one where it is a cross-frame protocol and we specifically want an object which belongs to 'our own' realm because its prototypes are frozen and specially extended, whereas the calling realm's prototypes notably are not frozen (it's outside of the shiny happy sandbox) and therefore constitute a risk to least-authority programming which we want to stop at the boundaries. (Note for MarkM: It's actually a little bit more complicated than this, but the details are irrelevant to the principle.)


for both cases, are you using Array.isArray to determine that you are operating upon an array?

what would be the appropriate thing to happen (all things considered) in a world where subclasses of Array exist?

Allen


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Kevin Reid-4
On Thu, Aug 29, 2013 at 2:21 PM, Allen Wirfs-Brock <[hidden email]> wrote:
Of the two cases I refer to, one is a function (the trademarking stamp()) which takes a list of objects as a parameter and needs to ensure that successive stages of processing operate on exactly the same set of objects and do not trigger any side effects in the list's implementation. Here, realm is irrelevant but the list's implementation must be relied on, so in practice we want an Array from stamp()'s own realm.

The other case is one where it is a cross-frame protocol and we specifically want an object which belongs to 'our own' realm because its prototypes are frozen and specially extended, whereas the calling realm's prototypes notably are not frozen (it's outside of the shiny happy sandbox) and therefore constitute a risk to least-authority programming which we want to stop at the boundaries. (Note for MarkM: It's actually a little bit more complicated than this, but the details are irrelevant to the principle.)
for both cases, are you using Array.isArray to determine that you are operating upon an array?
 
In both cases, all we want is the user-specified set of values, to store or operate on. So, in accordance with JavaScript idiom, we expect it to be array-like, but (since we are multi-frame code) not necessarily an Array from this frame.

Given this, there is no particular reason to perform an isArray test, unless we wanted to do type checks for linting purposes ("you passed a Foo, not an array of Foos; you probably made a mistake"), and we don't.

what would be the appropriate thing to happen (all things considered) in a world where subclasses of Array exist?

I don't have any examples to work from; I would think there is value in permitting them to be used to carry the intended set-of-values if the code calling our code uses them, but I do not see how any subclass could have a custom behavior which would be appropriate or useful to preserve rather than discarding in these two cases, or any other case where the array being passed is used in 'functional' fashion (immediately reading as opposed to either retaining it to look at later or mutating it).

(I admit I favor composition/delegation over inheritance, for public interfaces, and therefore dislike the notion of working with subclasses of concrete built-ins. But one could also consider, for example, the reasons why java.lang.String is final.)



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Brendan Eich-3
Kevin Reid wrote:
> (I admit I favor composition/delegation over inheritance, for public
> interfaces, and therefore dislike the notion of working with
> subclasses of concrete built-ins.

+∞

> But one could also consider, for example, the reasons why
> java.lang.String is final.)

One could also view that as a total failure of the java.lang.String
designers/implementors.

http://researcher.ibm.com/files/us-bacon/Corwin03MJSlides-Grove.pdf‎

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Array.prototype.slice web-compat issue?

Boris Zbarsky
In reply to this post by Allen Wirfs-Brock
 > However, do we actually understand what the real world use case that
 > tripped over this in FF?

Somewhat.  See https://bugzilla.mozilla.org/show_bug.cgi?id=683140

Or do you mean what exactly in Jira is doing the instanceof tests?

-Boris

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Allen Wirfs-Brock

On Sep 9, 2013, at 7:58 AM, Boris Zbarsky wrote:

> > However, do we actually understand what the real world use case that
> > tripped over this in FF?
>
> Somewhat.  See https://bugzilla.mozilla.org/show_bug.cgi?id=683140
>
> Or do you mean what exactly in Jira is doing the instanceof tests?

Yes, that's what I meant.  It's clear what the test is doing but I'd like to understand a bit better what the application logic thinks it's doing.

Allen











>
> -Boris
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Boris Zbarsky
On 9/9/13 12:01 PM, Allen Wirfs-Brock wrote:

>
> On Sep 9, 2013, at 7:58 AM, Boris Zbarsky wrote:
>
>>> However, do we actually understand what the real world use case that
>>> tripped over this in FF?
>>
>> Somewhat.  See https://bugzilla.mozilla.org/show_bug.cgi?id=683140
>>
>> Or do you mean what exactly in Jira is doing the instanceof tests?
>
> Yes, that's what I meant.  It's clear what the test is doing but I'd like to understand a bit better what the application logic thinks it's doing.

It's a bit sad that the bug doesn't have info on that.  :(

Jan, do you recall what the exact issue was with Jira here, by any chance?

-Boris
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Jan de Mooij-2

----- Original Message -----
> On 9/9/13 12:01 PM, Allen Wirfs-Brock wrote:
> > Yes, that's what I meant.  It's clear what the test is doing but I'd like
> > to understand a bit better what the application logic thinks it's doing.
>
> It's a bit sad that the bug doesn't have info on that.  :(
>
> Jan, do you recall what the exact issue was with Jira here, by any chance?

Unfortunately not :( IIRC an iframe for one of the widgets passed an Array to its parent frame, and the parent frame used slice + instanceof, but I don't remember the details after two years...

Jan
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Andrea Giammarchi-2
I see one of two problems mentioned in my other topic is already discussed here so I'd like to add this question that will most likely break the web:

  1. will `[].slice.call(arguments)` produce a pointless instanceof Arguments ?
  2. will `[].slice.call(document.querySelectorAll('*'))` produce an instanceof Static NodeList ?

AFAIK 99% of libraries out there believe that slice.call will return an Array of the current realm.
Wouldn't be wise to distinguish between explicit `Array.prototype.call(context)` VS `context.slice()` so that only latter one will produce the magic ES6 would like to add ?

Thanks for any clarification.


On Tue, Sep 10, 2013 at 4:26 AM, Jan de Mooij <[hidden email]> wrote:

----- Original Message -----
> On 9/9/13 12:01 PM, Allen Wirfs-Brock wrote:
> > Yes, that's what I meant.  It's clear what the test is doing but I'd like
> > to understand a bit better what the application logic thinks it's doing.
>
> It's a bit sad that the bug doesn't have info on that.  :(
>
> Jan, do you recall what the exact issue was with Jira here, by any chance?

Unfortunately not :( IIRC an iframe for one of the widgets passed an Array to its parent frame, and the parent frame used slice + instanceof, but I don't remember the details after two years...

Jan
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Allen Wirfs-Brock

On Sep 10, 2013, at 10:37 AM, Andrea Giammarchi wrote:

> AFAIK 99% of libraries out there believe that slice.call will return an Array of the current realm.

Can you explain why the Realm makes a difference to them?  Is it because they are doing instanceof Array tests rather than Array.isArray?

Allen


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Andrea Giammarchi-2
As short answer, let me reformulate:
AFAIK 99% of libraries out there believe that slice.call will return an Array, no matter which realm. In ES6 I see there's too much magic involved because of subclassing possibility.


Long story:

Historically, `instanceof` has been cross browser/engine the fastest way to understand if an object is an Array, compared with both `Object#toString.call(arr)` and/or `Array.isArray` plus the web does not really pass Arrays between iframes anymore thanks to `postMessage` and other serialization mechanisms where, once deserialized, `instanceof` will do the trick (also JSON.parse creates Arrays of the current realm)

Caja is a very-very-very specific use case that does not reflect majority of websites so `instanceof` worked most of the time for most of the site but regardless, Caja believes slice.call wil generate an `Array` that will be `instanceof Array` and this is a valid assumption for every sandboxed code that believes in `instanceof` rejecting all external "unknown" instances.

Finally, `Object.prototype.toString.call(object)` instead of `instanceof` is abusing a hack that is also slow ... subclassing is not only about `Array` .. or is it? 'cause in such case I'd rather suggest a new constructor called `ArrayLike` or `ArrayObject`, easier to polyfill and ready to be subclassed with all the needed magic (as reflection of `Array` behavior)

Off Topic:
I've personally tried to subclass Array since IE5 so this is a welcome thing but does not seem to be that practical as specced now considering existing code.




On Tue, Sep 10, 2013 at 10:46 AM, Allen Wirfs-Brock <[hidden email]> wrote:

On Sep 10, 2013, at 10:37 AM, Andrea Giammarchi wrote:

> AFAIK 99% of libraries out there believe that slice.call will return an Array of the current realm.

Can you explain why the Realm makes a difference to them?  Is it because they are doing instanceof Array tests rather than Array.isArray?

Allen




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Allen Wirfs-Brock

On Sep 10, 2013, at 11:12 AM, Andrea Giammarchi wrote:

> As short answer, let me reformulate:
> AFAIK 99% of libraries out there believe that slice.call will return an Array, no matter which realm. In ES6 I see there's too much magic involved because of subclassing possibility.

Presumably this is a 100% reasonable expectation today, because that's that the ES<=5.1 specs say.  However, often do they depend upon the value being a direct instance of Array as opposed to being an instance of a subclass of an array, assuming that the subclass how all the observable characteristics of an Array instances including answering true to Array.isArray and maintaining the Array invariant.

In other words, those libraries have never encountered a true subclass of Array.  When they do, is anything bad going to happen if the result object is also a subclass of Array?

BTW, I think it is useful to distinguish this use case from applying slice to non Array.isArray objects or using slice as a strange way to create a new Array instance.

Allen




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Andrea Giammarchi-2
My main concern was about non `Array` objects such instances of `Arguments` or `NodeList` or others Array_ish_ instances where to work with `.slice()` all we need is a `length` property.

If these will return not as `instanceof` current `Array` realm most of the code will be broken.

If `.slice()` will be that smart as I expect, I wonder why nobody is mentioning `.concat()` as able to concatenate every Array_ish_ and produce an `instanceof` the original object constructor that invoked that concat call.

`ArrayIsh.prototype.concat([]) instanceof ArrayIsh`

Last doubt would be about `Array.isArray` and the inability to distinguish, if not via `Object#toString` or `instanceof` between two different `ArrayIsh` objects ... so that `instanceof` will be not usable for `ArrayIsh` and at the same time the best solution to understand what kind of `ArrayIsh` it is so that extra, enriched, methods can be used.

Thoughts?




On Tue, Sep 10, 2013 at 12:25 PM, Allen Wirfs-Brock <[hidden email]> wrote:

On Sep 10, 2013, at 11:12 AM, Andrea Giammarchi wrote:

> As short answer, let me reformulate:
> AFAIK 99% of libraries out there believe that slice.call will return an Array, no matter which realm. In ES6 I see there's too much magic involved because of subclassing possibility.

Presumably this is a 100% reasonable expectation today, because that's that the ES<=5.1 specs say.  However, often do they depend upon the value being a direct instance of Array as opposed to being an instance of a subclass of an array, assuming that the subclass how all the observable characteristics of an Array instances including answering true to Array.isArray and maintaining the Array invariant.

In other words, those libraries have never encountered a true subclass of Array.  When they do, is anything bad going to happen if the result object is also a subclass of Array?

BTW, I think it is useful to distinguish this use case from applying slice to non Array.isArray objects or using slice as a strange way to create a new Array instance.

Allen






_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Rick Waldron
In reply to this post by Andrea Giammarchi-2



On Tue, Sep 10, 2013 at 1:37 PM, Andrea Giammarchi <[hidden email]> wrote:
I see one of two problems mentioned in my other topic is already discussed here so I'd like to add this question that will most likely break the web:

  1. will `[].slice.call(arguments)` produce a pointless instanceof Arguments ?

No, because you can't construct `new Arguments()` (Arguments is undefined), leaving A undefined at step 15.c, which means step 16 evaluates to true, which leads to 16.a and that produces an Array.

 
  2. will `[].slice.call(document.querySelectorAll('*'))` produce an instanceof Static NodeList ?

This is a good question, if NodeList has an internal [[Construct]] it will pass the IsConstructor test and then throw a TypeError exception as soon as 15.c.i occurs. Based on my interpretation of the steps in OrdinaryConstruct, it wouldn't survive. Maybe Allen can clarify?

Also, this is the exact pain point case that Array.from was designed to address, but existing code shouldn't break in the interim.

Rick


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Andrea Giammarchi-2
the polyfill for Array.from is based on slice 'cause slice works like that since, well, ever.
That's why I've raised some concern about a change on slice ... I'd rather extend a new `ArrayObject` instead of touching `Array` also because polyfills will make common/borrowed slice operations painfully slow.

My point is: `Array` has never been subclassed and nobody is expecting to be able to do that with current semantics/code/libraries if not redefining and delegating.

ES6 introduces new syntax that should desugar to what every browsers know already ... it's "easy", when possible, to polyfill a new global class ... it will make polyfills very painful otherwise.

I can already imagine ES6 shim overwriting all `Array.prototype` methods to obtain this new behavior ... it would be much easier to do this instead:

```javascript
function ArrayObject() {}
ArrayObject.prototype.slice = function () {
  return Object.setPrototypeOf(
    Array.prototype.slice.call(this, arguments),
    Object.getPrototypeOf(this)
  );
};
```

Cheers






On Tue, Sep 10, 2013 at 3:24 PM, Rick Waldron <[hidden email]> wrote:



On Tue, Sep 10, 2013 at 1:37 PM, Andrea Giammarchi <[hidden email]> wrote:
I see one of two problems mentioned in my other topic is already discussed here so I'd like to add this question that will most likely break the web:

  1. will `[].slice.call(arguments)` produce a pointless instanceof Arguments ?

No, because you can't construct `new Arguments()` (Arguments is undefined), leaving A undefined at step 15.c, which means step 16 evaluates to true, which leads to 16.a and that produces an Array.

 
  2. will `[].slice.call(document.querySelectorAll('*'))` produce an instanceof Static NodeList ?

This is a good question, if NodeList has an internal [[Construct]] it will pass the IsConstructor test and then throw a TypeError exception as soon as 15.c.i occurs. Based on my interpretation of the steps in OrdinaryConstruct, it wouldn't survive. Maybe Allen can clarify?

Also, this is the exact pain point case that Array.from was designed to address, but existing code shouldn't break in the interim.

Rick



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Array.prototype.slice web-compat issue?

Andrea Giammarchi-2
... apply for gosh sake ... 

```javascript
function ArrayObject() {}
ArrayObject.prototype.slice = function () {
  return Object.setPrototypeOf(
    Array.prototype.slice.apply(this, arguments),
    Object.getPrototypeOf(this)
  );
};
```


On Tue, Sep 10, 2013 at 3:42 PM, Andrea Giammarchi <[hidden email]> wrote:
the polyfill for Array.from is based on slice 'cause slice works like that since, well, ever.
That's why I've raised some concern about a change on slice ... I'd rather extend a new `ArrayObject` instead of touching `Array` also because polyfills will make common/borrowed slice operations painfully slow.

My point is: `Array` has never been subclassed and nobody is expecting to be able to do that with current semantics/code/libraries if not redefining and delegating.

ES6 introduces new syntax that should desugar to what every browsers know already ... it's "easy", when possible, to polyfill a new global class ... it will make polyfills very painful otherwise.

I can already imagine ES6 shim overwriting all `Array.prototype` methods to obtain this new behavior ... it would be much easier to do this instead:

```javascript
function ArrayObject() {}
ArrayObject.prototype.slice = function () {
  return Object.setPrototypeOf(
    Array.prototype.slice.call(this, arguments),
    Object.getPrototypeOf(this)
  );
};
```

Cheers






On Tue, Sep 10, 2013 at 3:24 PM, Rick Waldron <[hidden email]> wrote:



On Tue, Sep 10, 2013 at 1:37 PM, Andrea Giammarchi <[hidden email]> wrote:
I see one of two problems mentioned in my other topic is already discussed here so I'd like to add this question that will most likely break the web:

  1. will `[].slice.call(arguments)` produce a pointless instanceof Arguments ?

No, because you can't construct `new Arguments()` (Arguments is undefined), leaving A undefined at step 15.c, which means step 16 evaluates to true, which leads to 16.a and that produces an Array.

 
  2. will `[].slice.call(document.querySelectorAll('*'))` produce an instanceof Static NodeList ?

This is a good question, if NodeList has an internal [[Construct]] it will pass the IsConstructor test and then throw a TypeError exception as soon as 15.c.i occurs. Based on my interpretation of the steps in OrdinaryConstruct, it wouldn't survive. Maybe Allen can clarify?

Also, this is the exact pain point case that Array.from was designed to address, but existing code shouldn't break in the interim.

Rick




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12