Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

fixed issue #11

  • Loading branch information...
commit b4b2f7a22b9c5c5dc3f02040a525881e54e4caed 1 parent 6945efa
Tom Van Cutsem authored

Showing 1 changed file with 8 additions and 4 deletions. Show diff stats Hide diff stats

  1. +8 4 reflect.js
12 reflect.js
@@ -1601,15 +1601,19 @@ var Reflect = global.Reflect = {
1601 1601 }
1602 1602 // otherwise, isDataDescriptor(ownDesc) must be true
1603 1603 if (ownDesc.writable === false) return false;
1604   - if (receiver === target) {
  1604 + // we found an existing writable data property on the prototype chain.
  1605 + // Now update or add the data property on the receiver, depending on
  1606 + // whether the receiver already defines the property or not.
  1607 + var existingDesc = Object.getOwnPropertyDescriptor(receiver, name);
  1608 + if (existingDesc !== undefined) {
1605 1609 var updateDesc =
1606 1610 { value: value,
1607 1611 // FIXME: it should not be necessary to describe the following
1608 1612 // attributes. Added to circumvent a bug in tracemonkey:
1609 1613 // https://bugzilla.mozilla.org/show_bug.cgi?id=601329
1610   - writable: ownDesc.writable,
1611   - enumerable: ownDesc.enumerable,
1612   - configurable: ownDesc.configurable };
  1614 + writable: existingDesc.writable,
  1615 + enumerable: existingDesc.enumerable,
  1616 + configurable: existingDesc.configurable };
1613 1617 Object.defineProperty(receiver, name, updateDesc);
1614 1618 return true;
1615 1619 } else {

1 comment on commit b4b2f7a

Tom Van Cutsem
Owner

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.
Something went wrong with that request. Please try again.