Skip to content

Advanced Features

Named Arguments

ktox-js automatically reorders named arguments at call sites to match the target function's parameter order. This allows you to use Kotlin's named argument syntax even though JavaScript does not natively support it.

fun foo(a: Int, b: Int, c: Int) {}

fun test() {
    foo(c = 3, a = 1, b = 2)
}

Transpiles to:

function test() {
    foo(1, 2, 3);
}

Native Interop

@NativeName

Use @NativeName to map a Kotlin declaration to a different name in the generated JavaScript. This is useful for calling existing JavaScript functions or mapping Kotlin names to engine-provided globals.

import com.isycat.ktox.annotations.NativeName

@NativeName("externalFunction")
fun kotlinFunction(x: Int)

Calls to kotlinFunction(42) will transpile to externalFunction(42).

Where the annotation sits decides the emitted SHAPE:

  • @get:NativeName / @set:NativeName on a property — reads and writes become native METHOD CALLS: unit.health += 50unit.SetHealth(unit.GetHealth() + 50).
  • A bare @NativeName on a property — a FIELD rename (reads and writes stay property accesses); a dotted name (@NativeName("style.clip")) renames onto a nested path. Mixing get/set and bare is fine — each side resolves independently.

Resolution is receiver-type-aware: the annotation is looked up on the RECEIVER's type (source or compiled jar, following supertypes), so two types can map the same Kotlin name to different native names, and a plain data class field never borrows an unrelated type's accessor.

External data classes

Constructing a data class that exists ONLY in a types jar (no transpiled output — e.g. an engine event payload) emits an object literal, because the class never exists in the generated program:

send(LinkPayload(link = "item_blink", nav = true, shop = 1))
send({ link: "item_blink", nav: true, shop: 1 });

Data classes that ARE part of the program (your own modules, shared modules) construct normally with new.

Value classes

A @JvmInline value class is an identity at runtime — construction and .value reads vanish:

@JvmInline value class PanelID(val value: Int)

val id = PanelID(3)
val raw = id.value
const id = 3;
const raw = id;

@ReplaceReferencesWithLiteral

This annotation suppresses the declaration of a Kotlin property and replaces all references to it with a literal string. This is useful for mapping to global object paths.

import com.isycat.ktox.annotations.ReplaceReferencesWithLiteral

@ReplaceReferencesWithLiteral("GameEvents.Subscribe")
val gameEventsSubscribe: Any = TODO()

fun use() {
    gameEventsSubscribe
}

Transpiles to:

function use() {
    GameEvents.Subscribe;
}

V8 / Panorama Specifics

When targeting the V8 engine (e.g., in Dota 2 Panorama), ktox-js provides specialized behavior:

  • No Modules: Emits code suitable for inline script loading by suppressing import and require statements.
  • Engine Globals: Use @NativeName and @ReplaceReferencesWithLiteral to interact with engine-provided globals without emitting declarations.
  • Global Access: Since no modules are used, all top-level declarations are effectively global within the script's scope.

To enable V8 mode, use the com.isycat.ktox.js.v8 plugin:

plugins {
    id("com.isycat.ktox.js.v8") version "0.1.0"
}

kotlinToV8Js {
    // V8-specific configuration
}