DefineOwnProperty Allows non configurable property to change writable flag

# Peter Hallam (15 years ago)

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.

# Allen Wirfs-Brock (15 years ago)

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.

# Luke Hoban (15 years ago)

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.

# Allen Wirfs-Brock (15 years ago)

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.

# Mark S. Miller (15 years ago)

[+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.

# Peter Hallam (15 years ago)

Groovy. Thanks all.

# Allen Wirfs-Brock (15 years ago)

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?

# Mark S. Miller (15 years ago)

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.