Is there information about whether the new JS back...
# javascript
d
Is there information about whether the new JS backend in 1.4 will bring better interop with the ecosystem, like we have on the JVM side? Some crucial things that are pain-points right now: • Kotlin modules are compiled into one giant .js file instead of compiling each Kotlin file into one .js file (using the module system of the underlying platform, such as commonjs or ecmascript modules). This makes it so tree-shaking and DCE needs to be re-invented from scratch instead of re-using the existing tools. • Calling Kotlin from Javascript is technically possible, but very painful, because the generated code is hard to comprehend (see point one, this would be greatly improved if there was a 1:1 mapping from .kt to .js files) • Calling Kotlin from Typescript is also technically possible, but even more painful, since you need to write declaration files for everything. • Calling Javascript from Kotlin requires writing declaration files (even if there are .d.ts files for the javascript code, see next point) • Typescript / Typescript declarations are entirely unused. The code generated by dukat never works if you have something more complex than "left-pad" (and it can't, because things like
type Foo = "foo" | "bar"
cannot be expressed in Kotlin). Another thing that I have noticed is that the kotlinx libraries (ktor, kotlinx.serialization, io) and the stdlib seem to think that they should be polyfilling things themselves if they are missing in the underlying platform. This leads to things like
<http://kotlinx.io|kotlinx.io>
requiring an outdated npm library (
text-encoding
) using dynamic calls to require (what if the underlying module system is not commonjs?) if the global
TextEncoder
API is not found. Instead it should be the user's responsibility (based on their browser support demands) to load an appropriate polyfill if required. There are great tools (babel and their preset-env) that make it so you can transpile modern Javascript code to run on older browsers and polyfill missing APIs (using core-js). Kotlin should imho use this amazing toolchain, instead of re-inventing the wheel. </rant>
👍 5
q
In contrast to the smooth feel of Kotlin JVM, Kotlin JS is jarring, and the only projects I use it are small or isolated.
b
remember it is more recent as well
f
I wonder/hope that given Jetbrains seem to use it for there new project Space that this will lead to a lot of love and improvements especially for Kotlin JS
b
I hope too, it is still really painful to work with.
q
I think Kotlin/JS might have to pull a Scala/JS or an Elm. Kotlin is simply too far removed from JS semantics to be overly efficent.
d
Kotlin is simply too far removed from JS semantics to be overly efficent.
This just isn't true. • JS has classes (which Kotlin does not leverage - why not?). • The number type problem is solved (double works anyways, float can be emulated using Math.fround, int and lower can be done already using things like
Math.imul
. and now we even have bigint for longs) • Ecmascript modules allow exporting and importing single functions, classes and variables, this allows a very clear 1:1 mapping from .kt to .js files:
Copy code
val foo = "bar"
private val baz = "private value"

fun foo() {
}
turns into
Copy code
export const foo = "bar";
const baz = "private value"; // no export here

export function foo() {
}
These (simple?) changes would already make life a lot easier. Combine that with a
kotlin-loader
for webpack and suddenly you have kotlin has a first-class citizen in the modern web-development world instead of a "foreign tumor", which infects everything (you have to use gradle now? Tell that to a web developer!)
And the tooling needs to get better, too. The Kotlin compiler should not just emit .js files, but also d.ts files for them, so that Typescript can understand Kotlin. And the IDE should be able to understand this fact (You should get code completion for kotlin code in typescript, just like you do get code completation for kotlin code when working in java).
👍 3
And same goes for the other way around: You can call Java from kotlin with zero hassle. It just works. The same should be true for calling typescript from kotlin (or maybe even javascript, with
dynamic
everywhere).
q
I'm talking mainly about overloading semantics, which JetBrains seems eager to keep. In addition, the simplistic type system somewhat limits the ease of interop, whereas something like TS obviously just works. I think what I'm saying is the issues are not intractable, but the vision JB has for JS right now is heading into a closed or limited ecosystem.
d
Overloading is implemented on JS using name-mangling. However JS (and also TS) has overloading, which is based on runtime type checks. It is imaginable to let the compiler generate the following:
Copy code
fun foo(a: String)
fun foo(a: Int)
turns into
Copy code
function foo$mangled1(a)
function foo$mangled(a)
function foo(...args) {
    if (args.length === 1) {
        const a = args[0];
        if (typeof a === 'string') return foo$mangled1(a) ... etc
    } else {
        throw new TypeError()
    }
}
That is how overloading is done in JS. It's ugly, but that's why we have a compiler.
👍 2
the vision JB has for JS right now is heading into a closed or limited ecosystem.
I really hope not. This would imho be the "death" for Kotlin/JS. It also goes against Kotlin's explicit goals: Work in tandem with the underlying platform, whichever it might be.
👍 3
q
JB is free to prove me wrong for sure :). Although its also been established that runtime checks don't work for the semantics they want and add a lot of overhead in a forum post somewhere.
d
Well, in my example above the compiler would of course still emit code that calls the mangled functions (since in Kotlin code you know for sure which method to call). The runtime-bouncer is just for calls from TS and JS.
👍 1
e
@diesieben07 Have you created issues for each of these concerns? I like the emphasis you are adding.
d
Not yet, but that is a good point. I'll try to find existing issues on Youtrack or create new ones. I'll post a list here when I am done
Some searches already found these: • 5 year old issue (closed... 😢) that raises a lot of these issues already (1 .kt file => 1 .js file, use babel, etc.): https://youtrack.jetbrains.com/issue/KT-6957 • Runtime type-checking bouncer method for overloads: https://youtrack.jetbrains.com/issue/KT-34995 • Emitting TypeScript declarations for Kotlin code (will happen in 1.4, yay! let's hope the declarations are usable as opposed to what dukat emits): https://youtrack.jetbrains.com/issue/KT-16604 • Better interop with JavaScript "enums" (type unions): https://youtrack.jetbrains.com/issue/KT-23823 So... a lot of stuff is already known.
❤️ 1
Of all of those issues, KT-6957 is the most important. None of the issues it raised 5 years ago are addressed today. Yet it is still closed. Why?
Regarding webpack: There seems to be a webpack plugin for Kotlin, but only as part of
create-react-kotlin-app
and it is not used by the Kotlin gradle plugin when creating a browser-js target...
And it is also just a plugin, which seems to completely bypass webpack's own module resolution instead of being a a loader for
.kt
files.
e
@diesieben07 It looks like KT-6957 is closed because "Zalim Bashorov commented 22 Aug 2016 19:22 Close the issue since all topics covered by existing issues (see the first comment)." His first comment references: 1. https://youtrack.jetbrains.com/issue/KT-2993 provide a compiler switch for generating 'naked functions' in JavaScript rather than Kotlin modules 2. https://youtrack.jetbrains.com/issue/KT-6169 Generate JS result in background in IDEA projects 3. https://youtrack.jetbrains.com/issue/KT-6168 Ability to generate one JS file for each Kotlin source file 4. https://youtrack.jetbrains.com/issue/KT-7013 JS: load declarations directly from ts and d.ts files
d
I'm not sure how I missed that, I thought I had read the comments. Thank you