Skip to content

Browser Support Test — Kotlin source

Audit your real browser against 30 modern web capabilities - WebGPU, WASM, WebAuthn, Service Workers and more. Get a weighted readiness score, copy-paste detection snippets, and a shareable link.

This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.

// browser-support-test — Kotlin polyglot showcase port.
//
// Runtime capability probe, weighted score, and support tier.
//
// This is the Kotlin sibling of src/tools/BrowserSupportTest.tsx (+ the
// browser-support/* modules) that powers the live tool.
//
// ILLUSTRATIVE PORT: the live tool detects *browser* features at runtime
// (navigator/window probes) — a browser-only concern that cannot run in a
// JVM process. This port shows the ANALOGOUS pattern for Kotlin: probes
// query the JVM surface through Kotlin's lens — KotlinVersion, system
// properties, and class-presence lookups — the direct equivalent of
// `'feature' in window`. The scoring algorithm and tier thresholds below
// are byte-for-byte the same as the TypeScript lib's; only the probe
// targets differ.
//
// Language: Kotlin (1.9, JVM, standard library only).
// Ported from src/tools/BrowserSupportTest.tsx (+ browser-support/* modules).
// Source: CosmoDev polyglot showcase port.
// License: display source — part of CosmoDev's polyglot tool pages.

package org.cosmolabs.cosmodev.browsersupport

import kotlin.math.roundToInt

private const val SUPPORTED = "supported"
private const val LIMITED = "limited"
private const val UNSUPPORTED = "unsupported"
private const val UNKNOWN = "unknown"

/** One capability the audit can check: [probe] returns true when the
 *  capability is present in THIS runtime. */
private data class Check(
    val id: String,
    val title: String,
    val category: String,
    val weight: Double,
    val probe: () -> Boolean,
)

/** Outcome of one probe. */
private data class FeatureResult(val id: String, val status: String)

/** contribution × weight. Same values as src/tools/browser-support/score.ts. */
private fun contribution(status: String): Double = when (status) {
    "supported" -> 1.0
    "limited" -> 0.5
    "needs-https" -> 0.3
    else -> 0.0 // unsupported, unknown
}

/** Class-presence probe: true when [name] is loadable in THIS JVM
 *  (looked up without running static initializers). */
private fun hasClass(name: String): Boolean = try {
    Class.forName(name, false, ClassLoader.getSystemClassLoader())
    true
} catch (e: ClassNotFoundException) {
    false
}

/** Weighted readiness 0–100; matches computeScore() exactly. Results whose
 *  id isn't in the catalog are ignored. */
private fun computeScore(results: List<FeatureResult>, catalog: List<Check>): Int {
    val weights = catalog.associate { it.id to it.weight }
    var earned = 0.0
    var possible = 0.0
    for (r in results) {
        val w = weights[r.id] ?: continue
        earned += contribution(r.status) * w
        possible += w
    }
    if (possible == 0.0) return 0
    return (earned / possible * 100).roundToInt()
}

/** tier_for mirrors tierFor() in the island — same thresholds. */
private fun tierFor(score: Int): Pair<String, String> = when {
    score >= 90 -> "Fully modern" to "text-success"
    score >= 75 -> "Very capable" to "text-success"
    score >= 55 -> "Capable, minor gaps" to "text-accent"
    score >= 35 -> "Showing its age" to "text-fg-muted"
    else -> "Legacy browser" to "text-danger"
}

/** Representative catalog of JVM capability probes. */
private fun checks(): List<Check> = listOf(
    Check("jvm-64", "64-bit JVM", "Platform", 1.0) {
        "64" == System.getProperty("sun.arch.data.model")
    },
    Check("unix", "Unix platform", "Platform", 2.0) {
        !System.getProperty("os.name", "").lowercase().startsWith("windows")
    },
    Check("coroutines", "CoroutineContext", "Language", 2.0) {
        hasClass("kotlin.coroutines.CoroutineContext")
    },
    Check("unsigned", "Unsigned integers", "Language", 1.0) {
        hasClass("kotlin.UInt")
    },
    Check("sequences", "Lazy sequences", "Data", 2.0) {
        hasClass("kotlin.sequences.Sequence")
    },
    Check("virtual-threads", "Virtual threads", "Runtime", 3.0) {
        hasClass("java.lang.VirtualThread")
    },
)

/** Run probes; a throw degrades to 'unknown' so one failure can't abort
 *  the audit. */
private fun runChecks(catalog: List<Check>): List<FeatureResult> = catalog.map { c ->
    val status = runCatching { c.probe() }
        .fold({ if (it) SUPPORTED else UNSUPPORTED }, { UNKNOWN })
    FeatureResult(c.id, status)
}

fun main() {
    val catalog = checks()
    val results = runChecks(catalog)
    val score = computeScore(results, catalog)
    val (label, _) = tierFor(score)
    val supported = results.count { it.status == SUPPORTED }
    println("Kotlin ${KotlinVersion.CURRENT} · ${System.getProperty("os.name")}")
    println("$supported/${results.size} capabilities · readiness $score · $label")
    // LIMITED is intentionally absent from probes — kept for vocabulary parity.
    check(LIMITED.isNotEmpty())
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →