# Interop with native JavaScript ## Goal Provide the ways to interact with native JavaScript. ## Type-safe Declarations ### Annotation `native` TODO ### Annotation `nativeInvoke` Calls to functions annotated by `nativeInvoke` will be translated to calls of receiver with the arguments provided for original call. Applicable to: * member functions of native declarations * non-member extension functions Example: ```kotlin native class A { nativeInvoke fun invoke(): String = noImpl nativeInvoke fun foo(a: Int): Int = noImpl } fun A.bar(a: String): Int = noImpl fun test(baz: A) { baz() baz.invoke() baz.foo(1) baz.bar("str") } ``` Function `test` will be translated to: ```js ... test: function (baz) { foo() foo() foo(1) foo("str") } ... ``` ### Annotation `nativeGetter` Calls to functions annotated by `nativeGetter` will be translated to square/index operation on the receiver with the argument provided for original call. Applicable to: * member functions of native declarations * non-member extension functions Requirements: * must have exactly one argument * type of the argument must be `String` or subtype of `Number` * default values are prohibited * return type must be nullable Example: ```kotlin native class A { nativeGetter fun get(a: String): String? = noImpl nativeGetter fun foo(a: Int): Int? = noImpl } class B nativeGetter fun B.get(a: String): Int? = noImpl nativeGetter fun B.bar(a: Int): Int? = noImpl fun test(a: A, b: B) { a["foo"] a.get("bar") a.foo(1) b["foo"] b.get("bar") b.bar(1) } ``` Function `test` will be translated to: ```js ... test: function (a, b) { a["foo"] a["bar"] a[1] b["foo"] b["bar"] b[1] } ... ``` ### Annotation `nativeSetter` Calls of functions annotated by `nativeSetter` will be translated to assignment of the second argument to the receiver indexed (with square/index operation) with the first argument. Applicable to: * member functions of native declarations * non-member extension functions Requirements: * must have exactly two arguments * type of the first argument must be `String` or subtype of `Number` * default values are prohibited * the return type is either `Unit` or a supertype of the second parameter's type Example: ```kotlin native class A { nativeSetter fun set(a: String, v: Any) {} nativeSetter fun foo(a: Int, v: A) {} } class B nativeSetter fun B.set(a: String, v: B) {} nativeSetter fun B.bar(a: String, v: B?) {} fun test(a: A, b: B) { a["foo"] = "text" a.set("bar", "value") a.foo(1, A()) b["foo"] = B() b.set("bar", b) b.bar("a", null) } ``` Function `test` will be translated to: ```js ... test: function (a, b) { a["foo"] = "text" a["bar"] = "value" a[1] = A() b["foo"] = B() b["bar"] = b b["a"] = null } ... ``` ## Function `js` Argument of `js` function is parsed as JavaScript code and injected directly into the JavaScript code generated by the compiler. Requirements: * the argument should be a compile time constant of type `String` Example: ```kotlin fun test1() { js("console.log('Hello')") } fun test2(a: String) = js(""" var r = foo(a); return r; """) ``` is translated to: ```js function test1() { console.log('Hello') } function test2(a) { var r = foo(a); return r; } ``` ## Dynamic types All dynamic calls with explicit names (regular and infix function calls, and property calls) are translated "as is", without mangling. Additionally, many operations when applied to a receiver of type `dynamic` are translated "as is", instead of by convention. Operations translated "as is" to JavaScript: * binary: `+`, `-`, `*`, `/`, `%`, `>`, `<` `>=`, `<=`, `==`, `!=`, `===`, `!==`, `&&`, `||` * unary * prefix: `-`, `+`, `!` * prefix and postfix: `++`, `--` * assignments: `+=`, `-=`, `*=`, `/=`, `%=` * indexed access: * read: `d[a]`, more than one argument is an error * write: `d[a1] = a2`, more than one argument in `[]` is an error * `in` and `!in` are forbidden, an error is reported Note: * `..` is translated to a call to `rangeTo` * `~`, `|`, `&` and `^` are not supported (there's no Kotlin code that translates to these operations)