[].push wrt properties along the [[Prototype]] chain

Allen Wirfs-Brock allen at wirfs-brock.com
Sat Feb 16 10:51:13 PST 2013


On Feb 15, 2013, at 6:30 PM, Jeff Walden wrote:

> Consider:
> 
>  Object.defineProperty(Object.prototype, "0", { value: 17, writable: false, configurable: false });
>  [].push(42);
> 
> Per ES5, I think this is supposed to throw a TypeError.  The push should be setting property "0" with Throw = true, which means that when [[CanPut]] fails, a TypeError gets thrown.  No engine I can test does this, I suspect because everyone's mis-implemented an optimization.

Right, ES5 carefully put in all those Throw = true's, to account for exactly those situations.   Did you also test for non-writable and accessor properties on an actual Array instance.

Did you try this on IE9/10 (I don't have copies available with me right now).  All the other browsers had implementations of push and other Array methods  that predate ES5, so it is conceivable that those implementations have not been updated to match the spec. IE9, on the other-hand, was a new implementation that post dates ES5 and was supposed to be following the spec.

I'm shocked if Test262 doesn't include any tests for these situations.  I'm remember including them in a list of things that needed to be tested for all of the Array methods that was handed off to the team that wrote the  Test262 tests.

> 
> On IRC it was pointed out that http://wiki.ecmascript.org/doku.php?id=strawman:fixing_override_mistake is supposed to fix this: you should be able to shadow a non-writable property on a prototype.  Or something.  But there's contention there about this not actually being a mistake.  (I think that contention's probably right, for what it's worth, but I digress.)
> 
> But suppose it isn't, for the moment.  What then of this:
> 
>  Object.defineProperty(Object.prototype, 0, { set: function() { throw "FAIL"; } });
>  [].push(42)
> 
> I think this should throw, again because it's *setting* property "0".  But again, no engine I can test actually throws for this.
> 
> My gut says this is a case where every engine attempted to optimize, and optimized wrongly such that incorrect semantics resulted.  The question is, since no engine's following the spec, whether the spec should change, the engines should change, or what.  Given that indexed properties on Array.prototype and Object.prototype are not something anyone sane does, I tend to think changing it to [[DefineOwnProperty]] would be good.  But maybe the spec really should win, and everyone should change.  I dunno.  Please sort this out!  :-)

Prior to ES5, implementations were doing various random things for the edge cases of accessor properties in arrays.  ES5 now tells them what they are supposed to do.

Note that implementation bugs aren't just in the Array methods and don't require access to inherited properties.  I just tried the following  in a FF18 scratch pad:

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/
var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/
var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/
var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/

var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/


Note that no exception was reported on the [[Put]] to the accessor.

Allen
var a = []
Object.defineProperty(a, "1", {
    get: function() {throw "get"; return "got 1"},
    put: function(v) {throw "put"+v}, 
    configurable: true});

a[1]
/*
Exception: get
*/

a[1]=0
/*
0
*/


> 
> Jeff
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130216/001f6927/attachment-0001.html>


More information about the es-discuss mailing list