I have a problem where I am writing a multiplatfor...
# javascript
m
I have a problem where I am writing a multiplatform library, but marking classes with
@JsExport
only works on classes that exclusively use non-suspending functions. Is there a way to transform the suspending functions into functions returning promises automatically? In case I need to do it manually I am also not quite sure how to do that, since I want to mostly keep the existing class but only transform a couple of suspending functions to promises.
b
Hi! Support for `@JsExport`ing suspending function is on our roadmap. In the meantime, you can vote for this issue. There are some workaround mentioned there in the comments.
Also, there is a community-maintained compiler plugin for transforming
suspend
functions into
Promise
-returning ones: https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin
m
I saw this plugin, but it looks to be very new and potentially unstable. If possible, I would prefer sticking to official tools. Is there a way to basically replace the implementation for just JS? I know that in Kotlin the pattern one would use for this are extension functions, but those just get compiled to free-standing functions in JS. They certainly do what they are supposed to, but it messes with the API design a bit if only the JS functions are not methods on the class. Is there an alternative pattern that allows me to write manual wrappers that get exposed to JS as member functions?
There is talk of compiling suspending functions to generators in https://youtrack.jetbrains.com/issue/KT-63038, but I cannot find out how to enable it.
b
> Is there an alternative pattern that allows me to write manual wrappers that get exposed to JS as member functions? I don't think there is a built-in way to do it. > There is talk of compiling suspending functions to generators in https://youtrack.jetbrains.com/issue/KT-63038, but I cannot find out how to enable it. You can pass the
-Xes-generators
compiler flag if you are compiling to ES5. If your target is ES2015, then it should be enabled by default. See https://kotlinlang.org/docs/gradle-compiler-options.html on how to pass compiler flags and set the target JS edition.
m
Hmm, but it still doesn't actually compile my method, no matter what I set the flag or the target to. Am I misunderstanding what it actually does? For me seeing the
Declaration of such kind (suspend function) cannot be exported to JavaScript.
error when it should be trying to compile the function to generators does not make a lot of sense.
b
Yes, this flag only affects the internal representation of
suspend
functions, but it still doesn't allow them to be exported to JavaScript.
m
Alright, I see. Seems like the functionality required for my other idea of attaching target specific methods to classes is tracked here: https://youtrack.jetbrains.com/issue/KT-20427 Then I will try to find another solution. Thanks for the help!
e
In case I need to do it manually I am also not quite sure how to do that
If it can help you, somehow, just know that we maintain a separate layer for exposing a subset of our API to JS or Java consumers. We have separate modules, that depend on the "core" module, and that wrap the suspending functions. See the screenshot. It's important to keep in mind that you must take into account the coroutine scope in real world scenarios. You can't just slap in a
GlobalScope
. I mean you can, but it's most likely suboptimal.
The
ZDeferred
symbol maps to a
Promise
under JS, and to a
CompletableFuture
under Java.
If I were you, I would go with the community-contributed plugin. It's quite solid if your requirements in terms of flexibility aren't crazy.