Trouble with HTML5 code conversion

32 views
Skip to first unread message

Brigt Vik

unread,
Feb 12, 2015, 1:05:21 AM2/12/15
to PlayN group
The forum post new topic button doesn't seem to work for me at the moment, so I'm trying by email. Hope it works.

I'm using 1.9-SNAPSHOT.

I'm displaying some icons for whether sound is enabled and whether a connection to the server has been successfully made.

My code looks like this, and works fine in Java:

            Image soundImage;
           
if(game.getSoundManager().isMuted())
                soundImage
= assets.getImage(StatusAssets.STATUS_SOUND_DISABLED);
           
else
                soundImage
= assets.getImage(StatusAssets.STATUS_SOUND_ENABLED);

           
Image serverStatusImage;
           
if(game.getCommunicationStatus())
                serverStatusImage
= assets.getImage(StatusAssets.STATUS_COMMUNICATION_OK);
           
else
                serverStatusImage
= assets.getImage(StatusAssets.STATUS_COMMUNICATION_PROBLEM);


In the HTML5 code, it has however turned into this:

    this.game.sounds.isMuted?(soundImage = $getImage_4(this.assets, 2)):(soundImage = $getImage_4(this.assets, 1));

   
this.game.isServerCommunicationsOk?(serverStatusImage = $getImage_4(this.assets, 3)):(serverStatusImage = $getImage_4(this.assets, 4));


As you can see, the call to game.getSoundManager() has turned into game.sounds, while game.getCommunicationStatus() has turned into game.isServercommunicationsOk. When loading, the game crashes and the web console is flooded with messages that "this.game.sounds is undefined". That particular object seems to have been renamed to this$static.sounds, so it's not very surprising that it can't find it anymore:

  this$static.sounds = new SoundManager_0(this$static);

I suppose the "correct" conversion would be something like this, where the $static has been added:

    this.game$static.sounds.isMuted?(soundImage = $getImage_4(this.assets, 2)):(soundImage = $getImage_4(this.assets, 1));

   
this.game$static.isServerCommunicationsOk?(serverStatusImage = $getImage_4(this.assets, 3)):(serverStatusImage = $getImage_4(this.assets, 4));


Any idea if there is some configuration that prevents it from trying to optimize accessors into variable access? Or any way to rewrite my code so that it will still pick the right variable name when rewriting everything?

Michael Bayne

unread,
Feb 19, 2015, 1:35:03 PM2/19/15
to pl...@googlegroups.com

On Wed, Feb 11, 2015 at 10:05 PM, Brigt Vik <bov...@gmail.com> wrote:
Any idea if there is some configuration that prevents it from trying to optimize accessors into variable access? Or any way to rewrite my code so that it will still pick the right variable name when rewriting everything?

That looks like a GWT bug, but are you doing something peculiar like returning a static member from an instance member function in your game? Something like:

public class MyGame {
  private static final SoundManager sounds = new SoundManager(...);

  public SoundManager getSoundManager() { return sounds; }
}

? That might be confusing GWT. Obviously it should be legal because it's legal Java, but who knows what the GWT optimizer is doing.

If so, make the SoundManager non-static and see if that helps.

Brigt Vik

unread,
Feb 19, 2015, 2:50:06 PM2/19/15
to pl...@googlegroups.com
The SoundManager is an instance variable in my game class, so there really isn't much staticness to remove about it... It seems to me that the code conversion process decides that:

1. Making the SoundManager and server communication status variables static is a good idea, for reasons I don't know or understand.

2. Using the accessor isn't necessary and it can be shortcircuited to going straight to the javascript variable, presumably because the accessor does nothing other than return the variable.

And then, the results of those two decisions are made independent of eachother, so that the other classes try to access the variable directly but don't take its sudden staticness into account.

It's been a long while since I last tried my game in HTML5 (curse my laziness), but I *think* that the SoundManager was already included when it was last working there. For certain the networking code was in there at the time, and the same thing has happened to the isServerCommunicationsOk boolean variable (only, the game doesn't reach the point where it is used due to crashing over the sound manager).

Thinking about this a bit more, I will try two hacks just to see whether it makes any difference. I'll try to make the accessor not be called getSoundManager, but rather something else that the conversion might not recognize as an accessor, such as "asdf". Secondly, I'll try to stuff some bogus code in the accessor (creating some integers and adding them together or something) so that it might decide there's important stuff happening in the accessor so it won't choose to bypass it. I'll let you know how it goes.

Brigt Vik

unread,
Feb 25, 2015, 9:19:46 AM2/25/15
to pl...@googlegroups.com
Well, I must report that those changes didn't make any difference. GWT looks into what is actually done in the code and doesn't care if the accessor follows any naming standard. Adding a static integer to the class and incrementing it in the getter made GWT include the getter, but while that seemed to fix the error in the code trying to access the variable, it got transferred to the actual getter.

Using vanilla PlayN 1.8.5 (or otherwise downgrading to GWT 2.5.0) did make a difference to the generated code and got rid of the errors, but introduced other errors where something was null even though it by all rights should have been initialized by the time it got accessed. And it really is initialized and fine, when using GWT 2.6.1.

I tried to rip out and put the SoundManager into another adhoc game created from the archetype to isolate the problem code, but there it somehow worked without a hitch, which left me thoroughly flummoxed.

Finally, I extracted the SoundManager and its underlying components and put them into a separate utility jar, and those changes I made in order to do so seems to have worked around the problem, as my game is now running despite other variables still being made static by the code generation. I am leery of a "fix" which I can't understand, but I guess I'll take it.
Reply all
Reply to author
Forward
0 new messages