I created a KotlinJS library for another team in m...
# javascript
a
I created a KotlinJS library for another team in my org. Because of legacy reasons, they are linking the library twice in two separate js bundles. When either one runs separately it works fine, but if they load both bundles in the same js VM things start to behave strange. Is this a known limitation?
c
What kind of weird behavior are you seeing? But yeah, you're not supported to include the same code through multiple bundles, even in vanilla JS without using Kotlin
e
Wait, are you saying you have
Copy code
PKG1
     \ K/JS lib
     / 
PKG2
And then they output
Copy code
PKG1              BUNDLE1 
     \ K/JS lib /
     /          \
PKG2              BUNDLE2
And you load both bundles in Node/browser?
That's strange, why don't they bundle a single time?
a
Yes @Edoardo Luppi that is correct it seems to be a pretty weird setup because they are migrating from an old app to a new tech stack. But sometimes the old techstack is the "parent page" and loads the new tech stack inside of it.
Weird behaviour nr1: call to a regular suspend delay fails with
Copy code
UnsupportedOperationException {message: 'third-party implementation of CancellableContinuation is not supported'
Weird behaviour nr2: A kotlinx.serialization call to serialize a polymorph sealed class fails because it can't find the subclass serializer
Copy code
Serializer for subclass 'GoHome' is not found in the polymorphic scope of 'EndResult'.
Check if class with serial name 'GoHome' exists and serializer is registered in a corresponding SerializersModule. ...
e
I'm not sure if this applies to you too (are you running under Node or browser?), but I recall Coroutines write to the global `Window`: https://github.com/Kotlin/kotlinx.coroutines/issues/3874
a
Yeah maybe! This is a webapp running in the browser
Searching for the string "third-party implementation of CancellableContinuation is not supported" turns up only the source code itself making this pretty rare haha. My intuition is that there are two copies of CancellableContinuation and there is leakage between the instances of libraries so the class cast check fails
e
That's gonna be tough to workaround. You'll have to dissect the two bundles to understand how the compiled JS code works.
Could you post a screenshot of the outputted K/JS lib layout?
a
From what viewer?
e
IntelliJ, under the dist/ folder
a
image.png
e
Well, I would have supposed the Coroutines classes would be isolated in their own ES modules tbh.
Could you try recompiling with
Copy code
kotlin.js.ir.output.granularity = whole-program
?
a
Sure!
e
I don't think that it will change anything tho. The most likely issue is you're running bundled code in the browser with no module isolation.
a
I've published it for them to consume, but I can't test it myself right now.
✔️ 1
e
Let me know how it works, but I really doubt it's going to solve it.
a
Thanks I will. We might need to load the lib in a smarter way and share it between the two apps.
e
I was just going to say that's the bundler's duty to fix this issue, maybe by splitting into chunks.
t
I was just going to say that's the bundler's duty to fix this issue
It depends on root cause of the problem
For example connection
Promise
<->
Deferred
is unsafe now and should be fixed in coroutines
e
@turansky could you expand on the promise/deferred conversion? I wasn't aware of issues but good to know in case
t
If you will convert
Deferred
to
Promise
- result
Promise
will contain field
deferred
and it's unsafe - other Kotlin/JS applications can use it too 😞
In such situations private symbols should be used instead - for isolation reason. "`Deferred` from other JS application - isn't my
Deferred
!"
If
window
contains magic string properties, created by coroutines - redundant conflicts are expected 😞
✔️ 1
e
Ah yeah I was aware of that
deferred
property injected into the promise. Looking at the Git blame it's been there forever. I guess it was done as a potential optimization when converting back from the same promise.
t
I guess it was done as a potential optimization when converting back from the same promise.
It works fine with private symbol 😉
✔️ 1
gratitude thank you 1
In Kotlin Wrappers we plan to migrate on private symbols
a
Ok so we tried it (granularity = whole-program) and indeed it did not help.