DefineOwnProperty Allows non configurable property to change writable flag
Yes, it is intentional and was allowed to enable the "freezing" of objects that already had non-configurable properties. MarkM can probably provide some specific use cases in the context of secure sandboxes.
Related to this: We noticed that because of the behavior below, the text describing [[Configurable]] in Table 5 is not correct. It claims that [[Configurable]]=false implies no properties other than Value can be modified.
Could this be added to the errata?
Luke
From: es-discuss-bounces at mozilla.org [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Allen Wirfs-Brock Sent: Wednesday, January 05, 2011 2:09 PM To: Peter Hallam Cc: es-discuss at mozilla.org Subject: Re: DefineOwnProperty Allows non configurable property to change writable flag
Yes, it is intentional and was allowed to enable the "freezing" of objects that already had non-configurable properties. MarkM can probably provide some specific use cases in the context of secure sandboxes.
Allen
On Jan 5, 2011, at 1:38 PM, Peter Hallam wrote:
In 8.12.9 [[DefineOwnProperty]]
Step 10.a.i:
"Reject, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true."
This specifically allows making a non-configurable writable property read only.
For example:
var obj = {}; Object.defineOwnProperty(obj, 'p', {value: 'foo', writable: true:, configurable: false}); Object.defineOwnProperty(obj, 'p', {writable: false});
The spec explicitly allows the second call to succeed. Is that intentional? If so, what was the rationale?
Allowing changes to the value of the writable flag on the property violates my intuition for configurable:false.
Yes, I know about this...when the change was made to the ES5 spec. to allow the writable change we missed updating the table.
I'm already collecting items for the ES5.1 errata.
[+es5-discuss]
On Wed, Jan 5, 2011 at 2:09 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
Yes, it is intentional and was allowed to enable the "freezing" of objects that already had non-configurable properties. MarkM can probably provide some specific use cases in the context of secure sandboxes.
According to the ES5 spec (I haven't double checked against ES5.1), the following properties are initialized to {writable: true, configurable: false}:
13.2 step 18, 15.3.5.2
aFunction.prototype
15.4.5.2
anArray.length
15.10.7.5
aRegExp.lastIndex
However, we need to be able to freeze functions, arrays, and regExps. Were we willing to make the above properties configurable: true, then we wouldn't have needed this loophole in the spec. Given that we were not willing to make these properties configurable, this loophole was the least unpleasant way we could find to still allow us to freeze such objects. (Another approach that was mentioned at the time and promptly rejected: introducing yet another attribute flag to distinguish not-deletable-but-freezable from non-configurable.)
I think there were some other cases as well, but can't find them right now. No matter, the above cases are sufficient.
In addition, if I read the spec right, the following code
15.5.5.2
Object.getOwnPropertyDescriptor(Object("foo"), '1')
should return a descriptor claiming in effect that the (non-existent) '1' property on the String object is writable but not configurable. Is this a spec error? Is it already recorded as an errata? Cc'ing es5-discuss just in case.
Groovy. Thanks all.
On Jan 5, 2011, at 3:14 PM, Mark S. Miller wrote:
In addition, if I read the spec right, the following code
15.5.5.2 Object.getOwnPropertyDescriptor(Object("foo"), '1')
should return a descriptor claiming in effect that the (non-existent) '1' property on the String object is writable but not configurable. Is this a spec error? Is it already recorded as an errata? Cc'ing es5-discuss just in case.
I don't think so. Step 9 of 15.5.5.2 says return the property descriptor { [[Value]]: "o", [[Enumerable]]: true, [[Writable]]: false, [[Configurable]]: false} for this case. Where do you get that writable is true?
On Wed, Jan 5, 2011 at 3:49 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
On Jan 5, 2011, at 3:14 PM, Mark S. Miller wrote:
In addition, if I read the spec right, the following code
15.5.5.2 Object.getOwnPropertyDescriptor(Object("foo"), '1')
should return a descriptor claiming in effect that the (non-existent) '1' property on the String object is writable but not configurable. Is this a spec error? Is it already recorded as an errata? Cc'ing es5-discuss just in case.
I don't think so. Step 9 of 15.5.5.2 says return the property descriptor { [[Value]]: "o", [[Enumerable]]: true, [[Writable]]: false, [[Configurable]]: false} for this case. Where do you get that writable is true?
Doh!
My mistake. Most everywhere else, [[Writable]] is listed before [[Enumerable]] so I got in the habit of reading according to positional rather than name-based encoding.
In 8.12.9 [[DefineOwnProperty]]
Step 10.a.i:
"Reject, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true."
This specifically allows making a non-configurable writable property read only.
For example:
var obj = {}; Object.defineOwnProperty(obj, 'p', {value: 'foo', writable: true:, configurable: false}); Object.defineOwnProperty(obj, 'p', {writable: false});
The spec explicitly allows the second call to succeed. Is that intentional? If so, what was the rationale?
Allowing changes to the value of the writable flag on the property violates my intuition for configurable:false.