diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 0f475b58b74..53197137646 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1529,6 +1529,7 @@ NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value void PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc) { + isUndefined_ = false; pd_.setUndefined(); attrs = uint8_t(desc.attrs); JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER))); @@ -1560,6 +1561,8 @@ PropDesc::initFromPropertyDescriptor(const PropertyDescriptor &desc) bool PropDesc::makeObject(JSContext *cx) { + MOZ_ASSERT(!isUndefined()); + JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass); if (!obj) return false; @@ -1728,21 +1731,6 @@ HasProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, bool *foundp) 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 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. */ 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; bool found; diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index caf22adaac1..64dd1952dc6 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -20,12 +20,27 @@ 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 PropDesc::checkGetter(JSContext *cx) { - if (hasGet()) { - const Value &get = getterValue(); - if (!js_IsCallable(get) && !get.isUndefined()) { + if (hasGet_) { + if (!js_IsCallable(get_) && !get_.isUndefined()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD, js_getter_str); return false; @@ -37,9 +52,8 @@ PropDesc::checkGetter(JSContext *cx) bool PropDesc::checkSetter(JSContext *cx) { - if (hasSet()) { - const Value &set = setterValue(); - if (!js_IsCallable(set) && !set.isUndefined()) { + if (hasSet_) { + if (!js_IsCallable(set_) && !set_.isUndefined()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GET_SET_FIELD, js_setter_str); return false; @@ -68,6 +82,8 @@ bool PropDesc::unwrapDebuggerObjectsInto(JSContext *cx, Debugger *dbg, JSObject *obj, PropDesc *unwrapped) const { + MOZ_ASSERT(!isUndefined()); + *unwrapped = *this; if (unwrapped->hasValue()) { @@ -106,6 +122,8 @@ bool PropDesc::wrapInto(JSContext *cx, JSObject *obj, const jsid &id, jsid *wrappedId, PropDesc *desc) const { + MOZ_ASSERT(!isUndefined()); + JSCompartment *comp = cx->compartment; *wrappedId = id; diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 538ebe254f7..dfabb4e11fe 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -61,6 +61,9 @@ struct PropDesc { bool hasEnumerable_ : 1; bool hasConfigurable_ : 1; + /* Or maybe this represents a property's absence, and it's undefined. */ + bool isUndefined_ : 1; + public: friend class AutoPropDescArrayRooter; friend void JS::AutoGCRooter::trace(JSTracer *trc); @@ -91,68 +94,79 @@ struct PropDesc { void initFromPropertyDescriptor(const PropertyDescriptor &desc); bool makeObject(JSContext *cx); - bool hasGet() const { return hasGet_; } - 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_; } + void setUndefined() { isUndefined_ = true; } - 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(); } - uint8_t attributes() const { return attrs; } + uint8_t attributes() const { MOZ_ASSERT(!isUndefined()); return attrs; } /* 8.10.1 IsAccessorDescriptor(desc) */ bool isAccessorDescriptor() const { - return hasGet_ || hasSet_; + return !isUndefined() && (hasGet() || hasSet()); } /* 8.10.2 IsDataDescriptor(desc) */ bool isDataDescriptor() const { - return hasValue_ || hasWritable_; + return !isUndefined() && (hasValue() || hasWritable()); } /* 8.10.3 IsGenericDescriptor(desc) */ bool isGenericDescriptor() const { - return !isAccessorDescriptor() && !isDataDescriptor(); + return !isUndefined() && !isAccessorDescriptor() && !isDataDescriptor(); } bool configurable() const { - MOZ_ASSERT(hasConfigurable_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasConfigurable()); return (attrs & JSPROP_PERMANENT) == 0; } bool enumerable() const { - MOZ_ASSERT(hasEnumerable_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasEnumerable()); return (attrs & JSPROP_ENUMERATE) != 0; } bool writable() const { - MOZ_ASSERT(hasWritable_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasWritable()); return (attrs & JSPROP_READONLY) == 0; } const Value & value() const { - MOZ_ASSERT(hasValue_); + MOZ_ASSERT(hasValue()); return value_; } JSObject * getterObject() const { - MOZ_ASSERT(hasGet_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasGet()); return get_.isUndefined() ? NULL : &get_.toObject(); } JSObject * setterObject() const { - MOZ_ASSERT(hasSet_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasSet()); return set_.isUndefined() ? NULL : &set_.toObject(); } const Value & getterValue() const { - MOZ_ASSERT(hasGet_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasGet()); return get_; } const Value & setterValue() const { - MOZ_ASSERT(hasSet_); + MOZ_ASSERT(!isUndefined()); + MOZ_ASSERT(hasSet()); return set_; }