xpenatan / gdx-teavm

Run Libgdx in a webbrowser with teavm
Apache License 2.0
109 stars 16 forks source link

Can you help me fix some issue in app used dragome-backend? #20

Closed nicolaichuk closed 7 years ago

nicolaichuk commented 7 years ago

I have build error when run jetty (or gretty):


Compiling classes: ...................................................................

Exception in thread "Thread-13" java.lang.RuntimeException: java.lang.NullPointerException
    at com.dragome.compiler.DragomeJsCompiler.compile(DragomeJsCompiler.java:170)
    at com.dragome.web.helpers.serverside.DragomeCompilerLauncher.compileWithMainClass(DragomeCompilerLauncher.java:71)
    at com.dragome.web.serverside.compile.watchers.DirectoryWatcher.compile(DirectoryWatcher.java:263)
    at com.dragome.web.serverside.compile.watchers.DirectoryWatcher.startWatching(DirectoryWatcher.java:249)
    at com.dragome.web.serverside.servlets.CompilerServlet$1.run(CompilerServlet.java:92)

Caused by: java.lang.NullPointerException
    at com.dragome.compiler.Project.visitSuperTypes(Project.java:302)
    at com.dragome.compiler.Project.visitSuperTypes(Project.java:305)
    at com.dragome.compiler.Project.resolve(Project.java:481)
    at com.dragome.compiler.writer.Assembly.resolveNoTainting(Assembly.java:340)
    at com.dragome.compiler.DragomeJsCompiler.execute(DragomeJsCompiler.java:259)
    at com.dragome.compiler.DragomeJsCompiler.compile(DragomeJsCompiler.java:165)
    ... 4 more

I found discusion about same issue on groups.google.com/forum
https://groups.google.com/forum/#!topic/dragome/GuFCyGlHiDs

There are two fixed patches in dragome-web

https://github.com/nosix/dragome-sdk/commit/d1a2f34e0856ad4fc119832f84b22644cc807077

https://github.com/nosix/dragome-sdk/commit/ec297f51e609225af31e7302b6a40228ad2d927f

What can it do to fix this problem and apply this patches in dragome upstream?

@fpetrola, @xpenatan, you are mark as contributors in https://github.com/dragome/dragome-sdk/blob/master/dragome-web/src/main/java/com/dragome/web/helpers/serverside/DragomeCompilerLauncher.java Can you help?

xpenatan commented 7 years ago

NullPointerException in Project.visitSuperTypes usually happens when its trying to compile a class that have been filtered out.

Check when it prints #######Classpath order ##### is showing all your required projects and override filterClassPathLog method (from class that extends DragomeConfiguration) to return true and check in log if your classes have a true flag.

nicolaichuk commented 7 years ago

@xpenatan Is it possible to get more information about what class dragome trying to compile and crash?

maybe dragome have option for debug log-level?

NullPointerException is very bad and not informative behavior of the dragome js compiler in this case (

xpenatan commented 7 years ago

Added new method "filterClassLog". Will print each class that is set to compile or not.

In the class that extends gdx DragomeConfiguration

add this code:

import com.dragome.compiler.utils.Log;

@Override
public int filterClassLog () {
    Log.getLogger().setState(Log.DEBUG);
    return 2;
}

Execute: "gradlew :dragome:jettyRun --refresh-dependencies > log.txt" to download a newer snapshot and to log to a file.

The log should be big but I want to know the last "[DEBUG] Parsing " line and "Allow Class" logs before the error.

Also, is proguard enable (isRemoveUnusedCode() returning true) ?

nicolaichuk commented 7 years ago

@xpenatan, thanks for patch.

The log should be big but I want to know the last "[DEBUG] Parsing " line

[DEBUG] Parsing com.bulletphysics.util.ObjectArrayList#readExternal(java.io.ObjectInput)void

in file https://github.com/GoranM/bdx/blob/master/extern/gbullet/src/com/bulletphysics/util/ObjectArrayList.java

All compiled well if i remove implements java.io.Externalizable and methods writeExternal and readExternal.

Also, is proguard enable (isRemoveUnusedCode() returning true) ?

I done all like this https://github.com/xpenatan/gdx-shadertoy/blob/master/dragome/src/com/xoppa/JsConfiguration.java

Method isRemoveUnusedCode return false.

=============================================

Now i have log:


----------------------------------------------------------------------
03:11:36 INFO  Jetty 9.2.15.v20160210 started and listening on port 8080
03:11:36 INFO  Web Application runs at:
03:11:36 INFO    http://localhost:8080/dragome
Press any key to stop the server.
######################## ClassPath Order ########################
..........................
#################################################################
Compiling classes: ...................................................
Compiled classes: 3145
Total time: 218107 ms
----------------------------------------------------------------------
DRAGOME BUILD SUCCESSFUL: js application ready
----------------------------------------------------------------------
Finished at: 03:17:39
======================================
Scanning  ...

And nothing happens anymore (

Page on url http://localhost:8080/dragome/index.html is not opened. Browser write timeout error.

What url i should open for view my application?

in this page https://github.com/xpenatan/gdx-dragome-backend/wiki/Instructions you write

When lanching look for context in plugin launch configuration to know the http link for testing. Ex: http://localhost:8080/[CONTEXT]/index.html

What does mean "[CONTEXT]" in this case?

========================================

In this file https://github.com/xpenatan/gdx-shadertoy/blob/master/dragome/webapp/index.html i see loading dragome-resources/dragome-debug.js

but i can not find this file in my webapp folder (or somewhere else on file system) after run gradle task jettyRun.

xpenatan commented 7 years ago

What does mean "[CONTEXT]" in this case?

name of dragome project folder. gdx shader toy is "dragome" and the dragom tests examples is "gdx-tests-dragome".

when proguard is true see if allow true is printing for all ObjectArrayList imports:

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.AbstractList;
import java.util.RandomAccess;

It could be that proguard is removing AbstractList, RandomAccess or Externalizable and you have to add a proguard file to keep it. I didn't test yet proguard true with gradle and to see if any other command is needed.

In this file https://github.com/xpenatan/gdx-shadertoy/blob/master/dragome/webapp/index.html i see loading dragome-resources/dragome-debug.js

Its inside the fat jar file. Jetty automatically include it when testing in the browser.

What url i should open for view my application?

For some reason (bug!) calling index.html is not picking up the default launcher. For now you need to use the pagealias like in https://github.com/xpenatan/gdx-shadertoy/blob/master/dragome/src/com/xoppa/dragome/launcher/ShaderToyLauncher.java example for shadertoy: http://localhost:8080/dragome/index.html?ShaderToy-Dragome

nicolaichuk commented 7 years ago

@xpenatan thanks. I open my app in browser, but only with eclipse jetty plugin (i can not connect for port 8080 when used gradle plugin (: )

Now when i start my application after load all assert and ready SoundManager i have error in browser js console:

ReferenceError: javax_vecmath_Vector3f is not defined

.members.$$init_$void 
    .members.$$init_$void
    .members.$init$void
    .members.$init$void
    .members.$add___com_nilunder_bdx_Scene$boolean
    .members.$runBattleScence___java_lang_String$void
    .members.$create$void
    .members.$run$void
    .statics.$requestAnimationFrame___java_lang_Runnable$void/<

error in line

_2 = new javax_vecmath_Vector3f();

in this generate code:

qx.Class.define("com_bulletphysics_collision_narrowphase_VoronoiSimplexSolver", 
{
extend: com_bulletphysics_collision_narrowphase_SimplexSolverInterface,
construct: function(){},
members:
{
$$$subsimplexResultsPool___com_bulletphysics_util_ObjectPool : null,
$$$numVertices___int : 0,
$$$simplexVectorW___javax_vecmath_Vector3f_ARRAYTYPE : null,
$$$simplexPointsP___javax_vecmath_Vector3f_ARRAYTYPE : null,
$$$simplexPointsQ___javax_vecmath_Vector3f_ARRAYTYPE : null,
$$$cachedP1___javax_vecmath_Vector3f : null,
$$$cachedP2___javax_vecmath_Vector3f : null,
$$$cachedV___javax_vecmath_Vector3f : null,
$$$lastW___javax_vecmath_Vector3f : null,
$$$cachedValidClosest___boolean : false,
$$$cachedBC___com_bulletphysics_collision_narrowphase_VoronoiSimplexSolver$SubSimplexClosestResult : null,
$$$needsUpdate___boolean : false,
$$init_$void: function ()
{
var l20,_0,_1,_2,_3,_4,_5,_6,i,_7,_8,_9;
    arguments.callee.self.superclass.prototype.$$init_$void.call(this);
    _0 = this;
    _1 = java_lang_Class.$forName___java_lang_String$java_lang_Class("com.bulletphysics.collision.narrowphase.VoronoiSimplexSolver$SubSimplexClosestResult");
    l20 = dragomeJs.newArray('[Ljava.lang.Object;', [0]);
    _0.$$$subsimplexResultsPool___com_bulletphysics_util_ObjectPool = com_bulletphysics_util_ObjectPool.$get___java_lang_Class__com_bulletphysics_util_Supplier$com_bulletphysics_util_ObjectPool(_1, com_dragome_utils_DragomeCallsiteFactory.$create___java_lang_String__java_lang_String__java_lang_String__java_lang_String__java_lang_String__java_lang_Object__java_lang_String$java_lang_Object("com/bulletphysics/collision/narrowphase/VoronoiSimplexSolver", "get", "com.bulletphysics.util.Supplier", "()Lcom/bulletphysics/util/Supplier;", "com/bulletphysics/collision/narrowphase/VoronoiSimplexSolver.lambda$0()Lcom/bulletphysics/collision/narrowphase/VoronoiSimplexSolver$SubSimplexClosestResult; (6)", l20, "static"));
    this.$$$simplexVectorW___javax_vecmath_Vector3f_ARRAYTYPE = dragomeJs.newArray('[Ljavax.vecmath.Vector3f;', [5]);
    this.$$$simplexPointsP___javax_vecmath_Vector3f_ARRAYTYPE = dragomeJs.newArray('[Ljavax.vecmath.Vector3f;', [5]);
    this.$$$simplexPointsQ___javax_vecmath_Vector3f_ARRAYTYPE = dragomeJs.newArray('[Ljavax.vecmath.Vector3f;', [5]);
    _2 = new javax_vecmath_Vector3f();
    _2.$$init_$void();
    this.$$$cachedP1___javax_vecmath_Vector3f = _2;
    _3 = new javax_vecmath_Vector3f();
    _3.$$init_$void();
    this.$$$cachedP2___javax_vecmath_Vector3f = _3;
    _4 = new javax_vecmath_Vector3f();
    _4.$$init_$void();
    this.$$$cachedV___javax_vecmath_Vector3f = _4;
    _5 = new javax_vecmath_Vector3f();
    _5.$$init_$void();
    this.$$$lastW___javax_vecmath_Vector3f = _5;
    _6 = new com_bulletphysics_collision_narrowphase_VoronoiSimplexSolver$SubSimplexClosestResult();
    _6.$$init_$void();
    this.$$$cachedBC___com_bulletphysics_collision_narrowphase_VoronoiSimplexSolver$SubSimplexClosestResult = _6;
    i = 0;
    L1: {
        while (true) {
            if (i >= 5) {
                break L1;
            }
            _7 = new javax_vecmath_Vector3f();
            _7.$$init_$void();
            this.$$$simplexVectorW___javax_vecmath_Vector3f_ARRAYTYPE[i] = _7;
            _8 = new javax_vecmath_Vector3f();
            _8.$$init_$void();
            this.$$$simplexPointsP___javax_vecmath_Vector3f_ARRAYTYPE[i] = _8;
            _9 = new javax_vecmath_Vector3f();
            _9.$$init_$void();
            this.$$$simplexPointsQ___javax_vecmath_Vector3f_ARRAYTYPE[i] = _9;
            i += 1;
        }
    }
return this;
},

I used

-keep class javax.vecmath.** { *; }

and dragome compile all successful. But browser can not be found class in generate js code :(

P.S.: Link to original file: https://github.com/GoranM/bdx/blob/master/extern/gwt-vecmath/src/javax/vecmath/Vector3f.java

xpenatan commented 7 years ago

the problem is https://github.com/xpenatan/gdx-dragome-backend/blob/master/backends/gdx-backend-dragome/src/com/badlogic/gdx/backends/dragome/DragomeConfiguration.java#L141 . I remove all javax package from compiler. I think add this to save space or there was a error when compiling that package.

If you do

@Override
public int filterClassLog () {
    return 2;
}

You will see that it will have a "false" flag.

Solution now is to override "classClassPathFilter" method from DragomeConfiguration and to accept "javax.vecmath.**" something like

if(path.contains("javax/vecmath"))
   return true;

or all classes from javax

nicolaichuk commented 7 years ago

@xpenatan thanks.

Now i have this error

TypeError: java_lang_Integer.$compare___int__int$int is not a function

    .members.$compareTo___java_lang_Object$int
    .statics.$countRunAndMakeAscending___java_lang_Object_ARRAYTYPE__int__int$int
    .members.$doSort___java_lang_Object_ARRAYTYPE__int__int$void
    .members.$sort___com_artemis_utils_Bag$void
    .members.$registerSystems___com_artemis_WorldConfiguration$void
    .members.$build$com_artemis_WorldConfiguration
    .members.$build___com_nilunder_bdx_Scene__com_bulletphysics_dynamics_DiscreteDynamicsWorld$com_artemis_World
    .members.$init$void
    .members.$add___com_nilunder_bdx_Scene$boolean
    .members.$runBattleScence___java_lang_String$void
    .members.$create$void
    .members.$run$void
    .statics.$requestAnimationFrame___java_lang_Runnable$void/<

this line:

return java_lang_Integer.$compare___int__int$int(o.$$$priority___int, this.$$$priority___int);

in this code:

qx.Class.define("com_artemis_ConfigurationElement", 
{
extend: java_lang_Object,
construct: function(){},
implement: [java_lang_Comparable],
members:
{
$$$priority___int : 0,
$$$itemType___java_lang_Class : null,
$$$item___java_lang_Object : null,
$$init____java_lang_Object__int$void: function (item, priority)
{
    arguments.callee.self.superclass.prototype.$$init_$void.call(this);
    this.$$$item___java_lang_Object = item;
    this.$$$itemType___java_lang_Class = item.$getClass$java_lang_Class();
    this.$$$priority___int = priority;
return this;
},
$compareTo___com_artemis_ConfigurationElement$int: function (o)
{
    return java_lang_Integer.$compare___int__int$int(o.$$$priority___int, this.$$$priority___int);
},

Link to original java file: https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/ConfigurationElement.java#L26

xpenatan commented 7 years ago

compare dont exist in dragome emulated integer https://github.com/dragome/dragome-sdk/blob/master/dragome-js-jre/src/main/java/java/lang/Integer.java

nicolaichuk commented 7 years ago

compare dont exist in dragome emulated integer

@xpenatan Can you please add support this emulation or tell me how i can do it?

xpenatan commented 7 years ago

@nicolaichuk you will need to have dragomeSDK source, include changes to jre classes and do "mvn install" ( or clean install). After that in dragome-Backend source folder you type "gradle uploadArchives" and it will create a fat jat in "D:/Dev/mvn-repo/snapshots/" (change this in build.gradle for other location).

You can now redownload the fatjar, I added that method.

fpetrola commented 7 years ago

I'll open an issue on dragomeSDK repo to fix NPE problem, and implement a better error handling.

nicolaichuk commented 7 years ago

@xpenatan, @fpetrola thanks.

Next run error :)

InjectionException - FieldHandler lacks resolver capable of dealing with your custom injectables. Register a WiredFieldResolver or PojoFieldResolver with your FieldHandler.

.members.$initialize___com_artemis_World__java_util_Map$void
.members.$initialize___com_artemis_World__com_artemis_injection_Injector__com_artemis_AspectSubscriptionManager$void
.members.$$init____com_artemis_WorldConfiguration$void
.members.$build___com_nilunder_bdx_Scene__com_bulletphysics_dynamics_DiscreteDynamicsWorld$com_artemis_World
.members.$init$void
.members.$add___com_nilunder_bdx_Scene$boolean
.members.$runBattleScence___java_lang_String$void
.members.$create$void
.members.$run$void
.statics.$requestAnimationFrame___java_lang_Runnable$void/<

this exception throw from https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/injection/FieldHandler.java#L102

Artemis used this wrapper over java reflection https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/utils/reflect/ClassReflection.java

Is dragome support all reflection function used in ClassReflection?

Should I specific configure dragome for injection/reflection mechanism support?

xpenatan commented 7 years ago

Dragome have reflection but not all is supported yet (the most used methods should work).

Is there a demo/source that is also throwing this error ? not easy to know what is going on in that line.

nicolaichuk commented 7 years ago

i found bug in current IsInstance implimentation

in this line https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/injection/FieldHandler.java#L92

check

fieldResolver instanceof PojoFieldResolver

fieldResolver is WiredFieldResolver

public class WiredFieldResolver implements UseInjectionCache, PojoFieldResolver {
...
}

https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/injection/WiredFieldResolver.java#L16

UseInjectionCache and PojoFieldResolver are interface.

This is current implimentation isInstance:

$isInstance___java_lang_Object$boolean: function (obj)
{
var cls;
    cls = obj.$getClass$java_lang_Class();
    while (true) {
        L1: {
            if (!(cls.$getName$java_lang_String().$equals___java_lang_Object$boolean(this.$getName$java_lang_String()))) {
                break L1;
            }
            return 1;
        }
        L2: {
            if (!(cls.$getName$java_lang_String().$equals___java_lang_Object$boolean("java.lang.Object"))) {
                break L2;
            }
            return 0;
        }
        cls = cls.$getSuperclass$java_lang_Class();
    }
},

this

cls = cls.$getSuperclass$java_lang_Class(); 

return "java.lang.Object" because base class WiredFieldResolver is Object

but do not think that any class may have some count of interface.

@xpenatan, @fpetrola: I add this functionality, please apply PR https://github.com/dragome/dragome-sdk/pull/150.

nicolaichuk commented 7 years ago

I have bug with support instanceof with ParameterizedType

In this line

...
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
    ...
}
...

https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/utils/reflect/Field.java#L107

genericType is ParameterizedTypeImpl http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java#ParameterizedTypeImpl

ParameterizedType - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/reflect/ParameterizedType.java#ParameterizedType

This condition return true in java code.

========================

This line convert to js like:

....
genericType = this.$$$field___java_lang_reflect_Field.$getGenericType$java_lang_reflect_Type();
if ((dragomeJs.isInstanceof (genericType, java_lang_reflect_ParameterizedType)) == 0) {
    break L1;
}
....

This is $getGenericType$java_lang_reflect_Type:

$getGenericType$java_lang_reflect_Type: function ()
{
    return this.$getType$java_lang_Class();
},

// this.$$$signature___java_lang_String == "$$$mMapGameobject___com_artemis_ComponentMapper"
// this.__proto__.basename == "java_lang_reflect_Field"
// this.__proto__.classname == "java_lang_reflect_Field"
// this.__proto__.name == "java_lang_reflect_Field"

this.$getType$java_lang_Class() call this:

$getType$java_lang_Class: function ()
{
    return this.$$$fieldType___java_lang_Class;
},

// and return object with realName "com.artemis.ComponentMapper"
// with __proto__.classname == "java_lang_Class"  (why not BaseComponentMapper???)

com.artemis.ComponentMapper https://github.com/junkdog/artemis-odb/blob/master/artemis/src/main/java/com/artemis/ComponentMapper.java#L17

I think in javascript com.artemis.ComponentMapper don't implement ParameterizedType

And than used this for comparation in javascript code:

dragomeJs.isInstanceof = function(obj, type) {
    if (obj == undefined)
        return false;

    if ((typeof obj == "string" || obj instanceof String)
            && type == java_lang_String)
        return true;

    var clazz = !obj.$$type ? obj.constructor : obj;

    if (clazz == type)
        return true;

    if (type.$$type == "Interface") {
        if (obj.$$type == "Interface") {
            return checkInterfaceExtendsOther(obj, type);
        } else
            return qx.Class.hasInterface(clazz, type);
    } else
        return qx.Class.isSubClassOf(clazz, type);
}

https://github.com/dragome/dragome-sdk/blob/master/dragome-js-commons/src/main/resources/dragome/javascript/runtime.js#L124

clazz is "java_lang_Class" and than call qx.Class.hasInterface(clazz, type) and return false :( because "java_lang_Class" impliment nothing interfaces.

I do no understand getGenericType$java_lang_reflect_Type() return wrong genericType or dragomeJs.isInstanceof return wrong comparesion result... or ParameterizedType is not supported...

@xpenatan, @fpetrola: Can you help me fix this bug?

P.S.: May be help this implimentation artemis-odb for gwt:

Backend: https://github.com/junkdog/artemis-odb/blob/master/artemis-gwt/src/main/java/com/artemis/backends/gwt/emu/com/artemis/utils/reflect/Field.java#L105

Client: https://github.com/junkdog/artemis-odb/blob/master/artemis-gwt/src/main/java/com/artemis/gwtref/client/Field.java#L71

create issue https://github.com/dragome/dragome-sdk/issues/152

fpetrola commented 7 years ago

The problem is in Field.getGenericType method, it's not implemented yet. Current implementation is returning the same as getType method. I'll create a feature request issue to derived from this.