Bug 743311: Implement Debugger.prototype.findAllGlobals. r=jorendorff
authorJim Blandy <jimb@mozilla.com>
Sat, 13 Oct 2012 16:04:41 -0700
changeset 110339 801ed9c31fd5ea40a797f4641a80ec3452ce3d38
parent 110338 e44a8b7579fb531430a0711514f976992e19c38f
child 110340 f82c3f3bb6548edf4840ca7cafa7e0a9937dadb4
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersjorendorff
bugs743311
milestone19.0a1
Bug 743311: Implement Debugger.prototype.findAllGlobals. r=jorendorff
js/src/jit-test/tests/debug/Debugger-findAllGlobals-01.js
js/src/jit-test/tests/debug/Debugger-findAllGlobals-02.js
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Debugger-findAllGlobals-01.js
@@ -0,0 +1,24 @@
+// Debugger.prototype.findAllGlobals surface.
+
+load(libdir + 'asserts.js');
+
+var dbg = new Debugger;
+var d = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(dbg), 'findAllGlobals');
+assertEq(d.configurable, true);
+assertEq(d.enumerable, false);
+assertEq(d.writable, true);
+assertEq(typeof d.value, 'function');
+assertEq(dbg.findAllGlobals.length, 0);
+assertEq(dbg.findAllGlobals.name, 'findAllGlobals');
+
+// findAllGlobals can only be applied to real Debugger instances.
+assertThrowsInstanceOf(function() {
+                         Debugger.prototype.findAllGlobals.call(Debugger.prototype);
+                       },
+                       TypeError);
+var a = dbg.findAllGlobals();
+assertEq(a instanceof Array, true);
+assertEq(a.length > 0, true);
+for (g of a) {
+  assertEq(g instanceof Debugger.Object, true);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Debugger-findAllGlobals-02.js
@@ -0,0 +1,27 @@
+// Debugger.prototype.findAllGlobals finds ALL the globals!
+
+var g1 = newGlobal();           // Created before the Debugger; debuggee.
+var g2 = newGlobal();           // Created before the Debugger; not debuggee.
+
+var dbg = new Debugger;
+
+var g3 = newGlobal();           // Created after the Debugger; debuggee.
+var g4 = newGlobal();           // Created after the Debugger; not debuggee.
+
+var g1w = dbg.addDebuggee(g1);
+var g3w = dbg.addDebuggee(g3);
+
+var a = dbg.findAllGlobals();
+
+// Get Debugger.Objects viewing the globals from their own compartments;
+// this is the sort that findAllGlobals and addDebuggee return.
+var g2w = g1w.makeDebuggeeValue(g2).unwrap();
+var g4w = g1w.makeDebuggeeValue(g4).unwrap();
+var thisw = g1w.makeDebuggeeValue(this).unwrap();
+
+// Check that they're all there.
+assertEq(a.indexOf(g1w) != -1, true);
+assertEq(a.indexOf(g2w) != -1, true);
+assertEq(a.indexOf(g3w) != -1, true);
+assertEq(a.indexOf(g4w) != -1, true);
+assertEq(a.indexOf(thisw) != -1, true);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -11,16 +11,17 @@
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jswrapper.h"
 #include "jsarrayinlines.h"
 #include "jsgcinlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
+#include "jscompartment.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/BytecodeEmitter.h"
 #include "gc/Marking.h"
 #include "methodjit/Retcon.h"
 #include "js/Vector.h"
 
 #include "vm/Stack-inl.h"
@@ -2479,16 +2480,40 @@ Debugger::findScripts(JSContext *cx, uns
             return false;
         result->setDenseArrayElement(i, ObjectValue(*scriptObject));
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
+JSBool
+Debugger::findAllGlobals(JSContext *cx, unsigned argc, Value *vp)
+{
+    THIS_DEBUGGER(cx, argc, vp, "findAllGlobals", args, dbg);
+
+    RootedObject result(cx, NewDenseEmptyArray(cx));
+    if (!result)
+        return false;
+
+    for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
+        GlobalObject *global = c->maybeGlobal();
+        if (global) {
+            Value globalValue(ObjectValue(*global));
+            if (!dbg->wrapDebuggeeValue(cx, &globalValue))
+                return false;
+            if (!js_NewbornArrayPush(cx, result, globalValue))
+                return false;
+        }
+    }
+
+    args.rval().setObject(*result);
+    return true;
+}
+
 JSPropertySpec Debugger::properties[] = {
     JS_PSGS("enabled", Debugger::getEnabled, Debugger::setEnabled, 0),
     JS_PSGS("onDebuggerStatement", Debugger::getOnDebuggerStatement,
             Debugger::setOnDebuggerStatement, 0),
     JS_PSGS("onExceptionUnwind", Debugger::getOnExceptionUnwind,
             Debugger::setOnExceptionUnwind, 0),
     JS_PSGS("onNewScript", Debugger::getOnNewScript, Debugger::setOnNewScript, 0),
     JS_PSGS("onEnterFrame", Debugger::getOnEnterFrame, Debugger::setOnEnterFrame, 0),
@@ -2501,16 +2526,17 @@ JSPropertySpec Debugger::properties[] = 
 JSFunctionSpec Debugger::methods[] = {
     JS_FN("addDebuggee", Debugger::addDebuggee, 1, 0),
     JS_FN("removeDebuggee", Debugger::removeDebuggee, 1, 0),
     JS_FN("hasDebuggee", Debugger::hasDebuggee, 1, 0),
     JS_FN("getDebuggees", Debugger::getDebuggees, 0, 0),
     JS_FN("getNewestFrame", Debugger::getNewestFrame, 0, 0),
     JS_FN("clearAllBreakpoints", Debugger::clearAllBreakpoints, 1, 0),
     JS_FN("findScripts", Debugger::findScripts, 1, 0),
+    JS_FN("findAllGlobals", Debugger::findAllGlobals, 0, 0),
     JS_FS_END
 };
 
 
 /*** Debugger.Script *****************************************************************************/
 
 static inline JSScript *
 GetScriptReferent(JSObject *obj)
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -176,16 +176,17 @@ class Debugger {
     static JSBool setUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp);
     static JSBool addDebuggee(JSContext *cx, unsigned argc, Value *vp);
     static JSBool removeDebuggee(JSContext *cx, unsigned argc, Value *vp);
     static JSBool hasDebuggee(JSContext *cx, unsigned argc, Value *vp);
     static JSBool getDebuggees(JSContext *cx, unsigned argc, Value *vp);
     static JSBool getNewestFrame(JSContext *cx, unsigned argc, Value *vp);
     static JSBool clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp);
     static JSBool findScripts(JSContext *cx, unsigned argc, Value *vp);
+    static JSBool findAllGlobals(JSContext *cx, unsigned argc, Value *vp);
     static JSBool wrap(JSContext *cx, unsigned argc, Value *vp);
     static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
     static JSPropertySpec properties[];
     static JSFunctionSpec methods[];
 
     JSObject *getHook(Hook hook) const;
     bool hasAnyLiveHooks() const;