mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
226 lines
4.1 KiB
Markdown
226 lines
4.1 KiB
Markdown
# 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) |