Has it ever been discussed internally to split the...
# javascript
e
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
I think @Ilya Goncharov [JB] could know about it
a
There actually is a ticket for this
h
t
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
Well, why not? We also have 10+ iOS/macOS/watchOS/tvOS targets
✔️ 5
t
Because in case of JS we have more flexibility
And common JS library from NPM has single sourceset and check platform inside
e
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
Separate browser = separate platform? 😉
e
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
I agree with problem, I don't agree with solution
I think we need more elegant solution then targets
e
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
It's win, when you have strict platforms and can't polyfill classes
e
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
сс @Sergei Grishchenko
i
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
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
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
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
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
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.