cincheo / jsweet

A Java to JavaScript transpiler.
http://www.jsweet.org
Other
1.45k stars 160 forks source link

Error in browser: Object prototype may only be an Object or null #628

Open EricWittmann opened 3 years ago

EricWittmann commented 3 years ago

After upgrading from JSweet 2.3.5 to 2.3.6, we are getting the following error (browser only) for our transpiled js library:

image

I have created a reproducer project here:

https://github.com/EricWittmann/jsweet-reproducer

Steps to reproduce:

  1. git clone https://github.com/EricWittmann/jsweet-reproducer.git
  2. cd jsweet-reproducer
  3. mvn clean install -Ptranspilation
  4. Open chrome using: chrome.exe --allow-file-access-from-file
  5. Open the target/test.html file in the above Chrome
  6. View (above screenshotted) output in browser js console

If you change the version to 2.3.5 and repeat step (3) above, then reload the browser, there will be no failure and you'll see the following output:

image

The only differences I can find in the transpiled typescript files is some "import" ordering. I don't know enough about JS to further diagnose the issue. Help appreciated!

lgrignon commented 3 years ago

@EricWittmann Thanks for reporting and this nice repro.

EricWittmann commented 3 years ago

Note: this issue persists in JSweet 3 for our use-case. I am going to write a utility that will rewrite all of the transpiled TS files so that all imports are pushed to the top of the file if they aren't already. I'll report back if that fixes the issue for us.

EricWittmann commented 3 years ago

Initial tests indicate that re-organizing the imports so they are all on top doesn't fix the problem. :( Still working but am now flailing in the dark a bit. Stumped as to what's different between the TS generated by JSweet 2.3.5 and the TS generated by later versions. Ideas welcome. :)

lgrignon commented 2 years ago

Hello @EricWittmann Did you find something on your side? I didn't find time to look into it yet

EricWittmann commented 2 years ago

No - we had to revert back to JSweet 2.3.5. :( :(

I am not a competent enough javascript developer apparently to track this down. Here is what I discovered:

I'm ultimately using rollup to create a UMD library. So the build looks like this:

The only difference between the typescript generated by JSweet 2.3.5 and 3 seems to be what I mentioned above: some of the imports are at the bottom of the files instead of the top. After writing a simple tool to re-org those imports, the only differences that remain in the output are trivial (generated comments, whitespace, some extra brackets maybe, etc).

The javascript that is generated is also very similar. I couldn't find a smoking gun in there either. But rollup bundles that result up very differently -- critically the ordering of the JS files in the final UMD is very different. Such that the library can't be loaded due to that ordering: a class that depends on another class is loaded before the dependent class.

I can't for the life of me figure out why the rollup results are so different.

To be fair, ultimately the problem is that our class hierarchy has cycles in it, where e.g. class A extends class B which has a field of type C which extends class D which has a field of type A. Somehow it works with JSweet 2.3.5 and rollup, but not with JSweet 3 and rollup.

Can't figure out why. Very frustrating. :)

Eventually my plan is to rewrite the entire library, but I'm not sure if I'll be able to eliminate the cycles or not. It's a library that implements a data model for the OpenAPI spec, which is a spec that has cycles.

lgrignon commented 2 years ago

There might be an actual bug if it worked with JSweet 2 indeed. We are sorry for the inconvenience. It sounds related to import order indeed. Please tell us if at some point you have more information

EricWittmann commented 2 years ago

I'm pretty much out of ideas and additional information. I included a reproducer project at the top. I could try to slim that down even more than it already is, but other than that I'm not sure what extra info I might be able to get for you.

andreaTP commented 2 years ago

Ping on this thread as I started to look into this issue and I summarized here some preliminary findings: https://github.com/EricWittmann/jsweet-reproducer/pull/1

lgrignon commented 2 years ago

Thanks a lot for looking into that.

I genuinely don't think we will have enough time to handle this change on our side but let's discuss it here. We are always open to PR and review them as quickly as possible.

If I understand your point correctly, you want to generate internal.js to import/export all modules in a folder (or a @Root package), is that right? And generate imports from this folder's internal rather than the class' file itself. Therefore avoiding circular reference problem in projects transpiled by JSweet, are we clear on this?

andreaTP commented 2 years ago

Thanks for the answer @lgrignon !

you want to generate internal.js to import/export all modules in a folder (or a @Root package), is that right? And generate imports from this folder's internal rather than the class' file itself. Therefore avoiding circular reference problem in projects transpiled by JSweet, are we clear on this?

Yes, this is correct (yet to be validated as a viable solution), since this is the first time I look into JSweet any suggestion/recommendation/pointer on where to start would be highly appreciated.

lgrignon commented 1 year ago

Thanks @andreaTP for your desire to enhance this project :)

imports are generated in this code area: https://github.com/cincheo/jsweet/blob/develop/transpiler/src/main/java/org/jsweet/transpiler/Java2TypeScriptTranslator.java#L652

You can discover the TS files generation here: https://github.com/cincheo/jsweet/blob/develop/transpiler/src/main/java/org/jsweet/transpiler/JSweetTranspiler.java#L906

which seems a good place to consider where to put internal.ts file generation


Please feel free to ask any question that could help you understand how to achieve this improvement