File: javascript-interop.md

package info (click to toggle)
kotlin 1.3.31%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 109,908 kB
  • sloc: java: 454,756; xml: 18,599; javascript: 10,452; sh: 513; python: 97; makefile: 69; ansic: 4
file content (226 lines) | stat: -rw-r--r-- 4,177 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# 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)