diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 451b346a0e6d..e1bcee128b2f 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -388,11 +388,16 @@ AutoGCRooter::trace(JSTracer *trc) return; } - case DESCVECTOR: { - AutoPropDescVector::VectorImpl &descriptors = - static_cast(this)->vector; - for (size_t i = 0, len = descriptors.length(); i < len; i++) - descriptors[i].trace(trc); + case DESCRIPTORS: { + PropDescArray &descriptors = + static_cast(this)->descriptors; + for (size_t i = 0, len = descriptors.length(); i < len; i++) { + PropDesc &desc = descriptors[i]; + MarkValueRoot(trc, &desc.pd_, "PropDesc::pd_"); + MarkValueRoot(trc, &desc.value_, "PropDesc::value_"); + MarkValueRoot(trc, &desc.get_, "PropDesc::get_"); + MarkValueRoot(trc, &desc.set_, "PropDesc::set_"); + } return; } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index cf1cf71f72c0..7e4176c3a646 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -106,7 +106,7 @@ class JS_PUBLIC_API(AutoGCRooter) { PARSER = -3, /* js::frontend::Parser */ SHAPEVECTOR = -4, /* js::AutoShapeVector */ IDARRAY = -6, /* js::AutoIdArray */ - DESCVECTOR = -7, /* js::AutoPropDescVector */ + DESCRIPTORS = -7, /* js::AutoPropDescArrayRooter */ VALVECTOR = -10, /* js::AutoValueVector */ IDVECTOR = -13, /* js::AutoIdVector */ OBJVECTOR = -14, /* js::AutoObjectVector */ diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 0cbb19d92374..55e8c0b08bad 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -495,41 +495,6 @@ JSCompartment::wrap(JSContext *cx, AutoIdVector &props) return true; } -bool -JSCompartment::wrap(JSContext *cx, MutableHandle desc) -{ - if (desc.isUndefined()) - return true; - - JSCompartment *comp = cx->compartment(); - - if (desc.hasValue()) { - RootedValue value(cx, desc.value()); - if (!comp->wrap(cx, &value)) - return false; - desc.setValue(value); - } - if (desc.hasGet()) { - RootedValue get(cx, desc.getterValue()); - if (!comp->wrap(cx, &get)) - return false; - desc.setGetter(get); - } - if (desc.hasSet()) { - RootedValue set(cx, desc.setterValue()); - if (!comp->wrap(cx, &set)) - return false; - desc.setSetter(set); - } - if (desc.descriptorValue().isObject()) { - RootedObject descObj(cx, &desc.descriptorValue().toObject()); - if (!comp->wrap(cx, &descObj)) - return false; - desc.setDescriptorObject(descObj); - } - return true; -} - /* * This method marks pointers that cross compartment boundaries. It should be * called only for per-compartment GCs, since full GCs naturally follow pointers diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 169e353a2a2c..925968878d17 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -318,7 +318,6 @@ struct JSCompartment bool wrap(JSContext *cx, js::StrictPropertyOp *op); bool wrap(JSContext *cx, JS::MutableHandle desc); bool wrap(JSContext *cx, js::AutoIdVector &props); - bool wrap(JSContext *cx, JS::MutableHandle desc); bool putWrapper(JSContext *cx, const js::CrossCompartmentKey& wrapped, const js::Value& wrapper); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a0b6670f748f..ced858b44c41 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -268,17 +268,15 @@ js::NewPropertyDescriptorObject(JSContext *cx, Handle desc, d.initFromPropertyDescriptor(desc); if (!d.makeObject(cx)) return false; - vp.set(d.descriptorValue()); + vp.set(d.pd()); return true; } void PropDesc::initFromPropertyDescriptor(Handle desc) { - MOZ_ASSERT(isUndefined()); - isUndefined_ = false; - descObj_ = nullptr; + pd_.setUndefined(); attrs = uint8_t(desc.attributes()); JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER))); if (desc.hasGetterOrSetterObject()) { @@ -335,7 +333,7 @@ PropDesc::makeObject(JSContext *cx) return false; } - descObj_ = obj; + pd_.setObject(*obj); return true; } @@ -435,8 +433,6 @@ HasProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, bool PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors) { - MOZ_ASSERT(isUndefined()); - RootedValue v(cx, origval); /* 8.10.5 step 1 */ @@ -447,7 +443,7 @@ PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors) RootedObject desc(cx, &v.toObject()); /* Make a copy of the descriptor. We might need it later. */ - descObj_ = desc; + pd_ = v; isUndefined_ = false; @@ -539,8 +535,6 @@ PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors) void PropDesc::complete() { - MOZ_ASSERT(!isUndefined()); - if (isGenericDescriptor() || isDataDescriptor()) { if (!hasValue_) { hasValue_ = true; @@ -1054,7 +1048,7 @@ js::DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc * TrapDefineOwnProperty directly */ if (obj->is()) { - RootedValue pd(cx, desc.descriptorValue()); + RootedValue pd(cx, desc.pd()); return Proxy::defineProperty(cx, obj, id, pd); } return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval); @@ -1096,7 +1090,7 @@ js::DefineOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool js::ReadPropertyDescriptors(JSContext *cx, HandleObject props, bool checkAccessors, - AutoIdVector *ids, AutoPropDescVector *descs) + AutoIdVector *ids, AutoPropDescArrayRooter *descs) { if (!GetPropertyNames(cx, props, JSITER_OWNONLY, ids)) return false; @@ -1104,11 +1098,11 @@ js::ReadPropertyDescriptors(JSContext *cx, HandleObject props, bool checkAccesso RootedId id(cx); for (size_t i = 0, len = ids->length(); i < len; i++) { id = (*ids)[i]; - Rooted desc(cx); + PropDesc* desc = descs->append(); RootedValue v(cx); - if (!JSObject::getGeneric(cx, props, props, id, &v) || - !desc.initialize(cx, v, checkAccessors) || - !descs->append(desc)) + if (!desc || + !JSObject::getGeneric(cx, props, props, id, &v) || + !desc->initialize(cx, v, checkAccessors)) { return false; } @@ -1120,7 +1114,7 @@ bool js::DefineProperties(JSContext *cx, HandleObject obj, HandleObject props) { AutoIdVector ids(cx); - AutoPropDescVector descs(cx); + AutoPropDescArrayRooter descs(cx); if (!ReadPropertyDescriptors(cx, props, true, &ids, &descs)) return false; @@ -1141,7 +1135,7 @@ js::DefineProperties(JSContext *cx, HandleObject obj, HandleObject props) */ if (obj->is()) { for (size_t i = 0, len = ids.length(); i < len; i++) { - RootedValue pd(cx, descs[i].descriptorValue()); + RootedValue pd(cx, descs[i].pd()); if (!Proxy::defineProperty(cx, obj, ids[i], pd)) return false; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index e39c53b221b8..35f24f40c067 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -32,7 +32,7 @@ struct ObjectsExtraSizes; namespace js { -class AutoPropDescVector; +class AutoPropDescArrayRooter; struct GCMarker; struct NativeIterator; class Nursery; @@ -1401,7 +1401,7 @@ DefineProperties(JSContext *cx, HandleObject obj, HandleObject props); */ extern bool ReadPropertyDescriptors(JSContext *cx, HandleObject props, bool checkAccessors, - AutoIdVector *ids, AutoPropDescVector *descs); + AutoIdVector *ids, AutoPropDescArrayRooter *descs); /* Read the name using a dynamic lookup on the scopeChain. */ extern bool diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index d38692aaaa17..fef7f4a81c76 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -644,7 +644,7 @@ namespace js { PropDesc::PropDesc(const Value &getter, const Value &setter, Enumerability enumerable, Configurability configurable) - : descObj_(nullptr), + : pd_(UndefinedValue()), value_(UndefinedValue()), get_(getter), set_(setter), attrs(JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | @@ -772,17 +772,32 @@ IsInternalFunctionObject(JSObject *funobj) return fun->isLambda() && !funobj->getParent(); } -class AutoPropDescVector : public AutoVectorRooter +class AutoPropDescArrayRooter : private AutoGCRooter { public: - explicit AutoPropDescVector(JSContext *cx - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter(cx, DESCVECTOR) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; + explicit AutoPropDescArrayRooter(JSContext *cx) + : AutoGCRooter(cx, DESCRIPTORS), descriptors(cx) + { } + + PropDesc *append() { + if (!descriptors.append(PropDesc())) + return nullptr; + return &descriptors.back(); } - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + bool reserve(size_t n) { + return descriptors.reserve(n); + } + + PropDesc& operator[](size_t i) { + JS_ASSERT(i < descriptors.length()); + return descriptors[i]; + } + + friend void AutoGCRooter::trace(JSTracer *trc); + + private: + PropDescArray descriptors; }; /* diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 59e99565e432..53fbd410e3ec 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1111,7 +1111,7 @@ FromGenericPropertyDescriptor(JSContext *cx, MutableHandle desc, Mutab // steps 3-9 if (!desc.makeObject(cx)) return false; - rval.set(desc.descriptorValue()); + rval.set(desc.pd()); return true; } diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 68196d0c7f89..409fccc0dab0 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -809,63 +809,6 @@ Debugger::unwrapDebuggeeValue(JSContext *cx, MutableHandleValue vp) return true; } -/* - * Convert Debugger.Objects in desc to debuggee values. - * Reject non-callable getters and setters. - */ -static bool -CheckArgCompartment(JSContext *cx, JSObject *obj, HandleValue v, - const char *methodname, const char *propname) -{ - if (v.isObject() && v.toObject().compartment() != obj->compartment()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_COMPARTMENT_MISMATCH, - methodname, propname); - return false; - } - return true; -} - -bool -Debugger::unwrapPropDescInto(JSContext *cx, HandleObject obj, Handle wrapped, - MutableHandle unwrapped) -{ - MOZ_ASSERT(!wrapped.isUndefined()); - - unwrapped.set(wrapped); - - if (unwrapped.hasValue()) { - RootedValue value(cx, unwrapped.value()); - if (!unwrapDebuggeeValue(cx, &value) || - !CheckArgCompartment(cx, obj, value, "defineProperty", "value")) - { - return false; - } - unwrapped.setValue(value); - } - - if (unwrapped.hasGet()) { - RootedValue get(cx, unwrapped.getterValue()); - if (!unwrapDebuggeeValue(cx, &get) || - !CheckArgCompartment(cx, obj, get, "defineProperty", "get")) - { - return false; - } - unwrapped.setGetter(get); - } - - if (unwrapped.hasSet()) { - RootedValue set(cx, unwrapped.setterValue()); - if (!unwrapDebuggeeValue(cx, &set) || - !CheckArgCompartment(cx, obj, set, "defineProperty", "set")) - { - return false; - } - unwrapped.setSetter(set); - } - - return true; -} - JSTrapStatus Debugger::handleUncaughtExceptionHelper(Maybe &ac, MutableHandleValue *vp, bool callHook) @@ -5317,26 +5260,24 @@ DebuggerObject_defineProperty(JSContext *cx, unsigned argc, Value *vp) Rooted desc(cx); if (!desc.initialize(cx, args[1], false)) return false; - desc.clearDescriptorObject(); + desc.clearPd(); - if (!dbg->unwrapPropDescInto(cx, obj, desc, &desc)) + if (!desc.get().unwrapDebuggerObjectsInto(cx, dbg, obj, desc.address())) return false; if (!desc.checkGetter(cx) || !desc.checkSetter(cx)) return false; { + RootedId wrappedId(cx); + Maybe ac; ac.construct(cx, obj); - if (!cx->compartment()->wrapId(cx, id.address())) - return false; - if (!cx->compartment()->wrap(cx, &desc)) - return false; - if (!desc.makeObject(cx)) + if (!desc.get().wrapInto(cx, obj, id, wrappedId.address(), desc.address())) return false; ErrorCopier ec(ac, dbg->toJSObject()); bool dummy; - if (!DefineProperty(cx, obj, id, desc, true, &dummy)) + if (!DefineProperty(cx, obj, wrappedId, desc, true, &dummy)) return false; } @@ -5356,35 +5297,44 @@ DebuggerObject_defineProperties(JSContext *cx, unsigned argc, Value *vp) return false; AutoIdVector ids(cx); - AutoPropDescVector descs(cx); + AutoPropDescArrayRooter descs(cx); if (!ReadPropertyDescriptors(cx, props, false, &ids, &descs)) return false; size_t n = ids.length(); + AutoPropDescArrayRooter unwrappedDescs(cx); for (size_t i = 0; i < n; i++) { - if (!dbg->unwrapPropDescInto(cx, obj, descs[i], descs[i])) + if (!unwrappedDescs.append()) return false; - if (!descs[i].checkGetter(cx) || !descs[i].checkSetter(cx)) + if (!descs[i].unwrapDebuggerObjectsInto(cx, dbg, obj, &unwrappedDescs[i])) + return false; + if (!unwrappedDescs[i].checkGetter(cx) || !unwrappedDescs[i].checkSetter(cx)) return false; } { + AutoIdVector rewrappedIds(cx); + AutoPropDescArrayRooter rewrappedDescs(cx); + Maybe ac; ac.construct(cx, obj); + RootedId id(cx); for (size_t i = 0; i < n; i++) { - if (!cx->compartment()->wrapId(cx, ids[i].address())) + if (!rewrappedIds.append(JSID_VOID) || !rewrappedDescs.append()) return false; - if (!cx->compartment()->wrap(cx, descs[i])) - return false; - if (descs[i].descriptorValue().isUndefined() && !descs[i].makeObject(cx)) + id = ids[i]; + if (!unwrappedDescs[i].wrapInto(cx, obj, id, rewrappedIds[i].address(), &rewrappedDescs[i])) return false; } ErrorCopier ec(ac, dbg->toJSObject()); for (size_t i = 0; i < n; i++) { bool dummy; - if (!DefineProperty(cx, obj, ids[i], descs[i], true, &dummy)) + if (!DefineProperty(cx, obj, rewrappedIds[i], + rewrappedDescs[i], true, &dummy)) + { return false; + } } } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 0bc28b238ea0..df6da16ec406 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -506,8 +506,6 @@ class Debugger : private mozilla::LinkedListElement * happens in the target compartment--rotational symmetry.) */ bool unwrapDebuggeeValue(JSContext *cx, MutableHandleValue vp); - bool unwrapPropDescInto(JSContext *cx, HandleObject obj, Handle wrapped, - MutableHandle unwrapped); /* * Store the Debugger.Frame object for frame in *vp. diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 6c8bdea2d2ac..1538f04af933 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -18,29 +18,21 @@ using namespace js; using JS::GenericNaN; 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) { - setUndefined(); } -void -PropDesc::setUndefined() -{ - descObj_ = nullptr; - 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) { @@ -67,6 +59,94 @@ PropDesc::checkSetter(JSContext *cx) return true; } +static bool +CheckArgCompartment(JSContext *cx, JSObject *obj, HandleValue v, + const char *methodname, const char *propname) +{ + if (v.isObject() && v.toObject().compartment() != obj->compartment()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_COMPARTMENT_MISMATCH, + methodname, propname); + return false; + } + return true; +} + +/* + * Convert Debugger.Objects in desc to debuggee values. + * Reject non-callable getters and setters. + */ +bool +PropDesc::unwrapDebuggerObjectsInto(JSContext *cx, Debugger *dbg, HandleObject obj, + PropDesc *unwrapped) const +{ + MOZ_ASSERT(!isUndefined()); + + *unwrapped = *this; + + if (unwrapped->hasValue()) { + RootedValue value(cx, unwrapped->value_); + if (!dbg->unwrapDebuggeeValue(cx, &value) || + !CheckArgCompartment(cx, obj, value, "defineProperty", "value")) + { + return false; + } + unwrapped->value_ = value; + } + + if (unwrapped->hasGet()) { + RootedValue get(cx, unwrapped->get_); + if (!dbg->unwrapDebuggeeValue(cx, &get) || + !CheckArgCompartment(cx, obj, get, "defineProperty", "get")) + { + return false; + } + unwrapped->get_ = get; + } + + if (unwrapped->hasSet()) { + RootedValue set(cx, unwrapped->set_); + if (!dbg->unwrapDebuggeeValue(cx, &set) || + !CheckArgCompartment(cx, obj, set, "defineProperty", "set")) + { + return false; + } + unwrapped->set_ = set; + } + + return true; +} + +/* + * Rewrap *idp and the fields of *desc for the current compartment. Also: + * defining a property on a proxy requires pd_ to contain a descriptor object, + * so reconstitute desc->pd_ if needed. + */ +bool +PropDesc::wrapInto(JSContext *cx, HandleObject obj, const jsid &id, jsid *wrappedId, + PropDesc *desc) const +{ + MOZ_ASSERT(!isUndefined()); + + JSCompartment *comp = cx->compartment(); + + *wrappedId = id; + if (!comp->wrapId(cx, wrappedId)) + return false; + + *desc = *this; + RootedValue value(cx, desc->value_); + RootedValue get(cx, desc->get_); + RootedValue set(cx, desc->set_); + + if (!comp->wrap(cx, &value) || !comp->wrap(cx, &get) || !comp->wrap(cx, &set)) + return false; + + desc->value_ = value; + desc->get_ = get; + desc->set_ = set; + return !obj->is() || desc->makeObject(cx); +} + static const ObjectElements emptyElementsHeader(0, 0); /* Objects with no elements share one empty set of elements. */ @@ -302,7 +382,7 @@ js::ObjectImpl::markChildren(JSTracer *trc) void PropDesc::trace(JSTracer *trc) { - gc::MarkObjectRoot(trc, &descObj_, "PropDesc descriptor object"); + gc::MarkValueRoot(trc, &pd_, "PropDesc pd"); gc::MarkValueRoot(trc, &value_, "PropDesc value"); gc::MarkValueRoot(trc, &get_, "PropDesc get"); gc::MarkValueRoot(trc, &set_, "PropDesc set"); diff --git a/js/src/vm/PropDesc.h b/js/src/vm/PropDesc.h index b84ea548c786..bea886625635 100644 --- a/js/src/vm/PropDesc.h +++ b/js/src/vm/PropDesc.h @@ -12,6 +12,8 @@ namespace js { +class Debugger; + static inline JSPropertyOp CastAsPropertyOp(JSObject *object) { @@ -34,7 +36,7 @@ struct PropDesc { * Original object from which this descriptor derives, passed through for * the benefit of proxies. */ - JSObject *descObj_; + Value pd_; Value value_, get_, set_; @@ -53,7 +55,7 @@ struct PropDesc { bool isUndefined_ : 1; explicit PropDesc(const Value &v) - : descObj_(nullptr), + : pd_(UndefinedValue()), value_(v), get_(UndefinedValue()), set_(UndefinedValue()), attrs(0), @@ -64,6 +66,7 @@ struct PropDesc { } public: + friend void JS::AutoGCRooter::trace(JSTracer *trc); friend struct GCMethods; void trace(JSTracer *trc); @@ -79,7 +82,7 @@ struct PropDesc { PropDesc(const Value &v, Writability writable, Enumerability enumerable, Configurability configurable) - : descObj_(nullptr), + : pd_(UndefinedValue()), value_(v), get_(UndefinedValue()), set_(UndefinedValue()), attrs((writable ? 0 : JSPROP_READONLY) | @@ -126,8 +129,8 @@ struct PropDesc { void initFromPropertyDescriptor(Handle desc); bool makeObject(JSContext *cx); - /* Reset the descriptor entirely. */ - void setUndefined(); + void setUndefined() { isUndefined_ = true; } + bool isUndefined() const { return isUndefined_; } bool hasGet() const { MOZ_ASSERT(!isUndefined()); return hasGet_; } @@ -137,12 +140,8 @@ struct PropDesc { bool hasEnumerable() const { MOZ_ASSERT(!isUndefined()); return hasEnumerable_; } bool hasConfigurable() const { MOZ_ASSERT(!isUndefined()); return hasConfigurable_; } - Value descriptorValue() const { - MOZ_ASSERT(!isUndefined()); - return descObj_ ? ObjectValue(*descObj_) : UndefinedValue(); - } - void setDescriptorObject(JSObject *obj) { descObj_ = obj; } - void clearDescriptorObject() { setDescriptorObject(nullptr); } + Value pd() const { MOZ_ASSERT(!isUndefined()); return pd_; } + void clearPd() { pd_ = UndefinedValue(); } uint8_t attributes() const { MOZ_ASSERT(!isUndefined()); return attrs; } @@ -183,11 +182,6 @@ struct PropDesc { MOZ_ASSERT(hasValue()); return HandleValue::fromMarkedLocation(&value_); } - void setValue(const Value &value) { - MOZ_ASSERT(!isUndefined()); - value_ = value; - hasValue_ = true; - } JSObject * getterObject() const { MOZ_ASSERT(!isUndefined()); @@ -211,17 +205,6 @@ struct PropDesc { return HandleValue::fromMarkedLocation(&set_); } - void setGetter(const Value &getter) { - MOZ_ASSERT(!isUndefined()); - get_ = getter; - hasGet_ = true; - } - void setSetter(const Value &setter) { - MOZ_ASSERT(!isUndefined()); - set_ = setter; - hasSet_ = true; - } - /* * Unfortunately the values produced by these methods are used such that * we can't assert anything here. :-( @@ -240,6 +223,12 @@ struct PropDesc { */ bool checkGetter(JSContext *cx); bool checkSetter(JSContext *cx); + + bool unwrapDebuggerObjectsInto(JSContext *cx, Debugger *dbg, HandleObject obj, + PropDesc *unwrapped) const; + + bool wrapInto(JSContext *cx, HandleObject obj, const jsid &id, jsid *wrappedId, + PropDesc *wrappedDesc) const; }; } /* namespace js */ @@ -261,7 +250,7 @@ class PropDescOperations bool hasEnumerable() const { return desc()->hasEnumerable(); } bool hasConfigurable() const { return desc()->hasConfigurable(); } - Value descriptorValue() const { return desc()->descriptorValue(); } + Value pd() const { return desc()->pd(); } uint8_t attributes() const { return desc()->attributes(); } @@ -280,6 +269,10 @@ class PropDescOperations JSPropertyOp getter() const { return desc()->getter(); } JSStrictPropertyOp setter() const { return desc()->setter(); } + + // We choose not to expose the debugger-specific parts of PropDesc, both + // because they are not really general use, but also because they are a + // pain to expose. }; template @@ -306,20 +299,8 @@ class MutablePropDescOperations : public PropDescOperations return desc()->makeObject(cx); } - void setValue(const Value &value) { - desc()->setValue(value); - } - void setGetter(const Value &getter) { - desc()->setGetter(getter); - } - void setSetter(const Value &setter) { - desc()->setSetter(setter); - } - void setUndefined() { desc()->setUndefined(); } - - void setDescriptorObject(JSObject *obj) { desc()->setDescriptorObject(obj); } - void clearDescriptorObject() { desc()->clearDescriptorObject(); } + void clearPd() { desc()->clearPd(); } }; } /* namespace JS */ @@ -331,7 +312,8 @@ struct GCMethods { static PropDesc initial() { return PropDesc(); } static ThingRootKind kind() { return THING_ROOT_PROP_DESC; } static bool poisoned(const PropDesc &desc) { - return JS::IsPoisonedPtr(desc.descObj_) || + return (desc.pd_.isGCThing() && + JS::IsPoisonedPtr(desc.pd_.toGCThing())) || (desc.value_.isGCThing() && JS::IsPoisonedPtr(desc.value_.toGCThing())) || (desc.get_.isGCThing() &&