Add Debugger.Object.prototype.getOwnPropertyNames.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 11 Jul 2011 20:32:05 -0500
changeset 75199 5230957a9741940f6d2316a6ae741706a694bb3c
parent 75198 732f02ab150b54c18eef0fb6cce64a5d1ed5b703
child 75200 5e59a54938405c523d0a36b40a3e9b2f5e1442de
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone8.0a1
Add Debugger.Object.prototype.getOwnPropertyNames.
js/src/jit-test/tests/debug/Object-getOwnPropertyNames-01.js
js/src/jit-test/tests/debug/Object-getOwnPropertyNames-02.js
js/src/jsdbg.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Object-getOwnPropertyNames-01.js
@@ -0,0 +1,28 @@
+// Basic getOwnPropertyNames tests.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger();
+var gobj = dbg.addDebuggee(g);
+
+function test(code) {
+    code = "(" + code + ");";
+    var expected = Object.getOwnPropertyNames(eval(code));
+    g.eval("obj = " + code);
+    var actual = gobj.getOwnPropertyDescriptor("obj").value.getOwnPropertyNames();
+    assertEq(JSON.stringify(actual.sort()), JSON.stringify(expected.sort()));
+}
+
+test("{}");
+test("{a: 0, b: 1}");
+test("{'name with space': 0}");
+test("{get x() {}, set y(v) {}}");
+test("{get x() { throw 'fit'; }}");
+test("Object.create({a: 1})");
+test("Object.create({get a() {}, set a(v) {}})");
+test("(function () { var x = {a: 0, b: 1}; delete a; return x; })()");
+test("Object.create(null, {x: {value: 0}})");
+test("[]");
+test("[0, 1, 2]");
+test("[,,,,,]");
+test("/a*a/");
+test("function () {}");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Object-getOwnPropertyNames-02.js
@@ -0,0 +1,7 @@
+// obj.getOwnPropertyNames() works when obj's referent is itself a cross-compartment wrapper.
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger();
+var gobj = dbg.addDebuggee(g);
+g.p = {xyzzy: 8};  // makes a cross-compartment wrapper
+assertEq(gobj.getOwnPropertyDescriptor("p").value.getOwnPropertyDescriptor("xyzzy").value, 8);
--- a/js/src/jsdbg.cpp
+++ b/js/src/jsdbg.cpp
@@ -2867,16 +2867,60 @@ DebuggerObject_getOwnPropertyDescriptor(
                 return false;
             desc.setter = CastAsStrictPropertyOp(set.toObjectOrNull());
         }
     }
 
     return NewPropertyDescriptorObject(cx, &desc, vp);
 }
 
+static JSBool
+DebuggerObject_getOwnPropertyNames(JSContext *cx, uintN argc, Value *vp)
+{
+    THIS_DEBUGOBJECT_OWNER_REFERENT(cx, vp, "get script", dbg, obj);
+
+    AutoIdVector keys(cx);
+    {
+        AutoCompartment ac(cx, obj);
+        if (!ac.enter())
+            return false;
+
+        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &keys))
+            return false;
+    }
+
+    AutoValueVector vals(cx);
+    if (!vals.resize(keys.length()))
+        return false;
+
+    for (size_t i = 0, len = keys.length(); i < len; i++) {
+         jsid id = keys[i];
+         if (JSID_IS_INT(id)) {
+             JSString *str = js_ValueToString(cx, Int32Value(JSID_TO_INT(id)));
+             if (!str)
+                 return false;
+             vals[i].setString(str);
+         } else if (JSID_IS_ATOM(id)) {
+             vals[i].setString(JSID_TO_STRING(id));
+             if (!cx->compartment->wrap(cx, &vals[i]))
+                 return false;
+         } else {
+             vals[i].setObject(*JSID_TO_OBJECT(id));
+             if (!dbg->wrapDebuggeeValue(cx, &vals[i]))
+                 return false;
+         }
+    }
+
+    JSObject *aobj = NewDenseCopiedArray(cx, vals.length(), vals.begin());
+    if (!aobj)
+        return false;
+    vp->setObject(*aobj);
+    return true;
+}
+
 
 enum ApplyOrCallMode { ApplyMode, CallMode };
 
 static JSBool
 ApplyOrCall(JSContext *cx, uintN argc, Value *vp, ApplyOrCallMode mode)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, vp, "apply", dbg, obj);
 
@@ -2957,16 +3001,17 @@ static JSPropertySpec DebuggerObject_pro
     JS_PSG("name", DebuggerObject_getName, 0),
     JS_PSG("parameterNames", DebuggerObject_getParameterNames, 0),
     JS_PSG("script", DebuggerObject_getScript, 0),
     JS_PS_END
 };
 
 static JSFunctionSpec DebuggerObject_methods[] = {
     JS_FN("getOwnPropertyDescriptor", DebuggerObject_getOwnPropertyDescriptor, 1, 0),
+    JS_FN("getOwnPropertyNames", DebuggerObject_getOwnPropertyNames, 0, 0),
     JS_FN("apply", DebuggerObject_apply, 0, 0),
     JS_FN("call", DebuggerObject_call, 0, 0),
     JS_FS_END
 };
 
 
 // === Glue