Use Javascript libraries in Kotlin

The last time I used Kotlin was December 2015, when I used it to solve a couple of Project Euler problems.

This time I want to try its interaction with Javascript. Now my question is: how do we import / use existing Javascript libraries in Kotlin? I have seen some people using the native keyword, and I just want a short explanation of this.

+8
kotlin
source share
3 answers

There is no native keyword, there is an @native annotation. This is currently a working solution, and you can use it with the 1.0.x branch of the Kotlin compiler. However, we are going to denounce this annotation in favor of extern annotations, so be prepared to rewrite the code at the end for the 1.1.x branch.

When you put the @native annotation in a class or top-level function, two things happen:

  • His body is not compiled for JavaScript.
  • The compiler refers to this class or function directly, without the package name and mangling.

I think this is easier to explain by providing an example JavaScript library:

 function A(x) { this.x = x; this.y = 0; } A.prototype.foo = function(z) { return this.x + this.y + z; } function min(a, b) { return a < b ? a : b; } 

and the corresponding Kotlin declaration

 @native class A(val x: Int) { var y: Int = noImpl fun foo(z: Int): Int = noImpl } @native fun min(a: Int, b: Int): Int = noImpl 

Note that noImpl is a special placeholder that is required due to non-abstract functions, required bodies, and non-abstract properties that initializers require. BTW, when we replace @native with extern , we will get rid of this noImpl .

Another aspect of interacting with JS libraries is the inclusion of libraries through a modular system. Unfortunately, we do not have any solution now (but we will publish it soon). See proposal . You can use the following workaround for node.js / CommonJS:

 @native interface ExternalModule { fun foo(x: Int) } @native fun require(name: String): dynamic = noImpl fun main(args: Array<String>) { val module: ExternalModule = require("externalModule") module.foo(123) } 

where the external module is declared as follows

 function foo(x) { return x + 1; } module.exports = { foo : foo }; 
+6
source share

I added a simple barebone project as an example of how to do Kotlin2Js.

https://bitbucket.org/mantis78/gradle4kotlin2js/src

Here is the gradle file, which is the main recipe.

 group 'org.boonhighendtech' version '1.0-SNAPSHOT' buildscript { ext.kotlin_version = '1.1.2-5' repositories { maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' } mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin2js' repositories { maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' } mavenCentral() } dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" } build { outputs.dir("web/") } build.doLast { copy { from 'src/main/webapp' into 'web/' include '**/*.html' include '**/*.js' include '**/*.jpg' include '**/*.png' } configurations.compile.each { File file -> copy { includeEmptyDirs = false from zipTree(file.absolutePath) into "${projectDir}/web" include { fileTreeElement -> def path = fileTreeElement.path path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/")) } } } } clean.doLast { file(new File(projectDir, "/web")).deleteDir() } compileKotlin2Js { kotlinOptions.outputFile = "${projectDir}/web/output.js" kotlinOptions.moduleKind = "amd" kotlinOptions.sourceMap = true } 

First, you can assign a dynamic variable and then essentially encode it as if you were quickly encoding JavaScript.

eg.

 val jQuery: dynamic = passedInJQueryRef jQuery.whateverFunc() 

But if you intend to type it, you need to enter the types into an external library. One way is to use the relatively extensive typedefs libraries https://github.com/DefinitelyTyped/DefinitelyTyped

Find ts.d, then run ts2kt ( https://github.com/Kotlin/ts2kt ) to get your Kotlin files. This usually leads you there. Sometimes some conversions are not very well done. You will need to fix the conversion. For example. snapsvg snapsvg.attr () takes the value "{}", but it is converted to some strange interface.

It was

 fun attr(params: `ts$2`): Snap.Element 

And I replaced him

  fun attr(params: Json): Snap.Element 

and it works like a charm.

+1
source share

Kotlin 1.1 introduces an external modifier that can be used to declare functions and classes written directly in JS, see http://kotlinlang.org/docs/reference/js-interop.html

0
source share

All Articles