Fitz
Fitz

Reputation: 580

How to call Kotlin/JS functions from regular Javascript?

I’ve been using Kotlin to develop a small 2D simulation software, and I’m using Kotlin multiplatform projects to make it run on both the JVM and in a browser. So far it works well.

However, I have a problem when I want to call functions defined in Kotlin/JS from regular Javascript.

To make my application work in the browser, I’m including the big JS file which is under the “build/distributions” folder after running the “build” Gradle task. When my Kotlin/JS application contains a main() function, this one is automatically being called when the HTML pag referencing the JS file is opened, and it works well.

But if I remove the main function and instead I create a start() function which is supposed to be called manually (after a click on a button, for instance), it does not work: it says the function start() is not defined even though it is declared in the Kotlin code.

After opening the generated JS file it seems that indeed there is no start() function. It looks like all the name of the functions have been minified.

I tried adding @JsName, but it didn’t change anything.

So I guess I’m doing something wrong, but I really don’t know what and how to make it work.

Note: I'm using Kotlin 1.3.70

EDIT: Here is the core of my build.gradle.kts:

plugins {
    kotlin("js") version "1.3.70-eap-184"
}


repositories {
    mavenLocal()
    mavenCentral()

    maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
}

dependencies {

}

kotlin {
    target {
        nodejs {

        }
        browser {
            webpackTask {
                mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.PRODUCTION
                bin = "$projectDir/node_modules/$bin"
            }
        }
    }
}

Upvotes: 1

Views: 1901

Answers (1)

vanyochek
vanyochek

Reputation: 905

You should call the function with the module name and qualified name:

https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html#package-structure

package my.qualified.packagename

fun foo() = "Hello"
alert(myModule.my.qualified.packagename.foo());

https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html#jsname-annotation

In some cases (for example, to support overloads), Kotlin compiler mangles names of generated functions and attributes in JavaScript code. To control the generated names, you can use the  @JsName  annotation

UPD: You have two ways to change the module name:

1) If you use gradle you can add this code to your build.gradle

compileKotlinJs {
    kotlinOptions.outputFile = "${rootDir}/web/app.js" // should be valid js variable name
}

or in your build.gradle.kts

kotlin {
    target {
        compilations.all {
            kotlinOptions.outputFile = "${rootDir}/web/app.js"
        }
    }
}

in this case you should use generated file (app.js) in the web folder (you can use other folder and file names).

2) You should create folder webpack.config.d and create js file with any name, and content which configures library mode for webpack

config.output = config.output || {} // just in case where config.output is undefined
config.output.library = "libraryName" // should be valid js variable name

Upvotes: 3

Related Questions