domenic at domenicdenicola.com (2013-10-26T03:18:29.889Z)
Allen Wirfs-Brock wrote:
> Anybody want to argue that Object.assign shouldn't trigger
> [[SetPrototypeOf]]?
Given that `__proto__` is defined as an accessor on `Object.prototype`, I think this should be expected. Any other setter defined on the object or its prototype chain will be invoked in the same manner. It's directly triggering `[[SetPrototypeOf]]`, it's just invoking the `__proto__` setter which happens to trigger `[[SetPrototypeOf]]`. Any number of accessor properties could do weird things:
Object.defineProperty(Object.prototype, 'bloikle', {
set(value) { Object.freeze(this); }
});
// Somewhere else far off in the code...
Object.assign(foo, { bloikle: 'bar' });
// Now foo is strangely frozen...
For consistency, `__proto__` shouldn't be hidden from `Object.assign`.
Plus, there's no reason this shouldn't work:
var info = JSON.stringify(
'{ "__proto__": "A description of __proto__",' +
'"hasOwnProperty": "A description of hasOwnProperty" }'
);
var otherInfo = JSON.stringify(
'{ "propertyIsEnumerable": "A description of propertyIsEnumerable" }'
);
Object.assign(otherInfo, info);
console.log(info.__proto__);
Exploring other options.. A possible alternative consistent option would be to expose some mechanism to hide properties from `Object.assign`, so that the bloikle property could be hidden in the above... Doing this well would probably require a way to make it work cross-realm, which at first thought sounds pretty difficult. And it probably wouldn't play nice with the above `info` example.
I think I agree with Andrea on this. Should `Object.assign` be left out of ES6 for libraries to implement? ... especially given that this `__proto__` dilemma feels "messy".
> Allen Wirfs-Brock wrote: > Actually, this is a good point. As currently specified Object.assign > of with an own __proto__ property on the RHS object will trigger a > [[SetPrototypeOf]] on the LHS object. Is that what we want. It is a > direct fallout of specifying Object.assign as the equivalent of a > sequence of property assignments from the RHS to the LHS. "__proto__" > could be special cased. But should it? > > Object.mixin doesn't have this issue because, as Rick points out, it > uses GetOwnProperty/DefineProperty instead of Get/Set. > > Anybody want to argue that Object.assign shouldn't trigger > [[SetPrototypeOf]]? > > Allen Given that `__proto__` is defined as an accessor on `Object.prototype`, I think this should be expected. Any other setter defined on the object or its prototype chain will be invoked in the same manner. It's directly triggering `[[SetPrototypeOf]]`, it's just invoking the `__proto__` setter which happens to trigger `[[SetPrototypeOf]]`. Any number of accessor properties could do weird things: Object.defineProperty(Object.prototype, 'bloikle', { set(value) { Object.freeze(this); } }); // Somewhere else far off in the code... Object.assign(foo, { bloikle: 'bar' }); // Now foo is strangely frozen... For consistency, `__proto__` shouldn't be hidden from `Object.assign`. Plus, there's no reason this shouldn't work: var info = JSON.stringify( '{ "__proto__": "A description of __proto__",' + '"hasOwnProperty": "A description of hasOwnProperty" }' ); var otherInfo = JSON.stringify( '{ "propertyIsEnumerable": "A description of propertyIsEnumerable" }' ); Object.assign(otherInfo, info); console.log(info.__proto__); Exploring other options.. A possible alternative consistent option would be to expose some mechanism to hide properties from `Object.assign`, so that the bloikle property could be hidden in the above... Doing this well would probably require a way to make it work cross-realm, which at first thought sounds pretty difficult. And it probably wouldn't play nice with the above `info` example. I think I agree with Andrea on this. Should `Object.assign` be left out of ES6 for libraries to implement? ... especially given that this `__proto__` dilemma feels "messy". Nathan