Simplify and fix classloaders handling on script evaluation
#KT-37558 fixed
This commit is contained in:
+75
-36
@@ -19,6 +19,7 @@ import kotlin.script.experimental.host.with
|
|||||||
import kotlin.script.experimental.jvm.*
|
import kotlin.script.experimental.jvm.*
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.util.KotlinJars
|
import kotlin.script.experimental.jvm.util.KotlinJars
|
||||||
|
import kotlin.script.experimental.jvm.util.classpathFromClass
|
||||||
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
|
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
|
||||||
import kotlin.script.experimental.jvmhost.CompiledScriptJarsCache
|
import kotlin.script.experimental.jvmhost.CompiledScriptJarsCache
|
||||||
import kotlin.script.experimental.jvmhost.JvmScriptCompiler
|
import kotlin.script.experimental.jvmhost.JvmScriptCompiler
|
||||||
@@ -40,7 +41,10 @@ class CachingTest : TestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun testSimpleImportWithMemoryCache() {
|
fun testSimpleImportWithMemoryCache() {
|
||||||
val cache = SimpleMemoryScriptsCache()
|
val cache = SimpleMemoryScriptsCache()
|
||||||
checkWithCache(cache, scriptWithImport, scriptWithImportExpectedOutput) { makeSimpleConfigurationWithTestImport() }
|
checkWithCache(
|
||||||
|
cache, scriptWithImport, scriptWithImportExpectedOutput,
|
||||||
|
compilationConfiguration = { makeSimpleConfigurationWithTestImport() }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -60,7 +64,10 @@ class CachingTest : TestCase() {
|
|||||||
val cache = FileBasedScriptCache(cacheDir)
|
val cache = FileBasedScriptCache(cacheDir)
|
||||||
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
||||||
|
|
||||||
checkWithCache(cache, scriptWithImport, scriptWithImportExpectedOutput) { makeSimpleConfigurationWithTestImport() }
|
checkWithCache(
|
||||||
|
cache, scriptWithImport, scriptWithImportExpectedOutput,
|
||||||
|
compilationConfiguration = { makeSimpleConfigurationWithTestImport() }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +91,10 @@ class CachingTest : TestCase() {
|
|||||||
val cache = TestCompiledScriptJarsCache(cacheDir)
|
val cache = TestCompiledScriptJarsCache(cacheDir)
|
||||||
Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty())
|
Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty())
|
||||||
|
|
||||||
checkWithCache(cache, scriptWithImport, scriptWithImportExpectedOutput) { makeSimpleConfigurationWithTestImport() }
|
checkWithCache(
|
||||||
|
cache, scriptWithImport, scriptWithImportExpectedOutput,
|
||||||
|
compilationConfiguration = { makeSimpleConfigurationWithTestImport() }
|
||||||
|
)
|
||||||
|
|
||||||
// cannot make it work in this form - it requires a dependency on the current test classes, but classes directory seems
|
// cannot make it work in this form - it requires a dependency on the current test classes, but classes directory seems
|
||||||
// not work when specified in the manifest
|
// not work when specified in the manifest
|
||||||
@@ -95,31 +105,54 @@ class CachingTest : TestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testImplicitReceiversWithJarCache() {
|
||||||
|
withTempDir("scriptingTestJarCache") { cacheDir ->
|
||||||
|
val cache = TestCompiledScriptJarsCache(cacheDir)
|
||||||
|
Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty())
|
||||||
|
|
||||||
|
checkWithCache(
|
||||||
|
cache, simpleScript, simpleScriptExpectedOutput, checkDirectEval = false,
|
||||||
|
compilationConfiguration = {
|
||||||
|
updateClasspath(classpathFromClass<ScriptingHostTest>()) // the class defined here should be in the classpath
|
||||||
|
implicitReceivers(Implicit::class)
|
||||||
|
},
|
||||||
|
evaluationConfiguration = {
|
||||||
|
implicitReceivers(Implicit)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkWithCache(
|
private fun checkWithCache(
|
||||||
cache: ScriptingCacheWithCounters, script: String, expectedOutput: List<String>,
|
cache: ScriptingCacheWithCounters, script: String, expectedOutput: List<String>, checkDirectEval: Boolean = true,
|
||||||
configurationBuilder: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
compilationConfiguration: ScriptCompilationConfiguration.Builder.() -> Unit = {},
|
||||||
|
evaluationConfiguration: ScriptEvaluationConfiguration.Builder.() -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val hostConfiguration = defaultJvmScriptingHostConfiguration.with {
|
val myHostConfiguration = defaultJvmScriptingHostConfiguration.with {
|
||||||
jvm {
|
jvm {
|
||||||
baseClassLoader.replaceOnlyDefault(null)
|
baseClassLoader.replaceOnlyDefault(null)
|
||||||
compilationCache(cache)
|
compilationCache(cache)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val compiler = JvmScriptCompiler(hostConfiguration)
|
val compiler = JvmScriptCompiler(myHostConfiguration)
|
||||||
val evaluator = BasicJvmScriptEvaluator()
|
val evaluator = BasicJvmScriptEvaluator()
|
||||||
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
||||||
|
|
||||||
val scriptCompilationConfiguration = ScriptCompilationConfiguration(body = configurationBuilder).with {
|
val scriptCompilationConfiguration = ScriptCompilationConfiguration(body = compilationConfiguration).with {
|
||||||
updateClasspath(KotlinJars.kotlinScriptStandardJarsWithReflect)
|
updateClasspath(KotlinJars.kotlinScriptStandardJarsWithReflect)
|
||||||
|
hostConfiguration.update { myHostConfiguration }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val scriptEvaluationConfiguration = ScriptEvaluationConfiguration(body = evaluationConfiguration)
|
||||||
|
|
||||||
Assert.assertEquals(0, cache.storedScripts)
|
Assert.assertEquals(0, cache.storedScripts)
|
||||||
var compiledScript: CompiledScript<*>? = null
|
var compiledScript: CompiledScript? = null
|
||||||
val output = captureOut {
|
val output = captureOut {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
compiler(script.toScriptSource(), scriptCompilationConfiguration).onSuccess {
|
compiler(script.toScriptSource(), scriptCompilationConfiguration).onSuccess {
|
||||||
compiledScript = it
|
compiledScript = it
|
||||||
evaluator(it)
|
evaluator(it, scriptEvaluationConfiguration)
|
||||||
}.throwOnFailure()
|
}.throwOnFailure()
|
||||||
}
|
}
|
||||||
}.lines()
|
}.lines()
|
||||||
@@ -127,34 +160,40 @@ class CachingTest : TestCase() {
|
|||||||
Assert.assertEquals(1, cache.storedScripts)
|
Assert.assertEquals(1, cache.storedScripts)
|
||||||
Assert.assertEquals(0, cache.retrievedScripts)
|
Assert.assertEquals(0, cache.retrievedScripts)
|
||||||
|
|
||||||
val cachedScript = cache.get(script.toScriptSource(), scriptCompilationConfiguration)
|
if (checkDirectEval) {
|
||||||
Assert.assertNotNull(cachedScript)
|
val cachedScript = cache.get(script.toScriptSource(), scriptCompilationConfiguration)
|
||||||
Assert.assertEquals(1, cache.retrievedScripts)
|
Assert.assertNotNull(cachedScript)
|
||||||
|
Assert.assertEquals(1, cache.retrievedScripts)
|
||||||
|
|
||||||
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
||||||
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
||||||
|
|
||||||
val compiledScriptClass = compiledScriptClassRes.valueOrThrow()
|
val compiledScriptClass = compiledScriptClassRes.valueOrThrow()
|
||||||
val cachedScriptClass = cachedScriptClassRes.valueOrThrow()
|
val cachedScriptClass = cachedScriptClassRes.valueOrThrow()
|
||||||
|
|
||||||
Assert.assertEquals(compiledScriptClass.qualifiedName, cachedScriptClass.qualifiedName)
|
Assert.assertEquals(compiledScriptClass.qualifiedName, cachedScriptClass.qualifiedName)
|
||||||
Assert.assertEquals(compiledScriptClass.supertypes, cachedScriptClass.supertypes)
|
Assert.assertEquals(compiledScriptClass.supertypes, cachedScriptClass.supertypes)
|
||||||
|
|
||||||
val output2 = captureOut {
|
val output2 = captureOut {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
evaluator(cachedScript!!).throwOnFailure()
|
evaluator(cachedScript!!, scriptEvaluationConfiguration).throwOnFailure()
|
||||||
}
|
}
|
||||||
}.lines()
|
}.lines()
|
||||||
Assert.assertEquals(output, output2)
|
Assert.assertEquals(output, output2)
|
||||||
|
}
|
||||||
|
|
||||||
val output3 = captureOut {
|
val output3 = captureOut {
|
||||||
host.eval(script.toScriptSource(), scriptCompilationConfiguration, null).throwOnFailure()
|
host.eval(script.toScriptSource(), scriptCompilationConfiguration, scriptEvaluationConfiguration).throwOnFailure()
|
||||||
}.lines()
|
}.lines()
|
||||||
Assert.assertEquals(2, cache.retrievedScripts)
|
Assert.assertEquals(if (checkDirectEval) 2 else 1, cache.retrievedScripts)
|
||||||
Assert.assertEquals(output, output3)
|
Assert.assertEquals(output, output3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Implicit {
|
||||||
|
val ix = 0
|
||||||
|
}
|
||||||
|
|
||||||
private interface ScriptingCacheWithCounters : CompiledJvmScriptsCache {
|
private interface ScriptingCacheWithCounters : CompiledJvmScriptsCache {
|
||||||
|
|
||||||
val storedScripts: Int
|
val storedScripts: Int
|
||||||
@@ -163,7 +202,7 @@ private interface ScriptingCacheWithCounters : CompiledJvmScriptsCache {
|
|||||||
|
|
||||||
private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
||||||
|
|
||||||
internal val data = hashMapOf<Pair<SourceCode, Map<*, *>>, CompiledScript<*>>()
|
internal val data = hashMapOf<Pair<SourceCode, Map<*, *>>, CompiledScript>()
|
||||||
|
|
||||||
private var _storedScripts = 0
|
private var _storedScripts = 0
|
||||||
private var _retrievedScripts = 0
|
private var _retrievedScripts = 0
|
||||||
@@ -174,11 +213,11 @@ private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
|||||||
override val retrievedScripts: Int
|
override val retrievedScripts: Int
|
||||||
get() = _retrievedScripts
|
get() = _retrievedScripts
|
||||||
|
|
||||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? =
|
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript? =
|
||||||
data[script to scriptCompilationConfiguration.notTransientData]?.also { _retrievedScripts++ }
|
data[script to scriptCompilationConfiguration.notTransientData]?.also { _retrievedScripts++ }
|
||||||
|
|
||||||
override fun store(
|
override fun store(
|
||||||
compiledScript: CompiledScript<*>,
|
compiledScript: CompiledScript,
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
) {
|
) {
|
||||||
@@ -189,13 +228,13 @@ private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
|||||||
|
|
||||||
private class FileBasedScriptCache(val baseDir: File) : ScriptingCacheWithCounters {
|
private class FileBasedScriptCache(val baseDir: File) : ScriptingCacheWithCounters {
|
||||||
|
|
||||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? {
|
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript? {
|
||||||
val file = File(baseDir, uniqueScriptHash(script, scriptCompilationConfiguration))
|
val file = File(baseDir, uniqueScriptHash(script, scriptCompilationConfiguration))
|
||||||
return if (!file.exists()) null else file.readCompiledScript(scriptCompilationConfiguration)?.also { retrievedScripts++ }
|
return if (!file.exists()) null else file.readCompiledScript(scriptCompilationConfiguration)?.also { retrievedScripts++ }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun store(
|
override fun store(
|
||||||
compiledScript: CompiledScript<*>,
|
compiledScript: CompiledScript,
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
) {
|
) {
|
||||||
@@ -220,11 +259,11 @@ class TestCompiledScriptJarsCache(val baseDir: File) : CompiledScriptJarsCache(
|
|||||||
File(baseDir, uniqueScriptHash(script, scriptCompilationConfiguration) + ".jar")
|
File(baseDir, uniqueScriptHash(script, scriptCompilationConfiguration) + ".jar")
|
||||||
}), ScriptingCacheWithCounters
|
}), ScriptingCacheWithCounters
|
||||||
{
|
{
|
||||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? =
|
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript? =
|
||||||
super.get(script, scriptCompilationConfiguration)?.also { retrievedScripts++ }
|
super.get(script, scriptCompilationConfiguration)?.also { retrievedScripts++ }
|
||||||
|
|
||||||
override fun store(
|
override fun store(
|
||||||
compiledScript: CompiledScript<*>,
|
compiledScript: CompiledScript,
|
||||||
script: SourceCode,
|
script: SourceCode,
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
) {
|
) {
|
||||||
@@ -250,10 +289,10 @@ internal fun uniqueScriptHash(script: SourceCode, scriptCompilationConfiguration
|
|||||||
return digestWrapper.digest().toHexString()
|
return digestWrapper.digest().toHexString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun File.readCompiledScript(scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*> {
|
private fun File.readCompiledScript(scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript {
|
||||||
return inputStream().use { fs ->
|
return inputStream().use { fs ->
|
||||||
ObjectInputStream(fs).use {
|
ObjectInputStream(fs).use {
|
||||||
it.readObject() as KJvmCompiledScript<*>
|
it.readObject() as KJvmCompiledScript
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-12
@@ -8,11 +8,8 @@ package kotlin.script.experimental.jvmhost
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.util.jar.JarInputStream
|
import java.util.jar.JarInputStream
|
||||||
import kotlin.script.experimental.api.CompiledScript
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.api.SourceCode
|
|
||||||
import kotlin.script.experimental.api.hostConfiguration
|
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
|
||||||
import kotlin.script.experimental.jvm.CompiledJvmScriptsCache
|
import kotlin.script.experimental.jvm.CompiledJvmScriptsCache
|
||||||
import kotlin.script.experimental.jvm.baseClassLoader
|
import kotlin.script.experimental.jvm.baseClassLoader
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
@@ -33,12 +30,7 @@ open class CompiledScriptJarsCache(val scriptToFile: (SourceCode, ScriptCompilat
|
|||||||
it.manifest.mainAttributes.getValue("Main-Class")
|
it.manifest.mainAttributes.getValue("Main-Class")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val classLoader = URLClassLoader(
|
return KJvmCompiledScriptLazilyLoadedFromClasspath(className, listOf(file))
|
||||||
arrayOf(file.toURI().toURL()),
|
|
||||||
scriptCompilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]?.get(ScriptingHostConfiguration.jvm.baseClassLoader)
|
|
||||||
)
|
|
||||||
|
|
||||||
return createScriptFromClassLoader(className, classLoader)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun store(
|
override fun store(
|
||||||
@@ -54,4 +46,40 @@ open class CompiledScriptJarsCache(val scriptToFile: (SourceCode, ScriptCompilat
|
|||||||
|
|
||||||
jvmScript.saveToJar(file)
|
jvmScript.saveToJar(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class KJvmCompiledScriptLazilyLoadedFromClasspath(
|
||||||
|
private val scriptClassFQName: String,
|
||||||
|
private val classPath: List<File>
|
||||||
|
) : CompiledScript {
|
||||||
|
|
||||||
|
private var loadedScript: KJvmCompiledScript? = null
|
||||||
|
|
||||||
|
fun getScriptOrError(): KJvmCompiledScript = loadedScript ?: throw RuntimeException("Compiled script is not loaded yet")
|
||||||
|
|
||||||
|
override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>> {
|
||||||
|
if (loadedScript == null) {
|
||||||
|
val actualEvaluationConfiguration = scriptEvaluationConfiguration ?: ScriptEvaluationConfiguration()
|
||||||
|
val baseClassLoader = actualEvaluationConfiguration[ScriptEvaluationConfiguration.jvm.baseClassLoader]
|
||||||
|
val classLoader = URLClassLoader(
|
||||||
|
classPath.map { it.toURI().toURL() }.toTypedArray(),
|
||||||
|
baseClassLoader
|
||||||
|
)
|
||||||
|
loadedScript = createScriptFromClassLoader(scriptClassFQName, classLoader)
|
||||||
|
}
|
||||||
|
return getScriptOrError().getClass(scriptEvaluationConfiguration)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
get() = getScriptOrError().compilationConfiguration
|
||||||
|
|
||||||
|
override val sourceLocationId: String?
|
||||||
|
get() = getScriptOrError().sourceLocationId
|
||||||
|
|
||||||
|
override val otherScripts: List<CompiledScript>
|
||||||
|
get() = getScriptOrError().otherScripts
|
||||||
|
|
||||||
|
override val resultField: Pair<String, KotlinType>?
|
||||||
|
get() = getScriptOrError().resultField
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import java.util.jar.Manifest
|
|||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.jvm.JvmDependency
|
import kotlin.script.experimental.jvm.JvmDependency
|
||||||
import kotlin.script.experimental.jvm.impl.*
|
import kotlin.script.experimental.jvm.impl.*
|
||||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext
|
|
||||||
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrNull
|
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrNull
|
||||||
|
|
||||||
// TODO: generate execution code (main)
|
// TODO: generate execution code (main)
|
||||||
|
|||||||
+20
-9
@@ -8,7 +8,6 @@ package kotlin.script.experimental.jvm
|
|||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.jvm.impl.getConfigurationWithClassloader
|
|
||||||
|
|
||||||
open class BasicJvmScriptEvaluator : ScriptEvaluator {
|
open class BasicJvmScriptEvaluator : ScriptEvaluator {
|
||||||
|
|
||||||
@@ -16,26 +15,28 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
|
|||||||
compiledScript: CompiledScript,
|
compiledScript: CompiledScript,
|
||||||
scriptEvaluationConfiguration: ScriptEvaluationConfiguration
|
scriptEvaluationConfiguration: ScriptEvaluationConfiguration
|
||||||
): ResultWithDiagnostics<EvaluationResult> = try {
|
): ResultWithDiagnostics<EvaluationResult> = try {
|
||||||
val configuration = getConfigurationWithClassloader(compiledScript, scriptEvaluationConfiguration)
|
compiledScript.getClass(scriptEvaluationConfiguration).onSuccess { scriptClass ->
|
||||||
|
|
||||||
compiledScript.getClass(configuration).onSuccess { scriptClass ->
|
// configuration shared between all module scripts
|
||||||
// in the future, when (if) we'll stop to compile everything into constructor
|
val sharedConfiguration = scriptEvaluationConfiguration.getOrPrepareShared(scriptClass.java.classLoader)
|
||||||
// run as SAM
|
|
||||||
// return res
|
|
||||||
|
|
||||||
val sharedScripts = configuration[ScriptEvaluationConfiguration.jvm.scriptsInstancesSharingMap]
|
val sharedScripts = sharedConfiguration[ScriptEvaluationConfiguration.jvm.scriptsInstancesSharingMap]
|
||||||
|
|
||||||
sharedScripts?.get(scriptClass)?.asSuccess()
|
sharedScripts?.get(scriptClass)?.asSuccess()
|
||||||
?: compiledScript.otherScripts.mapSuccess {
|
?: compiledScript.otherScripts.mapSuccess {
|
||||||
invoke(it, configuration)
|
invoke(it, sharedConfiguration)
|
||||||
}.onSuccess { importedScriptsEvalResults ->
|
}.onSuccess { importedScriptsEvalResults ->
|
||||||
|
|
||||||
val refinedEvalConfiguration =
|
val refinedEvalConfiguration =
|
||||||
configuration.refineBeforeEvaluation(compiledScript).valueOr {
|
sharedConfiguration.refineBeforeEvaluation(compiledScript).valueOr {
|
||||||
return@invoke ResultWithDiagnostics.Failure(it.reports)
|
return@invoke ResultWithDiagnostics.Failure(it.reports)
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultValue = try {
|
val resultValue = try {
|
||||||
|
// in the future, when (if) we'll stop to compile everything into constructor
|
||||||
|
// run as SAM
|
||||||
|
// return res
|
||||||
|
|
||||||
val instance =
|
val instance =
|
||||||
scriptClass.evalWithConfigAndOtherScriptsResults(refinedEvalConfiguration, importedScriptsEvalResults)
|
scriptClass.evalWithConfigAndOtherScriptsResults(refinedEvalConfiguration, importedScriptsEvalResults)
|
||||||
|
|
||||||
@@ -99,3 +100,13 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ScriptEvaluationConfiguration.getOrPrepareShared(classLoader: ClassLoader): ScriptEvaluationConfiguration =
|
||||||
|
if (this[ScriptEvaluationConfiguration.jvm.actualClassLoader] != null)
|
||||||
|
this
|
||||||
|
else
|
||||||
|
with {
|
||||||
|
ScriptEvaluationConfiguration.jvm.actualClassLoader(classLoader)
|
||||||
|
if (this[ScriptEvaluationConfiguration.scriptsInstancesSharing] == true) {
|
||||||
|
ScriptEvaluationConfiguration.jvm.scriptsInstancesSharingMap(mutableMapOf())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import java.net.URLClassLoader
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.jvm.*
|
import kotlin.script.experimental.jvm.*
|
||||||
import kotlin.script.experimental.jvm.actualClassLoader
|
|
||||||
|
|
||||||
internal class KJvmCompiledScriptData(
|
internal class KJvmCompiledScriptData(
|
||||||
var sourceLocationId: String?,
|
var sourceLocationId: String?,
|
||||||
@@ -122,25 +121,6 @@ fun KJvmCompiledScript.getOrCreateActualClassloader(evaluationConfiguration: Scr
|
|||||||
return module.createClassLoader(classLoaderWithDeps)
|
return module.createClassLoader(classLoaderWithDeps)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getConfigurationWithClassloader(
|
|
||||||
script: CompiledScript, baseConfiguration: ScriptEvaluationConfiguration
|
|
||||||
): ScriptEvaluationConfiguration =
|
|
||||||
if (baseConfiguration.containsKey(ScriptEvaluationConfiguration.jvm.actualClassLoader))
|
|
||||||
baseConfiguration
|
|
||||||
else {
|
|
||||||
val jvmScript = (script as? KJvmCompiledScript)
|
|
||||||
?: throw IllegalArgumentException("Unexpected compiled script type: $script")
|
|
||||||
|
|
||||||
val classloader = jvmScript.getOrCreateActualClassloader(baseConfiguration)
|
|
||||||
|
|
||||||
ScriptEvaluationConfiguration(baseConfiguration) {
|
|
||||||
ScriptEvaluationConfiguration.jvm.actualClassLoader(classloader)
|
|
||||||
if (baseConfiguration[ScriptEvaluationConfiguration.scriptsInstancesSharing] == true) {
|
|
||||||
ScriptEvaluationConfiguration.jvm.scriptsInstancesSharingMap(mutableMapOf())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun CompiledScript.makeClassLoaderFromDependencies(baseClassLoader: ClassLoader?): ClassLoader? {
|
private fun CompiledScript.makeClassLoaderFromDependencies(baseClassLoader: ClassLoader?): ClassLoader? {
|
||||||
val processedScripts = mutableSetOf<CompiledScript>()
|
val processedScripts = mutableSetOf<CompiledScript>()
|
||||||
fun recursiveScriptsSeq(res: Sequence<CompiledScript>, script: CompiledScript): Sequence<CompiledScript> =
|
fun recursiveScriptsSeq(res: Sequence<CompiledScript>, script: CompiledScript): Sequence<CompiledScript> =
|
||||||
|
|||||||
Reference in New Issue
Block a user