ToPropertyDescriptor({}) erroneously completes the property descriptor with missing attributes

RESOLVED FIXED

Status

()

Core
JavaScript Engine
P2
normal
RESOLVED FIXED
8 years ago
6 years ago

People

(Reporter: Tom Van Cutsem, Unassigned)

Tracking

Trunk
x86
Mac OS X
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

8 years ago
According to the ES5 spec., ToPropertyDescriptor({}) should return a completely empty property descriptor. The implementation currently seems to auto-complete this descriptor to { value: (void 0), writable: false, enumerable: false, configurable: false }.

Without proxies, I think this was unobservable to JS code, but with the addition of proxies this changes:

var x;
var p = Proxy.create({
  defineProperty: function(name, desc) { x = ('value' in desc); }
});
Object.defineProperty(p, 'foo', {});

x is true while it should be false.
(Reporter)

Updated

8 years ago
Priority: -- → P2
(Reporter)

Comment 1

7 years ago
I would like to draw renewed attention to this open issue:

Problem: property descriptor objects are currently always fully completed before being passed to a proxy handler's defineProperty trap.
The ES5 and harmony:proxies spec do not require the property descriptor to be completed, only for it to be "normalized".
Not completing the descriptor is necessary for proxies to be able to accurately emulate the built-in [[DefineOwnProperty]] algorithm (whose behavior depends on the presence or absence of attributes), and for proxies to be able to handle changes to just a single attribute of an existing property. Consider:

var o = { x: 1 };
Object.defineProperty(o, 'x', { writable: false}); // will only set writable from true to false, and leave other attributes untouched
Object.getOwnPropertyDescriptor(o, 'x').configurable; // is still 'true'

// now try to do the same on a proxy
var target = { x: 1 };
var p = Proxy.create({
  getOwnPropertyDescriptor: function(name) { return Object.getOwnPropertyDescriptor(target, name); },
  defineProperty: function(name, desc) { Object.defineProperty(target, name, desc); return true; }
});
// since desc is completed in the current implementation, the following call will actually be
// interpreted as Object.defineProperty(p, 'x', {writable:false,configurable:false,enumerable:false,value:undefined})
// which is probably not what the programmer intended
Object.defineProperty(p, 'x', { writable: false }); null; // null added to ensure p doesn't need to be printed to the shell
Object.getOwnPropertyDescriptor(p, 'x').configurable; // expected 'true' but is currently 'false'
(Reporter)

Updated

7 years ago
Blocks: 546590
Blocks: 694103
No longer blocks: 694103
Need an owner for this bug.

/be

Comment 3

6 years ago
Updated test case:
===
var d;
var p = new Proxy({}, {
  defineProperty: function(target, name, desc) { d = desc; }
});
Object.defineProperty(p, 'foo', {});

console.log('d', d);
===
It works with direct proxies. Closing this bug as fixed.
Blocks: 703537
Status: NEW → RESOLVED
Last Resolved: 6 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.