зеркало из https://github.com/mozilla/pjs.git
Bug 746262 - Augment PropDesc so that it can represent the absence of a property by adding an isUndefined() method and bit, and checking it in all the relevant accessors. r=jorendorff
--HG-- extra : rebase_source : 45b29d3f65a9e01119f01d9a30f574038abcaea1
This commit is contained in:
Родитель
c86091dc20
Коммит
a97bbc022d
|
@ -1529,6 +1529,7 @@ NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value
|
||||||
void
|
void
|
||||||
PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc)
|
PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc)
|
||||||
{
|
{
|
||||||
|
isUndefined_ = false;
|
||||||
pd_.setUndefined();
|
pd_.setUndefined();
|
||||||
attrs = uint8_t(desc.attrs);
|
attrs = uint8_t(desc.attrs);
|
||||||
JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||||
|
@ -1560,6 +1561,8 @@ PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc)
|
||||||
bool
|
bool
|
||||||
PropDesc::makeObject(JSContext *cx)
|
PropDesc::makeObject(JSContext *cx)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
|
||||||
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass);
|
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1728,21 +1731,6 @@ HasProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, bool *foundp)
|
||||||
return !!obj->getGeneric(cx, id, vp);
|
return !!obj->getGeneric(cx, id, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropDesc::PropDesc()
|
|
||||||
: pd_(UndefinedValue()),
|
|
||||||
value_(UndefinedValue()),
|
|
||||||
get_(UndefinedValue()),
|
|
||||||
set_(UndefinedValue()),
|
|
||||||
attrs(0),
|
|
||||||
hasGet_(false),
|
|
||||||
hasSet_(false),
|
|
||||||
hasValue_(false),
|
|
||||||
hasWritable_(false),
|
|
||||||
hasEnumerable_(false),
|
|
||||||
hasConfigurable_(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
|
PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
|
||||||
{
|
{
|
||||||
|
@ -1758,7 +1746,12 @@ PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
|
||||||
/* Make a copy of the descriptor. We might need it later. */
|
/* Make a copy of the descriptor. We might need it later. */
|
||||||
pd_ = v;
|
pd_ = v;
|
||||||
|
|
||||||
/* Start with the proper defaults. */
|
isUndefined_ = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start with the proper defaults. XXX shouldn't be necessary when we get
|
||||||
|
* rid of PropDesc::attributes()
|
||||||
|
*/
|
||||||
attrs = JSPROP_PERMANENT | JSPROP_READONLY;
|
attrs = JSPROP_PERMANENT | JSPROP_READONLY;
|
||||||
|
|
||||||
bool found;
|
bool found;
|
||||||
|
|
|
@ -20,12 +20,27 @@
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
|
PropDesc::PropDesc()
|
||||||
|
: pd_(UndefinedValue()),
|
||||||
|
value_(UndefinedValue()),
|
||||||
|
get_(UndefinedValue()),
|
||||||
|
set_(UndefinedValue()),
|
||||||
|
attrs(0),
|
||||||
|
hasGet_(false),
|
||||||
|
hasSet_(false),
|
||||||
|
hasValue_(false),
|
||||||
|
hasWritable_(false),
|
||||||
|
hasEnumerable_(false),
|
||||||
|
hasConfigurable_(false),
|
||||||
|
isUndefined_(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PropDesc::checkGetter(JSContext *cx)
|
PropDesc::checkGetter(JSContext *cx)
|
||||||
{
|
{
|
||||||
if (hasGet()) {
|
if (hasGet_) {
|
||||||
const Value &get = getterValue();
|
if (!js_IsCallable(get_) && !get_.isUndefined()) {
|
||||||
if (!js_IsCallable(get) && !get.isUndefined()) {
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
|
||||||
js_getter_str);
|
js_getter_str);
|
||||||
return false;
|
return false;
|
||||||
|
@ -37,9 +52,8 @@ PropDesc::checkGetter(JSContext *cx)
|
||||||
bool
|
bool
|
||||||
PropDesc::checkSetter(JSContext *cx)
|
PropDesc::checkSetter(JSContext *cx)
|
||||||
{
|
{
|
||||||
if (hasSet()) {
|
if (hasSet_) {
|
||||||
const Value &set = setterValue();
|
if (!js_IsCallable(set_) && !set_.isUndefined()) {
|
||||||
if (!js_IsCallable(set) && !set.isUndefined()) {
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD,
|
||||||
js_setter_str);
|
js_setter_str);
|
||||||
return false;
|
return false;
|
||||||
|
@ -68,6 +82,8 @@ bool
|
||||||
PropDesc::unwrapDebuggerObjectsInto(JSContext *cx, Debugger *dbg, JSObject *obj,
|
PropDesc::unwrapDebuggerObjectsInto(JSContext *cx, Debugger *dbg, JSObject *obj,
|
||||||
PropDesc *unwrapped) const
|
PropDesc *unwrapped) const
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
|
||||||
*unwrapped = *this;
|
*unwrapped = *this;
|
||||||
|
|
||||||
if (unwrapped->hasValue()) {
|
if (unwrapped->hasValue()) {
|
||||||
|
@ -106,6 +122,8 @@ bool
|
||||||
PropDesc::wrapInto(JSContext *cx, JSObject *obj, const jsid &id, jsid *wrappedId,
|
PropDesc::wrapInto(JSContext *cx, JSObject *obj, const jsid &id, jsid *wrappedId,
|
||||||
PropDesc *desc) const
|
PropDesc *desc) const
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
|
||||||
JSCompartment *comp = cx->compartment;
|
JSCompartment *comp = cx->compartment;
|
||||||
|
|
||||||
*wrappedId = id;
|
*wrappedId = id;
|
||||||
|
|
|
@ -61,6 +61,9 @@ struct PropDesc {
|
||||||
bool hasEnumerable_ : 1;
|
bool hasEnumerable_ : 1;
|
||||||
bool hasConfigurable_ : 1;
|
bool hasConfigurable_ : 1;
|
||||||
|
|
||||||
|
/* Or maybe this represents a property's absence, and it's undefined. */
|
||||||
|
bool isUndefined_ : 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend class AutoPropDescArrayRooter;
|
friend class AutoPropDescArrayRooter;
|
||||||
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
||||||
|
@ -91,68 +94,79 @@ struct PropDesc {
|
||||||
void initFromPropertyDescriptor(const PropertyDescriptor &desc);
|
void initFromPropertyDescriptor(const PropertyDescriptor &desc);
|
||||||
bool makeObject(JSContext *cx);
|
bool makeObject(JSContext *cx);
|
||||||
|
|
||||||
bool hasGet() const { return hasGet_; }
|
void setUndefined() { isUndefined_ = true; }
|
||||||
bool hasSet() const { return hasSet_; }
|
|
||||||
bool hasValue() const { return hasValue_; }
|
|
||||||
bool hasWritable() const { return hasWritable_; }
|
|
||||||
bool hasEnumerable() const { return hasEnumerable_; }
|
|
||||||
bool hasConfigurable() const { return hasConfigurable_; }
|
|
||||||
|
|
||||||
Value pd() const { return pd_; }
|
bool isUndefined() const { return isUndefined_; }
|
||||||
|
|
||||||
|
bool hasGet() const { MOZ_ASSERT(!isUndefined()); return hasGet_; }
|
||||||
|
bool hasSet() const { MOZ_ASSERT(!isUndefined()); return hasSet_; }
|
||||||
|
bool hasValue() const { MOZ_ASSERT(!isUndefined()); return hasValue_; }
|
||||||
|
bool hasWritable() const { MOZ_ASSERT(!isUndefined()); return hasWritable_; }
|
||||||
|
bool hasEnumerable() const { MOZ_ASSERT(!isUndefined()); return hasEnumerable_; }
|
||||||
|
bool hasConfigurable() const { MOZ_ASSERT(!isUndefined()); return hasConfigurable_; }
|
||||||
|
|
||||||
|
Value pd() const { MOZ_ASSERT(!isUndefined()); return pd_; }
|
||||||
void clearPd() { pd_ = UndefinedValue(); }
|
void clearPd() { pd_ = UndefinedValue(); }
|
||||||
|
|
||||||
uint8_t attributes() const { return attrs; }
|
uint8_t attributes() const { MOZ_ASSERT(!isUndefined()); return attrs; }
|
||||||
|
|
||||||
/* 8.10.1 IsAccessorDescriptor(desc) */
|
/* 8.10.1 IsAccessorDescriptor(desc) */
|
||||||
bool isAccessorDescriptor() const {
|
bool isAccessorDescriptor() const {
|
||||||
return hasGet_ || hasSet_;
|
return !isUndefined() && (hasGet() || hasSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 8.10.2 IsDataDescriptor(desc) */
|
/* 8.10.2 IsDataDescriptor(desc) */
|
||||||
bool isDataDescriptor() const {
|
bool isDataDescriptor() const {
|
||||||
return hasValue_ || hasWritable_;
|
return !isUndefined() && (hasValue() || hasWritable());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 8.10.3 IsGenericDescriptor(desc) */
|
/* 8.10.3 IsGenericDescriptor(desc) */
|
||||||
bool isGenericDescriptor() const {
|
bool isGenericDescriptor() const {
|
||||||
return !isAccessorDescriptor() && !isDataDescriptor();
|
return !isUndefined() && !isAccessorDescriptor() && !isDataDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool configurable() const {
|
bool configurable() const {
|
||||||
MOZ_ASSERT(hasConfigurable_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasConfigurable());
|
||||||
return (attrs & JSPROP_PERMANENT) == 0;
|
return (attrs & JSPROP_PERMANENT) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enumerable() const {
|
bool enumerable() const {
|
||||||
MOZ_ASSERT(hasEnumerable_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasEnumerable());
|
||||||
return (attrs & JSPROP_ENUMERATE) != 0;
|
return (attrs & JSPROP_ENUMERATE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writable() const {
|
bool writable() const {
|
||||||
MOZ_ASSERT(hasWritable_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasWritable());
|
||||||
return (attrs & JSPROP_READONLY) == 0;
|
return (attrs & JSPROP_READONLY) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value & value() const {
|
const Value & value() const {
|
||||||
MOZ_ASSERT(hasValue_);
|
MOZ_ASSERT(hasValue());
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject * getterObject() const {
|
JSObject * getterObject() const {
|
||||||
MOZ_ASSERT(hasGet_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasGet());
|
||||||
return get_.isUndefined() ? NULL : &get_.toObject();
|
return get_.isUndefined() ? NULL : &get_.toObject();
|
||||||
}
|
}
|
||||||
JSObject * setterObject() const {
|
JSObject * setterObject() const {
|
||||||
MOZ_ASSERT(hasSet_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasSet());
|
||||||
return set_.isUndefined() ? NULL : &set_.toObject();
|
return set_.isUndefined() ? NULL : &set_.toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value & getterValue() const {
|
const Value & getterValue() const {
|
||||||
MOZ_ASSERT(hasGet_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasGet());
|
||||||
return get_;
|
return get_;
|
||||||
}
|
}
|
||||||
const Value & setterValue() const {
|
const Value & setterValue() const {
|
||||||
MOZ_ASSERT(hasSet_);
|
MOZ_ASSERT(!isUndefined());
|
||||||
|
MOZ_ASSERT(hasSet());
|
||||||
return set_;
|
return set_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче