Closed aghasemi closed 10 months ago
Update: To solve this, one solution is something like the following code,
import("https://esm.sh/toastify-js@1.12.0").then( ({default :Toastify}) => {
Toastify({text: "This is a test toast",duration: 3000,}).showToast()
})
, which I can run from a <script>
tag in index.html
(without type="module"
), but not in the script
argument of a JSBody
, because Uncaught TypeError: $rt_globals.import is not a function
. Is there another step I need to do to make this work?
P.S. Apparently, the problem boils down to how I can prevent TeaVM from appending $rt_globals.
to the import statement in the above snippet.
P.S.` Is it this line of code whose changing can fix this?
Why don't you just include toastify.js with <script>
element and use it from global name? Where did you get the library? Is it this one? So documentation states that you need following:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
And then you don't need any imports
TeaVM's import functionality is a little-bit old-fashioned. Currently TeaVM only supports ES5 output. It's a subject of change in the future, but right not it can't use ES6 import. Instead, it generates common.js compatible imports, which can be used with node.js and webpack.
Why don't you just include toastify.js with
<script>
element and use it from global name? Where did you get the library? Is it this one? So documentation states that you need following:<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
And then you don't need any imports
Injecting a script tag is fine and works for this library, but not easily for all others (I'm looking at Transformer.js for example). Looking forward to having the ES6 modules.
Now another thing: A very "hacky" solution to have import parsed verbatim would be to wrap it in an eval
. I tried and it worked, but it seems TeaVM parser only recognises single-line, double-quotation strings, and everything else (including multi-line or template strings) is rendered as eval()
, i.e. evaluating nothing (as I saw in classes.js
).
Hence, this works:
eval("console.log(99) ")
, but this doesn't:
eval(`console.log(99)`)
Is it also part of the consequences of supporting older Javascript standards?
Thanks
Yes, I as said, TeaVM only works with ES5. But I don't understand this thing with eval
. How are you going to use it to work-around ES6 module issue?
If I put the code snippet with import() inside an eval, then TeaVM parser
will not prepend it with $rt_globals
.
I can suggest another workaround: you can write JavaScript code that imports everything you need and puts it into global objects, than access these objects from TeaVM.
Yes. I'm thinking of that exactly :)
For the context, assume I want to write an independent Java library on top
of TeaVM, not a one-time thing for my current project. Hence everything
should be dynamic and modifying index.html
is not an option.
One working example is this:
private static final String tstfy = """
const doc = window.document;
var head = doc.head;
var script = doc.createElement('script');
script.type = 'module';
script.innerHTML = 'import Toastify from "https://esm.sh/toastify-js@1.12.0";Toastify({text: "This is a test toast",duration: 3000,}).showToast();console.log("Loaded ToastifyJS module");';
script.async = false
// Fire the loading
head.appendChild(script);
""";
@JSBody(script = tstfy)
private static native void callToastify();
Consider the following Javascript code:
If I want to convert it to the equivalent TeaVM code, it should be something like:
The code however doesn't work, saying that the object
Toastify
does not exist (it seems):Also Network tab of Devtools shows no connection has been made to
unpkg.sh
(again I may be wrong). In general, does TeaVM support such "remote" imports? If yes, is there an example?And in general, how does calling third-party Javascript libraries from TeaVM work? Should we dynamically add
<script>
tags to the HTML head for loading the library and then calling it in native snippets?Thanks