or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-scripting-host.mdindex.mdjsr223-integration.mdrepl-support.mdscript-caching.mdscript-compilation.mdscript-persistence.md

jsr223-integration.mddocs/

0

# JSR-223 Integration

1

2

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

3

4

## Capabilities

5

6

### KotlinJsr223InvocableScriptEngine

7

8

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

9

10

```kotlin { .api }

11

/**

12

* JSR-223 invocable script engine interface with Kotlin-specific extensions

13

*/

14

interface KotlinJsr223InvocableScriptEngine : Invocable {

15

16

/** Optional wrapper for function/method invocation */

17

val invokeWrapper: InvokeWrapper?

18

19

/** Sequence of previously evaluated script instances for backward compatibility */

20

val backwardInstancesHistory: Sequence<Any>

21

22

/** Base class loader for script execution context */

23

val baseClassLoader: ClassLoader

24

25

/**

26

* Invokes a top-level function from previously evaluated scripts

27

* @param name Function name to invoke

28

* @param args Function arguments

29

* @returns Function result or null

30

*/

31

override fun invokeFunction(name: String?, vararg args: Any?): Any?

32

33

/**

34

* Invokes a method on a specific object instance

35

* @param thiz Object instance to invoke method on

36

* @param name Method name to invoke

37

* @param args Method arguments

38

* @returns Method result or null

39

*/

40

override fun invokeMethod(thiz: Any?, name: String?, vararg args: Any?): Any?

41

42

/**

43

* Gets an interface implementation from script context

44

* @param clasz Interface class to implement

45

* @returns Interface implementation or null

46

*/

47

override fun <T : Any> getInterface(clasz: Class<T>?): T?

48

49

/**

50

* Gets an interface implementation from specific object instance

51

* @param thiz Object instance to use as interface implementation

52

* @param clasz Interface class to implement

53

* @returns Interface implementation or null

54

*/

55

override fun <T : Any> getInterface(thiz: Any?, clasz: Class<T>?): T?

56

}

57

```

58

59

### KotlinJsr223ScriptEngineImpl

60

61

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

62

63

```kotlin { .api }

64

/**

65

* JSR-223 script engine implementation with REPL support

66

* @param factory Script engine factory instance

67

* @param baseCompilationConfiguration Base compilation configuration

68

* @param baseEvaluationConfiguration Base evaluation configuration

69

* @param getScriptArgs Function to extract script arguments from JSR-223 context

70

*/

71

class KotlinJsr223ScriptEngineImpl(

72

factory: ScriptEngineFactory,

73

baseCompilationConfiguration: ScriptCompilationConfiguration,

74

baseEvaluationConfiguration: ScriptEvaluationConfiguration,

75

val getScriptArgs: (context: ScriptContext) -> ScriptArgsWithTypes?

76

) : KotlinJsr223JvmScriptEngineBase(factory), KotlinJsr223InvocableScriptEngine {

77

78

/** JSR-223 host configuration with context integration */

79

val jsr223HostConfiguration: ScriptingHostConfiguration

80

81

/** Final compilation configuration with JSR-223 refinements */

82

val compilationConfiguration: ScriptCompilationConfiguration

83

84

/** Final evaluation configuration with JSR-223 refinements */

85

val evaluationConfiguration: ScriptEvaluationConfiguration

86

87

/** REPL compiler for incremental compilation */

88

val replCompiler: ReplCompilerWithoutCheck

89

90

/** REPL evaluator for script execution */

91

val replEvaluator: ReplFullEvaluator

92

93

/** Current REPL state */

94

val state: IReplStageState<*>

95

96

/**

97

* Creates new REPL state with thread synchronization

98

* @param lock Read-write lock for thread safety

99

* @returns New REPL stage state

100

*/

101

fun createState(lock: ReentrantReadWriteLock): IReplStageState<*>

102

103

/**

104

* Overrides script arguments from JSR-223 context

105

* @param context JSR-223 script context

106

* @returns Script arguments with types or null

107

*/

108

fun overrideScriptArgs(context: ScriptContext): ScriptArgsWithTypes?

109

110

/**

111

* Compiles and evaluates script code with context integration

112

* @param script Script code to execute

113

* @param context JSR-223 script context

114

* @returns Evaluation result

115

*/

116

fun compileAndEval(script: String, context: ScriptContext): Any?

117

}

118

```

119

120

**Usage Examples:**

121

122

```kotlin

123

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

124

import javax.script.*

125

126

// Create JSR-223 script manager

127

val manager = ScriptEngineManager()

128

129

// Register Kotlin script engine (typically done by service loader)

130

val factory = KotlinJsr223DefaultScriptEngineFactory()

131

manager.registerEngineExtension("kts", factory)

132

133

// Get Kotlin script engine

134

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

135

136

// Basic script execution

137

val result = engine.eval("""

138

fun greet(name: String) = "Hello, ${'$'}name!"

139

val message = greet("World")

140

println(message)

141

message

142

""")

143

144

println("Script result: $result")

145

146

// Function invocation

147

val greeting = engine.invokeFunction("greet", "JSR-223")

148

println("Function result: $greeting")

149

150

// Context integration

151

val context = engine.context

152

context.setAttribute("userName", "Alice", ScriptContext.ENGINE_SCOPE)

153

context.setAttribute("userAge", 30, ScriptContext.ENGINE_SCOPE)

154

155

val contextResult = engine.eval("""

156

val user = mapOf("name" to userName, "age" to userAge)

157

println("User: ${'$'}user")

158

user

159

""")

160

161

// Interface implementation

162

interface Calculator {

163

fun add(a: Int, b: Int): Int

164

fun multiply(a: Int, b: Int): Int

165

}

166

167

engine.eval("""

168

fun add(a: Int, b: Int) = a + b

169

fun multiply(a: Int, b: Int) = a * b

170

""")

171

172

val calculator = engine.getInterface(Calculator::class.java)

173

println("5 + 3 = ${calculator.add(5, 3)}")

174

println("5 * 3 = ${calculator.multiply(5, 3)}")

175

```

176

177

## Configuration System

178

179

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

180

181

### Configuration Builders

182

183

```kotlin { .api }

184

/** JSR-223 host configuration keys */

185

interface Jsr223HostConfigurationKeys

186

187

/** Builder for JSR-223 host configuration */

188

open class Jsr223HostConfigurationBuilder

189

190

/** JSR-223 compilation configuration keys */

191

interface Jsr223CompilationConfigurationKeys

192

193

/** Builder for JSR-223 compilation configuration */

194

open class Jsr223CompilationConfigurationBuilder

195

196

/** JSR-223 evaluation configuration keys */

197

interface Jsr223EvaluationConfigurationKeys

198

199

/** Builder for JSR-223 evaluation configuration */

200

open class Jsr223EvaluationConfigurationBuilder

201

```

202

203

### Configuration Extension Properties

204

205

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

206

207

```kotlin { .api }

208

/** JSR-223 host configuration extension */

209

val ScriptingHostConfigurationKeys.jsr223: Jsr223HostConfigurationBuilder

210

211

/** JSR-223 compilation configuration extension */

212

val ScriptCompilationConfigurationKeys.jsr223: Jsr223CompilationConfigurationBuilder

213

214

/** JSR-223 evaluation configuration extension */

215

val ScriptEvaluationConfigurationKeys.jsr223: Jsr223EvaluationConfigurationBuilder

216

```

217

218

### Configuration Keys

219

220

```kotlin { .api }

221

/** Function to get JSR-223 script context from host configuration */

222

val Jsr223HostConfigurationKeys.getScriptContext: () -> ScriptContext?

223

224

/** Function to get JSR-223 script context from compilation configuration */

225

val Jsr223CompilationConfigurationKeys.getScriptContext: () -> ScriptContext?

226

227

/** Whether to import all JSR-223 context bindings as script properties */

228

val Jsr223CompilationConfigurationKeys.importAllBindings: Boolean

229

230

/** Function to get JSR-223 script context from evaluation configuration */

231

val Jsr223EvaluationConfigurationKeys.getScriptContext: () -> ScriptContext?

232

```

233

234

**Configuration Examples:**

235

236

```kotlin

237

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

238

import javax.script.ScriptContext

239

240

// Host configuration with JSR-223 integration

241

val hostConfig = ScriptingHostConfiguration {

242

jsr223 {

243

getScriptContext = {

244

// Provide access to current script context

245

getCurrentScriptContext()

246

}

247

}

248

}

249

250

// Compilation configuration with automatic binding import

251

val compilationConfig = ScriptCompilationConfiguration {

252

jsr223 {

253

getScriptContext = { getCurrentScriptContext() }

254

importAllBindings = true // Import all context bindings as script properties

255

}

256

257

// Standard Kotlin scripting configuration

258

dependencies(JvmDependency(kotlinStdlib))

259

}

260

261

// Evaluation configuration with context access

262

val evaluationConfig = ScriptEvaluationConfiguration {

263

jsr223 {

264

getScriptContext = { getCurrentScriptContext() }

265

}

266

267

// Provide additional context variables

268

providedProperties(

269

"scriptContext" to ScriptContext::class

270

)

271

}

272

273

// Create engine with custom configuration

274

val customEngine = KotlinJsr223ScriptEngineImpl(

275

factory = KotlinJsr223DefaultScriptEngineFactory(),

276

baseCompilationConfiguration = compilationConfig,

277

baseEvaluationConfiguration = evaluationConfig

278

) { context ->

279

// Extract script arguments from context

280

val args = context.getBindings(ScriptContext.ENGINE_SCOPE)["args"] as? Array<String>

281

args?.let { ScriptArgsWithTypes(it, arrayOf(Array<String>::class)) }

282

}

283

```

284

285

## Context Property Integration

286

287

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

288

289

### Context Configuration Functions

290

291

```kotlin { .api }

292

/**

293

* Configures provided properties from JSR-223 context for compilation

294

* @param context Script configuration refinement context

295

* @returns Updated compilation configuration or failure

296

*/

297

fun configureProvidedPropertiesFromJsr223Context(

298

context: ScriptConfigurationRefinementContext

299

): ResultWithDiagnostics<ScriptCompilationConfiguration>

300

301

/**

302

* Configures provided properties from JSR-223 context for evaluation

303

* @param context Script evaluation configuration refinement context

304

* @returns Updated evaluation configuration or failure

305

*/

306

fun configureProvidedPropertiesFromJsr223Context(

307

context: ScriptEvaluationConfigurationRefinementContext

308

): ResultWithDiagnostics<ScriptEvaluationConfiguration>

309

```

310

311

**Context Integration Example:**

312

313

```kotlin

314

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

315

import javax.script.*

316

317

// Setup context with properties

318

val context = SimpleScriptContext()

319

val bindings = context.getBindings(ScriptContext.ENGINE_SCOPE)

320

bindings["database"] = DatabaseConnection("localhost:5432")

321

bindings["logger"] = LoggerFactory.getLogger("script")

322

bindings["config"] = mapOf("debug" to true, "maxRetries" to 3)

323

324

// Custom engine with automatic context property configuration

325

val contextEngine = KotlinJsr223ScriptEngineImpl(

326

factory = KotlinJsr223DefaultScriptEngineFactory(),

327

baseCompilationConfiguration = ScriptCompilationConfiguration {

328

refineConfiguration {

329

onAnnotations { context ->

330

// Automatically configure properties from JSR-223 context

331

configureProvidedPropertiesFromJsr223Context(context)

332

}

333

}

334

},

335

baseEvaluationConfiguration = ScriptEvaluationConfiguration {

336

refineConfiguration {

337

beforeEvaluation { context ->

338

// Configure evaluation properties from JSR-223 context

339

configureProvidedPropertiesFromJsr223Context(context)

340

}

341

}

342

}

343

) { scriptContext ->

344

// No special argument processing needed

345

null

346

}

347

348

contextEngine.context = context

349

350

// Script can now access context properties directly

351

val result = contextEngine.eval("""

352

// Properties from JSR-223 context are automatically available

353

logger.info("Starting script execution")

354

355

val users = database.query("SELECT * FROM users")

356

logger.info("Found ${'$'}{users.size} users")

357

358

if (config["debug"] as Boolean) {

359

println("Debug mode enabled")

360

println("Max retries: ${'$'}{config["maxRetries"]}")

361

}

362

363

users.size

364

""")

365

366

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

367

```

368

369

## Error Handling

370

371

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

372

373

### Exception Translation

374

375

```kotlin

376

// JSR-223 exceptions are automatically translated from Kotlin diagnostics

377

try {

378

val result = engine.eval("invalid kotlin syntax !!!")

379

} catch (e: ScriptException) {

380

println("Script compilation error: ${e.message}")

381

println("Line number: ${e.lineNumber}")

382

println("Column number: ${e.columnNumber}")

383

384

// Access original Kotlin diagnostics if available

385

val kotlinDiagnostics = e.cause as? ScriptDiagnosticException

386

kotlinDiagnostics?.diagnostics?.forEach { diagnostic ->

387

println("Kotlin diagnostic: ${diagnostic.severity} - ${diagnostic.message}")

388

}

389

}

390

391

// Function invocation errors

392

try {

393

val result = engine.invokeFunction("nonExistentFunction", "arg")

394

} catch (e: NoSuchMethodException) {

395

println("Function not found: ${e.message}")

396

}

397

398

// Interface implementation errors

399

try {

400

val impl = engine.getInterface(Calculator::class.java)

401

if (impl == null) {

402

println("Cannot create interface implementation - required functions not defined")

403

}

404

} catch (e: ClassCastException) {

405

println("Interface implementation error: ${e.message}")

406

}

407

```

408

409

## Advanced Features

410

411

### Thread Safety

412

413

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

414

415

```kotlin

416

import java.util.concurrent.*

417

418

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

419

420

// Thread-safe concurrent execution

421

val executor = ForkJoinPool.commonPool()

422

val futures = (1..10).map { i ->

423

executor.submit(Callable {

424

val localContext = SimpleScriptContext()

425

localContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE)

426

localContext.setAttribute("threadId", i, ScriptContext.ENGINE_SCOPE)

427

428

engine.eval("""

429

println("Executing on thread ${'$'}threadId")

430

Thread.currentThread().name + " - " + threadId

431

""", localContext)

432

})

433

}

434

435

val results = futures.map { it.get() }

436

results.forEach { println("Result: $it") }

437

```

438

439

### Performance Optimization

440

441

```kotlin

442

// Reuse compiled scripts for better performance

443

val precompiledEngine = KotlinJsr223ScriptEngineImpl(

444

// Configuration optimized for repeated execution

445

baseCompilationConfiguration = ScriptCompilationConfiguration {

446

// Enable compilation caching

447

hostConfiguration(ScriptingHostConfiguration {

448

jvm {

449

compilationCache(FileBasedScriptCache(File("jsr223-cache")))

450

}

451

})

452

}

453

)

454

455

// Execute the same script multiple times efficiently

456

val scriptCode = """

457

fun factorial(n: Int): Long = if (n <= 1) 1 else n * factorial(n - 1)

458

factorial(args[0].toInt())

459

"""

460

461

val results = (1..10).map { n ->

462

val context = SimpleScriptContext()

463

context.setAttribute("args", arrayOf(n.toString()), ScriptContext.ENGINE_SCOPE)

464

precompiledEngine.eval(scriptCode, context)

465

}

466

467

println("Factorials: $results")

468

```