CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-scripting-jvm-host

Kotlin Scripting JVM host for executing and compiling Kotlin scripts in JVM environments with JSR-223 integration and comprehensive caching mechanisms

Pending
Overview
Eval results
Files

jsr223-integration.mddocs/

JSR-223 Integration

Complete JSR-223 (Java Scripting API) compatible implementation for seamless integration with existing Java scripting frameworks and applications.

Capabilities

KotlinJsr223InvocableScriptEngine

Interface extending JSR-223 Invocable for function and method invocation with backward compatibility support.

/**
 * JSR-223 invocable script engine interface with Kotlin-specific extensions
 */
interface KotlinJsr223InvocableScriptEngine : Invocable {
    
    /** Optional wrapper for function/method invocation */
    val invokeWrapper: InvokeWrapper?
    
    /** Sequence of previously evaluated script instances for backward compatibility */
    val backwardInstancesHistory: Sequence<Any>
    
    /** Base class loader for script execution context */
    val baseClassLoader: ClassLoader
    
    /**
     * Invokes a top-level function from previously evaluated scripts
     * @param name Function name to invoke
     * @param args Function arguments
     * @returns Function result or null
     */
    override fun invokeFunction(name: String?, vararg args: Any?): Any?
    
    /**
     * Invokes a method on a specific object instance
     * @param thiz Object instance to invoke method on
     * @param name Method name to invoke
     * @param args Method arguments
     * @returns Method result or null
     */
    override fun invokeMethod(thiz: Any?, name: String?, vararg args: Any?): Any?
    
    /**
     * Gets an interface implementation from script context
     * @param clasz Interface class to implement
     * @returns Interface implementation or null
     */
    override fun <T : Any> getInterface(clasz: Class<T>?): T?
    
    /**
     * Gets an interface implementation from specific object instance
     * @param thiz Object instance to use as interface implementation
     * @param clasz Interface class to implement
     * @returns Interface implementation or null
     */
    override fun <T : Any> getInterface(thiz: Any?, clasz: Class<T>?): T?
}

KotlinJsr223ScriptEngineImpl

Complete JSR-223 script engine implementation with REPL capabilities and context integration.

/**
 * JSR-223 script engine implementation with REPL support
 * @param factory Script engine factory instance
 * @param baseCompilationConfiguration Base compilation configuration
 * @param baseEvaluationConfiguration Base evaluation configuration
 * @param getScriptArgs Function to extract script arguments from JSR-223 context
 */
class KotlinJsr223ScriptEngineImpl(
    factory: ScriptEngineFactory,
    baseCompilationConfiguration: ScriptCompilationConfiguration,
    baseEvaluationConfiguration: ScriptEvaluationConfiguration,
    val getScriptArgs: (context: ScriptContext) -> ScriptArgsWithTypes?
) : KotlinJsr223JvmScriptEngineBase(factory), KotlinJsr223InvocableScriptEngine {
    
    /** JSR-223 host configuration with context integration */
    val jsr223HostConfiguration: ScriptingHostConfiguration
    
    /** Final compilation configuration with JSR-223 refinements */
    val compilationConfiguration: ScriptCompilationConfiguration
    
    /** Final evaluation configuration with JSR-223 refinements */
    val evaluationConfiguration: ScriptEvaluationConfiguration
    
    /** REPL compiler for incremental compilation */
    val replCompiler: ReplCompilerWithoutCheck
    
    /** REPL evaluator for script execution */
    val replEvaluator: ReplFullEvaluator
    
    /** Current REPL state */
    val state: IReplStageState<*>
    
    /**
     * Creates new REPL state with thread synchronization
     * @param lock Read-write lock for thread safety
     * @returns New REPL stage state
     */
    fun createState(lock: ReentrantReadWriteLock): IReplStageState<*>
    
    /**
     * Overrides script arguments from JSR-223 context
     * @param context JSR-223 script context
     * @returns Script arguments with types or null
     */
    fun overrideScriptArgs(context: ScriptContext): ScriptArgsWithTypes?
    
    /**
     * Compiles and evaluates script code with context integration
     * @param script Script code to execute
     * @param context JSR-223 script context
     * @returns Evaluation result
     */
    fun compileAndEval(script: String, context: ScriptContext): Any?
}

Usage Examples:

import kotlin.script.experimental.jvmhost.jsr223.*
import javax.script.*

// Create JSR-223 script manager
val manager = ScriptEngineManager()

// Register Kotlin script engine (typically done by service loader)
val factory = KotlinJsr223DefaultScriptEngineFactory()
manager.registerEngineExtension("kts", factory)

// Get Kotlin script engine
val engine = manager.getEngineByExtension("kts") as KotlinJsr223InvocableScriptEngine

// Basic script execution
val result = engine.eval("""
    fun greet(name: String) = "Hello, ${'$'}name!"
    val message = greet("World")
    println(message)
    message
""")

println("Script result: $result")

// Function invocation
val greeting = engine.invokeFunction("greet", "JSR-223")
println("Function result: $greeting")

// Context integration
val context = engine.context
context.setAttribute("userName", "Alice", ScriptContext.ENGINE_SCOPE)
context.setAttribute("userAge", 30, ScriptContext.ENGINE_SCOPE)

val contextResult = engine.eval("""
    val user = mapOf("name" to userName, "age" to userAge)
    println("User: ${'$'}user")
    user
""")

// Interface implementation
interface Calculator {
    fun add(a: Int, b: Int): Int
    fun multiply(a: Int, b: Int): Int
}

engine.eval("""
    fun add(a: Int, b: Int) = a + b
    fun multiply(a: Int, b: Int) = a * b
""")

val calculator = engine.getInterface(Calculator::class.java)
println("5 + 3 = ${calculator.add(5, 3)}")
println("5 * 3 = ${calculator.multiply(5, 3)}")

Configuration System

JSR-223 specific configuration keys and builders for customizing script engine behavior.

Configuration Builders

/** JSR-223 host configuration keys */
interface Jsr223HostConfigurationKeys

/** Builder for JSR-223 host configuration */
open class Jsr223HostConfigurationBuilder

/** JSR-223 compilation configuration keys */
interface Jsr223CompilationConfigurationKeys

/** Builder for JSR-223 compilation configuration */
open class Jsr223CompilationConfigurationBuilder

/** JSR-223 evaluation configuration keys */
interface Jsr223EvaluationConfigurationKeys

/** Builder for JSR-223 evaluation configuration */
open class Jsr223EvaluationConfigurationBuilder

Configuration Extension Properties

Extension properties for integrating JSR-223 configuration with standard Kotlin scripting configuration.

/** JSR-223 host configuration extension */
val ScriptingHostConfigurationKeys.jsr223: Jsr223HostConfigurationBuilder

/** JSR-223 compilation configuration extension */
val ScriptCompilationConfigurationKeys.jsr223: Jsr223CompilationConfigurationBuilder

/** JSR-223 evaluation configuration extension */
val ScriptEvaluationConfigurationKeys.jsr223: Jsr223EvaluationConfigurationBuilder

Configuration Keys

/** Function to get JSR-223 script context from host configuration */
val Jsr223HostConfigurationKeys.getScriptContext: () -> ScriptContext?

/** Function to get JSR-223 script context from compilation configuration */
val Jsr223CompilationConfigurationKeys.getScriptContext: () -> ScriptContext?

/** Whether to import all JSR-223 context bindings as script properties */
val Jsr223CompilationConfigurationKeys.importAllBindings: Boolean

/** Function to get JSR-223 script context from evaluation configuration */
val Jsr223EvaluationConfigurationKeys.getScriptContext: () -> ScriptContext?

Configuration Examples:

import kotlin.script.experimental.jvmhost.jsr223.*
import javax.script.ScriptContext

// Host configuration with JSR-223 integration
val hostConfig = ScriptingHostConfiguration {
    jsr223 {
        getScriptContext = { 
            // Provide access to current script context
            getCurrentScriptContext()
        }
    }
}

// Compilation configuration with automatic binding import
val compilationConfig = ScriptCompilationConfiguration {
    jsr223 {
        getScriptContext = { getCurrentScriptContext() }
        importAllBindings = true // Import all context bindings as script properties
    }
    
    // Standard Kotlin scripting configuration
    dependencies(JvmDependency(kotlinStdlib))
}

// Evaluation configuration with context access
val evaluationConfig = ScriptEvaluationConfiguration {
    jsr223 {
        getScriptContext = { getCurrentScriptContext() }
    }
    
    // Provide additional context variables
    providedProperties(
        "scriptContext" to ScriptContext::class
    )
}

// Create engine with custom configuration
val customEngine = KotlinJsr223ScriptEngineImpl(
    factory = KotlinJsr223DefaultScriptEngineFactory(),
    baseCompilationConfiguration = compilationConfig,
    baseEvaluationConfiguration = evaluationConfig
) { context ->
    // Extract script arguments from context
    val args = context.getBindings(ScriptContext.ENGINE_SCOPE)["args"] as? Array<String>
    args?.let { ScriptArgsWithTypes(it, arrayOf(Array<String>::class)) }
}

Context Property Integration

Functions for integrating JSR-223 context properties with Kotlin script compilation and evaluation.

Context Configuration Functions

/**
 * Configures provided properties from JSR-223 context for compilation
 * @param context Script configuration refinement context
 * @returns Updated compilation configuration or failure
 */
fun configureProvidedPropertiesFromJsr223Context(
    context: ScriptConfigurationRefinementContext
): ResultWithDiagnostics<ScriptCompilationConfiguration>

/**
 * Configures provided properties from JSR-223 context for evaluation
 * @param context Script evaluation configuration refinement context
 * @returns Updated evaluation configuration or failure
 */
fun configureProvidedPropertiesFromJsr223Context(
    context: ScriptEvaluationConfigurationRefinementContext
): ResultWithDiagnostics<ScriptEvaluationConfiguration>

Context Integration Example:

import kotlin.script.experimental.jvmhost.jsr223.*
import javax.script.*

// Setup context with properties
val context = SimpleScriptContext()
val bindings = context.getBindings(ScriptContext.ENGINE_SCOPE)
bindings["database"] = DatabaseConnection("localhost:5432")
bindings["logger"] = LoggerFactory.getLogger("script")
bindings["config"] = mapOf("debug" to true, "maxRetries" to 3)

// Custom engine with automatic context property configuration
val contextEngine = KotlinJsr223ScriptEngineImpl(
    factory = KotlinJsr223DefaultScriptEngineFactory(),
    baseCompilationConfiguration = ScriptCompilationConfiguration {
        refineConfiguration {
            onAnnotations { context ->
                // Automatically configure properties from JSR-223 context
                configureProvidedPropertiesFromJsr223Context(context)
            }
        }
    },
    baseEvaluationConfiguration = ScriptEvaluationConfiguration {
        refineConfiguration {
            beforeEvaluation { context ->
                // Configure evaluation properties from JSR-223 context
                configureProvidedPropertiesFromJsr223Context(context)
            }
        }
    }
) { scriptContext ->
    // No special argument processing needed
    null
}

contextEngine.context = context

// Script can now access context properties directly
val result = contextEngine.eval("""
    // Properties from JSR-223 context are automatically available
    logger.info("Starting script execution")
    
    val users = database.query("SELECT * FROM users")
    logger.info("Found ${'$'}{users.size} users")
    
    if (config["debug"] as Boolean) {
        println("Debug mode enabled")
        println("Max retries: ${'$'}{config["maxRetries"]}")
    }
    
    users.size
""")

println("Script found ${result} users")

Error Handling

JSR-223 integration provides comprehensive error handling that bridges Kotlin diagnostics with JSR-223 exceptions.

Exception Translation

// JSR-223 exceptions are automatically translated from Kotlin diagnostics
try {
    val result = engine.eval("invalid kotlin syntax !!!")
} catch (e: ScriptException) {
    println("Script compilation error: ${e.message}")
    println("Line number: ${e.lineNumber}")
    println("Column number: ${e.columnNumber}")
    
    // Access original Kotlin diagnostics if available
    val kotlinDiagnostics = e.cause as? ScriptDiagnosticException
    kotlinDiagnostics?.diagnostics?.forEach { diagnostic ->
        println("Kotlin diagnostic: ${diagnostic.severity} - ${diagnostic.message}")
    }
}

// Function invocation errors
try {
    val result = engine.invokeFunction("nonExistentFunction", "arg")
} catch (e: NoSuchMethodException) {
    println("Function not found: ${e.message}")
}

// Interface implementation errors
try {
    val impl = engine.getInterface(Calculator::class.java)
    if (impl == null) {
        println("Cannot create interface implementation - required functions not defined")
    }
} catch (e: ClassCastException) {
    println("Interface implementation error: ${e.message}")
}

Advanced Features

Thread Safety

JSR-223 implementation provides thread-safe execution through proper synchronization and isolated state management.

import java.util.concurrent.*

val engine = manager.getEngineByExtension("kts") as KotlinJsr223InvocableScriptEngine

// Thread-safe concurrent execution
val executor = ForkJoinPool.commonPool()
val futures = (1..10).map { i ->
    executor.submit(Callable {
        val localContext = SimpleScriptContext()
        localContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE)
        localContext.setAttribute("threadId", i, ScriptContext.ENGINE_SCOPE)
        
        engine.eval("""
            println("Executing on thread ${'$'}threadId")
            Thread.currentThread().name + " - " + threadId
        """, localContext)
    })
}

val results = futures.map { it.get() }
results.forEach { println("Result: $it") }

Performance Optimization

// Reuse compiled scripts for better performance
val precompiledEngine = KotlinJsr223ScriptEngineImpl(
    // Configuration optimized for repeated execution
    baseCompilationConfiguration = ScriptCompilationConfiguration {
        // Enable compilation caching
        hostConfiguration(ScriptingHostConfiguration {
            jvm {
                compilationCache(FileBasedScriptCache(File("jsr223-cache")))
            }
        })
    }
)

// Execute the same script multiple times efficiently
val scriptCode = """
    fun factorial(n: Int): Long = if (n <= 1) 1 else n * factorial(n - 1)
    factorial(args[0].toInt())
"""

val results = (1..10).map { n ->
    val context = SimpleScriptContext()
    context.setAttribute("args", arrayOf(n.toString()), ScriptContext.ENGINE_SCOPE)
    precompiledEngine.eval(scriptCode, context)
}

println("Factorials: $results")

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-scripting-jvm-host

docs

core-scripting-host.md

index.md

jsr223-integration.md

repl-support.md

script-caching.md

script-compilation.md

script-persistence.md

tile.json