google / j2cl

Java to Closure JavaScript transpiler
Apache License 2.0
1.23k stars 145 forks source link

Plans for more core JRE classes? #149

Closed reportmill closed 2 years ago

reportmill commented 2 years ago

I'm interested in porting SnapKit UI toolkit to J2CL. I have previously done this with TeaVM and CheerpJ (see demos).

However, it seems while TeaVM has the same base JRE packages, it has significantly more coverage inside. This surprises me since J2CL seems to have significantly more support, activity, clients and contributors.

Question 1: Is J2CL intended for this use case (existing Java libs)?

Question 2: Is there a convention, accepted starting point, or "best-practices" for adding new JRE classes?

Here is TeaVM's class lib for comparison: TeaVM JRE. Some of the packages it includes currently missing from J2CL: java.lang.ref, java.lang.reflect, java.nio, java.text, java.net, java.util.jar, java.util.regex, java.util.zip.

This is a fantastic project, so I ask with admiration and respect! Thanks for any info.

jeff

treblereel commented 2 years ago

@reportmill if you are looking for nio, i have ported some classes to j2cl and i use it in j2cl quake2 port: https://github.com/treblereel/gwt-nio

reportmill commented 2 years ago

Hi Dmitrii! Thanks for the response - this looks very nice!

Did you write this from scratch or start from a prior implementation? Also, is there any reason why this shouldn't be added to J2CL?

treblereel commented 2 years ago

@reportmill thanks

I relied on several projects like libgdx or Apache Harmony and gwt-nio is just a small part of what our community does. J2CL team is consistently adding new features and emulations and if something is missed, it's not difficult to implement it by ourselves. There are many community projects that fill these gaps. So you can reuse such projects with bazel as the preferred way for Google or with j2cl-maven-plugin as i do. Maybe except for reflection api, but i am not sure, if we need it, mostly because it's too heavy and lack of it can be fixed by apt.

reportmill commented 2 years ago

I'm still surprised that the core JRE non-gui packages aren't a "must have" for most use cases. Is this because most J2CL projects are Android based? Otherwise it seems like a complete (as possible) JRE would be fundamental part of the MVP. I admit I'm from the Java desktop world, though. :-)

I don't rely on reflection for my browser deployments. But it's nice that TeaVM/CheerpJ support basic functionality, if only to make it easy to stub things out. I do think it leads to larger JS size if you use reflection in TeaVM.

niloc132 commented 2 years ago

I think java.nio.* packages are a pretty good example of this case, where "simply" emulating them might have surprising results. For example, the project that @treblereel linked is a very complete implementation of those packages, whereas https://github.com/Vertispan/gwt-nio/ is a deliberately incomplete version (sources copied, updated from the PlayN project). The incompleteness stems from limitations in the browser - while @treblereel sought complete emulation to allow a project to be entirely agnostic of running in the JVM or browser (...from the perspective of the java.nio packages at least), my goal was quite different, to allow an application to use the browser TypedArray APIs, yet still run on a normal JVM.

Some quick examples:

This seems to me to be a point in which reasonable people can disagree - do you make the emulation as complete as possible, with potential pitfalls, or do you make the API clearly something that makes sense to run in a browser?

reportmill commented 2 years ago

Thanks Colin - those are very insightful observations and gave me a lot to consider!

However, I would say the clear choice is make the J2CL JRE match the functionality of the standard JRE as much as possible despite drawbacks, for several reasons. For one: this would lead to more out-of-the-box compatibility. And two: As J2CL transitions to WebAssembly, many of these mismatches with JavaScript may go away.

I think most developers are happy to have standard library functionality even if it eventually falls short in cases. Those cases can be addressed with customizations and optimizations to the app and/or the JRE in successive versions.

I am certainly thrilled with the TeaVM JRE implementation, even though it also is incomplete. My apps aren't as functional in the browser (yet), but deployment is a huge win on that platform. Users that eventually demand more can move to a desktop version.

gkdn commented 2 years ago

In general we are very conservative in what we provide as emulation (with the exception of some legacy choices that we inherited from GWT).

The reasoning behind that is; J2CL targets code bases where thousand of engineers are working on products with huge dependency graph and not necessary web experts themselves. In order to be able to scale at that level; we try to minimize anything surprising related performance, code size and correctness.

This strategy has been working well for us but I do understand that it may not for all. The biggest negative is; less libraries work out of box if you just want to able to just compile something which wasn't a priority for us. In our case we would rather break during compilation and have the user either: a- Propose a change the 3rd party library code itself. b- Avoid the dependency to the library in the first place. c- Explicitly opt-in by pulling 3rd party emulation of the missing JRE.

gkdn commented 2 years ago

Also see: https://github.com/google/j2cl/blob/master/docs/limitations.md

reportmill commented 2 years ago

Thanks Goktug - that makes good sense. I will have to revisit this later this year when I can invest more time on missing dependencies for SnapKit. If anyone else is struggling with similar use case or similar need for more JRE, please leave a comment!

treblereel commented 2 years ago

@reportmill there is an active community https://gitter.im/vertispan/j2cl of j2cl users who are focused on libs and frameworks around it (we mostly use maven, but it's not an issue). So lets join forces!

As for your initial question, we can write ( and we do) enumations for missed classed by ourselves, but ppl from outside google struggle with issues like 'java 11 support and above', better enums support and so on (if forces us to support a fork). According to J2CL Now & Next at least 'java 11' is pretty close to be released coz bazel5 has been released as well.

gkdn commented 2 years ago

I already switched to new bazel and enabled the Java 11 support for open-source; I haven't updated the list yet.

What are you referring to as better enums support? Enum.valueOf?

treblereel commented 2 years ago

yeah, Enum.valueOf would be nice, plus @JsEnum

i working on webgpu externs ( well, it's mostly webidl parser) to generate elemental2-like wrappers, so for now i have to use string instead of enum . But as far as i remember, it's more closure issue. But i can be wrong

I really appreciate your help

gkdn commented 2 years ago

Enum.valueOf is a reflective API so we cannot realistically support that as it would cause code bloat. We were only considering to support very limited scenarios, e.g. when the parameter is statically known, however that won't help a lot use cases when you can simple do FooEnum.valueOf instead.

For JsEnum, are you referring to limitations like MyJsEnum[]?