Has anyone managed to call kotlin from javascript ...
# webassembly
d
Has anyone managed to call kotlin from javascript using the @JsExport annotation? I've been trying to implement the wasm version of the Google sign in button I have in my compose app. The only missing piece left is getting the data back to my kotlin code to finish the process, but I'm getting stuck and the info here seems outdated. Update - half resolved it but I think I've identified significant issues with the interoperability feature and documentation around it.
The documentation says to add this to the html file:
import exports from "./module.mjs"
but it doesn't say where. I'm not a web developer so this is where it gets more confusing for me but I've come to adding this in order to attach the function to the window object so I can invoke it from the google data-callback function:
Copy code
<script type="module">
    import exports from "./composeApp.mjs"
    window.authGoogleLoginComplete = exports.authGoogleLoginComplete;
</script>
I changed it to ./composeApp.mjs since there is no module.mjs file, but I did find this file being generated that includes the export for my function:
Copy code
import * as Li9za2lrby5tanM from './skiko.mjs';
import * as _ref_QGpzLWpvZGEvY29yZQ_ from '@js-joda/core';
import { instantiate } from './composeApp.uninstantiated.mjs';


const exports = (await instantiate({
    './skiko.mjs': Li9za2lrby5tanM,
    '@js-joda/core': _ref_QGpzLWpvZGEvY29yZQ_
})).exports;

export const {
    authGoogleLoginComplete,
    memory,
    _initialize,
    startUnitTests
} = exports;
But trying to load that file gives me this error: > Failed to resolve module specifier "@js-joda/core". Relative references must start with either "/", "./", or "../". So apparently it doesn't like the @js-joda/core path, but that's not something I've added. To debug I removed the js-joda/core references from the file manually, so that resolves the issue (in an unacceptable way), but then I get another error: > The requested module './composeApp.mjs' does not provide an export named 'exports'
Just got it working by changing the import bit to:
Copy code
<script type="module">
    import { authGoogleLoginComplete } from "./composeApp.mjs"
    window.authGoogleLoginComplete = authGoogleLoginComplete;
</script>
so now I'm just left with this @js-joda/core thing since manually deleting for every build isn't really an option
👍 1
t
Hey. Found any solutions?
d
The js-joda/core stuff didn’t come back after I deleted it, so that and making sure the mjs filename matched worked for me. Ultimately for my particular use case I ended up just going with the solution I had for the desktop version by doing oauth in a new tab and websocket callbacks. Google’s popup script seemed kind of unreliable. and was also making requests on its own on the page load.
👍 1
t
thanks for the reply. Bummer the docs are off on this. The only workaround that i have is moving the logic inside the compose app via
WebElementView
+ have the js logic inside calling the kotlin part
👍 1
a
I am getting the js-joda/core problem. I'm wondering if its coming from a dependency on kotlinx-datetime since js-joda is a datetime library.
To solve the @js-joda import problem, you can set up an importmap in your index.html like this:
Copy code
<head>
<script type="importmap">
        {
          "imports": {
            "@js-joda/core": "<https://cdn.jsdelivr.net/npm/@js-joda/core/+esm>"
          }
        }
    </script>
...
</head>
This points to a standard server for js-joda. We ought to also be able to get it locally since its in ./build/wasm/node_modules/@js-joda, but I haven't figured out how the directory is munged. Next, you will probably get this error: Element.attachShadow: Unable to re-attach to existing ShadowDOM This means you've initialized your WASM module (probably composeApp.js) multiple times. I was unable to pull it in as a normal script like this:
Copy code
<!--script type="application/javascript" src="composeApp.js"></script -->
(without the comments OFC) and also import my symbols. However, if I imported it as a module in index.html like this:
Copy code
<script type="module">
        import { createOngoingOp, updateOngoingOp } from './composeApp.mjs';
    </script>
(note that createOngoingOp and updateOngoingOp are my @JsExport functions) I was also able to import it into my other module .js files, like this:
Copy code
import { createOngoingOp, updateOngoingOp } from "./composeApp.mjs";
Note in both cases I'm importing the .mjs NOT the .js file (this is the module wrapper).