diff --git a/libraries/scripting/jsr223-test/build.gradle.kts b/libraries/scripting/jsr223-test/build.gradle.kts index b893b04d026..2ec67498372 100644 --- a/libraries/scripting/jsr223-test/build.gradle.kts +++ b/libraries/scripting/jsr223-test/build.gradle.kts @@ -10,12 +10,21 @@ val embeddableTestRuntime by configurations.creating { } } +val testJsr223Runtime by configurations.creating { + extendsFrom(configurations["testRuntimeClasspath"]) +} + +val testCompilationClasspath by configurations.creating + dependencies { testApi(commonDep("junit")) testCompileOnly(project(":kotlin-scripting-jvm-host-unshaded")) testCompileOnly(project(":compiler:cli")) testCompileOnly(project(":core:util.runtime")) - + + testApi(projectTests(":compiler:test-infrastructure-utils")) + testApi(projectTests(":kotlin-scripting-compiler")) { isTransitive = false } + testRuntimeOnly(project(":kotlin-scripting-jsr223-unshaded")) testRuntimeOnly(project(":kotlin-compiler")) testRuntimeOnly(project(":kotlin-reflect")) @@ -24,6 +33,8 @@ dependencies { embeddableTestRuntime(project(":kotlin-scripting-jsr223")) embeddableTestRuntime(project(":kotlin-scripting-compiler-embeddable")) embeddableTestRuntime(testSourceSet.output) + + testCompilationClasspath(kotlinStdlib()) } sourceSets { @@ -35,7 +46,16 @@ tasks.withType> { kotlinOptions.freeCompilerArgs += "-Xallow-kotlin-package" } -projectTest(parallel = true) +projectTest(parallel = true) { + dependsOn(":dist") + workingDir = rootDir + val testRuntimeProvider = project.provider { testJsr223Runtime.asPath } + val testCompilationClasspathProvider = project.provider { testCompilationClasspath.asPath } + doFirst { + systemProperty("testJsr223RuntimeClasspath", testRuntimeProvider.get()) + systemProperty("testCompilationClasspath", testCompilationClasspathProvider.get()) + } +} projectTest(taskName = "embeddableTest", parallel = true) { workingDir = rootDir diff --git a/libraries/scripting/jsr223-test/test/kotlin/script/experimental/jsr223/test/KotlinJsr223ScriptEngineIT.kt b/libraries/scripting/jsr223-test/test/kotlin/script/experimental/jsr223/test/KotlinJsr223ScriptEngineIT.kt index 5adb72a6392..11fe6c451fe 100644 --- a/libraries/scripting/jsr223-test/test/kotlin/script/experimental/jsr223/test/KotlinJsr223ScriptEngineIT.kt +++ b/libraries/scripting/jsr223-test/test/kotlin/script/experimental/jsr223/test/KotlinJsr223ScriptEngineIT.kt @@ -6,11 +6,18 @@ package kotlin.script.experimental.jsr223.test import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.config.KotlinCompilerVersion +import org.jetbrains.kotlin.scripting.compiler.plugin.runAndCheckResults +import org.jetbrains.kotlin.test.util.KtTestUtil +import org.jetbrains.kotlin.utils.PathUtil import org.junit.Assert import org.junit.Ignore import org.junit.Test +import java.io.File import java.lang.management.ManagementFactory +import java.nio.file.Files.createTempDirectory +import java.nio.file.Files.createTempFile import javax.script.* import kotlin.script.experimental.jvmhost.jsr223.KotlinJsr223ScriptEngineImpl @@ -376,6 +383,55 @@ obj else System.setProperty(KOTLIN_JSR223_RESOLVE_FROM_CLASSLOADER_PROPERTY, prevProp) } } + + @Test + fun testInliningInJdk171() { + val jdk17 = try { + KtTestUtil.getJdk17Home() + } catch (_: NoClassDefFoundError) { + println("IGNORED: Test infrastructure doesn't work yet with embeddable compiler") + return + } + val javaExe = if (System.getProperty("os.name").contains("windows", ignoreCase = true)) "java.exe" else "java" + val runtime = File(jdk17, "bin" + File.separator + javaExe) + + val tempDir = createTempDirectory(KotlinJsr223ScriptEngineIT::class.simpleName!!) + try { + val outJar = createTempFile(tempDir, "inlining17", ".jar").toFile() + val compileCp = System.getProperty("testCompilationClasspath")!!.split(File.pathSeparator).map(::File) + Assert.assertTrue( + "Expecting \"testCompilationClasspath\" property to contain stdlib jar:\n$compileCp", + compileCp.any { it.name.startsWith("kotlin-stdlib") } + ) + val paths = PathUtil.kotlinPathsForDistDirectory + runAndCheckResults( + listOf( + runtime.absolutePath, + "-cp", paths.compilerClasspath.joinToString(File.pathSeparator), + K2JVMCompiler::class.java.name, + "-no-stdlib", + "-cp", compileCp.joinToString(File.pathSeparator) { it.path }, + "-d", outJar.absolutePath, + "-jvm-target", "17", + "libraries/scripting/jsr223-test/testData/testJsr223Inlining.kt" + ), + additionalEnvVars = listOf("JAVA_HOME" to jdk17.absolutePath) + ) + + val runtimeCp = System.getProperty("testJsr223RuntimeClasspath")!!.split(File.pathSeparator).map(::File) + outJar + Assert.assertTrue( + "Expecting \"testJsr223RuntimeClasspath\" property to contain JSR223 jar:\n$runtimeCp", + runtimeCp.any { it.name.startsWith("kotlin-scripting-jsr223") } + ) + + runAndCheckResults( + listOf(runtime.absolutePath, "-cp", runtimeCp.joinToString(File.pathSeparator) { it.path }, "TestJsr223InliningKt"), + listOf("OK") + ) + } finally { + tempDir.toFile().deleteRecursively() + } + } } fun assertThrows(exceptionClass: Class<*>, body: () -> Unit) { diff --git a/libraries/scripting/jsr223-test/testData/testJsr223Inlining.kt b/libraries/scripting/jsr223-test/testData/testJsr223Inlining.kt new file mode 100644 index 00000000000..9f5417d6821 --- /dev/null +++ b/libraries/scripting/jsr223-test/testData/testJsr223Inlining.kt @@ -0,0 +1,9 @@ + +import javax.script.* + +inline fun foo(body: () -> T): T = body() + +fun main() { + val scriptEngine = ScriptEngineManager().getEngineByExtension("kts")!! + scriptEngine.eval("println(foo { \"OK\" })") +} diff --git a/libraries/scripting/jsr223/src/kotlin/script/experimental/jsr223/KotlinJsr223DefaultScript.kt b/libraries/scripting/jsr223/src/kotlin/script/experimental/jsr223/KotlinJsr223DefaultScript.kt index 1811b1db820..09cfb12bff8 100644 --- a/libraries/scripting/jsr223/src/kotlin/script/experimental/jsr223/KotlinJsr223DefaultScript.kt +++ b/libraries/scripting/jsr223/src/kotlin/script/experimental/jsr223/KotlinJsr223DefaultScript.kt @@ -14,6 +14,8 @@ import kotlin.script.experimental.api.ScriptCompilationConfiguration import kotlin.script.experimental.api.ScriptEvaluationConfiguration import kotlin.script.experimental.api.refineConfiguration import kotlin.script.experimental.api.refineConfigurationBeforeEvaluate +import kotlin.script.experimental.jvm.jvm +import kotlin.script.experimental.jvm.jvmTarget import kotlin.script.experimental.jvmhost.jsr223.configureProvidedPropertiesFromJsr223Context import kotlin.script.experimental.jvmhost.jsr223.importAllBindings import kotlin.script.experimental.jvmhost.jsr223.jsr223 @@ -66,6 +68,11 @@ object KotlinJsr223DefaultScriptCompilationConfiguration : ScriptCompilationConf jsr223 { importAllBindings(true) } + jvm { + System.getProperty("java.specification.version")?.let { + jvmTarget(it) + } + } } ) diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt index 1c9e4fce182..bae7b93c46b 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt @@ -101,6 +101,8 @@ val JvmScriptCompilationConfigurationKeys.jdkHome getSourceProperties = { get(ScriptCompilationConfiguration.hostConfiguration) } ) +val JvmScriptCompilationConfigurationKeys.jvmTarget by PropertiesCollection.key() + @Suppress("unused") val ScriptCompilationConfigurationKeys.jvm get() = JvmScriptCompilationConfigurationBuilder() diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/compilationContext.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/compilationContext.kt index 320fee83fd0..38df7cf6147 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/compilationContext.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/compilationContext.kt @@ -48,11 +48,8 @@ import kotlin.script.experimental.api.ScriptCompilationConfiguration import kotlin.script.experimental.api.compilerOptions import kotlin.script.experimental.api.dependencies import kotlin.script.experimental.host.ScriptingHostConfiguration -import kotlin.script.experimental.jvm.JvmDependency -import kotlin.script.experimental.jvm.jdkHome -import kotlin.script.experimental.jvm.jvm +import kotlin.script.experimental.jvm.* import kotlin.script.experimental.jvm.util.KotlinJars -import kotlin.script.experimental.jvm.withUpdatedClasspath const val SCRIPT_BASE_COMPILER_ARGUMENTS_PROPERTY = "kotlin.script.base.compiler.arguments" @@ -233,8 +230,17 @@ private fun createInitialCompilerConfiguration( setupJvmSpecificArguments(baseArguments) - // Default value differs from the argument's default (see #KT-29405 and #KT-29319) - put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_8) + val definedTarget = scriptCompilationConfiguration[ScriptCompilationConfiguration.jvm.jvmTarget] + if (definedTarget != null) { + val target = JvmTarget.values().find { it.description == definedTarget } + if (target == null) { + messageCollector.report( + CompilerMessageSeverity.STRONG_WARNING, "Unknown JVM target \"$definedTarget\", using default" + ) + } else { + put(JVMConfigurationKeys.JVM_TARGET, target) + } + } val jdkHomeFromConfigurations = scriptCompilationConfiguration[ScriptCompilationConfiguration.jvm.jdkHome] // TODO: check if this is redundant and/or incorrect since the default is now taken from the host configuration anyway (the one linked to the compilation config)