From e1bd0564271fa7a6fd06dc7990b75397acfb9e23 Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Tue, 3 Jun 2014 12:37:44 -0700 Subject: [PATCH] Bug 1002737 - Implement PropDesc::wrapInto as JSCompartment::wrap. (r=jorendorff) --- js/src/jscompartment.cpp | 35 +++++++++++++++++++++++++++++++++++ js/src/jscompartment.h | 1 + js/src/vm/Debugger.cpp | 20 +++++++++++++------- js/src/vm/ObjectImpl.cpp | 31 ------------------------------- js/src/vm/PropDesc.h | 12 ++++-------- 5 files changed, 53 insertions(+), 46 deletions(-) diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 55e8c0b08bad..0cbb19d92374 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -495,6 +495,41 @@ 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 925968878d17..169e353a2a2c 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -318,6 +318,7 @@ 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/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 69187c2be591..2d0d21fef8c1 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -5342,16 +5342,18 @@ DebuggerObject_defineProperty(JSContext *cx, unsigned argc, Value *vp) return false; { - RootedId wrappedId(cx); - Maybe ac; ac.construct(cx, obj); - if (!desc.get().wrapInto(cx, obj, id, wrappedId.address(), desc.address())) + if (!cx->compartment()->wrapId(cx, id.address())) + return false; + if (!cx->compartment()->wrap(cx, &desc)) + return false; + if (!desc.makeObject(cx)) return false; ErrorCopier ec(ac, dbg->toJSObject()); bool dummy; - if (!DefineProperty(cx, obj, wrappedId, desc, true, &dummy)) + if (!DefineProperty(cx, obj, id, desc, true, &dummy)) return false; } @@ -5393,10 +5395,14 @@ DebuggerObject_defineProperties(JSContext *cx, unsigned argc, Value *vp) Maybe ac; ac.construct(cx, obj); for (size_t i = 0; i < n; i++) { - if (!rewrappedIds.append(JSID_VOID) || !rewrappedDescs.append(PropDesc())) + if (!rewrappedIds.append(ids[i]) || !rewrappedDescs.append(unwrappedDescs[i])) return false; - if (!unwrappedDescs[i].get().wrapInto(cx, obj, ids[i], rewrappedIds[i].address(), - rewrappedDescs[i].address())) + if (!cx->compartment()->wrapId(cx, rewrappedIds[i].address())) + return false; + if (!cx->compartment()->wrap(cx, rewrappedDescs[i])) + return false; + if (rewrappedDescs[i].descriptorValue().isUndefined() && + !rewrappedDescs[i].makeObject(cx)) { return false; } diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 11c4f0e8ebbf..9cbd3ed85f96 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -67,37 +67,6 @@ PropDesc::checkSetter(JSContext *cx) 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. */ diff --git a/js/src/vm/PropDesc.h b/js/src/vm/PropDesc.h index c6cb64494b60..64ca1ec72ac7 100644 --- a/js/src/vm/PropDesc.h +++ b/js/src/vm/PropDesc.h @@ -142,7 +142,8 @@ struct PropDesc { MOZ_ASSERT(!isUndefined()); return descObj_ ? ObjectValue(*descObj_) : UndefinedValue(); } - void clearDescriptorObject() { descObj_ = nullptr; } + void setDescriptorObject(JSObject *obj) { descObj_ = obj; } + void clearDescriptorObject() { setDescriptorObject(nullptr); } uint8_t attributes() const { MOZ_ASSERT(!isUndefined()); return attrs; } @@ -240,9 +241,6 @@ struct PropDesc { */ bool checkGetter(JSContext *cx); bool checkSetter(JSContext *cx); - - bool wrapInto(JSContext *cx, HandleObject obj, const jsid &id, jsid *wrappedId, - PropDesc *wrappedDesc) const; }; } /* namespace js */ @@ -283,10 +281,6 @@ 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 @@ -324,6 +318,8 @@ class MutablePropDescOperations : public PropDescOperations } void setUndefined() { desc()->setUndefined(); } + + void setDescriptorObject(JSObject *obj) { desc()->setDescriptorObject(obj); } void clearDescriptorObject() { desc()->clearDescriptorObject(); } };