If you think a bug might affect users in the 57 release, please set the correct tracking and status flags for Release Management.

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

RESOLVED INVALID

Status

()

Core
JavaScript Engine
RESOLVED INVALID
7 years ago
7 years ago

People

(Reporter: David Bruant, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

7 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

7 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

7 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

7 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

7 years ago
Filed Bug 641274
(Reporter)

Comment 6

7 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: 7 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.