Script Panel Refactoring

From FirebugWiki

(Difference between revisions)
Jump to: navigation, search
(Added more links)
(17 intermediate revisions not shown)
Line 1: Line 1:
-
This page summarizes support for remote JS debugging in Firebug (based on JSD2).
+
This page summarizes refactoring the Firebug debugger to use JSD2 and adding support for remote JavaScript debugging. [http://code.google.com/p/fbug/issues/detail?id=5421 Issue 5421] tracks the actual changes done.
 +
 
 +
== Resources ==
 +
Firebug Wiki:
 +
* [[HTTP Monitor]]
 +
* [[Firebug 1.7: Mozilla Backend|Firebug 1.7 BTI]]
 +
* [[Net Panel Architecture Review]]
 +
* [[Remoting Prototype#Prototype|Remoting Prototype]]
 +
* [[Remoting Architecture|Remoting Architecture]]
 +
 
 +
Mozilla Wiki:
 +
* [https://wiki.mozilla.org/Debugger Debugger]
 +
* [https://wiki.mozilla.org/Debugger_Client_API Debugger Client API]
 +
* [https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Guide JS Debugger API Guide]
 +
* [https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference JS Debugger API Reference]
 +
* [https://wiki.mozilla.org/DevTools/Features/Debugger DevTools Debugger]
 +
* [https://wiki.mozilla.org/Remote_Debugging_Protocol Remote Debugging Protocol]
== Goals ==
== Goals ==
* Adopt JSD2 (get rid of all JSD1 APIs)
* Adopt JSD2 (get rid of all JSD1 APIs)
-
* Support Remote Debugging
+
* Support remote debugging
 +
== Related Issues ==
 +
* [http://code.google.com/p/fbug/issues/detail?id=5421 Issue 5421]: Implement JSD2
 +
* [http://code.google.com/p/fbug/issues/detail?id=5837 Issue 5837]: Implement remote debugging
== JSD2 API Requirements ==
== JSD2 API Requirements ==
-
The following list summarizes list of high-level features that Firebug needs to support. It should be verified that all the features can re-implemented on top of JSD2 before starting the refactoring.
+
The following list summarizes the high-level features that Firebug needs to support. It should be verified that all the features can re-implemented on top of JSD2 before starting the refactoring.
-
* List of scripts available on selected tab (including static, events and evaluated scripts) including iframes.
+
* List of scripts available on selected tab (including static, events and evaluated scripts) including iframes &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#findScripts%28%29 Debugger.findScripts()]</code>
-
* Stepping (into, over, out, resume, current line)  
+
* Stepping (into, over, out, resume, current line)
-
* Support for <code>debugger;</code> keyword
+
* Support for <code>debugger;</code> keyword &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onDebuggerStatement%28%29 Debugger.onDebuggerStatement()]</code>
-
* Support for breakpoints (add, remove, enable, disabled, conditional, list of existing breakpoints)
+
* Support for breakpoints (add, remove, enable, disabled, conditional, list of existing breakpoints) &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Script#Methods Debugger.Script methods]</code>
* Recognize executable lines
* Recognize executable lines
-
* Dynamic eval in a frame (used e.g. by the Watch panel when the debugger is halted)
+
* Dynamic eval in a frame (used e.g. by the [[Watch Side Panel]] when the debugger is halted) &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame#eval%28%29 Debugger.Frame.eval()]</code> and <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame#evalWithBindings%28%29 Debugger.Frame.evalWithBindings()]</code>
-
* Get stack frames (including passed arguments)
+
* Get stack frames (including passed arguments) &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#getNewestFrame%28%29 Debugger.getNewestFrame()]</code> and <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame#Accessor_properties Debugger.Frame.older]</code>
-
* Scope chain variable exploring (with & closure scopes). It should be possible to see all values.
+
* Scope chain variable exploring (with & closure scopes). It should be possible to see all values. &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger.Frame#Accessor_properties Debugger.Frame.environment]</code>
* Break on next call
* Break on next call
* Profiling (was part of JSD1)
* Profiling (was part of JSD1)
-
* Tracking (break on) throw/catch/error
+
* Tracking (break on) throw/catch/error &rarr; <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onThrow%28%29 Debugger.onThrow()]</code> and <code>[https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onError%28%29 Debugger.onError()]</code>
* Tracking (monitoring) function calls
* Tracking (monitoring) function calls
* Freezing page UI if debugger is halted (including timeouts, intervals and worker threads)
* Freezing page UI if debugger is halted (including timeouts, intervals and worker threads)
 +
=== Not Ready in JSD2 ===
 +
* There is not source for evals.
 +
* [https://developer.mozilla.org/en/SpiderMonkey/JS_Debugger_API_Reference/Debugger#onNewScript%28%29 new Function scripts?]
 +
* [https://bugzilla.mozilla.org/show_bug.cgi?id=676586 Meta bug]: Implement a script Debugger
 +
** As soon as this one is fixed
 +
** Profiling is unrelated to JSD2. What is the plan here?
 +
** Tracking (break on) throw/catch/error; also what is the plan?
 +
* Conditional breakpoints ([https://bugzilla.mozilla.org/show_bug.cgi?id=740825 bug 740825])
== Script Panel Architecture ==
== Script Panel Architecture ==
-
The Script panel needs to be built on top of JSD2, remote protocol and Firebug remote architecture. Remoting is already supported by [HTTP Monitor] and both components should share the same approaches and API
+
The Script panel needs to be built on top of JSD2, remote protocol and Firebug remote architecture. Remoting is already supported by [[HTTP Monitor]] and both components should share the same approaches and API.
TBD
TBD
 +
== Current Debugger Architecture ==
 +
This section describes the current debugger architecture.
-
== Resources ==
+
[[File:Current-debugger-architecture.png]]
-
* [https://wiki.mozilla.org/Debugger Debugger]
+
 
-
* [https://wiki.mozilla.org/DevTools/Features/Debugger DevTools Debugger]
+
There are several layers/objects so, let's describe them step by step starting from the bottom.
-
* [https://wiki.mozilla.org/Remote_Debugging_Protocol Remote Debugging Protocol]
+
 
 +
* Backend: JSD1, FirebugService, Debugger
 +
* Frontend: JavaScriptTool, ScriptPanel
 +
 
 +
=== JSD1 ===
 +
This layer represents JSD1 platform API. These API allows to implement script debuggers and represent direct competition to JSD2 API. Of course this layer should entirely disappear and should be replaced by JSD2.
 +
 
 +
=== Firebug Service ===
 +
Firebug service is implemented as [https://developer.mozilla.org/en-US/docs/JavaScript_code_modules/Using?redirectlocale=en-US&redirectslug=Using_JavaScript_code_modules js module] on top of JSD1 layer. The object is called ''FBS'' and it's purpose is to wrap JSD1 API so, they are not directly accessed anywhere else. This layer also maintain list of registered debuggers (usually <code>Firebug.Debugger</code> module) and fires various events to them (e.g. ''onToggleBreakpoint'', ''onToggleMonitor'', etc.) or execute theirs callback (e.g. ''onBreak'', ''onFunctionCall'', ''onError'', ''onThrow'', ''onScriptCreated'', etc.)
 +
 
 +
Main responsibilities:
 +
* Activate/deactivate JSD in the browser. The activation is global for all current browser windows.
 +
* Hook debugger events (interrupts, break on a breakpoint, etc.)
 +
* Maintains list of registered debuggers (there is usually just one - Firebug debugger) and sends events to them.
 +
* Manages nested event loop that is created for the debugger UI when page JS execution breaks.
 +
* Sets/removes/enables/disables/saves/loads breakpoints
 +
* Implements debugger stepping over/in/out/runUntil
 +
* Monitors function calls
 +
* Starts/stops profiling
 +
* Tracks exceptions and errors (not working well)
 +
* Tracks compiled scripts (not all of them)
 +
 
 +
=== Debugger ===
 +
This object is derived from <code>Firebug.Module</code> and represents Firebug's debugger. It's also registered as a debugger into ''Firebug Service'' (FBS). This object should be the only one accessing FBS. It calls FBS API and receives various callbacks and events.
 +
 
 +
This object implements methods that can be used by the Script panel or other parts of Firebug (e.g. by those panels which implements BON).
 +
 
 +
Some examples of the API:
 +
* ''evaluate'', ''evaluateInCallingFrame''
 +
* ''breakNow'', ''getCurrentStackTrace''
 +
* ''rerun''
 +
* ''stepOver'', ''stepInto'', ''stepOut'', ''runUntil, ''resume''
 +
* ''setBreakpoint'', ''clearBrakpoint'', etc.
 +
* ''monitorFunction'', ''unmonitorFunction''
 +
* ''monitorScript'', ''unmonitorScript''
 +
* ''activateDebugger'', ''deactivateDebugger''
 +
 
 +
Implementation of these methods is based on FBS API.
 +
 
 +
There is also <code>Firebug.DebuggerListener</code> that defines the interface used by FBS
 +
* ''onStop'', ''onResume'', ''onThrow'', ''onError'', ''onScriptCreated'' (there is more ''onScriptCreated'' events)
 +
 
 +
This object is ''observable'' and it activates the underlying JSD only if an observer exists. The observer is currently the Script panel even if it would make a bit more sense if it's actually the ''JavaScriptTool''.
 +
 
 +
=== JavaScriptTool ===
 +
This object is part or BTI and represents a javascript debugger tool. This object is like a proxy sitting between <code>Firebug.Debugger</code> and the <code>ScriptPanel</code>. The current implementation is in-process only so, based on direct <code>Firebug.Debugger</code> API calls.
 +
 
 +
API of the tool is as follows:
 +
* ''setBreakpoint'', ''clearBreakpoint'', ''enableBreakpoint'', ''disableBreakpoint'', ''isBreakpointDisabled'', ''getBreakpointCondition''
 +
* ''rerun''
 +
* ''resumeJavaScript'', ''stepOver'', ''stepInto'', ''stepOut'', ''runUntil''
 +
* ''onConnect'', ''onDisconnect''
 +
* ''onStartDebugging'', ''onStopDebugging''
 +
* ''onCompilationUnit''
 +
 
 +
The BTI is used by [[Crossfire]]. Crossfire has the following structure:
 +
 
 +
    Crossfire Panel
 +
        ↓
 +
    Crossfire Module
 +
        ↓
 +
    Crossfire Server
 +
        ↓
 +
    Crossfire Socket Transport
 +
 
 +
When starting up it does the following.
 +
 
 +
# Register tools (e.g. console, inspector, ...)
 +
# Start server
 +
# Create socket transport
 +
# Add BTI listener
 +
# Set connection status
 +
 
 +
=== Script Panel ===
 +
The [[Script Panel]] sits at the top of the whole stack of layers/objects. It represents the debugger UI (a view + a controller). The implementation of this object is quite extensive since it also includes the source code view and viewport (see <code>[https://github.com/firebug/firebug/blob/master/extension/content/firebug/js/sourceBox.js firebug/js/sourceBox.js]</code> module.
 +
 
 +
The ''Script'' panel should never access the <code>Firebug.Debugger</code> directly. It should always use the <code>JavaScriptTool</code>.
 +
 
 +
So, for example, if the user clicks on the Breakpoint Column, the action is handled by the ''Script'' panel, forwarded to the <code>JavaScriptTool</code>, which forwards it to the <code>Firebug.Debugger</code>, which forwards it to <code>FBS</code>. Finally, <code>FBS</code> is using JSD1 API to set the breakpoint.
 +
 
 +
There are side panels ([[Breakpoints Side Panel|Breakpoints]], [[Watch Side Panel|Watch]] and [[Stack Side Panel|Stack]]), which are synchronized automatically with the ''Script'' panel. They should all use <code>JavaScriptTool</code> to get appropriate data to display.
 +
 
 +
The synchronization happens through basic Firebug mechanisms like, <code>updateSelection</code> and <code>updateLocation</code>.

Revision as of 08:58, 10 September 2012

This page summarizes refactoring the Firebug debugger to use JSD2 and adding support for remote JavaScript debugging. Issue 5421 tracks the actual changes done.

Contents

Resources

Firebug Wiki:

Mozilla Wiki:

Goals

  • Adopt JSD2 (get rid of all JSD1 APIs)
  • Support remote debugging

Related Issues

JSD2 API Requirements

The following list summarizes the high-level features that Firebug needs to support. It should be verified that all the features can re-implemented on top of JSD2 before starting the refactoring.

Not Ready in JSD2

  • There is not source for evals.
  • new Function scripts?
  • Meta bug: Implement a script Debugger
    • As soon as this one is fixed
    • Profiling is unrelated to JSD2. What is the plan here?
    • Tracking (break on) throw/catch/error; also what is the plan?
  • Conditional breakpoints (bug 740825)

Script Panel Architecture

The Script panel needs to be built on top of JSD2, remote protocol and Firebug remote architecture. Remoting is already supported by HTTP Monitor and both components should share the same approaches and API.

TBD

Current Debugger Architecture

This section describes the current debugger architecture.

Current-debugger-architecture.png

There are several layers/objects so, let's describe them step by step starting from the bottom.

  • Backend: JSD1, FirebugService, Debugger
  • Frontend: JavaScriptTool, ScriptPanel

JSD1

This layer represents JSD1 platform API. These API allows to implement script debuggers and represent direct competition to JSD2 API. Of course this layer should entirely disappear and should be replaced by JSD2.

Firebug Service

Firebug service is implemented as js module on top of JSD1 layer. The object is called FBS and it's purpose is to wrap JSD1 API so, they are not directly accessed anywhere else. This layer also maintain list of registered debuggers (usually Firebug.Debugger module) and fires various events to them (e.g. onToggleBreakpoint, onToggleMonitor, etc.) or execute theirs callback (e.g. onBreak, onFunctionCall, onError, onThrow, onScriptCreated, etc.)

Main responsibilities:

  • Activate/deactivate JSD in the browser. The activation is global for all current browser windows.
  • Hook debugger events (interrupts, break on a breakpoint, etc.)
  • Maintains list of registered debuggers (there is usually just one - Firebug debugger) and sends events to them.
  • Manages nested event loop that is created for the debugger UI when page JS execution breaks.
  • Sets/removes/enables/disables/saves/loads breakpoints
  • Implements debugger stepping over/in/out/runUntil
  • Monitors function calls
  • Starts/stops profiling
  • Tracks exceptions and errors (not working well)
  • Tracks compiled scripts (not all of them)

Debugger

This object is derived from Firebug.Module and represents Firebug's debugger. It's also registered as a debugger into Firebug Service (FBS). This object should be the only one accessing FBS. It calls FBS API and receives various callbacks and events.

This object implements methods that can be used by the Script panel or other parts of Firebug (e.g. by those panels which implements BON).

Some examples of the API:

  • evaluate, evaluateInCallingFrame
  • breakNow, getCurrentStackTrace
  • rerun
  • stepOver, stepInto, stepOut, runUntil, resume
  • setBreakpoint, clearBrakpoint, etc.
  • monitorFunction, unmonitorFunction
  • monitorScript, unmonitorScript
  • activateDebugger, deactivateDebugger

Implementation of these methods is based on FBS API.

There is also Firebug.DebuggerListener that defines the interface used by FBS

  • onStop, onResume, onThrow, onError, onScriptCreated (there is more onScriptCreated events)

This object is observable and it activates the underlying JSD only if an observer exists. The observer is currently the Script panel even if it would make a bit more sense if it's actually the JavaScriptTool.

JavaScriptTool

This object is part or BTI and represents a javascript debugger tool. This object is like a proxy sitting between Firebug.Debugger and the ScriptPanel. The current implementation is in-process only so, based on direct Firebug.Debugger API calls.

API of the tool is as follows:

  • setBreakpoint, clearBreakpoint, enableBreakpoint, disableBreakpoint, isBreakpointDisabled, getBreakpointCondition
  • rerun
  • resumeJavaScript, stepOver, stepInto, stepOut, runUntil
  • onConnect, onDisconnect
  • onStartDebugging, onStopDebugging
  • onCompilationUnit

The BTI is used by Crossfire. Crossfire has the following structure:

   Crossfire Panel
       ↓
   Crossfire Module
       ↓
   Crossfire Server
       ↓
   Crossfire Socket Transport

When starting up it does the following.

  1. Register tools (e.g. console, inspector, ...)
  2. Start server
  3. Create socket transport
  4. Add BTI listener
  5. Set connection status

Script Panel

The Script Panel sits at the top of the whole stack of layers/objects. It represents the debugger UI (a view + a controller). The implementation of this object is quite extensive since it also includes the source code view and viewport (see firebug/js/sourceBox.js module.

The Script panel should never access the Firebug.Debugger directly. It should always use the JavaScriptTool.

So, for example, if the user clicks on the Breakpoint Column, the action is handled by the Script panel, forwarded to the JavaScriptTool, which forwards it to the Firebug.Debugger, which forwards it to FBS. Finally, FBS is using JSD1 API to set the breakpoint.

There are side panels (Breakpoints, Watch and Stack), which are synchronized automatically with the Script panel. They should all use JavaScriptTool to get appropriate data to display.

The synchronization happens through basic Firebug mechanisms like, updateSelection and updateLocation.

Personal tools