Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 16, 2014, at 11:08 PM, Tom Van Cutsem wrote: 2014-11-17 3:34 GMT+01:00 Frankie Bagnardi f.bagna...@gmail.com: Consider when Array.isArray would be used. In my experience, checks to see if something is an array are used for: - deciding how to iterate it (for(;;) vs for..in, for example) This is a good one. Here, again, a typical proxy-for-array would work as intended, as the for(;;) loop just queries .length and properties named 0, 1, ... via standard [[Get]] access. Can someone come up with a convincing example where a proxy-for-array would *not* work as intended? (convincing here means it doesn't involve a proxy that blatantly violates the Array contract on purpose) Probably not, because the Array.prototype methods are all carefully coded to not have any internal slot or this identify dependencies. But probing through the proxy as has been proposed is a terrible violation of the MOP API boundary and isn't generalizable to other built-ins that are dependent upon internal state. While a null handler proxy on a direct instance of Array would work under that design, a comparable Map.isMap or Promise.isPromise method would not. Rather than a one-off hack I think we should use a new pattern that is generalizable: Here is a proposal: Array.isArray is redefined equivalently to: ```js Array.isArray = function (obj) { let constructor = obj.constructor; If (typeof constructor != 'function') return false; return !!constructor[Symbol.isArray]; } ``` and also ```js Array[Symbol.isArray]] = true; //note, this is a constructor property, not an Array.prototype property. ``` we also change Array.prototype.concat to do the above Array.isArray test instead of using @@comcatSpreadable and change JSON.stringify to use this test where it current checks for an exotic array object. Then we have the following: assert(Array.isArray( [ ] )); //just like ES5 assert( ! Array.isArray( Object.create(Array.prototype))); //just like ES5 assert (new class extends Array{}); //ES6 Array subclass instances answer true unless the subclass over-rides the static @@isArray property assert(new class extends Array { constructor() {return {}}; }); // even if the subclass instance isn't an exotic array object (this is an improvement over the current ES6 spec. which says that //isArray answers false in this case assert(new Proxy( [ ], { }); //because it's all done with property access, no instance inspection required. assert( ! new Int32Array(10)); //not array-like, just like ES5 However, I think we should experiment with giving %TypedArrau% is true valued @@isArray property. I'm guessing that this change won't actually break anything. the above proposal completely decouples Array.isArray from exotic array object checking or any other direct instance inspection. Everything works at the property access level and so is (by default) transparent to proxies and completely controllable at the ES cod level. allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Allen Wirfs-Brock wrote: ```js Array[Symbol.isArray]] = true; //note, this is a constructor property, not an Array.prototype property. Minomer, then -- how about Symbol.isArrayClass? we also change Array.prototype.concat to do the above Array.isArray test instead of using @@comcatSpreadable and change JSON.stringify to use this test where it current checks for an exotic array object. Then we have the following: assert(Array.isArray( [ ] )); //just like ES5 assert( ! Array.isArray( Object.create(Array.prototype))); //just like ES5 How so? True: js Array.isArray(Array.prototype) true js Array.isArray(Object.create(Array.prototype)) false but constructor isn't shadowed: js Array.prototype.constructor function Array() { [native code] } js Object.create(Array.prototype).constructor function Array() { [native code] } assert (new class extends Array{}); //ES6 Array subclass instances answer true unless the subclass over-rides the static @@isArray property assert(new class extends Array { constructor() {return {}}; }); // even if the subclass instance isn't an exotic array object (this is an improvement over the current ES6 spec. which says that //isArray answers false in this case assert(new Proxy( [ ], { }); //because it's all done with property access, no instance inspection required. (These want Array.isArray inside assert, of course.) assert( ! new Int32Array(10)); //not array-like, just like ES5 However, I think we should experiment with giving %TypedArrau% is true valued @@isArray property. I'm guessing that this change won't actually break anything. Probably ok. the above proposal completely decouples Array.isArray from exotic array object checking or any other direct instance inspection. Everything works at the property access level and so is (by default) transparent to proxies and completely controllable at the ES cod level. Righteous goal! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 17, 2014, at 11:06 AM, Brendan Eich wrote: Allen Wirfs-Brock wrote: ```js Array[Symbol.isArray]] = true; //note, this is a constructor property, not an Array.prototype property. Minomer, then -- how about Symbol.isArrayClass? perhaps, I have a negative reaction to including the work class but can probably live with it. we also change Array.prototype.concat to do the above Array.isArray test instead of using @@comcatSpreadable and change JSON.stringify to use this test where it current checks for an exotic array object. Then we have the following: assert(Array.isArray( [ ] )); //just like ES5 assert( ! Array.isArray( Object.create(Array.prototype))); //just like ES5 How so? True: js Array.isArray(Array.prototype) true js Array.isArray(Object.create(Array.prototype)) false but constructor isn't shadowed: js Array.prototype.constructor function Array() { [native code] } js Object.create(Array.prototype).constructor function Array() { [native code] } Shit, you're right. This is the hard case for legacy compat using this technique. I think I see a way to make this give the legacy answer, but I suspect I can't make it give the same answer for Array.isArray(new Proxy(Object.create(Array.prototype), { })); May limiting the WTF=ness to that case isn't so bad. assert (new class extends Array{}); //ES6 Array subclass instances answer true unless the subclass over-rides the static @@isArray property assert(new class extends Array { constructor() {return {}}; }); // even if the subclass instance isn't an exotic array object (this is an improvement over the current ES6 spec. which says that //isArray answers false in this case assert(new Proxy( [ ], { }); //because it's all done with property access, no instance inspection required. (These want Array.isArray inside assert, of course.) of course assert( ! new Int32Array(10)); //not array-like, just like ES5 However, I think we should experiment with giving %TypedArrau% is true valued @@isArray property. I'm guessing that this change won't actually break anything. Probably ok. the above proposal completely decouples Array.isArray from exotic array object checking or any other direct instance inspection. Everything works at the property access level and so is (by default) transparent to proxies and completely controllable at the ES cod level. Righteous goal! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 17, 2014, at 2:30 PM, Allen Wirfs-Brock wrote: On Nov 17, 2014, at 11:06 AM, Brendan Eich wrote: Allen Wirfs-Brock wrote: ```js Array[Symbol.isArray]] = true; //note, this is a constructor property, not an Array.prototype property. Minomer, then -- how about Symbol.isArrayClass? perhaps, I have a negative reaction to including the work class but can probably live with it. we also change Array.prototype.concat to do the above Array.isArray test instead of using @@comcatSpreadable and change JSON.stringify to use this test where it current checks for an exotic array object. Then we have the following: assert(Array.isArray( [ ] )); //just like ES5 assert( ! Array.isArray( Object.create(Array.prototype))); //just like ES5 How so? True: js Array.isArray(Array.prototype) true js Array.isArray(Object.create(Array.prototype)) false but constructor isn't shadowed: js Array.prototype.constructor function Array() { [native code] } js Object.create(Array.prototype).constructor function Array() { [native code] } Shit, you're right. This is the hard case for legacy compat using this technique. I think I see a way to make this give the legacy answer, but I suspect I can't make it give the same answer for Array.isArray(new Proxy(Object.create(Array.prototype), { })); May limiting the WTF=ness to that case isn't so bad. OK, this should deal with the Object.create(Array.prototype) case Array.isArray = function isArray(obj) { let constructor = obj.constructor; If (typeof constructor != 'function') return false; let construictorIs be Object.getOwnPropertyDescript(constructor,isArray); if (constructorIs) { //the constructor has an isArray property, so we'll assume it is a built-in Array constructor if (isOrdinaryObject(obj)) return false; //The Object.create(Array.prototype) legacy compat. case. if (isProxy(obj)) return isArray(getProxyTarget(obj)); //Array.isArray(new Proxy(Object.create(Array.prototype), {})) //I'm not sure that the above line is really a compat. issue. I'd prefer to leave it out. } return !!constructor[Symbol.isArray]; } It takes a little hackery to deal with the legacy Object.create(Array.prototype) cases but for ES6 subclasses and non-subclasses such as typed arrays it doesn't perform any exotic instance sniffing. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Allen Wirfs-Brock wrote: if (isProxy(obj)) return isArray(getProxyTarget(obj)); //Array.isArray(new Proxy(Object.create(Array.prototype), {})) //I'm not sure that the above line is really a compat. issue. I'd prefer to leave it out. Please do -- it contradicts the righteous goal. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-17 18:30 GMT+01:00 Allen Wirfs-Brock al...@wirfs-brock.com: But probing through the proxy as has been proposed is a terrible violation of the MOP API boundary and isn't generalizable to other built-ins that are dependent upon internal state. While a null handler proxy on a direct instance of Array would work under that design, a comparable Map.isMap or Promise.isPromise method would not. Rather than a one-off hack I think we should use a new pattern that is generalizable: If we can find consensus on this much more general pattern of type-testing by using a symbol on the constructor, I'm all for it. +1! I also think we don't want to special-case Proxies in the proposed type-testing algorithm. That said, if we cannot come to a consensus on this more generic form of type-testing, I would still defend the position that Array.isArray merits an exception (compared to Map.isMap/Promise.isPromise etc.) *precisely because* Arrays were carefully defined not to depend on any special instance state. In this scenario, repurposing the @@isConcatSpreadable symbol seems like the most obvious thing to do (it currently feels terribly ad-hoc, making it something more generic such as @@isArrayLike makes more sense to me) Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On 11/16/14, 2:12 AM, Brendan Eich wrote: Are you confident this change is web-compatible? No, I said that up-thread already. So there may be nothing to worry about here spec-wise for now. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Consider when Array.isArray would be used. In my experience, checks to see if something is an array are used for: - deciding how to iterate it (for(;;) vs for..in, for example) - deciding if the output should be an array or plain object (e.g. lodash) - early errors, e.g. runtime typecheck errors In all of these situations, I don't care if it is an actual per-spec exact array, I care if I can use it like an array. That's how Array.isArray will likely be used, and if it runs into problems, then expect github to be full of 'don't use Array.isArray' patches on many libraries, much like the existing instanceof situation. On Sun, Nov 16, 2014 at 11:20 AM, Boris Zbarsky bzbar...@mit.edu wrote: On 11/16/14, 2:12 AM, Brendan Eich wrote: Are you confident this change is web-compatible? No, I said that up-thread already. So there may be nothing to worry about here spec-wise for now. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-17 3:34 GMT+01:00 Frankie Bagnardi f.bagna...@gmail.com: Consider when Array.isArray would be used. In my experience, checks to see if something is an array are used for: - deciding how to iterate it (for(;;) vs for..in, for example) This is a good one. Here, again, a typical proxy-for-array would work as intended, as the for(;;) loop just queries .length and properties named 0, 1, ... via standard [[Get]] access. Can someone come up with a convincing example where a proxy-for-array would *not* work as intended? (convincing here means it doesn't involve a proxy that blatantly violates the Array contract on purpose) Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Le 13/11/2014 17:29, Boris Zbarsky a écrit : On 11/13/14, 6:44 AM, Andreas Rossberg wrote: Well, the actual diabolic beast and universal foot gun in this example is setPrototypeOf. ;) Note that there is at least some discussion within Mozilla about trying to make the prototype of Object.prototype immutable (such that Object.getPrototypeOf(Object.prototype) is guaranteed to always return the same thing, modulo someone overriding Object.getPrototypeOf), along with a few other things along those lines. See https://bugzilla.mozilla.org/show_bug.cgi?id=1052139. This would result in objects which [[Prototype]] cannot be changed but which properties can be changed. This is not possible per ES6 semantics I believe unless the object is a proxy (which setPrototypeOf trap throws unconditionally and forwards the rest to the target). Is it a satisfactory explanation? Should new primitives be added? Whether this is web-compatible, we'll see. I guess my above questions can wait the answer to this part. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 15, 2014, at 1:24 AM, David Bruant wrote: Le 13/11/2014 17:29, Boris Zbarsky a écrit : On 11/13/14, 6:44 AM, Andreas Rossberg wrote: Well, the actual diabolic beast and universal foot gun in this example is setPrototypeOf. ;) Note that there is at least some discussion within Mozilla about trying to make the prototype of Object.prototype immutable (such that Object.getPrototypeOf(Object.prototype) is guaranteed to always return the same thing, modulo someone overriding Object.getPrototypeOf), along with a few other things along those lines. See https://bugzilla.mozilla.org/show_bug.cgi?id=1052139. This would result in objects which [[Prototype]] cannot be changed but which properties can be changed. This is not possible per ES6 semantics I believe unless the object is a proxy (which setPrototypeOf trap throws unconditionally and forwards the rest to the target). Is it a satisfactory explanation? Should new primitives be added? Actually the ES6 semantics does allow for this. The global object would have t be implemented as a new kind of implementation specific exotic object whose [[SetPrototypeOf]] internal method always returns false. A Proxy would be required to self-host such an object using ES code, but at the implementation level a Proxy would not be required. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On 11/15/14, 11:47 AM, Allen Wirfs-Brock wrote: Actually the ES6 semantics does allow for this. The global object would have t be implemented as a new kind of implementation specific exotic object whose [[SetPrototypeOf]] internal method always returns false. That works for the global object (which is an exotic object anyway in browsers, because it has Web IDL branding of various sorts), but not for Object.prototype -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Boris Zbarsky wrote: On 11/15/14, 11:47 AM, Allen Wirfs-Brock wrote: - hide quoted text -- show quoted text - Actually the ES6 semantics does allow for this. The global object would have t be implemented as a new kind of implementation specific exotic object whose [[SetPrototypeOf]] internal method always returns false. That works for the global object (which is an exotic object anyway in browsers, because it has Web IDL branding of various sorts), but not for Object.prototype Perhaps a one-off exception? Are you confident this change is web-compatible? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
As quick parenthesis, I do hope the potentially evil code I've written will be possible in the future, as universal solution to `undefined is not defined` error in development code. evil is never necessarily evil, going with prohibitionism won't make anyone happy. About `Array.isArray` though, I believe devs expect the Proxy to be transparent, but again, for development or library sake, I expect developers to be able to tell if there is some cellophane around their objects. Array.isArray(proxied) whould be true if the proxied object isArray, but please consider give developers a way to understand if there is a proxy around. It won't be a good looking thing, but as it's needed internally, it might be needed out there too. Regards On Thu, Nov 13, 2014 at 3:48 PM, David Bruant bruan...@gmail.com wrote: The best defense is Object.freeze(Object.prototype); No application worth considering needs to arbitrarily modify Object.prototype at an arbitrary point in time (or someone should bring a use case for discussion). It usually shouldn't and even if it does, it should do it at startup and freeze it afterwards. Le 13/11/2014 12:25, Andrea Giammarchi a écrit : well, Proxy can be a diabolic beast ```js Object.setPrototypeOf( Object.prototype, new Proxy(Object.prototype, evilPlan) ) ``` having no way to understand if an object is a Proxy looks like a footgun to me in the long term, for libraries, and code alchemists You're giving guns to people and try to evaluate how to defend from them. Consider not letting guns around the rooms ;-) David You indeed wrote that different Array methods need to know if there's a Proxy in there ... if dev cannot know the same via code they are unable again to subclass properly or replicate native behaviors behind magic internal checks. If there is a way and I'm missing it, then it's OK Regards On Thu, Nov 13, 2014 at 7:15 AM, Tom Van Cutsem tomvc...@gmail.com wrote: 2014-11-12 23:49 GMT+01:00 Andrea Giammarchi andrea.giammar...@gmail.com : If Array.isArray should fail for non pure Arrays, can we have a Proxy.isProxy that never fails with proxies ? We ruled out `Proxy.isProxy` very early on in the design. It's antithetical to the desire of keeping proxies transparent. In general, we want to discourage type checks like you just wrote. If you're getting handed an object you don't trust and need very strong guarantees on its behavior, you'll need to make a copy. This is true regardless of proxies. In your example, even if the array is genuine, there may be some pointer alias to the array that can change the array at a later time. Regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Tom Van Cutsem Is the `length` invariant really the dominant meaning JS developers attribute to Array.isArray? I think to most developers Array.isArray(obj) returning true means that it's safe to call the array utilities (map, forEach, ...) on obj, not so much that obj.length is special. This is really interesting. It does argue for some kind of redefinition of Array.isArray to return is this an instance of some %ArrayPrototype% in some realm? That is very close to does the object have an @@isConcatSpreadable property, the main difference being that you can fake the latter via `myObj[Symbol.isConcatSpreadable] = true` while still not inheriting from any %ArrayPrototype%. --- To me the most interesting question is how to create objects that get JSON-stringified as [], not {}. Some sort of symbol-based mechanism makes sense for that, IMO... ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Hai. Why not Symbol.isArray? To me the most interesting question is how to create objects that get JSON-stringified as [], not {}. Some sort of symbol-based mechanism makes sense for that, IMO... toJSON method. `JSON.stringify({toJSON: () = [2,3,4,5]})` ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
This is really interesting. It does argue for some kind of redefinition of Array.isArray to return is this an instance of some %ArrayPrototype% in some realm? Yeah, my guess would be that if (Array.isArray(obj) === true), then the user will infer that one or both of the following is true: - It behaves as if it were created with an array literal (including the length invariant and Array.prototype methods). - It should be rendered (via JSON or console output) as if it were created with an array literal. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 13, 2014, at 5:02 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: We might redefine Array.isArray to be based upon testing for @@isConcatSpreadable but that potentially would give different results for legacy uses that did __proto__ hacking such as I mentioned in my previous mote. How about we turn the @@ property into @@isArrayLike or @@isStronglyArrayLike if you insist. This could be done, but that property could pre-exist on Array prototype. If it did, it would change the behavior (probably including the JSON.stringify behavior) of existing code that puts Array.prototype on its [[Prototype]] chain. The definition of Array.isArray(obj) would be roughly: 1. Let isArray be ToBoolean(Get(obj, @@isArrayLike)); 2. If isArray is true, then return true; 3. If obj is an exotic array object, then return true; 4. return false Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 14, 2014, at 4:53 AM, Domenic Denicola wrote: From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Tom Van Cutsem Is the `length` invariant really the dominant meaning JS developers attribute to Array.isArray? I think to most developers Array.isArray(obj) returning true means that it's safe to call the array utilities (map, forEach, ...) on obj, not so much that obj.length is special. This is really interesting. It does argue for some kind of redefinition of Array.isArray to return is this an instance of some %ArrayPrototype% in some realm? That is very close to does the object have an @@isConcatSpreadable property, the main difference being that you can fake the latter via `myObj[Symbol.isConcatSpreadable] = true` while still not inheriting from any %ArrayPrototype%. What do you mean by is an instance of some %ArrayPrototype%? Do you mean that it has some %ArratPrototype% in it's prototype chain? This is actually fairly hard to determine. We look at trying to identify known prototypes independent of realm for an earlier issue and rejected the possibility because it would require additional tragging of such prototypes. Also, it wasn't clear who the concept could be extended to JS defined classes. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
From: Allen Wirfs-Brock [mailto:al...@wirfs-brock.com] What do you mean by is an instance of some %ArrayPrototype%? Do you mean that it has some %ArratPrototype% in it's prototype chain? Yeah, more or less. A realm-independent instanceof. This makes sense also from the historical perspective that `Array.isArray` was meant to provide a cross-realm alternative to `instanceof Array`. (I believe that was the case; before my time.) However as you pointed out in a related conversation this would not be backward-compatible, i.e. it would change the answer for code that does prototype munging. This is actually fairly hard to determine. We look at trying to identify known prototypes independent of realm for an earlier issue and rejected the possibility because it would require additional tragging of such prototypes. Also, it wasn't clear who the concept could be extended to JS defined classes. Right, good points. Probably not the way to go, indeed. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 14, 2014, at 11:41 AM, Domenic Denicola wrote: From: Allen Wirfs-Brock [mailto:al...@wirfs-brock.com] What do you mean by is an instance of some %ArrayPrototype%? Do you mean that it has some %ArratPrototype% in it's prototype chain? Yeah, more or less. A realm-independent instanceof. This makes sense also from the historical perspective that `Array.isArray` was meant to provide a cross-realm alternative to `instanceof Array`. (I believe that was the case; before my time.) No really, it was a way to expose a test of the [[Class]] internal property. That test wasn't dependent upon the [[Prototype]] chain. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-14 21:00 GMT+01:00 Allen Wirfs-Brock al...@wirfs-brock.com: On Nov 14, 2014, at 11:41 AM, Domenic Denicola wrote: Yeah, more or less. A realm-independent instanceof. This makes sense also from the historical perspective that `Array.isArray` was meant to provide a cross-realm alternative to `instanceof Array`. (I believe that was the case; before my time.) No really, it was a way to expose a test of the [[Class]] internal property. That test wasn't dependent upon the [[Prototype]] chain. I think what Domenic was saying is that Array.isArray used such a test *because* instanceof Array didn't work reliably cross-realms. I too vaguely recollect that reliable cross-realm instanceof Array testing was a primary motivation for Array.isArray. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Tom Van Cutsem wrote: No really, it was a way to expose a test of the [[Class]] internal property. That test wasn't dependent upon the [[Prototype]] chain. I think what Domenic was saying is that Array.isArray used such a test *because* instanceof Array didn't work reliably cross-realms. I too vaguely recollect that reliable cross-realm instanceof Array testing was a primary motivation for Array.isArray. Yes, that was Crock's stated motivation as I recall. Here's a 2003-era post from Doug: https://groups.google.com/forum/#!msg/comp.lang.javascript/XTWYCOwC96I/70rNoQ3L-xoJ /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-13 22:35 GMT+01:00 Tom Van Cutsem tomvc...@gmail.com: My intuition is that Array.isArray is often used to branch based on whether code received just one versus a collection of values. E.g. a function may take a single parameter that can be bound to either a single value or a collection of values, and treat a collection of values differently. In fact, that is essentially what Array.prototype.concat does: if the argument is an array, splice its values, otherwise, don't splice. This has nothing to do with `length` magic. The same goes for JSON.stringify (serialize as [] vs {}). Amusingly, not only does JSON.stringify(value, replacer, space) branch on the type of its `value` argument (to serialize as [] vs {}), it apparently also type-tests its `replacer` argument, which can either be a function or an array. If it's an array, it serves as a whitelist of the properties that can appear in the output. While it's unlikely anyone would ever want to pass a proxy-for-array as a JSON whitelist, JSON.stringify is an example of the kind of type-testing I had in mind to simply distinguish whether one of its parameters is just one value vs. a collection of values. For such functions, there would be no harm in treating proxies-for-arrays as arrays. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
I don't have the data to back this up, but I would argue that the developer community has essentially adopted `Array.isArray()` as a sane replacement for `Object.prototype.toString.call(maybeArray) === '[object Array]'`. I realize this forum doesn't have the luxury of *not* considering the nuances between a value having the right [[Class] property vs. having Array.prototype in the chain vs. having an exotic length property, etc., but I would at least suggest that the consumers of `Array.isArray()` are largely just concerned with whether or not they can do everything with a particular value that they could do if it were an actual array, while maintaining equal code semantics. Allen's previous comments: Proxies are not transparent forwarders! In particular their default handling of the `this` value on method invokes will break any built-in method that needs to access internal slots of an object. ...lead me to believe that this isn't the case for proxified Arrays, so I'd have to reverse my earlier position, as `Array.isArray(proxifiedArray)` evaluating to true just seems likely to break code. On Fri, Nov 14, 2014 at 3:36 PM, Brendan Eich bren...@mozilla.org wrote: Tom Van Cutsem wrote: No really, it was a way to expose a test of the [[Class]] internal property. That test wasn't dependent upon the [[Prototype]] chain. I think what Domenic was saying is that Array.isArray used such a test *because* instanceof Array didn't work reliably cross-realms. I too vaguely recollect that reliable cross-realm instanceof Array testing was a primary motivation for Array.isArray. Yes, that was Crock's stated motivation as I recall. Here's a 2003-era post from Doug: https://groups.google.com/forum/#!msg/comp.lang.javascript/XTWYCOwC96I/ 70rNoQ3L-xoJ /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Jeremy Martin 661.312.3853 http://devsmash.com @jmar777 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-14 21:52 GMT+01:00 Jeremy Martin jmar...@gmail.com: Allen's previous comments: Proxies are not transparent forwarders! In particular their default handling of the `this` value on method invokes will break any built-in method that needs to access internal slots of an object. ...lead me to believe that this isn't the case for proxified Arrays, so I'd have to reverse my earlier position, as `Array.isArray(proxifiedArray)` evaluating to true just seems likely to break code. For the particular case of Arrays though, because Array methods were carefully specified to be generic (i.e. to also work on non-array objects), they will work just fine on proxies-for-arrays: var p = new Proxy([1,2,3] , {} ); var a = p.map(function(x) { return x + 1; }); console.log(a); // [2,3,4] So, of all the exotic objects in the ES and WebIDL specs, Arrays are probably one of the few exceptions where a Proxy wrapper *is* transparent by default. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Tom Van Cutsem wrote: 2014-11-14 21:52 GMT+01:00 Jeremy Martin jmar...@gmail.com mailto:jmar...@gmail.com: Allen's previous comments: Proxies are not transparent forwarders! In particular their default handling of the `this` value on method invokes will break any built-in method that needs to access internal slots of an object. ...lead me to believe that this isn't the case for proxified Arrays, so I'd have to reverse my earlier position, as `Array.isArray(proxifiedArray)` evaluating to true just seems likely to break code. For the particular case of Arrays though, because Array methods were carefully specified to be generic (i.e. to also work on non-array objects), they will work just fine on proxies-for-arrays: var p = new Proxy([1,2,3] , {} ); var a = p.map(function(x) { return x + 1; }); console.log(a); // [2,3,4] So, of all the exotic objects in the ES and WebIDL specs, Arrays are probably one of the few exceptions where a Proxy wrapper *is* transparent by default. Right. There is no all-or-nothing solution. Allen's words applie to exceptions to the rule. Arrays and well-written proxies for them fit in the rule. Jeremy, what do you say? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
(Mostly) transparent forwarding seems to be one of the more compelling and generally useful characteristics of Proxies. I have to lean heavily on the deeper knowledge of the group here, but *if* `new Proxy([], {})` otherwise behaves like a bonafide array when you treat it like one, then it would be a pity to lose the ability to take advantage of that over `Array.isArray()` resolving to false. *If* transparent forwarding is an intended feature of proxied arrays, then I'd argue it's far too common of a test to discount . But again, I can't answer those ifs. :) On Fri, Nov 14, 2014 at 4:54 PM, Brendan Eich bren...@mozilla.org wrote: Tom Van Cutsem wrote: 2014-11-14 21:52 GMT+01:00 Jeremy Martin jmar...@gmail.com mailto: jmar...@gmail.com: Allen's previous comments: Proxies are not transparent forwarders! In particular their default handling of the `this` value on method invokes will break any built-in method that needs to access internal slots of an object. ...lead me to believe that this isn't the case for proxified Arrays, so I'd have to reverse my earlier position, as `Array.isArray(proxifiedArray)` evaluating to true just seems likely to break code. For the particular case of Arrays though, because Array methods were carefully specified to be generic (i.e. to also work on non-array objects), they will work just fine on proxies-for-arrays: var p = new Proxy([1,2,3] , {} ); var a = p.map(function(x) { return x + 1; }); console.log(a); // [2,3,4] So, of all the exotic objects in the ES and WebIDL specs, Arrays are probably one of the few exceptions where a Proxy wrapper *is* transparent by default. Right. There is no all-or-nothing solution. Allen's words applie to exceptions to the rule. Arrays and well-written proxies for them fit in the rule. Jeremy, what do you say? /be -- Jeremy Martin 661.312.3853 http://devsmash.com @jmar777 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
well, Proxy can be a diabolic beast ```js Object.setPrototypeOf( Object.prototype, new Proxy(Object.prototype, evilPlan) ) ``` having no way to understand if an object is a Proxy looks like a footgun to me in the long term, for libraries, and code alchemists You indeed wrote that different Array methods need to know if there's a Proxy in there ... if dev cannot know the same via code they are unable again to subclass properly or replicate native behaviors behind magic internal checks. If there is a way and I'm missing it, then it's OK Regards On Thu, Nov 13, 2014 at 7:15 AM, Tom Van Cutsem tomvc...@gmail.com wrote: 2014-11-12 23:49 GMT+01:00 Andrea Giammarchi andrea.giammar...@gmail.com : If Array.isArray should fail for non pure Arrays, can we have a Proxy.isProxy that never fails with proxies ? We ruled out `Proxy.isProxy` very early on in the design. It's antithetical to the desire of keeping proxies transparent. In general, we want to discourage type checks like you just wrote. If you're getting handed an object you don't trust and need very strong guarantees on its behavior, you'll need to make a copy. This is true regardless of proxies. In your example, even if the array is genuine, there may be some pointer alias to the array that can change the array at a later time. Regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On 13 November 2014 12:25, Andrea Giammarchi andrea.giammar...@gmail.com wrote: well, Proxy can be a diabolic beast ```js Object.setPrototypeOf( Object.prototype, new Proxy(Object.prototype, evilPlan) ) ``` having no way to understand if an object is a Proxy looks like a footgun to me in the long term, for libraries, and code alchemists Well, the actual diabolic beast and universal foot gun in this example is setPrototypeOf. ;) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Same would be reassigning any prototype but it was just to make the diabolic point... also yeah, sPO is powerful, that's why we love it! ( it's also way less diabolic than any __proto__ string floating around ;) ) On Thu, Nov 13, 2014 at 11:44 AM, Andreas Rossberg rossb...@google.com wrote: On 13 November 2014 12:25, Andrea Giammarchi andrea.giammar...@gmail.com wrote: well, Proxy can be a diabolic beast ```js Object.setPrototypeOf( Object.prototype, new Proxy(Object.prototype, evilPlan) ) ``` having no way to understand if an object is a Proxy looks like a footgun to me in the long term, for libraries, and code alchemists Well, the actual diabolic beast and universal foot gun in this example is setPrototypeOf. ;) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
The best defense is Object.freeze(Object.prototype); No application worth considering needs to arbitrarily modify Object.prototype at an arbitrary point in time (or someone should bring a use case for discussion). It usually shouldn't and even if it does, it should do it at startup and freeze it afterwards. Le 13/11/2014 12:25, Andrea Giammarchi a écrit : well, Proxy can be a diabolic beast ```js Object.setPrototypeOf( Object.prototype, new Proxy(Object.prototype, evilPlan) ) ``` having no way to understand if an object is a Proxy looks like a footgun to me in the long term, for libraries, and code alchemists You're giving guns to people and try to evaluate how to defend from them. Consider not letting guns around the rooms ;-) David You indeed wrote that different Array methods need to know if there's a Proxy in there ... if dev cannot know the same via code they are unable again to subclass properly or replicate native behaviors behind magic internal checks. If there is a way and I'm missing it, then it's OK Regards On Thu, Nov 13, 2014 at 7:15 AM, Tom Van Cutsem tomvc...@gmail.com mailto:tomvc...@gmail.com wrote: 2014-11-12 23:49 GMT+01:00 Andrea Giammarchi andrea.giammar...@gmail.com mailto:andrea.giammar...@gmail.com: If Array.isArray should fail for non pure Arrays, can we have a Proxy.isProxy that never fails with proxies ? We ruled out `Proxy.isProxy` very early on in the design. It's antithetical to the desire of keeping proxies transparent. In general, we want to discourage type checks like you just wrote. If you're getting handed an object you don't trust and need very strong guarantees on its behavior, you'll need to make a copy. This is true regardless of proxies. In your example, even if the array is genuine, there may be some pointer alias to the array that can change the array at a later time. Regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On 11/13/14, 6:44 AM, Andreas Rossberg wrote: Well, the actual diabolic beast and universal foot gun in this example is setPrototypeOf. ;) Note that there is at least some discussion within Mozilla about trying to make the prototype of Object.prototype immutable (such that Object.getPrototypeOf(Object.prototype) is guaranteed to always return the same thing, modulo someone overriding Object.getPrototypeOf), along with a few other things along those lines. See https://bugzilla.mozilla.org/show_bug.cgi?id=1052139. Whether this is web-compatible, we'll see. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 12, 2014, at 12:12 PM, Tom Van Cutsem tomvc...@gmail.com wrote: 2014-11-12 19:53 GMT+01:00 Rick Waldron waldron.r...@gmail.com: I agree and I want to know if you think this is worth revisiting once more? Next meeting's agenda? I don't think we've ever discussed this issue before during a TC39 meeting (but I didn't attend quite a few, so I may be wrong). Adding it to the agenda for next meeting seems good to me. Yes, this has been discussed at TC39 meetings although I’d have to go search notes for a record of it. Regardless, I’ll try to summarize the logic that lead to the current decision. First Array.isArray was introduced in ES5 to provide a reliable way to detect Array instances that works regardless of what realm created the instance. In ES5, Array.isArray is specified as a test whether the [[Class]] internal property has the the value “Array”. In ES5 the only objects that have that [[Class]] values are objects created use the Array constructor or using an Array literal (or internally instantiated objects created “as if” by `new Array`). Any such object responds true for Array.isArray even if its [[Prototype]] is set (using __proto__) to something different than Array.prototype. All ES5 objects for which Array.isArray answers true have exotic `length` behavior where adding an index property beyond the current `length` increases the value of `length` and deleting training index properties decrease the value of `length`. ES6 eliminates the [[Class]] internal properties, but the equivalent is any object that is an “exotic array object’ . Any “exotic array object” is an exotic object whose [[DefineProperty]] internal method maintains the `length` property invariant described above. ES6 specifies that Array.isArray answers true only for exotic array objects. Given any ES5-level ES code, the ES6 spec. will produce exactly the same result of Array.isArray as was produced by ES5. In deciding the ES6 behavior for Array.isArray we considered at least four significant issues: 1) Backwards compatibility with ES5 level code that uses ES5.1. It must produce the same result for all such code. This includes code that does __proto__ hacking. 2) ES6 subclassing. Given `let sa = new (class extends Array {});` what should be the value of `Array.isArray(sa)` ? This is something we explicitly talked about at TC39 meetings and agreed that the answer should be true (except when…). However, there are really two kinds of subclass to consider. Subclasses of Array that automatically inherit the creation of exotic array object instances and subclasses of Array that explicit over-ride in their constructor to produce some other kind of instance object (an ordinary object or perhaps some other kind of exotic object or a Proxy). Note this is roughly equivalent to ad hoc ES5 subclassing where you might either use __proto__ to change the [[Prototype]] of an array instance to something other than Array.prototype or where you might create an ordinary object (not an Array instance) and set its [[Prototype]] to Array.prototype in order to inherit Arrray.prototype methods. In the TC39 discussions we concluded that the exotic array based isArray definition gives reasonable answers for both ES5 and Es6 subclassing. 3) Proxies. Should Array.isArray treat proxy instances specially? To answer this question we need to think about what a ES programmer actually thinks Array.isArray means? The meaning that ES5 established is that Array.isArray returning true means that the object observably maintains the array `length` invariant. There is no general way to determine whether this invariant is true for an arbitrary proxy. Checking if the proxy’s target object is an exotic array object isn’t sufficient to say isArray is true because the defineProperty/get/set/delete traps might not maintain the invariant. Similar, checking that the object is an ordinary object isn’t suffiient for isArray to say false because appropriate the handler may impose the array `length` invariants upon an ordinary object. 4)Self-hosting Array. An ES6 goal was to allow self-hosting of built-ins using Proxy where necessary to implement self-hosted exotic objects. A implementation could self-host Array by using a Proxy that targeted an ordinary object and a handler that maintained the `length` invariants. However, if it did this, it would also have to provide an implementation of Array.isArray that was able to recognize those Proxy based self-hosted Array instances. It might by using some sort of private tagging mechanism of Array instances (for example via a WeakSet) that it’s Array.isArray would recognize. The current ES6 definition still seems like the best definition, if you accept that Array.isArray means does this object maintain the `length` invariant? Tunneling through a Proxy and testing if its target is an exotic array object isn’t an adequate fix, because of the reasons
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Nov 12, 2014, at 11:58 AM, Jeremy Martin wrote: My opinion is that array testing is fundamental to core JS and is worth the exception. Knowing that Array.isArray() tests fail for proxies, I'd be afraid to ever create a Proxy for an array that I don't control the complete lifecycle of. That seems to critically inhibit the usefulness of Proxies, especially when transparency seems to have been an intended characteristic of them going all the way back to the strawman days. Proxies are not transparent forwarders! In particular their default handling of the `this` value on method invokes will break any built-in method that needs to access internal slots of an object. ```js var p = new Proxy(new Array, {}); ``` will give you an object that will fail on serval of the Array.prototype methods. It is even worse for other built-ins such as Map or the typed array constructors. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-13 20:31 GMT+01:00 Allen Wirfs-Brock al...@wirfs-brock.com: 3) Proxies. Should Array.isArray treat proxy instances specially? To answer this question we need to think about what a ES programmer actually thinks Array.isArray means? The meaning that ES5 established is that Array.isArray returning true means that the object observably maintains the array `length` invariant. Is the `length` invariant really the dominant meaning JS developers attribute to Array.isArray? I think to most developers Array.isArray(obj) returning true means that it's safe to call the array utilities (map, forEach, ...) on obj, not so much that obj.length is special. My intuition is that Array.isArray is often used to branch based on whether code received just one versus a collection of values. E.g. a function may take a single parameter that can be bound to either a single value or a collection of values, and treat a collection of values differently. In fact, that is essentially what Array.prototype.concat does: if the argument is an array, splice its values, otherwise, don't splice. This has nothing to do with `length` magic. The same goes for JSON.stringify (serialize as [] vs {}). Now, if we take the meaning of Array.isArray to be supports the Array.prototype utility methods, a proxy-for-array may of course expose a totally different API, leading a client that expects to be able to use the Array.prototype methods to fail. But this foregoes the fact that for virtually all practical use cases of proxies, proxy authors will not do this. They want to be able to wrap objects, intercept some things, but mostly faithfully forward those operations to the wrapped target. It would be rare for a proxy to change the API of the thing it wraps. Indeed, the whole point of proxies is to be able to intercept operations without modifying client code. Regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Allen Wirfs-Brock wrote: We might redefine Array.isArray to be based upon testing for @@isConcatSpreadable but that potentially would give different results for legacy uses that did __proto__ hacking such as I mentioned in my previous mote. How about we turn the @@ property into @@isArrayLike or @@isStronglyArrayLike if you insist. Now, if we take the meaning of Array.isArray to be supports the Array.prototype utility methods, a proxy-for-array may of course expose a totally different API, leading a client that expects to be able to use the Array.prototype methods to fail. But this foregoes the fact that for virtually all practical use cases of proxies, proxy authors will not do this. They want to be able to wrap objects, intercept some things, but mostly faithfully forward those operations to the wrapped target. It would be rare for a proxy to change the API of the thing it wraps. Indeed, the whole point of proxies is to be able to intercept operations without modifying client code. Certainly if you use a proxy to define a virtual object, to self-host, spec-defined exotic objects or to implement DOM objects you just aren't transparently wrapping the target object... I think at the root of this is that many JS programmer don't really understand what is (or isn't special about Array instances and that Array.isArray may have just added to the confusion. That may be, but (part of) our job is to help them. So progressively refining the meaning via @@isArrayLike seems winning. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
I agree with your sentiment. I have previously advocated that Array.isArray should be transparent for proxies. My harmony-reflect shim explicitly differs from the spec on this point because people using the shim spontaneously reported this as the expected behaviour and thought it was a bug that Array.isArray didn't work transparently on proxies. As far as I can remember, the argument against making Array.isArray transparent is that it's ad hoc and doesn't generalize to other types / type tests. My opinion is that array testing is fundamental to core JS and is worth the exception. Regards, Tom 2014-11-12 17:04 GMT+01:00 Axel Rauschmayer a...@rauschma.de: The subject is a SpiderMonkey bug. Is that really desirable? Doesn’t it invalidate the Proxy’s role as an interceptor? -- Dr. Axel Rauschmayer a...@rauschma.de rauschma.de ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
Le 12/11/2014 17:23, Tom Van Cutsem a écrit : I agree with your sentiment. I have previously advocated that Array.isArray should be transparent for proxies. My harmony-reflect shim explicitly differs from the spec on this point because people using the shim spontaneously reported this as the expected behaviour and thought it was a bug that Array.isArray didn't work transparently on proxies. For reference https://github.com/tvcutsem/harmony-reflect/issues/13 As far as I can remember, the argument against making Array.isArray transparent is that it's ad hoc and doesn't generalize to other types / type tests. My opinion is that array testing is fundamental to core JS and is worth the exception. Agreed. Author usability should trump language purity. David Regards, Tom 2014-11-12 17:04 GMT+01:00 Axel Rauschmayer a...@rauschma.de mailto:a...@rauschma.de: The subject is a SpiderMonkey bug. Is that really desirable? Doesn’t it invalidate the Proxy’s role as an interceptor? -- Dr. Axel Rauschmayer a...@rauschma.de mailto:a...@rauschma.de rauschma.de http://rauschma.de ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Wed, Nov 12, 2014 at 11:23 AM, Tom Van Cutsem tomvc...@gmail.com wrote: My opinion is that array testing is fundamental to core JS and is worth the exception. I agree and I want to know if you think this is worth revisiting once more? Next meeting's agenda? Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-12 19:53 GMT+01:00 Rick Waldron waldron.r...@gmail.com: I agree and I want to know if you think this is worth revisiting once more? Next meeting's agenda? I don't think we've ever discussed this issue before during a TC39 meeting (but I didn't attend quite a few, so I may be wrong). Adding it to the agenda for next meeting seems good to me. regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
In general, it appears that SM unwraps proxies so that internal slot access is transparently forwarded. I don't see any such unwrapping in the ES spec though. I assume that the spec is correct? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On Wed, Nov 12, 2014 at 2:12 PM, Tom Van Cutsem tomvc...@gmail.com wrote: 2014-11-12 19:53 GMT+01:00 Rick Waldron waldron.r...@gmail.com: I agree and I want to know if you think this is worth revisiting once more? Next meeting's agenda? I don't think we've ever discussed this issue before during a TC39 meeting (but I didn't attend quite a few, so I may be wrong). Adding it to the agenda for next meeting seems good to me. Done https://github.com/tc39/agendas/blob/master/2014/11.md Rick regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
My opinion is that array testing is fundamental to core JS and is worth the exception. Knowing that Array.isArray() tests fail for proxies, I'd be afraid to ever create a Proxy for an array that I don't control the complete lifecycle of. That seems to critically inhibit the usefulness of Proxies, especially when transparency seems to have been an intended characteristic of them going all the way back to the strawman days. On Wed, Nov 12, 2014 at 2:37 PM, Kevin Smith zenpars...@gmail.com wrote: In general, it appears that SM unwraps proxies so that internal slot access is transparently forwarded. I don't see any such unwrapping in the ES spec though. I assume that the spec is correct? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Jeremy Martin 661.312.3853 http://devsmash.com @jmar777 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
If Array.isArray should fail for non pure Arrays, can we have a Proxy.isProxy that never fails with proxies ? At least this would give a better idea on what's eventually going on: ```js if (Array.isArray(obj) !Proxy.isProxy(obj)) { // ... ok, pure Array, no magic wrappers } ``` Regards On Wed, Nov 12, 2014 at 6:47 PM, David Bruant bruan...@gmail.com wrote: Le 12/11/2014 17:23, Tom Van Cutsem a écrit : I agree with your sentiment. I have previously advocated that Array.isArray should be transparent for proxies. My harmony-reflect shim explicitly differs from the spec on this point because people using the shim spontaneously reported this as the expected behaviour and thought it was a bug that Array.isArray didn't work transparently on proxies. For reference https://github.com/tvcutsem/harmony-reflect/issues/13 As far as I can remember, the argument against making Array.isArray transparent is that it's ad hoc and doesn't generalize to other types / type tests. My opinion is that array testing is fundamental to core JS and is worth the exception. Agreed. Author usability should trump language purity. David Regards, Tom 2014-11-12 17:04 GMT+01:00 Axel Rauschmayer a...@rauschma.de: The subject is a SpiderMonkey bug. Is that really desirable? Doesn’t it invalidate the Proxy’s role as an interceptor? -- Dr. Axel Rauschmayer a...@rauschma.de rauschma.de ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing listes-discuss@mozilla.orghttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-12 20:37 GMT+01:00 Kevin Smith zenpars...@gmail.com: In general, it appears that SM unwraps proxies so that internal slot access is transparently forwarded. I don't see any such unwrapping in the ES spec though. I assume that the spec is correct? This auto-unwrapping for internal slots used to be part of an early iteration of direct proxies http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies#wrapping_irregular_objects but was not carried over into the ES6 spec. IIRC, mainly because just forwarding any internal slot access endangers the encapsulation properties of membrane-like use cases. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-12 23:49 GMT+01:00 Andrea Giammarchi andrea.giammar...@gmail.com: If Array.isArray should fail for non pure Arrays, can we have a Proxy.isProxy that never fails with proxies ? We ruled out `Proxy.isProxy` very early on in the design. It's antithetical to the desire of keeping proxies transparent. In general, we want to discourage type checks like you just wrote. If you're getting handed an object you don't trust and need very strong guarantees on its behavior, you'll need to make a copy. This is true regardless of proxies. In your example, even if the array is genuine, there may be some pointer alias to the array that can change the array at a later time. Regards, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
On 12 November 2014 17:23, Tom Van Cutsem tomvc...@gmail.com wrote: My opinion is that array testing is fundamental to core JS and is worth the exception. This change would only make sense if we also were to special-case all other places in the spec that currently say if O is an exotic Array object, ... to magically handle proxies. Otherwise, all you get is a predicate that gives a misleading result. However, I don't think we want to special-case all those places. That would put us on a very slippery slope. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-12 20:53 GMT+01:00 Rick Waldron waldron.r...@gmail.com: Done https://github.com/tc39/agendas/blob/master/2014/11.md Thanks. A related point: my harmony-reflect shim also patches Array.prototype.concat such that it recognizes proxies-for-arrays and will splice their elements (rather than adding the proxy as a single element to the target array). In ES6, this may not be necessary since a proxy could implement @@isConcatSpreadable (see http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.concat step 9.b) However, looking at IsConcatSpreadable http://people.mozilla.org/~jorendorff/es6-draft.html#sec-isconcatspreadable step 5, you'll notice it explicitly tests for Arrays. *If* we decide that Array.isArray should return `true` for proxies-for-arrays, *then* I think we should relax this step 5 to also return `true` for proxies-for-arrays, on the grounds of consistency and principle-of-least-surprise. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.isArray(new Proxy([], {})) should be false (Bug 1096753)
2014-11-13 8:18 GMT+01:00 Andreas Rossberg rossb...@google.com: On 12 November 2014 17:23, Tom Van Cutsem tomvc...@gmail.com wrote: My opinion is that array testing is fundamental to core JS and is worth the exception. This change would only make sense if we also were to special-case all other places in the spec that currently say if O is an exotic Array object, ... to magically handle proxies. Otherwise, all you get is a predicate that gives a misleading result. Yes, good point. See my just-recent post on Array.prototype.concat. However, I don't think we want to special-case all those places. That would put us on a very slippery slope. A cursory look at the spec reveals the following built-ins that test for exotic Arrays: - Array.isArray - Array.prototype.concat - Array.prototype.filter - Array.prototype.map - Array.prototype.slice - Array.prototype.splice - JSON.parse - JSON.stringify - Object.prototype.toString filter, map, slice and splice didn't used to test for arrays in ES5. They seem to test for arrays such that the new array they create derives from the same realm. This can probably be made to work with proxies-for-arrays, but I'm not sure it is necessary or desirable. For JSON.stringify, the question is whether a proxy-for-array should serialize as [] vs {}. Obviously, if Array.isArray(proxyForArray), I would expect it to serialize as []. For toString, proxies could still implement @@toStringTag to be able to intercept that call. At this point, I believe Object.prototype.toString.call(proxyForArray) would return [object Object]. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss