I have been using Chrome Developer Tools (CDT) for the past couple of weeks to build a JavaScript debugger. Though you can debug JavaScript in Chrome browser itself, my requirement was such that I needed a debugger that runs outside Chrome and debugs pages running in Chrome. I found that Chrome Developer Tools provides a JavaScript debugger plugin for Eclipse. CDT has exposed Java APIs, if you want to build the debugger yourself. It also has exposed JavaScript APIs for its debugger.
So I first evaluated Eclipse plugin that CDT provides. Before I get to that plugin, here are some useful links about CDT –
- Chrome Debugger – Eclipse Plugin : This is a tutorial for installing and using Eclipse plugin for Chrome debugger
- Tutorial for using Java SDK for Chrome Debugger : Useful if you want to create your own Chrome debugger. The above Eclipse plugin uses this SDK
- Javadoc for Chrome Debugger SDK : Java API reference for the debugger classes
- JavaScript APIs for Chrome Debugger : Useful if you want to build Chrome debugger using JavaScript
- Debugging Chrome on Mobile : This is not part of the CDT, but I found this link interesting because it explains how to connect to Chrome running on mobile from your desktop and debug pages running on mobile.
Eclipse Plugin for Chrome Debugger:
From the documentation of Eclipse Chrome debugger plugin , it seemed like a perfect fit for my requirements. However when I actually installed and tried to use it, I ran into a few issues.
- This plugin creates a virtual project from your JS project. It copies only those files that have JavaScript code in this Virtual project. Even in HTML file has JS code, it masks all non-JS code and shows only the JS code. Though I did not necessarily have any problem with this approach, I did not really understand the need to create Virtual project. Also I preferred looking at the entire code, than one in which non-JS code is masked.
- I set a breakpoint in the JS code (you have to set breakpoints in the file created in the virtual project, not in the original file) and was not able to make the debugger hit the breakpoint. It was a simple JS script for testing, but breakpoints did not work. Whenever I refreshed the page, all breakpoints in scripts in that page were removed. A colleague of mine then told me that I needed to set breakpoints after the script was loaded and then execute scripts without loading the page, e.g. on click of a button in the same page.
- I needed to customize how this debugger worked. I could have probably done that by making changes in the source code,but did not do so because of above two issues.
So I decided to create my own Eclipse plugin using Java SDK for Chrome debugger.
Java SDK for Chrome Debugger:
Using the SDK for debugger was quite easy. I created an Eclipse debugger plugin and called debugger SDK from the plugin to perform operations like setting breakpoints, stepping and handling debugger events. The tutorial I mentioned above was very helpful. However I still have a few issues –
- The way my debugger plugin works is -user right clicks on a file and selects option to debug the page. Chrome is launched in the debug mode and the page is opened in Chrome. I wanted the debugger to hit any breakpoints that were set before the page was launched. However I did not find any way to tell Chrome to wait for the debugger to attach, after it was launched. I tried many of the launch related command line switches, but could not make Chrome to wait for the debugger to attach.Therefore the page executes without hitting any breakpoint on the first launch. For in-browser debugger this is not a big limitation because you have to execute the page once before you can set breakpoints in the scripts in that page. However that is not how a typical Eclipse debugger work.
- The debugger has to work properly on HTML pages where some of the content might be inserted dynamically, e,g, by the server that is serving the page. Because of this the line numbers of JS code in the generated output might be different from ones in the source file. So when user sets a breakpoint in the source file, that same code may not be at the same line number in the generated output. Therefore I have to resolve line numbers when the script is loaded.Good thing is that, Chrome informs debugger when it loads a script – so the debugger could set breakpoints on the script if they are not already set. However Chrome does not pause execution of the script to give chance to the debugger to set breakpoints. Sometimes breakpoints may not be hit when the script is loaded the first time – e.g. suppose a HTML page has one JS block and you have set 5 breakpoints in it. When the page is executed, Chrome sends an event notification to the debugger when the script is loaded. If the debugger starts setting breakpoints at this point, some of the initial breakpoints may not be hit because Chrome has already executed the script past those breakpoints.
- This is not really an issue, but incorrect documentation. JavaDoc for setBreakpoint method says that line number is 1-based, but in fact it is 0-based.
You also need to pass correct value of column number to this function. Do not pass Breakpoint.EMPTY_VALUE. Column numbers are also zero based.
Other than uncertainty about debugging the page on the first load (breakpoints may not be hit), the debugger works fine. The issues related to the first time load of the page may not be very severe, because all breakpoints works fine if you refresh the page after running the page once, which is not very different from in-browser debugger where you have to load a page once before setting breakpoints. However the debugger could be made much better if CDT provides following two APIs –
- Make Chrome wait for debugger to connect
- Notify debugger before executing the script (not just after script is loaded) and wait till debugger returns from the event notification (function). This would give debugger a chance to set breakpoints where there is need to compute JS line numbers at runtime.
-Ram Kulkarni
i really like that you are giving information on core and advance java concepts. Being enrolled at http://www.wiziq.com/course/1779-core-and-advance-java-concepts i found your information very helpful indeed.thanks for it.
Dear Ram,
Please is it supports Eclipse rcp,swt etc and plug-ins and I am very much intrested these technologies.
Debugger from Chrome Developer Tools (for Eclipse) and the one that I developed are Eclipse plugin and RCP is not part of them. You can however include them in your own RCP application or in existing Eclipse install. The debugger has very little UI (most of the views are provided by Eclipse). The UI it implements using SWT is for creating debug configuration.
Hi Ram. Thank you for your interest in the project. Hope you don’t mind some comments about Debugger plugin.
The idea of Virtual project is covered here: http://code.google.com/p/chromedevtools/wiki/VirtualProject
In particular, it’s the only way you can work with eval or other dynamically generated scripts.
However you should be able to work with your local files. You only have to set up sources in your debug configuration: http://code.google.com/p/chromedevtools/wiki/FeatureDebugOnRealFiles
The thing with debugger not being able to hit a breakpoint sounds like a problem. How breakpoints do not normally survive reloads. Maybe you reload your page after the breakpoint is set and before it’s supposed to be hit.
Hi Peter,
Thanks for your comment and links you have posted. Yes, I understand now why CDT creates Virtual Project – to debug scripts that are generated at runtime and for which you may not have source files. Could this have been made easier by creating virtual folder in the same project and at the same time allowing users to set breakpoints in actual files where JavaScript source code exists? For the scripts that do not have source code, the users will have to set breakpoints/step in the the virtual files. Since debugging scripts generated at runtime is rear (at least in my experience), users would be debugging in actual files most of the time with this approach. However I admit that I haven’t evaluated this option in detail to understand all possible issues and complexities.
Regarding breakpoints being removed from Virtual Project, they were removed after I set them and reload the page. I followed these steps –
– Create debug configuration for Webkit Protocol
– Launch Chrome in debug mode
– Launch the newly created debug configuration. At this point an empty Virtual project was created
– Open the URL of the page containing JS code. Virtual project now contains the file with JS code
– I set breakpoint in the virtual file
– Reload the page in the browser. At this point page runts without hitting the breakpoint. And In Eclipse yhe breakpoint that I had set was removed.
As to SDK. Thank you very much for finding an incorrect documentation.
I don’t see why you may need chrome to wait for the connection. To me it’s like you always can start debugging an empty page and then manually navigate the page to your URL. However your request to pause at newly compiled script looks very reasonable. Could you please file a bug against ChromeDevTools for Java or Chromium project?
I was trying to avoid making users to start debug session with empty page. I have my source in a project in Eclipse. I let users right click on a file and select debug option. Then I launch Chrome and open file to be debugged in the first tab. So users need not type URL in the Chrome, the debugger does it for them. To support this, I want Chrome to not start executing the page till debugger has a chance to connect to it. Right now what happens is that Chrome opens the page before Eclipse launches the debug target.
I will log an enhancement request to pause execution at newly compiled script and send an event to the debugger.Logged issue #156556