Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonlindholm/5627711 to your computer and use it in GitHub Desktop.
Save simonlindholm/5627711 to your computer and use it in GitHub Desktop.
From a4537a44618140589f8448281d6f7616bf9ff09c Mon Sep 17 00:00:00 2001
From: Simon Lindholm <simon.lindholm10@gmail.com>
Date: Wed, 22 May 2013 15:52:57 +0200
Subject: [PATCH] Add Debugger.prototype.makeDebuggeeValueFromGlobal
---
Debugger-makeDebuggeeValueFromGlobal-01.js | 31 ++++++++++++++++++++++++++++++
Debugger.cpp | 26 ++++++++++++++++++++++---
Debugger.h | 2 +-
3 files changed, 55 insertions(+), 4 deletions(-)
create mode 100644 Debugger-makeDebuggeeValueFromGlobal-01.js
diff --git a/Debugger-makeDebuggeeValueFromGlobal-01.js b/Debugger-makeDebuggeeValueFromGlobal-01.js
new file mode 100644
index 0000000..3836f2d
--- /dev/null
+++ b/Debugger-makeDebuggeeValueFromGlobal-01.js
@@ -0,0 +1,31 @@
+// Debugger.prototype.makeDebuggeeValueFromGlobal creates a debuggee value from
+// a global without adding it as a debuggee.
+
+var g = newGlobal();
+var dbg = new Debugger();
+
+var gw = dbg.makeDebuggeeValueFromGlobal(g);
+assertEq(dbg.hasDebuggee(g), false);
+
+
+// Sanity test that the object is usable without having to be a debuggee.
+
+assertEq(gw.getOwnPropertyDescriptor('Math').value, gw.makeDebuggeeValue(g.Math));
+assertEq(gw['class'], 'global');
+assertEq(gw.callable, false);
+assertEq(gw.global, gw);
+
+assertEq(gw.evalInGlobal('1+1'), 2);
+
+g.eval('with ({a: 1}) { function f(x) { eval(x); } }');
+var df = gw.makeDebuggeeValue(g.f);
+assertEq(df.environment.getVariable('a'), 1);
+
+assertEq(gw.asEnvironment().object, gw);
+
+assertEq(df.callable, true);
+assertEq(df.script, undefined);
+
+
+var gw2 = dbg.addDebuggee(g);
+assertEq(gw, gw2);
diff --git a/Debugger.cpp b/Debugger.cpp
index 89cc92c..898a072 100644
--- a/Debugger.cpp
+++ b/Debugger.cpp
@@ -1869,28 +1869,31 @@ Debugger::setUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp)
}
dbg->uncaughtExceptionHook = args[0].toObjectOrNull();
args.rval().setUndefined();
return true;
}
GlobalObject *
-Debugger::unwrapDebuggeeArgument(JSContext *cx, const Value &v)
+Debugger::unwrapDebuggeeArgument(JSContext *cx, const Value &v, bool allowDO)
{
if (!v.isObject()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
"argument", "not a global object");
return NULL;
}
RootedObject obj(cx, &v.toObject());
- /* If it's a Debugger.Object belonging to this debugger, dereference that. */
- if (obj->getClass() == &DebuggerObject_class) {
+ /*
+ * If it's a Debugger.Object belonging to this debugger, dereference that if
+ * the caller allows us.
+ */
+ if (allowDO && obj->getClass() == &DebuggerObject_class) {
RootedValue rv(cx, v);
if (!unwrapDebuggeeValue(cx, &rv))
return NULL;
obj = &rv.toObject();
}
/* If we have a cross-compartment wrapper, dereference as far as is secure. */
obj = CheckedUnwrap(obj);
@@ -1929,16 +1932,32 @@ Debugger::addDebuggee(JSContext *cx, unsigned argc, Value *vp)
RootedValue v(cx, ObjectValue(*global));
if (!dbg->wrapDebuggeeValue(cx, &v))
return false;
args.rval().set(v);
return true;
}
JSBool
+Debugger::makeDebuggeeValueFromGlobal(JSContext *cx, unsigned argc, Value *vp)
+{
+ REQUIRE_ARGC("Debugger.makeDebuggeeValueFromGlobal", 1);
+ THIS_DEBUGGER(cx, argc, vp, "makeDebuggeeValueFromGlobal", args, dbg);
+ Rooted<GlobalObject*> global(cx, dbg->unwrapDebuggeeArgument(cx, args[0], false));
+ if (!global)
+ return false;
+
+ RootedValue v(cx, ObjectValue(*global));
+ if (!dbg->wrapDebuggeeValue(cx, &v))
+ return false;
+ args.rval().set(v);
+ return true;
+}
+
+JSBool
Debugger::addAllGlobalsAsDebuggees(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "addAllGlobalsAsDebuggees", args, dbg);
AutoDebugModeGC dmgc(cx->runtime);
for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
if (c == dbg->object->compartment())
continue;
c->zone()->scheduledForDestruction = false;
@@ -2649,16 +2668,17 @@ const JSFunctionSpec Debugger::methods[] = {
JS_FN("removeDebuggee", Debugger::removeDebuggee, 1, 0),
JS_FN("removeAllDebuggees", Debugger::removeAllDebuggees, 0, 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_FN("makeDebuggeeValueFromGlobal", Debugger::makeDebuggeeValueFromGlobal, 1, 0),
JS_FS_END
};
/*** Debugger.Script *****************************************************************************/
static inline JSScript *
GetScriptReferent(JSObject *obj)
diff --git a/Debugger.h b/Debugger.h
index faa4352..e029f1e 100644
--- a/Debugger.h
+++ b/Debugger.h
@@ -280,17 +280,17 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
* null - Return JSTRAP_ERROR to terminate the debuggee with an
* uncatchable error.
* anything else - Make a new TypeError the pending exception and
* return handleUncaughtException(ac, vp, callHook).
*/
JSTrapStatus parseResumptionValue(mozilla::Maybe<AutoCompartment> &ac, bool ok, const Value &rv,
MutableHandleValue vp, bool callHook = true);
- GlobalObject *unwrapDebuggeeArgument(JSContext *cx, const Value &v);
+ GlobalObject *unwrapDebuggeeArgument(JSContext *cx, const Value &v, bool allowDO = true);
static void traceObject(JSTracer *trc, JSObject *obj);
void trace(JSTracer *trc);
static void finalize(FreeOp *fop, JSObject *obj);
void markKeysInCompartment(JSTracer *tracer);
static Class jsclass;
--
1.8.1.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment