Debugger Client API: Difference between revisions
Jump to navigation
Jump to search
(Debugger Client API) |
No edit summary |
||
Line 188: | Line 188: | ||
</pre> | </pre> | ||
<br> | <br> | ||
See [http://past.pastebin.mozilla.org/1376464 here] for the full example program. |
Revision as of 16:00, 14 November 2011
/* * Debugger API demo. * Try it in Scratchpad with Environment -> Browser, using * http://htmlpad.org/debugger/ as the current page. */ let client; let threadClient; function startDebugger() { // Start the server. if (!DebuggerServer.initialized) { DebuggerServer.init(); DebuggerServer.addBrowserActors(); } // Listen to an nsIPipe let transport = DebuggerServer.connectPipe(); // For an nsIServerSocket we do this: // DebuggerServer.openListener(aPort, aLocalOnly); // ...and this at the client: // let transport = debuggerSocketConnect(aHost, aPort); // Start the client. client = new DebuggerClient(transport); // Attach listeners for client events. client.addListener("tabNavigated", onTab); client.addListener("newScript", fooListener); client.ready(function(aType, aTraits) { // Now the client is conected to the server. debugTab(); }); } function shutdownDebugger() { client.close(); } /** * Start debugging the current tab. */ function debugTab() { // Get the list of tabs to find the one to attach to. client.listTabs(function(aResponse) { // Find the active tab. let tab = aResponse.tabs[aResponse.selected]; // Attach to the tab. client.attachTab(tab.actor, function(aResponse, aTabClient) { if (!aTabClient) return; // Attach to the thread (context). client.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) { if (!aThreadClient) return; threadClient = aThreadClient; // Attach listeners for thread events. threadClient.addListener("paused", onPause); threadClient.addListener("resumed", fooListener); threadClient.addListener("detached", fooListener); threadClient.addListener("framesadded", onFrames); threadClient.addListener("framescleared", fooListener); threadClient.addListener("scriptsadded", onScripts); threadClient.addListener("scriptscleared", fooListener); // Resume the thread. threadClient.resume(); // Debugger is now ready and debuggee is running. }); }); }); } /** * Handler for location changes. */ function onTab() { // Detach from the previous thread. client.activeThread.detach(function() { // Detach from the previous tab. client.activeTab.detach(function() { // Start debugging the new tab. debugTab(); }); }); } /** * Handler for entering pause state. */ function onPause() { // Get the top 20 frames in the server's frame stack cache. client.activeThread.fillFrames(20); // Get the scripts loaded in the server's source script cache. client.activeThread.fillScripts(); } /** * Handler for framesadded events. */ function onFrames() { // Get the list of frames in the server. for each (let frame in client.activeThread.cachedFrames) { // frame is a Debugger.Frame grip. dump("frame: " + frame.toSource() + "\n"); inspectFrame(frame); } } /** * Handler for scriptsadded events. */ function onScripts() { // Get the list of scripts in the server. for each (let script in client.activeThread.cachedScripts) { // script is a Debugger.Script grip. dump("script: " + script.toSource() + "\n"); } // Resume execution, since this is the last thing going on in the paused // state and there is no UI in this program. Wait a bit so that object // inspection has a chance to finish. setTimeout(function() { threadClient.resume(); }, 1000); } /** * Helper function to inspect the provided frame. */ function inspectFrame(aFrame) { // Get the "this" object. if (aFrame["this"]) { getObjectProperties(aFrame["this"]); } // Add "arguments". if (aFrame.arguments && aFrame.arguments.length > 0) { // frame.arguments is a regular Array. dump("frame.arguments: " + aFrame.arguments.toSource() + "\n"); // Add variables for every argument. let objClient = client.activeThread.pauseGrip(aFrame.callee); objClient.nameAndParameters(function(aResponse) { for (let i = 0; i < aResponse.parameters.length; i++) { let name = aResponse.parameters[i]; let value = aFrame.arguments[i]; if (typeof value == "object" && value.type == "object") { getObjectProperties(value); } } }); } } /** * Helper function that retrieves the specified object's properties. */ function getObjectProperties(aObject) { let thisClient = client.activeThread.pauseGrip(aObject); thisClient.prototypeAndProperties(function(aResponse) { // Get prototype as a protocol-specified grip. if (aResponse.prototype.type != "null") { dump("__proto__: " + aResponse.prototype.toSource() + "\n"); } // Get the rest of the object's own properties as protocol-specified grips. for each (let prop in Object.keys(aResponse.ownProperties)) { dump(prop + ": " + aResponse.ownProperties[prop].toSource() + "\n"); } }); } /** * Generic event listener. */ function fooListener(aEvent) { dump(aEvent + "\n"); } // Run the program. startDebugger(); // Execute the following line to stop the program. //shutdownDebugger();
See here for the full example program.