Object.defineProperties doesn't work when the second argument is an Harmony proxy

RESOLVED INVALID

Status

()

RESOLVED INVALID
8 years ago
8 years ago

People

(Reporter: bruant.d, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

8 years ago
User-Agent:       Mozilla/5.0 (X11; Linux i686; rv:2.0) Gecko/20100101 Firefox/4.0
Build Identifier: FF4RC1

Test case:
----------------------------------
function handlerMaker(obj) {
  return {
   getOwnPropertyDescriptor: function(name) {
     var desc = Object.getOwnPropertyDescriptor(obj, name);
     if (desc !== undefined) { desc.configurable = true; }
     return desc;
   },
   
   getPropertyDescriptor: function(name) {
     return this.getOwnPropertyDescriptor(name); // incorrect !
   },
   
   getOwnPropertyNames: function() {
     return Object.getOwnPropertyNames(obj);
   },
   
   getPropertyNames: function() {
     return this.getOwnPropertyNames(); // incorrect !
   },
   
   defineProperty: function(name, desc) {
     Object.defineProperty(obj, name, desc);
   }
  };
}

var target = {};
var props = Proxy.create(handlerMaker(target));
props['a'] = 'a';

var o = {};
Object.defineProperties(o, props);
console.log(o);
----------------------------------

If I had to guess, I'd say that this is related to defineProperties definition (http://es5.github.com/#x15.2.3.7). At step 3, "Let names be an internal list containing the names of each enumerable own property of props.". Note at the end of the algorithm: "If an implementation defines a specific order of enumeration for the for-in statement, that same enumeration order must be used to order the list elements in step 3 of this algorithm."

For proxies, this is supposed to be the 'keys' trap (which is supposed to be a derived trap).

Reproducible: Always

Steps to Reproduce:
1. Run test case
2.
3.
Actual Results:  
Error message in Web console: "value is not a non-null object" at the line of the Object.defineProperties call

Expected Results:  
o has same own enumerable properties than props (and target)
(Reporter)

Comment 1

8 years ago
May be related to bug 609005?
This works fore me, when i return the expected stuff with getPropertyDescriptor.
  {
    value: {     
      value: 1
      enumerable: true,
      configurable: true,
      writable: true
    }
    enumerable: true,
    configurable: true,
    writable: true
  }

Minimal Example:
function handlerMaker(obj) {
  return {
    getPropertyDescriptor: function(name) {
        print('getPropertyDescriptor: ' + name);
        var desc = Object.getOwnPropertyDescriptor(obj, name);
        desc.value = Object.getOwnPropertyDescriptor(obj, name);
        return desc;
    },
    keys: function () {
        print('keys');
        return Object.keys(obj);
    }
  };
}

var props = Proxy.create(handlerMaker({a: 1}));
var o = {};
Object.defineProperties(o, props);
print(o.a);

Or did you wanted to show something else, related to enumeration?
(Reporter)

Comment 3

8 years ago
Why would the return value of getPropertyDescriptor look like:  {
value: {     
      value: 1
      enumerable: true,
      configurable: true,
      writable: true
    }
    enumerable: true,
    configurable: true,
    writable: true
  }
?

In ES5, a property descriptor (for data properties) looks like:
{value:true, enumerable:true, configurable:true, writable:true}
That's what you pass to Object.defineProperty and what is returned by Object.getOwnPropertyDescriptor.
On the WebConsole:
< Object.getOwnPropertyDescriptor(Array, 'prototype');
> ({value:[], writable:false, enumerable:false, configurable:false})

I assumed an bug in the enumeration, but the bug may be from what is expected as the getPropertyDescriptor output.
As explained here (http://wiki.ecmascript.org/doku.php?id=harmony:proxies), getOwnPropertyDescriptor and getPropertyDescriptor traps are both expected to return property descriptors, but nothing imposes the 'value' of this property descriptor to be itself a property descriptor.

Is there a reason why you said that this is expected?
(Reporter)

Comment 4

8 years ago
Ok. So I was half wrong in my previous comment. Here is the fixed reduced test case:
----------------------
function handlerMaker(obj) {
  return {
    getPropertyDescriptor: function(name) {
        print('getPropertyDescriptor: ' + name);
        var desc = Object.getOwnPropertyDescriptor(obj, name);
        return desc;
    },
    keys: function () {
        print('keys');
        return Object.keys(obj);
    }
  };
}

var props = Proxy.create(handlerMaker({a: {va1ue:1, enumerable:true}, b:{value:false, enumerable:true}}));
var o = {};
Object.defineProperties(o, props);
----------------------
However, for some reason, o.a in undefined (should be 1) and o.b is false (expected).
(Reporter)

Comment 5

8 years ago
Filed Bug 641274
(Reporter)

Comment 6

8 years ago
My mistake, there was no bug here with proxies or enumeration. Glad it helped catching another bug :-p
Status: UNCONFIRMED → RESOLVED
Last Resolved: 8 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.