- Build and distribute a fully extensible self debugging debugger.
- Shift as much as possible of the activity and responsibility of evolving and maintaining a world class debugger to the community who uses it.
- 100% free and open.
- Full support for just-in-time debugging.
- Capable of exploring properties of all objects associated with all windows.
- Support arbitrary inspection/evaluation in any stack frame.
- Breakpoints and data watchpoints.
- Capable of intercepting runtime errors and showing their origins
- Capable of debugging instances of itself.
- Fully extensible and reloadable while in use.
- All scarey multi-threaded plumbing hidden under the covers.
Architecture of builtin support
The bulk of the new code to enable the debugger will be in libmocha. The js and jsd modules already fully support the debug api (exposed to native code and reflected into Java). However, some additional work is already being done to enhance that debug api. These enhancements will help for this use of the api.
Navigator startup sequence
- libmocha initializes
- calls js/jsd to initialize
- calls lm_debug to initialize
- if debugger.html is in specific place on disk
- put js/jsd in an 'active' state - register callback for debugger keyword and js errors so that if the events occur, then lm_debug will be called and will start a debugger window (loading the afore mentioned debugger.html). js/jsd will track all html and js files loaded in Navigator (being careful to discard copies of pages abandoned by Navigator) to allow for just-in-time access to the source for the debugger.
- js/jsd not activated and debugging is not available (except via the legacy Java applet).
- if debugger.html is in specific place on disk
Debugger startup sequence
the 'debugger' keyword (which can either be on a page or by
- the hook that lm_debug set at startup is called. It creates a new window
(with a separate JS thread) and initializes an instance of a nativly
window. This jsdapi object can only be created in this fashion and is not
accessible from non-debugger windows. The debugger html document is
loaded into the window.
- the debugger.html file then sets up its UI and sets hooks into jsdapi. It notifies jsdapi that it is done loading.
- at this point a hook event is posted to the debugger and debugging begins.
Hook handling sequence
- hook is encountered on the target mocha thread (breakpoint, interrupt, error, or debugger keyword) and calls through jsd to hook handler in lm_debug. lm_debug maps this to the function in the debugger which needs to be called to handle the hook. That handler, however, needs to be called on a different thread in order to allow the user to interact with the debugger.
- lm_debug posts a message to the FE using the same mechanism used for events like timeouts. The target mocha thread then goes into an event wait loop ready to be told by the debugger to continue execution, or do an expression evaluation, etc.
- the FE retrieves the hook event on the mozilla thread and routes it to the debugger in the same fashion a timeout or mouse event is routed.
- Some calls that the debugger makes into jsdapi can be handled directly by
calling functions in js/jsd/jsdebug.h (e.g. gather stack information). Other
calls will require thread handoffs (e.g. evaluating an expression in the
context of a stack frame in the stopped target thread). jsdapi will hide this
- the debugger will call a jsdapi method.
- that method will post an event into the queue in lm_debug where the target thread has been parked since the hook happened. The debugger's mocha thread will then enter its own event queue awaiting the response from the target mocha thread.
- the target mocha thread will call into jsdebug.h to do the eval. When the eval returns the target mocha thread will post it back to the debugger's queue and go back to waiting for another event.
- the debugger mocha thread will receive the answer and return it to the debugger. The debugger will go about its business without knowing that this dance happened.
While this all sounds very complicated (and there are complications not mentioned here), I've already had to implement this same stuff to make the ssjs debugger work over a Corba connection. It is all very doable.
Architecture of the Debugger UI
There is a lot of flexibility in determining the architecture of the debugger UI. Upgrading the UI will not require changes to Navigator itself. Part of the point of the whole project is to have an easily upgradable -- even user upgradable -- UI.
The debugger will be fully event driven. While it will be primarily graphical, it will have a console to allow manual inspection of the target code and arbitrary access to the methods of the objects which comprise the debugger itself. I expect that early development iterations of the debugger UI will be primarily console driven.
There is a lot of good dhtml code available to reuse. Our visual dhtml tool is full of treasures. My inclination is to port much of the logic used in the Java version of the debugger into the dhtml world. This is made significantly simpler by the code in jsapi which hides the cross-thread communication and synchronization between code running on the debugger UI/mocha threads and the target mocha thread.
How to get there from here
New and modified native code
- new file: lm_debug.c in libmocha will reflect jsd, start debugger, and route events.
Dependencies and Unknowns
- The code to for multi mocha threads it required. mlm has this working and it is scheduled to be part of Nav 5.0.
- It is critical that no cases exist where code can be stopped in a target mocha thread while layout is locked and unable to process the UI for the debugger. Any problems that may exist in this area are bugs and will need fixing for any client of the multi thread code (though the debugger will be 'testing' this a lot and may be the best 'finder' of potential bugs of this sort).
- We'll have to be very careful with potential new security holes. The main protection is that none of the new code will run unless the user has installed the debugger.html file on his disk. Still, we need to exercise due diligence to assure that pages from the web can not exploit anything here.
- Navigator 4.x really sucks up memory in code that does a lot of document.writes to layers. This is said to be caused by layout's use of arenas - memory is not reclaimed until the Window closes. This is bad for a rich dhtml page. This is likely to be fixed in Navigator 5.
- Time is tight. Approval and support are critical.
Engineering Sequence (rough outline - details and schedule TBD)
- libmocha work to implement app and debugger startup code
- write code for jsdapi object
- write a simple console to debug code in simulated 'other' window
- write some proof of concept dhtml parts - e.g. simple inspector
- Add extensions to JSD for multi-context debugging, fast inspection,...
- integration of multi mocha thread code - work with real tragets
- Improve UI and get it all working smoothly
Addendum 1 - Status Update - 25 Aug. 1998
Despite the utter coolness of this project, I've decided that now is not the right time to pursue it. Rewriting so much UI and working around layers issues does not appear to be the best use of time. Nor is it likely to produce a tool which will most benefit the greatest number of customers. Instead, I'm concentrating on improving the existing Java-based UI; smoothing out the user experience and adding a significantly more powerful data browser. Incorporating Rhino into the debugger to facilitate scripting of the debugger's behavior is a strong possibility.
I still would like to do the JSD-in-JS debugger proposed here. Possibly the Raptor based client will be the right platform to support (and be supported by) this debugger. This will certainly be revisited...