https://kotlinlang.org logo
#javascript
Title
# javascript
e

Edoardo Luppi

11/01/2023, 1:33 PM
Has it ever been discussed internally to split the JS browser and Node targets, so that they're effectively two different platforms?
plus1 2
a

Artem Kobzar

11/01/2023, 1:37 PM
I think @Ilya Goncharov [JB] could know about it
a

andylamax

11/01/2023, 2:15 PM
There actually is a ticket for this
h

hfhbd

11/01/2023, 2:42 PM
t

turansky

11/01/2023, 3:06 PM
From my experience it doesn't work that way (I mean targets). In fact your target = your dependencies. We already have common API for Browser and Node in kotlin-web. But
kotlin-web
is also for workers, service workers, audio worklets. As result - 6 platforms at start? 1. Web (JS Common) 2. Browser 3. Browser Worker 4. Browser Service Worker 5. Browser Audio Worklet 6. Node
h

hfhbd

11/01/2023, 3:08 PM
Well, why not? We also have 10+ iOS/macOS/watchOS/tvOS targets
✔️ 5
t

turansky

11/01/2023, 3:09 PM
Because in case of JS we have more flexibility
And common JS library from NPM has single sourceset and check platform inside
e

Edoardo Luppi

11/01/2023, 3:38 PM
We can have a
jsCommomMain
and the two targets to build on top. This improves flexibility, avoids runtime checks and workarounds, and allow being clear on the supported platforms.
t

turansky

11/01/2023, 3:54 PM
Separate browser = separate platform? 😉
e

Edoardo Luppi

11/01/2023, 4:05 PM
Well, to me the browser is indeed a separate platform. This is a piece of code you can find on the
kotlinx-io
library.
Copy code
internal val fs: dynamic
    get(): dynamic {
        return try {
            js("require('fs')")
        } catch (t: Throwable) {
            null
        }
    }
You could avoid this kind of stuff with the two being separated.
Not to mention the performance gains you can have by accessing platform-specific capabilities.
t

turansky

11/01/2023, 4:07 PM
I agree with problem, I don't agree with solution
I think we need more elegant solution then targets
e

Edoardo Luppi

11/01/2023, 4:11 PM
I think we need more elegant solution then targets
I can't think of any other solution tbh. The targets architecture and HMPP model are the most immediate things that come to mind. Multiple targets > multiple actualizations of expect declarations > it's a win for me
plus1 1
t

turansky

11/01/2023, 4:12 PM
It's win, when you have strict platforms and can't polyfill classes
e

Edoardo Luppi

11/01/2023, 4:14 PM
polyfill classes
Polyfills are a workaround imo. If Kotlin is able to enforce better boundaries, that's another win
Another example of library that would benefit from this is xmlutil. Currently it is unable to support Node.js. Someone suggested to polyfill with JSDom, but that's bad in my book
Another example from the issue that @hfhbd posted:
Copy code
kotlin {
  ...

  js("jsNode", IR) {
    nodejs()
    attributes.attribute(kotlinJsTargetAttribute, targetName)
  }
  js("jsBrowser", IR) {
    browser()
    attributes.attribute(kotlinJsTargetAttribute, targetName)
  }
Someone correct me if I'm wrong but now specifying multiple targets of the same type is deprecated/going to be removed. So yeah you can't even do that.
plus1 1
t

turansky

11/01/2023, 5:09 PM
сс @Sergei Grishchenko
i

Ilya Goncharov [JB]

11/01/2023, 5:31 PM
Another example from the issue
It is how personally I recommend to solve this issue. Case with different targets are indeed has problems that in fact we compile just JS, compiler doesn’t care about its runtime, and I don’t think that knowing of runtime is useful for compiler (native is different here, because Native actually compiles different binary files for different targets with different dependencies). But for JS you can use dependencies for all of targets. So I think that usage with different targets and attributes can help now
e

Edoardo Luppi

11/01/2023, 5:38 PM
Thanks @Ilya Goncharov [JB]! I personally don't want the compiler to understand the runtime/platform. It would be just a way to keep the two in their own worlds. Unfortunately, looking at the documentation I can see > Here's the planned deprecation cycle: > • 1.9.20: introduce a deprecation warning when similar multiple targets are used in Kotlin Multiplatform projects > • 2.0: report an error in such cases, causing the build to fail So not sure how viable that issue approach is now.
plus1 1
h

hfhbd

11/01/2023, 5:46 PM
Yes, the compiler itself should not change. But I still think, adding some default targets would be helpful to allow library authors to use the same Gradle attributes and not define them again, or create different not matching attributes. Additionally, these targets could enable/disable by default some stdlib references to not accidentally depend on the dom while targeting nodeJS. And, after the feedback, it should be possible to remove this restriction to allow polyfill classes and to depend eg nodejs on a browser variant, if you want.
💯 1
a

andylamax

11/02/2023, 5:38 AM
I am really all for this issue. Compiler should remain the same but the gradle plugin could offer different dependency sets for different "targets", but also now, the kotlin team could provide some default targets for popular platform like in the stdlib, or even a kotlinx library for that matter
b

Big Chungus

11/20/2023, 11:40 AM
Hierarchical js source sets would help a ton in the short term as it would at least let us use expect/actual pattern to wrap appropriate APIs
e

Edoardo Luppi

11/20/2023, 11:44 AM
The hierarchy described by Adam in the YT issue seem to work. I'm just very hesitant to adopt it as it may get removed in 2.0 and refactoring is time consuming.
2 Views