Hello, I have an issue with kotlinjs. I tracked it...
# javascript
e
Hello, I have an issue with kotlinjs. I tracked it down to this code:
Copy code
val s = run { p.toString() }
val p = 4
fun main() { println(s) }
It produces TypeError: p is undefined. When the first two lines are swapped, it works.
k
It's expected behaviour
e
Really? It is a different behaviour than with Kotlin on JVM.
It also happens when the code is inside a
object { ... }
k
Yes, but in general behaviour will be the same. Java BE performs optimization for constants. In your case
4
will be set as an initial value for
p
, whereas
s
gets initialized in
<clinit>
section.
Consider this:
Copy code
val s = run { p.toString() }
val p = foo()
fun foo() = 4
fun main() { println(s) }
e
The code with foo() gives the same "p is undefined" error.
Oh, on the JVM it prints 0 instead of 4.
So it's not a flaw specific to the JS backend?
k
What about this
Copy code
val s = run { p.toString() }
val p: Any = foo()
fun foo() = 4
fun main() { println(s) }
e
NullPointerException
k
I don't know. I just raised a question in internal JB chat whether this is a JVM-specific behavior or a part of language specification
e
Ok so the problem is at the langage level. If this code is not going to run correctly, I think it should fail at compile time, with
unresolved reference: p
k
I'm not sure
The answer is no: it's not a problem in the language level. Even if we won't resolve
p
in the first line, it would be possible to write code like this:
Copy code
fun foo() = p.toString()
val s: Any = run(::foo)
val p: Any = run { 42 }

fun main(args: Array<String>) { 
    println(s) 
}
e
I've just reproduced a similar issue with Scala. The problem must be very general.
A correct initialization order does not always exist.
The only way to prevent this kind of error would be by disallowing references to thing defined after -- just like if you wrap all the code into a fun() { ... }
But this is probably too restrictive.