Skip to content

KotlinJsBindingParitySmokeTest.kt

src/jvmMain/kotlin/afield/examples/KotlinJsBindingParitySmokeTest.kt · 67 lines

package afield.examples

import afield.lang.remotejs.RemoteArKotlinJs

FIELD_TEST id: remotejs.kotlinjs-binding-parity runner: jvm-main entrypoint: afield.examples.KotlinJsBindingParitySmokeTest tags: [smoke, remotejs, kotlinjs] timeoutSec: 60 expect: exitCode: 0 stdoutContains: - "KotlinJsBindingParitySmokeTest ok"

object KotlinJsBindingParitySmokeTest

Guards the invariants that motivated generating both façades from one binding model (afield.lang.remotejs.KotlinJsBinding): the compiler declarations and the completion mirror must agree. These are exactly the two discrepancies that hand-maintenance had produced.

object KotlinJsBindingParitySmokeTest {

fun main(args: Array<String>)

body — 42 lines, from line 25
    @JvmStatic
    fun main(args: Array<String>) {
        val compiler = RemoteArKotlinJs.declarations
        val completion = RemoteArKotlinJs.completionDeclarations

        // Structural sanity: compiler is `external`, completion is plain.
        require(compiler.contains("external object THREE")) { "compiler THREE must be external" }
        require(completion.contains("object THREE") && !completion.contains("external")) {
            "completion mirror must be plain (no `external`)"
        }

        // Parity fix 1 — Vector2/3 and Euler components are MUTABLE in BOTH renderings (were `var` in
        // the compiler but `val` ctor params in the old completion mirror).
        for (name in listOf("var x: Double", "var y: Double", "var z: Double")) {
            require(compiler.contains(name)) { "compiler missing `$name`" }
            require(completion.contains(name)) { "completion missing `$name` (mutability parity)" }
        }
        require(!completion.contains("val x: Double")) { "completion still declares Vector.x as `val` — parity regressed" }

        // Parity fix 2 — Mesh.geometry / Mesh.material are PROPERTIES in BOTH (the old compiler decl
        // had only constructor parameters, so completion offered members compilation rejected).
        for (member in listOf("var geometry: BufferGeometry", "var material: Material")) {
            require(compiler.contains(member)) { "compiler Mesh missing property `$member`" }
            require(completion.contains(member)) { "completion Mesh missing property `$member`" }
        }

        // dynamic ↔ Any? split is applied (MeshBasicMaterial's `parameters`), and `stage` uses the
        // dynamic-with-typed-completion split (permissive `dynamic` for the compiler, typed `Stage`
        // for completion) — see KotlinJsRemoteArSurfaceSmokeTest for the fuller stage checks.
        require(compiler.contains("parameters: dynamic")) { "compiler MeshBasicMaterial param must be `dynamic`" }
        require(completion.contains("parameters: Any?")) { "completion MeshBasicMaterial param must be `Any?`" }
        require(compiler.contains("external val stage: dynamic")) { "compiler stage must be `dynamic`" }
        require(completion.contains("val stage: Stage")) { "completion stage must be typed `Stage`" }

        // Compiler-only glue must not leak into the completion surface.
        require(compiler.contains("__remoteArLog")) { "compiler missing log glue" }
        require(!completion.contains("__remoteArLog")) { "completion must not carry compiler-only glue" }

        println("compiler=${compiler.length} chars, completion=${completion.length} chars; parity invariants hold")
        println("KotlinJsBindingParitySmokeTest ok")
    }
}