Bug 599464 - Object.preventExtensions should be idempotent. r=brendan

This commit is contained in:
Jeff Walden 2010-11-12 16:15:55 -08:00
parent 08acfd00c4
commit c036e81169
4 changed files with 42 additions and 6 deletions

View File

@ -2542,15 +2542,18 @@ obj_preventExtensions(JSContext *cx, uintN argc, Value *vp)
return false;
vp->setObject(*obj);
if (!obj->isExtensible())
return true;
AutoIdVector props(cx);
return obj->preventExtensions(cx, &props);
}
bool
JSObject::sealOrFreeze(JSContext *cx, bool freeze)
JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
{
assertSameCompartment(cx, this);
JS_ASSERT(it == SEAL || it == FREEZE);
AutoIdVector props(cx);
if (isExtensible()) {
@ -2573,7 +2576,7 @@ JSObject::sealOrFreeze(JSContext *cx, bool freeze)
/* Make all attributes permanent; if freezing, make data attributes read-only. */
uintN new_attrs;
if (freeze && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
if (it == FREEZE && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
new_attrs = JSPROP_PERMANENT | JSPROP_READONLY;
else
new_attrs = JSPROP_PERMANENT;

View File

@ -708,22 +708,24 @@ struct JSObject : js::gc::Cell {
*/
private:
enum ImmutabilityType { SEAL, FREEZE };
/*
* The guts of Object.seal (ES5 15.2.3.8) and Object.freeze (ES5 15.2.3.9): mark the
* object as non-extensible, and adjust each property's attributes appropriately: each
* property becomes non-configurable, and if |freeze|, data properties become
* read-only as well.
*/
bool sealOrFreeze(JSContext *cx, bool freeze = false);
bool sealOrFreeze(JSContext *cx, ImmutabilityType it);
public:
bool isExtensible() const { return !(flags & NOT_EXTENSIBLE); }
bool preventExtensions(JSContext *cx, js::AutoIdVector *props);
/* ES5 15.2.3.8: non-extensible, all props non-configurable */
inline bool seal(JSContext *cx) { return sealOrFreeze(cx); }
inline bool seal(JSContext *cx) { return sealOrFreeze(cx, SEAL); }
/* ES5 15.2.3.9: non-extensible, all properties non-configurable, all data props read-only */
bool freeze(JSContext *cx) { return sealOrFreeze(cx, true); }
bool freeze(JSContext *cx) { return sealOrFreeze(cx, FREEZE); }
/*
* Primitive-specific getters and setters.

View File

@ -41,3 +41,4 @@ script object-toString-01.js
script vacuous-accessor-unqualified-name.js
script add-property-non-extensible.js
skip-if(!xulRuntime.shell) script freeze-global-eval-const.js # uses evalcx
script preventExtensions-idempotent.js

View File

@ -0,0 +1,30 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor:
* Jeff Walden <jwalden+code@mit.edu>
*/
var gTestfile = 'preventExtensions-idempotent.js';
//-----------------------------------------------------------------------------
var BUGNUMBER = 599459;
var summary = 'Object.preventExtensions should be idempotent';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var obj = {};
assertEq(Object.preventExtensions(obj), obj);
assertEq(Object.isExtensible(obj), false);
assertEq(Object.preventExtensions(obj), obj);
assertEq(Object.isExtensible(obj), false);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");