Browse files

fixed issue #11

  • Loading branch information...
tvcutsem committed Dec 20, 2012
1 parent 6945efa commit b4b2f7a22b9c5c5dc3f02040a525881e54e4caed
Showing with 8 additions and 4 deletions.
  1. +8 −4 reflect.js
@@ -1601,15 +1601,19 @@ var Reflect = global.Reflect = {
// otherwise, isDataDescriptor(ownDesc) must be true
if (ownDesc.writable === false) return false;
- if (receiver === target) {
+ // we found an existing writable data property on the prototype chain.
+ // Now update or add the data property on the receiver, depending on
+ // whether the receiver already defines the property or not.
+ var existingDesc = Object.getOwnPropertyDescriptor(receiver, name);
+ if (existingDesc !== undefined) {
var updateDesc =
{ value: value,
// FIXME: it should not be necessary to describe the following
// attributes. Added to circumvent a bug in tracemonkey:
- writable: ownDesc.writable,
- enumerable: ownDesc.enumerable,
- configurable: ownDesc.configurable };
+ writable: existingDesc.writable,
+ enumerable: existingDesc.enumerable,
+ configurable: existingDesc.configurable };
Object.defineProperty(receiver, name, updateDesc);
return true;
} else {

1 comment on commit b4b2f7a


tvcutsem commented on b4b2f7a Dec 20, 2012

In Reflect.set (or [[SetP]] as the algorithm is called in the ES6 draft spec), at one point, the algorithm must decide whether to update an existing data property, or rather to add a new data property to the receiver object.

Previously, the decision was made based on whether receiver === target. If the target and receiver are the same, we know we are performing a "direct" update, and since we just found a data property (ownDesc) on target, we know the descriptor also exists on the receiver object.

However, this identity test failed in the presence of proxies where receiver could be a proxy for the target object. This caused the test to take the wrong branch in the presence of proxies, with behavior like the one reported in issue #11.

The fix was to no longer use object identity to test whether we need to add or update a property, but rather simply to query the receiver object to see if it already defines a property with the same name. This test works correctly even if receiver is a proxy for the target.

For normal objects, the new test is more expensive and a bit redundant, but inside an ES6 engine, the fast path (where both target and receiver are normal objects) will be optimized and would probably not make use of this algorithm at all.

Please sign in to comment.