Bug 702491 - Don't set JSPROP_READONLY for accessor properties. r=Waldo

This commit is contained in:
Bobby Holley 2011-12-15 11:40:57 -08:00
parent 9d65e2424c
commit f178ecf8cc
4 changed files with 23 additions and 3 deletions

View File

@ -3508,6 +3508,15 @@ DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value,
PropertyOp getter, StrictPropertyOp setter, uintN attrs,
uintN flags, intN tinyid)
{
/*
* JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
* throw if this happens, but we've accepted it for long enough that it's
* not worth trying to make callers change their ways. Just flip it off on
* its way through the API layer so that we can enforce this internally.
*/
if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
attrs &= ~JSPROP_READONLY;
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id, value,
(attrs & JSPROP_GETTER)

View File

@ -1677,7 +1677,10 @@ JSVAL_IS_UNIVERSAL(jsval v)
/* Property attributes, set in JSPropertySpec and passed to API functions. */
#define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */
#define JSPROP_READONLY 0x02 /* not settable: assignment is no-op */
#define JSPROP_READONLY 0x02 /* not settable: assignment is no-op.
This flag is only valid when neither
JSPROP_GETTER nor JSPROP_SETTER is
set. */
#define JSPROP_PERMANENT 0x04 /* property cannot be deleted */
#define JSPROP_GETTER 0x10 /* property holds getter function */
#define JSPROP_SETTER 0x20 /* property holds setter function */

View File

@ -1749,6 +1749,7 @@ PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc)
{
pd.setUndefined();
attrs = uint8(desc.attrs);
JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
if (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
hasGet = true;
get = ((desc.attrs & JSPROP_GETTER) && desc.getter)
@ -2025,6 +2026,7 @@ PropDesc::initialize(JSContext* cx, const Value &origval, bool checkAccessors)
hasGet = true;
get = v;
attrs |= JSPROP_GETTER | JSPROP_SHARED;
attrs &= ~JSPROP_READONLY;
if (checkAccessors && !checkGetter(cx))
return false;
}
@ -2036,6 +2038,7 @@ PropDesc::initialize(JSContext* cx, const Value &origval, bool checkAccessors)
hasSet = true;
set = v;
attrs |= JSPROP_SETTER | JSPROP_SHARED;
attrs &= ~JSPROP_READONLY;
if (checkAccessors && !checkSetter(cx))
return false;
}
@ -2046,6 +2049,8 @@ PropDesc::initialize(JSContext* cx, const Value &origval, bool checkAccessors)
return false;
}
JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
return true;
}
@ -2352,9 +2357,9 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const jsid &id, const PropD
if (desc.hasEnumerable)
changed |= JSPROP_ENUMERATE;
if (desc.hasGet)
changed |= JSPROP_GETTER | JSPROP_SHARED;
changed |= JSPROP_GETTER | JSPROP_SHARED | JSPROP_READONLY;
if (desc.hasSet)
changed |= JSPROP_SETTER | JSPROP_SHARED;
changed |= JSPROP_SETTER | JSPROP_SHARED | JSPROP_READONLY;
attrs = (desc.attrs & changed) | (shape->attributes() & ~changed);
if (desc.hasGet) {
@ -6697,6 +6702,8 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
}
}
JS_ASSERT_IF(*attrsp & JSPROP_READONLY, !(*attrsp & (JSPROP_GETTER | JSPROP_SETTER)));
/*
* If obj's class has a stub (null) checkAccess hook, use the per-runtime
* checkObjectAccess callback, if configured.

View File

@ -164,6 +164,7 @@ Shape::Shape(UnownedBaseShape *base, jsid propid, uint32 slot, uint32 nfixed,
JS_ASSERT(base);
JS_ASSERT(!JSID_IS_VOID(propid));
JS_ASSERT_IF(isMethod(), !base->rawGetter);
JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
kids.setNull();
}