Bug 1002737 - Find a new home for PropDesc::unwrapDebuggerObjectsInto. (r=jorendorff)
authorEric Faust <efaustbmo@gmail.com>
Tue, 03 Jun 2014 12:37:43 -0700
changeset 207298 98b5ebd7a3d2f69d76d629de4aa4bf3a9152fc61
parent 207297 4058f94dc21adeb2590a113d31f367762d1df2b3
child 207299 00481a443cf0a10162d8b928ff0d66fc24b18ca9
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1002737
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1002737 - Find a new home for PropDesc::unwrapDebuggerObjectsInto. (r=jorendorff)
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
js/src/vm/ObjectImpl.cpp
js/src/vm/PropDesc.h
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -804,16 +804,73 @@ Debugger::unwrapDebuggeeValue(JSContext 
             return false;
         }
 
         vp.setObject(*static_cast<JSObject*>(dobj->getPrivate()));
     }
     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<PropDesc> wrapped,
+                             MutableHandle<PropDesc> 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<AutoCompartment> &ac,
                                         MutableHandleValue *vp, bool callHook)
 {
     JSContext *cx = ac.ref().context()->asJSContext();
     if (cx->isExceptionPending()) {
         if (callHook && uncaughtExceptionHook) {
             RootedValue exc(cx);
@@ -5274,17 +5331,17 @@ DebuggerObject_defineProperty(JSContext 
     if (!ValueToId<CanGC>(cx, args[0], &id))
         return false;
 
     Rooted<PropDesc> desc(cx);
     if (!desc.initialize(cx, args[1], false))
         return false;
     desc.clearPd();
 
-    if (!desc.get().unwrapDebuggerObjectsInto(cx, dbg, obj, desc.address()))
+    if (!dbg->unwrapPropDescInto(cx, obj, desc, &desc))
         return false;
     if (!desc.checkGetter(cx) || !desc.checkSetter(cx))
         return false;
 
     {
         RootedId wrappedId(cx);
 
         Maybe<AutoCompartment> ac;
@@ -5318,17 +5375,20 @@ DebuggerObject_defineProperties(JSContex
     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 (!unwrappedDescs.append())
             return false;
-        if (!descs[i].unwrapDebuggerObjectsInto(cx, dbg, obj, &unwrappedDescs[i]))
+        Handle<PropDesc> wrapped = Handle<PropDesc>::fromMarkedLocation(&descs[i]);
+        MutableHandle<PropDesc> unwrapped =
+            MutableHandle<PropDesc>::fromMarkedLocation(&unwrappedDescs[i]);
+        if (!dbg->unwrapPropDescInto(cx, obj, wrapped, unwrapped))
             return false;
         if (!unwrappedDescs[i].checkGetter(cx) || !unwrappedDescs[i].checkSetter(cx))
             return false;
     }
 
     {
         AutoIdVector rewrappedIds(cx);
         AutoPropDescArrayRooter rewrappedDescs(cx);
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -502,16 +502,18 @@ class Debugger : private mozilla::Linked
      *
      * (Extreme nerd sidebar: Unwrapping happens in two steps because there are
      * two different kinds of symmetry at work: regardless of which direction
      * we're going, we want any exceptions to be created and thrown in the
      * debugger compartment--mirror symmetry. But compartment wrapping always
      * happens in the target compartment--rotational symmetry.)
      */
     bool unwrapDebuggeeValue(JSContext *cx, MutableHandleValue vp);
+    bool unwrapPropDescInto(JSContext *cx, HandleObject obj, Handle<PropDesc> wrapped,
+                            MutableHandle<PropDesc> unwrapped);
 
     /*
      * Store the Debugger.Frame object for frame in *vp.
      *
      * Use this if you have already access to a frame pointer without having
      * to incur the cost of walking the stack.
      */
     bool getScriptFrame(JSContext *cx, AbstractFramePtr frame, MutableHandleValue vp) {
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -54,73 +54,16 @@ PropDesc::checkSetter(JSContext *cx)
             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_GET_SET_FIELD,
                                  js_setter_str);
             return false;
         }
     }
     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
--- a/js/src/vm/PropDesc.h
+++ b/js/src/vm/PropDesc.h
@@ -7,18 +7,16 @@
 #ifndef vm_PropDesc_h
 #define vm_PropDesc_h
 
 #include "jsapi.h"
 #include "NamespaceImports.h"
 
 namespace js {
 
-class Debugger;
-
 static inline JSPropertyOp
 CastAsPropertyOp(JSObject *object)
 {
     return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
 }
 
 static inline JSStrictPropertyOp
 CastAsStrictPropertyOp(JSObject *object)
@@ -178,16 +176,21 @@ struct PropDesc {
         MOZ_ASSERT(hasWritable());
         return (attrs & JSPROP_READONLY) == 0;
     }
 
     HandleValue value() const {
         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());
         MOZ_ASSERT(hasGet());
         return get_.isUndefined() ? nullptr : &get_.toObject();
     }
     JSObject * setterObject() const {
         MOZ_ASSERT(!isUndefined());
@@ -201,16 +204,27 @@ struct PropDesc {
         return HandleValue::fromMarkedLocation(&get_);
     }
     HandleValue setterValue() const {
         MOZ_ASSERT(!isUndefined());
         MOZ_ASSERT(hasSet());
         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.  :-(
      */
     JSPropertyOp getter() const {
         return CastAsPropertyOp(get_.isUndefined() ? nullptr : &get_.toObject());
     }
     JSStrictPropertyOp setter() const {
@@ -220,19 +234,16 @@ struct PropDesc {
     /*
      * Throw a TypeError if a getter/setter is present and is neither callable
      * nor undefined. These methods do exactly the type checks that are skipped
      * by passing false as the checkAccessors parameter of initialize.
      */
     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 */
 
 namespace JS {
 
@@ -295,16 +306,26 @@ class MutablePropDescOperations : public
 
     void initFromPropertyDescriptor(Handle<JSPropertyDescriptor> descriptor) {
         desc()->initFromPropertyDescriptor(descriptor);
     }
     bool makeObject(JSContext *cx) {
         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 clearPd() { desc()->clearPd(); }
 };
 
 } /* namespace JS */
 
 namespace js {