Open Bug 520882 Opened 15 years ago Updated 2 years ago

Object.getOwnPropertyDescriptor treats properties with native getter/setter as data properties

Categories

(Core :: JavaScript Engine, defect)

Other Branch
defect

Tracking

()

People

(Reporter: jorendorff, Unassigned)

References

Details

The JSAPI makes it easy to define properties that are neither ES5 data properties nor exactly ES5 accessor properties. In fact any property with a JSPropertyOp getter or setter is such a beast; but there are also properties that have both a native getter/setter *and* a slot, like expando properties on DOM objects. The code in obj_getOwnPropertyDescriptor seems to ignore this possibility. The results are weird. Properties with native (JSPropertyOp) getters/setters are treated as data properties. To get the value for such a property, we call the getter. The native getter might do anything, including deleting the property; it seems odd for Object.getOwnPropertyDescriptor to have that kind of side effect. js> it.noisy = true; true js> Object.getOwnPropertyDescriptor(it, "noisy") getting its property noisy, initial value true ({value:true, writable:true, enumerable:true, configurable:true}) I think the weird way this behaves when applied to DOM properties is related to this. Ordinary XPConnect properties representing XPIDL attributes are JSPROP_GETTER|JSPROP_SETTER and thus are treated as accessor properties: > Object.getOwnPropertyDescriptor(document.body.__proto__, "children") ({get:getter function children() {[native code]}, set:(void 0), enumerable:true, configurable:true}) (The stray "getter" there seems like a bug too, unrelated maybe.) But quick-stubbed properties have JSPropertyOp getters/setters, so they are treated as data properties. > Object.getOwnPropertyDescriptor(document.body.__proto__, "firstChild") NS_ERROR_XPC_BAD_OP_ON_WN_PROTO on line 1: Illegal operation on WrappedNative prototype object That's the same error you get for `document.body.__proto__.firstChild`, so I think it's caused by trying to get the value. We should reflect this kind of property as an accessor property instead. That way we don't have to get the value. Desired behavior: js> Object.getOwnPropertyDescriptor(it, "noisy") ({get:function () {[native code]}, set: function () {[native code]}, enumerable:true, configurable:true}) mrbkap has expressed some paranoia about reflecting arbitrary native getters and setters as JS functions before. I don't remember why. If we want to maintain maximum paranoia, we could create functions here that always throw if they're applied to any object other than the one you extracted them from.
Bug 430133 has more comment on this, as well as on its interaction with shared-permanent properties with native getters. For the cases described here it does make sense to expose native getters/setters as accessor descriptors, but for others it does not. There doesn't seem to be a simple or obvious solution unless I'm missing something.
(In reply to comment #1) > Bug 430133 has more comment on this, as well as on its interaction with > shared-permanent properties with native getters. For the cases described here > it does make sense to expose native getters/setters as accessor descriptors, > but for others it does not. There doesn't seem to be a simple or obvious > solution unless I'm missing something. Right, it will require case analysis. We could retrofit a case-labeling system on top of the otherwise-unconstrained JSPropertyOp getters and setters, but it may not be worth the trouble. Not sure. /be
Depends on: 560072
Blocks: 560072
No longer depends on: 560072
Assignee: general → nobody
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.