konsoletyper / teavm

Compiles Java bytecode to JavaScript, WebAssembly and C
https://teavm.org
Apache License 2.0
2.64k stars 265 forks source link

Generated code contains wrong function reference Yy -> Yz #584

Open dsyer opened 2 years ago

dsyer commented 2 years ago
Uncaught ReferenceError: Yz is not defined
    at GX (classes.js:75)
    at V6 (classes.js:73)
    at IR (classes.js:1568)
    at MV (classes.js:1567)
    at Object.cu (classes.js:29)
    at K$ (classes.js:1324)
    at O$ (classes.js:1323)
    at H1.ix (classes.js:29)
    at PG (classes.js:1441)
    at VX (classes.js:1439)

If you find usage of Yz in classes.js you can see that it looks like a typo:

...
function Yy(a,b){var c=new Dr();Fa(c,a,b);return c;}
function GX(a){CT();Fa(a,Yz,(R1()).jZ());}
...

The function Yy is greyed out in the IDE because it is never used. You can manually edit and replace Yz with Yy and it then works.

I have seen the same problem with different function names in various combinations when I edit the main() method.

Sample app with the stack trace above: https://github.com/scratches/teavm-scratch

ScraM-Team commented 2 years ago

Thanks for posting this. I tried it with 0.6.1 (the last full release) but I had build issues unrelated to the function naming issue you describe. I will try with 0.7.0-SNAPSHOT soon. Please let us know how it's going and what projects you are working on. I think Spring integration with TeaVM could help enable full-stack single-page apps. The Flavour example app is already Spring-based server-side: https://github.com/konsoletyper/teavm-flavour/tree/master/example/src/main/java/org/teavm/flavour/example

ScraM-Team commented 2 years ago

Actually the error in 0.6.1 might be related, it is an NPE while processing names in lambdas:

Caused by: java.lang.NullPointerException at org.teavm.backend.javascript.codegen.DefaultNamingStrategy.getRealField (DefaultNamingStrategy.java:162) at org.teavm.backend.javascript.codegen.DefaultNamingStrategy.getNameFor (DefaultNamingStrategy.java:89) at org.teavm.backend.javascript.codegen.NamingOrderer.lambda$consume$5 (NamingOrderer.java:93) at org.teavm.backend.javascript.codegen.NamingOrderer.apply (NamingOrderer.java:115) at org.teavm.backend.javascript.rendering.Renderer.prepare (Renderer.java:274) at org.teavm.backend.javascript.JavaScriptTarget.emit (JavaScriptTarget.java:390) at org.teavm.backend.javascript.JavaScriptTarget.emit (JavaScriptTarget.java:319) at org.teavm.vm.TeaVM.build (TeaVM.java:419)

ScraM-Team commented 2 years ago

If I comment out the constraint call (".constraint(Foo::getValue, "value", c -> c.notBlank())"), it builds fine in 0.6.1 and prints "Valid: true" on the console.

I'll keep digging to see what about that call (or, more likely, its parameters) is causing trouble.

ScraM-Team commented 2 years ago

This alternate syntax works:

this.bundle = ValidatorBuilder.<Foo>of(Foo.class).constraintOnTarget(foo -> !foo.getValue().isEmpty(), "foo", "foo.isNotEmpty", "foo must not be empty").build();
konsoletyper commented 2 years ago

@dsyer first of all, you should disable minification for better understanding what's going on

konsoletyper commented 2 years ago

@dsyer with minification disabled I found that following code produces error:

function aiyc_CharSequenceConstraint__init_0($this) {
    aiyc_CharSequenceConstraint_$callClinit();
    aiyc_CharSequenceConstraint__init_2($this, jt_Normalizer$Form_NFC, (aiyccv_VariantOptions_builder()).$build());
}

That is: java.text.Normalizer is not supported in standard Java library emulation. That's definitely strange that TeaVM did not report this as a compilation error. Will investigate it.

konsoletyper commented 2 years ago

@dsyer Ok, I fixed error reporter and now can get following error message during compilation:

[ERROR] Field java.text.Normalizer$Form.NFC was not found
    at am.ik.yavi.constraint.CharSequenceConstraint.<init>(CharSequenceConstraint.java:72)
    at am.ik.yavi.builder.ValidatorBuilder$constraint$lambda$_10_0.get(ValidatorBuilder.java:219)
    at am.ik.yavi.builder.ValidatorBuilder$constraint$lambda$_10_0.get(ValidatorBuilder.java:219)
    at am.ik.yavi.builder.ValidatorBuilder.constraint(ValidatorBuilder.java:947)
    at am.ik.yavi.builder.ValidatorBuilder.constraint(ValidatorBuilder.java:219)
    at com.example.demo.HelloWorld.<init>(HelloWorld.java:14)
    at com.example.demo.HelloWorld.main(HelloWorld.java:10)

As for Unicode normalization. Most of Unicode stuff I had to write myself, since I can't use GPL-based code from OpenJDK. So most of TeaVM classlib is either written by hands or ported from Harmony. Harmony relies on C version of ICU (although I found that there's ICU4J project). Another challenge for Unicode support is table sizes: my implementations try to minify Unicode tables as much as possible. With normalization table it seems hard to pack them dramatically. Fortunately, I found that recent browser versions implement all necessary normalization options, so it's a possible way to go. However, this requires to find a way to implement normalization for C version of TeaVM.