Bug 1200444 - Make JS::dbg::{IsDebugger,GetDebuggeeGlobals} handle CCWs; r=sfink
authorNick Fitzgerald <fitzgen@gmail.com>
Wed, 02 Sep 2015 21:04:56 -0700
changeset 260650 928ff2e0c463887aa96a0e37f18eb6a1d18a5144
parent 260649 5cc421782909055b81fa51ad465601f3854cfd90
child 260651 290e13dc24b51c18820a622a57674e48b37f0dff
push id29318
push usercbook@mozilla.com
push dateThu, 03 Sep 2015 11:15:07 +0000
treeherdermozilla-central@74fbd245369c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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 1200444 - Make JS::dbg::{IsDebugger,GetDebuggeeGlobals} handle CCWs; r=sfink Most devtools code that uses a Debugger actually ends up doing it through modules with a different global from the one the Debugger was instantiated in, and so it gets a CCW. When we pass one of these CCWs to ThreadSafeChromeUtils.saveHeapSnapshot, it would throw NS_ERROR_INVALID_ARG. The most straightforward fix is to have the JS APIs that ThreadSafeChromeUtils.saveHeapSnapshot calls peek through CCWs.
--- a/js/public/Debug.h
+++ b/js/public/Debug.h
@@ -318,22 +318,22 @@ onNewPromise(JSContext* cx, HandleObject
 // unsettled to settled once).
 onPromiseSettled(JSContext* cx, HandleObject promise);
 // Return true if the given value is a Debugger object, false otherwise.
-IsDebugger(const JSObject& obj);
+IsDebugger(JSObject& obj);
 // Append each of the debuggee global objects observed by the Debugger object
 // |dbgObj| to |vector|. Returns true on success, false on failure.
-GetDebuggeeGlobals(JSContext* cx, const JSObject& dbgObj, AutoObjectVector& vector);
+GetDebuggeeGlobals(JSContext* cx, JSObject& dbgObj, AutoObjectVector& vector);
 // Hooks for reporting where JavaScript execution began.
 // Our performance tools would like to be able to label blocks of JavaScript
 // execution with the function name and source location where execution began:
 // the event handler, the callback, etc.
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8118,27 +8118,29 @@ JS::dbg::onNewPromise(JSContext* cx, Han
 JS::dbg::onPromiseSettled(JSContext* cx, HandleObject promise)
     AssertIsPromise(cx, promise);
     Debugger::slowPathPromiseHook(cx, Debugger::OnPromiseSettled, promise);
-JS::dbg::IsDebugger(const JSObject& obj)
-    return js::GetObjectClass(&obj) == &Debugger::jsclass &&
-           js::Debugger::fromJSObject(&obj) != nullptr;
+JS::dbg::IsDebugger(JSObject& obj)
+    JSObject* unwrapped = CheckedUnwrap(&obj);
+    return unwrapped &&
+           js::GetObjectClass(unwrapped) == &Debugger::jsclass &&
+           js::Debugger::fromJSObject(unwrapped) != nullptr;
-JS::dbg::GetDebuggeeGlobals(JSContext* cx, const JSObject& dbgObj, AutoObjectVector& vector)
+JS::dbg::GetDebuggeeGlobals(JSContext* cx, JSObject& dbgObj, AutoObjectVector& vector)
-    js::Debugger* dbg = js::Debugger::fromJSObject(&dbgObj);
+    js::Debugger* dbg = js::Debugger::fromJSObject(CheckedUnwrap(&dbgObj));
     if (!vector.reserve(vector.length() + dbg->debuggees.count())) {
         return false;
     for (WeakGlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront())
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -202,18 +202,18 @@ typedef JSObject Env;
 class Debugger : private mozilla::LinkedListElement<Debugger>
     friend class Breakpoint;
     friend class DebuggerMemory;
     friend class SavedStacks;
     friend class mozilla::LinkedListElement<Debugger>;
     friend bool (::JS_DefineDebuggerObject)(JSContext* cx, JS::HandleObject obj);
-    friend bool (::JS::dbg::IsDebugger)(const JSObject&);
-    friend bool (::JS::dbg::GetDebuggeeGlobals)(JSContext*, const JSObject&, AutoObjectVector&);
+    friend bool (::JS::dbg::IsDebugger)(JSObject&);
+    friend bool (::JS::dbg::GetDebuggeeGlobals)(JSContext*, JSObject&, AutoObjectVector&);
     friend void JS::dbg::onNewPromise(JSContext* cx, HandleObject promise);
     friend void JS::dbg::onPromiseSettled(JSContext* cx, HandleObject promise);
     friend bool JS::dbg::FireOnGarbageCollectionHook(JSContext* cx,
                                                      JS::dbg::GarbageCollectionEvent::Ptr&& data);
     enum Hook {