Javascript top level variables and initialization

#1

I recently came across an interesting problem. In a JS project I have a top level val object that defines tool information for all tools available in the application. That worked fine while the information I put was all in-lined. However, I tried to add some new information (tutorial information) and decided to separate that to a new object that was also a top level val object. So basically the setup was like this
in one file I define:
val allTools=listOf(tool(…, specificToolTutorial))
and in a different file I define:
val specificToolTutorial = …

When the application would run specificToolTutorial was always null even though it was defined as top level. It occurred to me then that both of those files were in the same package and that the one holding specificToolTutorial was below the other one. So I thought the problem was that when the first file runs in JS the second one hasn’t run yet so specificToolTutorial is essentially an undefined variable. I tried to inline the specificToolTutorial definition in the first file and after that things worked fine. I thought that that if moved them to different packages so that the imports would take care of getting initialization to take place before using the variable would work but it didn’t. In the end I had to wrap the data in objects.

My question is, should I get a warning of some sort to avoid having this happen in the future? or is there another way to handle them in the same package?

I’m using Kotlin 1.3.20

#2

One of the workarounds would be is to initialise property lazily:

// file1.kt
val allTools = listOf(tool(..., specificToolTutorial)) 

// file2.kt
val specificToolTutorial by lazy { ... }

There is a similar issue in YouTrack you can upvote and watch: KT-25796

Warning for general case is hard to do because uninitialised property can be accessed inside a deep chain of function calls:

val prop1 = f1()

fun f1() = /* ... */ f2() /* ... */
fun f2() = /* ... */ f3() /* ... */
// ...
fun fN() = /* ... */ prop2 /* ... */

Warning for some simple cases might be possible.

#3

Makes sense, thank you