Skip to content

Commit

Permalink
Add JSR-223 examples
Browse files Browse the repository at this point in the history
  • Loading branch information
ligee committed Aug 18, 2020
1 parent 345fd4f commit 74d213e
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 1 deletion.
3 changes: 2 additions & 1 deletion ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ when needed
### Script definitions with scripting hosts

- [Simple script definition](jvm/basic/jvm-simple-script/SimpleScript.md)
- [Script with Dynamic dependencies from Maven](jvm/basic/jvm-maven-deps/MavenDeps.md)
- [Script with dynamic dependencies from Maven](jvm/basic/jvm-maven-deps/MavenDeps.md)
- [Scripting Host with Kotlin Compiler Embeddable](jvm/basic/jvm-embeddable-host/EmbeddableCompiler.md)
- [Simplified main-kts-like script implementation](jvm/simple-main-kts/SimpleMainKts.md)
- [`main-kts` scripts examples](jvm/main-kts/MainKts.md)
- [using scripting via JSR 223 interface](jvm/jsr223/jsr223.md)

## External examples

Expand Down
14 changes: 14 additions & 0 deletions jvm/jsr223/jsr223-main-kts/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

plugins {
kotlin("jvm")
}

val kotlinVersion: String by rootProject.extra

dependencies {
runtimeOnly("org.jetbrains.kotlin:kotlin-main-kts:$kotlinVersion")
runtimeOnly("org.jetbrains.kotlin:kotlin-scripting-jsr223:$kotlinVersion")
testRuntimeOnly("org.jetbrains.kotlin:kotlin-main-kts:$kotlinVersion")
testRuntimeOnly("org.jetbrains.kotlin:kotlin-scripting-jsr223:$kotlinVersion")
testImplementation("junit:junit:4.12")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package org.jetbrains.kotlin.script.examples.jvm.jsr223.mainKts

import javax.script.ScriptEngineManager

fun main(vararg args: String) {
val engine = ScriptEngineManager().getEngineByExtension("main.kts")!!

print("> ")
System.`in`.reader().forEachLine {
val res = engine.eval(it)
println(res)
print("> ")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2000-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package org.jetbrains.kotlin.script.examples.jvm.jsr223.mainKts.test

import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import javax.script.ScriptEngineManager

// Adapted from kotlin-main-kts module tests in the main Kotlin repo

class MainKtsJsr223Test {

@Test
fun testBasicEval() {
val engine = ScriptEngineManager().getEngineByExtension("main.kts")!!
val res1 = engine.eval("val x = 3")
assertNull(res1)
val res2 = engine.eval("x + 2")
assertEquals(5, res2)
}

@Test
fun testWithImport() {
val engine = ScriptEngineManager().getEngineByExtension("main.kts")!!
val out = captureOut {
val res1 = engine.eval("""
@file:Import("testData/import-common.main.kts")
@file:Import("testData/import-middle.main.kts")
sharedVar = sharedVar + 1
println(sharedVar)
""".trimIndent())
assertNull(res1)
}.lines()
assertEquals(listOf("Hi from common", "Hi from middle", "5"), out)
}

@Test
fun testKotlinxHtmlExample() {
val engine = ScriptEngineManager().getEngineByExtension("main.kts")!!
val scriptFile = File("../../main-kts/scripts/kotlinx-html.main.kts")
val out = captureOut {
engine.eval(scriptFile.reader())
}.lines()
assertEquals(listOf("<html>", " <body>", " <h1>Hello, World!</h1>", " </body>", "</html>"), out)
}
}

private fun captureOut(body: () -> Unit): String {
val outStream = ByteArrayOutputStream()
val prevOut = System.out
System.setOut(PrintStream(outStream))
try {
body()
} finally {
System.out.flush()
System.setOut(prevOut)
}
return outStream.toString().trim()
}
4 changes: 4 additions & 0 deletions jvm/jsr223/jsr223-main-kts/testData/import-common.main.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

var sharedVar = 2

println("Hi from common")
6 changes: 6 additions & 0 deletions jvm/jsr223/jsr223-main-kts/testData/import-middle.main.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

@file:Import("import-common.main.kts")

sharedVar *= 2

println("Hi from middle")
12 changes: 12 additions & 0 deletions jvm/jsr223/jsr223-simple/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

plugins {
kotlin("jvm")
}

val kotlinVersion: String by rootProject.extra

dependencies {
runtimeOnly("org.jetbrains.kotlin:kotlin-scripting-jsr223:$kotlinVersion")
testRuntimeOnly("org.jetbrains.kotlin:kotlin-scripting-jsr223:$kotlinVersion")
testImplementation("junit:junit:4.12")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package org.jetbrains.kotlin.script.examples.jvm.jsr223.simple

import javax.script.ScriptEngineManager

fun main(vararg args: String) {
val engine = ScriptEngineManager().getEngineByExtension("kts")!!

print("> ")
System.`in`.reader().forEachLine {
val res = engine.eval(it)
println(res)
print("> ")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright 2000-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package org.jetbrains.kotlin.script.examples.jvm.jsr223.simple.test

import org.junit.Assert.*
import org.junit.Test
import javax.script.Compilable
import javax.script.Invocable
import javax.script.ScriptEngineManager
import javax.script.ScriptException

// Adapted from kotlin-scripting-jsr223 module tests in the main Kotlin repo

class SimpleJsr223Test {

@Test
fun testBasicEval() {
val engine = ScriptEngineManager().getEngineByExtension("kts")!!
val res1 = engine.eval("val x = 3")
assertNull(res1)
val res2 = engine.eval("x + 2")
assertEquals(5, res2)
}

@Test
fun testEvalWithBindings() {
val engine = ScriptEngineManager().getEngineByExtension("kts")!!

engine.put("z", 33)

engine.eval("val x = 10 + z")

val result = engine.eval("x + 20")
assertEquals(63, result)

val result2 = engine.eval("11 + boundValue", engine.createBindings().apply {
put("boundValue", 100)
})
assertEquals(111, result2)
}

@Test
fun testEvalWithErrorsAndExceptions() {
val engine = ScriptEngineManager().getEngineByExtension("kts")!!

try {
engine.eval("java.lang.fish")
fail("Script error expected")
} catch (e: ScriptException) {}

val res1 = engine.eval("val x = 3")
assertNull(res1)

try {
engine.eval("throw Exception(\"!!\")")
fail("Expecting exception to propagate")
} catch (e: ScriptException) {
assertEquals("!!", e.cause?.message)
}

try {
engine.eval("y")
fail("Script error expected")
} catch (e: ScriptException) {}

val res3 = engine.eval("x + 2")
assertEquals(5, res3)
}

@Test
fun testInvocable() {
val engine = ScriptEngineManager().getEngineByExtension("kts")!!
val res1 = engine.eval("""
fun fn(x: Int) = x + 2
val obj = object {
fun fn1(x: Int) = x + 3
}
obj""".trimIndent())
assertNotNull(res1)

val invocator = engine as? Invocable
assertNotNull(invocator)

try {
invocator!!.invokeFunction("fn1", 3)
fail("NoSuchMethodException expected")
} catch (e: NoSuchMethodException) {}

val res2 = invocator!!.invokeFunction("fn", 3)
assertEquals(5, res2)

val res3 = invocator.invokeMethod(res1, "fn1", 3)
assertEquals(6, res3)
}

@Test
fun testCompilable() {
val engine = ScriptEngineManager().getEngineByExtension("kts") as Compilable
val comp1 = engine.compile("val x = 3")
val comp2 = engine.compile("x + 2")
val res1 = comp1.eval()
assertNull(res1)
val res2 = comp2.eval()
assertEquals(5, res2)
}

@Test
fun testResolveSymbolsFromContext() {
val scriptEngine = ScriptEngineManager().getEngineByExtension("kts")!!
val result = scriptEngine.eval("${this::class.java.name}.shouldBeVisibleFromRepl * 6")
assertEquals(42, result)
}

companion object {
@Suppress("unused") // accessed from the tests below
@JvmStatic
val shouldBeVisibleFromRepl = 7
}
}
14 changes: 14 additions & 0 deletions jvm/jsr223/jsr223.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# Kotlin Scripting Examples: using Kotlin scripting via JSR 223 API

[JSR 223](https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/) is a common JVM scripting API specification.
The implementations of this API are available for Kotlin too. These examples demonstrate usage of the default
implementation (`kotlin-scripting-jsr223`) and the one based on the `kotlin-main-kts`.

The examples(
[simple](jsr223-simple/src/main/kotlin/org/jetbrains/kotlin/script/examples/jvm/jsr223/simple/repl.kt),
[main-kts](jsr223-main-kts/src/main/kotlin/org/jetbrains/kotlin/script/examples/jvm/jsr223/mainKts/repl.kt))
are very bare-bone REPL implementations, while tests(
([simple](jsr223-simple/src/test/kotlin/org/jetbrains/kotlin/script/examples/jvm/jsr223/simple/test/simpleJsr223Test.kt),
[main-kts](jsr223-main-kts/src/test/kotlin/org/jetbrains/kotlin/script/examples/jvm/jsr223/mainKts/test/mainKtsJsr223Test.kt))
demonstrate various features of the implementations.
3 changes: 3 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ include("jvm:basic:jvm-maven-deps:host")

include("jvm:basic:jvm-embeddable-host")

include("jvm:jsr223:jsr223-simple")
include("jvm:jsr223:jsr223-main-kts")

include("jvm:simple-main-kts:simple-main-kts")
include("jvm:simple-main-kts:simple-main-kts-test")

0 comments on commit 74d213e

Please sign in to comment.