You will see something like below with the bold line being the breakpoint you set (I have added some comments above the functions):
// thats the class initializer of MyHandler. It is empty because there is no static {} block in Java
function $clinit_App$1MyHandler_0_g$(){
$clinit_App$1MyHandler_0_g$ = Object;
$clinit_Object_0_g$();
}
// Thats the default constructor which receives everything that the nested MyHandler class can reach in the outer class App.
function App$1MyHandler_1_g$(this$0_0_g$, val$errorLabel_0_g$, val$nameField_0_g$, val$sendButton_0_g$, val$textToServerLabel_0_g$, val$serverResponseLabel_0_g$, val$dialogBox_0_g$, val$closeButton_0_g$){
$clinit_App$1MyHandler_0_g$();
this.this$01_1_g$ = this$0_0_g$;
this.val$errorLabel2_0_g$ = val$errorLabel_0_g$;
this.val$nameField3_0_g$ = val$nameField_0_g$;
this.val$sendButton4_0_g$ = val$sendButton_0_g$;
this.val$textToServerLabel5_0_g$ = val$textToServerLabel_0_g$;
this.val$serverResponseLabel6_0_g$ = val$serverResponseLabel_0_g$;
this.val$dialogBox7_0_g$ = val$dialogBox_0_g$;
this.val$closeButton8_0_g$ = val$closeButton_0_g$;
Object_1_g$.call(this);
this.$init_1443_g$();
}
// defineClass creates an underscore variable which is used to define all the functions of MyHandler.
defineClass_0_g$(5, 1, {5:1, 757:1, 838:1, 891:1, 1:1}, App$1MyHandler_1_g$);
$clinit_App$1MyHandler_0_g$ = Object;
$clinit_Object_0_g$();
}
// Thats the default constructor which receives everything that the nested MyHandler class can reach in the outer class App.
function App$1MyHandler_1_g$(this$0_0_g$, val$errorLabel_0_g$, val$nameField_0_g$, val$sendButton_0_g$, val$textToServerLabel_0_g$, val$serverResponseLabel_0_g$, val$dialogBox_0_g$, val$closeButton_0_g$){
$clinit_App$1MyHandler_0_g$();
this.this$01_1_g$ = this$0_0_g$;
this.val$errorLabel2_0_g$ = val$errorLabel_0_g$;
this.val$nameField3_0_g$ = val$nameField_0_g$;
this.val$sendButton4_0_g$ = val$sendButton_0_g$;
this.val$textToServerLabel5_0_g$ = val$textToServerLabel_0_g$;
this.val$serverResponseLabel6_0_g$ = val$serverResponseLabel_0_g$;
this.val$dialogBox7_0_g$ = val$dialogBox_0_g$;
this.val$closeButton8_0_g$ = val$closeButton_0_g$;
Object_1_g$.call(this);
this.$init_1443_g$();
}
// defineClass creates an underscore variable which is used to define all the functions of MyHandler.
defineClass_0_g$(5, 1, {5:1, 757:1, 838:1, 891:1, 1:1}, App$1MyHandler_1_g$);
// thats the instance initializer of MyHandler called by the constructor above. It is empty because MyHandler does not have instance variables
_.$init_1443_g$ = function $init_3_g$(){
$clinit_App$1MyHandler_0_g$();
}
;
_.$init_1443_g$ = function $init_3_g$(){
$clinit_App$1MyHandler_0_g$();
}
;
// thats the lambda definition that you have used in the delay function.
_.lambda$0_72_g$ = function lambda$0_1_g$(){
$clinit_App$1MyHandler_0_g$();
{
this.sendNameToServer_1_g$();
}
}
;
_.lambda$0_72_g$ = function lambda$0_1_g$(){
$clinit_App$1MyHandler_0_g$();
{
this.sendNameToServer_1_g$();
}
}
;
// Here you see how GWT uses the lambda you have defined.
// GWT still uses for lambdas the same logic as for anonymous classes.
// So App$1MyHandler$lambda$0$Type_1_g$ is actually a class implementing the functional interface
// and it receives the outer scope (MyHandler) so its execute() method (from the interface) can
// call the lambda defined above on MyHandler.
_.onClick_5_g$ = function onClick_1_g$(event_0_g$){
delay_0_g$(1000, new App$1MyHandler$lambda$0$Type_1_g$(this));
}
;
_.onKeyUp_5_g$ = function onKeyUp_0_g$(event_0_g$){
if (event_0_g$.getNativeKeyCode_1_g$() == 13) {
this.sendNameToServer_1_g$();
}
}
;
_.sendNameToServer_1_g$ = function sendNameToServer_0_g$(){
$clinit_App$1MyHandler_0_g$();
var textToServer_0_g$;
this.val$errorLabel2_0_g$.setText_15_g$('');
textToServer_0_g$ = this.val$nameField3_0_g$.getText_14_g$();
if (!isValidName_0_g$(textToServer_0_g$)) {
this.val$errorLabel2_0_g$.setText_15_g$('Please enter at least four characters');
return;
}
this.val$sendButton4_0_g$.setEnabled_4_g$(false);
this.val$textToServerLabel5_0_g$.setText_15_g$(textToServer_0_g$);
this.val$serverResponseLabel6_0_g$.setText_15_g$('');
this.this$01_1_g$.greetingService_0_g$.greetServer_1_g$(textToServer_0_g$, new App$1MyHandler$1_1_g$(this, this.val$dialogBox7_0_g$, this.val$serverResponseLabel6_0_g$, this.val$closeButton8_0_g$));
}
;
delay_0_g$(1000, new App$1MyHandler$lambda$0$Type_1_g$(this));
}
;
_.onKeyUp_5_g$ = function onKeyUp_0_g$(event_0_g$){
if (event_0_g$.getNativeKeyCode_1_g$() == 13) {
this.sendNameToServer_1_g$();
}
}
;
_.sendNameToServer_1_g$ = function sendNameToServer_0_g$(){
$clinit_App$1MyHandler_0_g$();
var textToServer_0_g$;
this.val$errorLabel2_0_g$.setText_15_g$('');
textToServer_0_g$ = this.val$nameField3_0_g$.getText_14_g$();
if (!isValidName_0_g$(textToServer_0_g$)) {
this.val$errorLabel2_0_g$.setText_15_g$('Please enter at least four characters');
return;
}
this.val$sendButton4_0_g$.setEnabled_4_g$(false);
this.val$textToServerLabel5_0_g$.setText_15_g$(textToServer_0_g$);
this.val$serverResponseLabel6_0_g$.setText_15_g$('');
this.this$01_1_g$.greetingService_0_g$.greetServer_1_g$(textToServer_0_g$, new App$1MyHandler$1_1_g$(this, this.val$dialogBox7_0_g$, this.val$serverResponseLabel6_0_g$, this.val$closeButton8_0_g$));
}
;
// this creates the class literal for MyHandler
var La_App$1MyHandler_2_classLit_0_g$ = createForClass_0_g$('a', 'App/1MyHandler', 5, Ljava_lang_Object_2_classLit_0_g$);
var La_App$1MyHandler_2_classLit_0_g$ = createForClass_0_g$('a', 'App/1MyHandler', 5, Ljava_lang_Object_2_classLit_0_g$);
So when you place the breakpoint at the line you have used JS sourcemaps maps that line to the definition of the lambda and not the call to delay(). I am not sure if there is a right or wrong because it has to choose between the two and generally before you can call delay() the lambda must be created. So I think it is logical that way. In such cases you better place the breakpoint inside the delay() function.
-- J.
Craig Mitchell schrieb am Mittwoch, 17. Dezember 2025 um 09:07:01 UTC+1:
I also just noticed, the breakpoint doesn't get hit when you click the "send" button on the page (when it should get hit).On Wednesday, 17 December 2025 at 7:03:18 pm UTC+11 Craig Mitchell wrote:When debugging in Chrome, sometimes my breakpoints get hit on a page refresh, but the code is not executed (nor should it be).I reproduced the issue with the following:1. Create a sample project with https://github.com/NaluKit/gwt-maven-springboot-archetype:mvn archetype:generate -DarchetypeGroupId=com.github.nalukit.archetype -DarchetypeVersion=LATEST -DarchetypeArtifactId=modular-springboot-webapp(use any values, I just entered "a" for everything)2. Modify the a-client\src\main\java\a\App.java with the following:2.1 Add this static method:public static void delay(int delayMs, com.google.gwt.user.client.Command run) {
com.google.gwt.core.client.Scheduler.get().scheduleFixedDelay(() -> {
run.execute();
return false;
}, delayMs);
}2.2 In the MyHandler class onClick, call the static method:public void onClick(ClickEvent event) {
delay(1000, () -> {
sendNameToServer();
});
}3. Start it up:3.1: mvn gwt:codeserver -pl *-client -am3.2: mvn spring-boot:run -pl *-server -am4. Open it in Chrome: http://localhost:8080/5. Open the Chrome debugger, put a breakpoint on the line:delay(1000, () -> {6. Refresh the page. The breakpoint gets hit. It looks like this:It doesn't have a call stack, and if you try to step into it, it doesn't step into the delay method.Any idea why this occurs?
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-web-toolkit/a2d0f3d8-7d87-4c92-bd67-926b2b046128n%40googlegroups.com.

No comments:
Post a Comment