Kotlin WebAssembly runtime provides a global JavaScript array called heap
which can be accessed if the pointer of a variable is known
The pointer and size of the variable can be determined by library methods stringPointer and stringLengthBytes
The from JavaScript the value can be updated with below logic
Kotlin Main Code
package wasm
import kotlinx.interop.wasm.dom.*
import kotlinx.wasm.jsinterop.*
import mymod.*
var str1 = " "
fun main() {
mod.domEval("document.getElementById('mydiv').innerHTML", stringPointer(str1), stringLengthBytes(str1))
println(str1)
}
Kotlin Stub
@SymbolName("domEval")
external public fun domEval(arena: Int, index: Int, idPtr: Int, idLen: Int, rdPtr: Int, rdLen: Int, resultArena: Int): Unit
open class MyModule(arena: Int, index: Int): JsValue(arena, index) {
constructor(jsValue: JsValue): this(jsValue.arena, jsValue.index)
fun domEval(js: String, rdPtr: Int, rdLen: Int): Unit {
domEval(this.arena, this.index, stringPointer(js), stringLengthBytes(js), rdPtr, rdLen, ArenaManager.currentArena)
}
companion object {
}
}
val mod: MyModule
get() {
val wasmRetVal = getMyModule(ArenaManager.currentArena)
return MyModule(ArenaManager.currentArena, wasmRetVal)
}
JavaScript Stub
function fromUTF16String(string, pointer, size) {
var j=0;
for (let i = pointer; i < pointer + size; i += 2) {
if(j<string.length)
heap[i] = string.charCodeAt(j);
else
heap[i] = 0
heap[i + 1] = 0
j++;
}
}
konan.libraries.push ({
domEval(arena, obj, idPtr, idLen, rdPtr, rdLen, resultArena) {
var js = toUTF16String(idPtr, idLen);
var result = eval(js);
fromUTF16String(result, rdPtr, rdLen)
}
})
Explanation
UTF16 String holds two heap spaces therefore a loop with i += 2 will allows us to put values in heap, the above code explains each character converted to ASCII code and stored in heap[1], heap[3], heap[5] ... accordingly
heap[2], heap[4], heap[6] are filled with zero reason being the ASCII is less than or equal to 255 which is plain english
if there is asian/latin/accented characters or symbols then it should be split
Example ASCII code for Ĝ is 196 156 then
heap[1] = 196
heap[2] = 156
when converting it back, we should do
String.fromCharCode(heap[1] + heap[2] * 256)
this is already done in the inbuilt method toUTF16String
This reduces the method calls between WebAssembly and JavaScript for each byte, but in the code we need to allocate a big string string with spaces as below
var str1 = " "
the double quotes allocates around 90 size string, which sound little bit unethical, but it works fine
GitHub: https://github.com/dickensas/kotlin-gradle-templates/tree/master/sboot-wasm-heap