Beyond Dev Mode
New Tools for Debugging GWT Apps
Brian Slesinsky
December 2013
GWT.create conference
What's Development Mode?
What's Development Mode? (2)
Dev Mode JVM
GWT App
(Java)
Browser
GWT App (JavaScript)
Plugin
(C++)
Browser
Channel
Browser API's
What's Development Mode? (3)
IDE
Dev Mode JVM
GWT App
(Java)
Browser
GWT App (JavaScript)
Plugin
(C++)
Browser
Channel
Browser API's
Browser Debugger
(JavaScript, DOM, CSS)
Java Debugger
(GWT code, servlets)
Life of a button click (1)
IDE
Dev Mode JVM
GWT App
(Java)
Browser
GWT App
(JavaScript)
Browser
API's
public void onClick(ClickEvent event) {� elt.setInnerText("Clicked!");�}�
IDE
Life of a button click (2)
IDE
Dev Mode JVM
GWT App
Browser
GWT App
API's
public void onClick(ClickEvent event) {� elt.setInnerText("Clicked!");�}�
IDE
Life of a button click (3)
IDE
Dev Mode JVM
Browser
public void onClick(ClickEvent event) {� elt.setInnerText("Clicked!");�}�
IDE
Stack view of a button click (1)
public void onClick(ClickEvent event) {� elt.setInnerText("Clicked!");�}�
onClick()
onClick()
Plugin
BrowserChannel
Java
JavaScript
Stack view of a button click (2)
public void onClick(ClickEvent event) {� elt.setInnerText("Clicked!");�}�
onClick()
setInnerText()
onClick()
Plugin
JSNI proxy
BrowserChannel
Java
JavaScript
Stack view of a button click (3)
public void onClick(ClickEvent event) {� elt.setInnerText("Clicked!");�}�
onClick()
onClick()
Plugin
BrowserChannel
Java
JavaScript
Unfortunately...
"Developers will be able to update their existing NPAPI-based Apps and Extensions until May 2014 [...] In September 2014, all existing NPAPI-based Apps and Extensions will be unpublished."
http://blog.chromium.org/2013/09/saying-goodbye-to-our-old-friend-npapi.html
New plugin API is asynchronous
"The JavaScript does not wait for a reply from Native Client, thus avoiding bogging down the main JavaScript thread."
Meanwhile on Firefox...
DevMode Status
Safari | Stopped working in 5.1 (Plugin architecture changed) |
Chrome | Will stop working this year (Plugin architecture changed) |
Firefox | Stops working with every release (Plugin uses internal API's) |
Internet Explorer | Works fine (no complaints?) |
Mobile browsers | Never implemented |
Lessons learned
Maybe having two stacks is not a good idea.
How can we avoid this?
All-JavaScript Debugging
Trying out Super Dev Mode
$ unzip ~/Downloads/gwt-2.6.0-rc3.zip
$ cd gwt-2.6.0-rc3/samples/Hello
$ ant gwtc
$ ant devmode
# in a different window
$ ant superdevmode
Running Super Dev Mode
Running Super Dev Mode (2)
Running Super Dev Mode (3)
Starting Super Dev Mode (In detail)
# production compile
CLASSPATH=$SDK/gwt-dev.jar:$SDK/gwt-user.jar:src \
java com.google.gwt.dev.Compiler \
com.google.gwt.sample.hello.Hello
# Super Dev Mode
CLASSPATH=$SDK/gwt-dev.jar:$SDK/gwt-user.jar:
$SDK/gwt-codeserver.jar:src \
java com.google.gwt.dev.codesever.CodeServer \
com.google.gwt.sample.hello.Hello
Your own compile button
function compile(module_name) {
window.__gwt_bookmarklet_params = {
server_url: 'http://127.0.0.1:9876/',
module_name: module_name,
};
var s = document.createElement('script');
s.src = 'http://127.0.0.1:9876/dev_mode_on.js';
document.getElementsByTagName('head')[0]
.appendChild(s);
}
compile('showcase');
Your own compile button (2)
native void compile(String module_name) /*-{
$wnd.__gwt_bookmarklet_params = {
server_url: 'http://127.0.0.1:9876/',
module_name: module_name,
};
var s =$doc.createElement('script');
s.src = 'http://127.0.0.1:9876/dev_mode_on.js';
$doc.getElementsByTagName('head')[0]
.appendChild(s);
}-*/;
compile("showcase");
Server-side compile request
$ RECOMPILE='http://127.0.0.1:9876/recompile/showcase'
$ curl "$RECOMPILE?locale=en&user.agent=safari&_callback=done"
done({"status":"ok","moduleNames":["showcase"]});
$
Super Dev Mode Browser Support
Chrome | Works! |
Firefox | Works! |
Safari | Works! |
Internet Explorer | Works! |
Mobile | Works, but requires extra setup because bookmarklets aren't available. |
All-JavaScript Debugging
More speed coming soon
Separate talk:
The GWT Java to JavaScript compiler:
present and future
Configure the compiler for speed
com.google.gwt.dev.Compiler -draftCompile …
<module>
...
<set-property name="user.agent" value="safari"/>
<set-property name="locale" value="en"/>
</module>
(Super Dev Mode does this for you.)
Remove module dependencies
<!-- faster -->
<module>
<inherits name="com.example.Util" />
</module>
All-JavaScript Debugging
Source-level debugging
Source-level debugging
defineSeed(932, 1, makeCastMap([Q$ClickHandler, Q$EventHandler]), CwBasicButton$1_0);
_.onClick = function onClick_27(event_0){
alert_0(this.this$0.constants.cwBasicButtonClickMessage());
}
Button normalButton = new Button(
constants.cwBasicButtonNormal(), new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert(constants.cwBasicButtonClickMessage());
}
});
Source-level debugging
defineSeed(932, 1, makeCastMap([Q$ClickHandler, Q$EventHandler]), CwBasicButton$1_0);
_.onClick = function onClick_27(event_0){
alert_0(this.this$0.constants.cwBasicButtonClickMessage());
}
Button normalButton = new Button(
constants.cwBasicButtonNormal(), new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert(constants.cwBasicButtonClickMessage());
}
});
?
Source-level debugging
normalButton = new Button_2(this$static.constants.cwBasicButtonNormal(), new CwBasicButton$1_0(this$static));
$ensureDebugId(normalButton, 'cwBasicButton-normal');
Button normalButton = new Button(
constants.cwBasicButtonNormal(), new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert(constants.cwBasicButtonClickMessage());
}
});
normalButton.ensureDebugId("cwBasicButton-normal");
Workarounds for breakpoint quirks
TODO: better sourcemaps
expr1, expr2; expr1; expr2;
var a=1, b=2; var a=1; var b=2;
All-JavaScript Debugging
Firefox
IntelliJ IDEA
IntelliJ IDEA (2)
Debugger support for GWT
Chrome | Works now. |
IDEA 13.x + Chrome | Demoable but not released yet. (Coming soon!) |
Firefox 26 | Demoable, but slow to load and sometimes hangs. |
Safari 7 | Very slow; sourcemaps load on gwtproject.org but not Super Dev Mode. Breakpoints skipped. |
Internet Explorer | No sourcemap support. (Typescript uses sourcemaps, so we can hope.) |
All-JavaScript Debugging
Substitute for a breakpoint
void someMethod(int a, String b) {
GWT.debugger();
...
}
Conditional breakpoint
void someMethod(int a, String b) {
if (a<0) GWT.debugger();
...
}
Conditional breakpoint (2)
void someMethod(int a, String b) {
assert a>=0; # use -ea or SuperDevMode
...
}
Watching a variable
void someMethod(int a, String b) {
GWT.log("someMethod: " + a); # see console
...
}
How to prepare
Questions?
Backup slides
Starting Super Dev Mode
Browser
Server
Super Dev Mode Server
HTML
nocache.js
nocache.js
cache.js
Seeing which code is used
Seeing which code is used (2)
Filter out unused source files
<!-- default -->
<module>
<source path="client" />
</module>
<!-- faster -->
<module>
<source path="client/*.java"
excludes="client/android" />
</module>
TODO: emit nicer JavaScript
When in -draftCompile: