From a6f0bd66771ed73b076b12dcd0d09cf0c513ca9b Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 4 Apr 2019 17:41:59 +0200 Subject: [PATCH] Refactor jvm evaluation to make module operations cleaner and more robust in addition: - hide internal configuration keys - add keys for flags controlling evaluation - add initial module implementation for using scripts from a classpath --- .../experimental/api/scriptEvaluation.kt | 11 +- .../jvmhost/impl/KJvmCompiledModule.kt | 37 +++++ .../jvmhost/impl/KJvmCompiledScript.kt | 50 +------ .../jvmhost/impl/KJvmCompilerImpl.kt | 13 +- .../jvmhost/jvmScriptEvaluation.kt | 128 +++++++++++++----- .../experimental/jvmhost/jvmScriptSaving.kt | 15 +- .../jvmhost/test/ScriptingHostTest.kt | 13 +- 7 files changed, 170 insertions(+), 97 deletions(-) create mode 100644 libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledModule.kt diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt index 9810b59ff4e..490e3514ef7 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt @@ -50,12 +50,15 @@ val ScriptEvaluationConfigurationKeys.providedProperties by PropertiesCollection */ val ScriptEvaluationConfigurationKeys.constructorArgs by PropertiesCollection.key>() +@Deprecated("use scriptsInstancesSharing flag instead", level = DeprecationLevel.ERROR) +val ScriptEvaluationConfigurationKeys.scriptsInstancesSharingMap by PropertiesCollection.key, EvaluationResult>>() + /** - * A map that is used to store evaluated script instances; if provided - the evaluator will try to get imported script from the map and - * only create/evaluate instances if not found, and evaluator will put newly created instances into the map + * If enabled - the evaluator will try to get imported script from a shared container + * only create/evaluate instances if not found, and evaluator will put newly created instances into the container * This allows to have a single instance of the script if it is imported several times via different import paths. */ -val ScriptEvaluationConfigurationKeys.scriptsInstancesSharingMap by PropertiesCollection.key, EvaluationResult>>() +val ScriptEvaluationConfigurationKeys.scriptsInstancesSharing by PropertiesCollection.key(false) /** * The callback that will be called on the script compilation immediately before starting the compilation @@ -67,7 +70,7 @@ val ScriptEvaluationConfigurationKeys.refineConfigurationBeforeEvaluate by Prope */ fun ScriptEvaluationConfiguration.Builder.enableScriptsInstancesSharing() { this { - scriptsInstancesSharingMap(HashMap()) + scriptsInstancesSharing(true) } } diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledModule.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledModule.kt new file mode 100644 index 00000000000..df64f8813e5 --- /dev/null +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledModule.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package kotlin.script.experimental.jvmhost.impl + +import java.io.File +import java.io.Serializable +import java.net.URLClassLoader + +interface KJvmCompiledModule { + fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader +} + +class KJvmCompiledModuleInMemory(val compilerOutputFiles: Map) : KJvmCompiledModule, Serializable { + + override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader = + CompiledScriptClassLoader(baseClassLoader, compilerOutputFiles) + + companion object { + @JvmStatic + private val serialVersionUID = 0L + } +} + +class KJvmCompiledModuleFromClassPath(val classpath: Collection) : KJvmCompiledModule { + + override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader = + URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), baseClassLoader) +} + +class KJvmCompiledModuleFromLoadedClasses : KJvmCompiledModule { + + override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader = + baseClassLoader ?: KJvmCompiledModuleFromLoadedClasses::class.java.classLoader +} diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledScript.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledScript.kt index cb37bd4ae61..469cd639e6c 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledScript.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompiledScript.kt @@ -5,35 +5,19 @@ package kotlin.script.experimental.jvmhost.impl -import org.jetbrains.kotlin.codegen.state.GenerationState import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io.Serializable -import java.net.URLClassLoader import kotlin.reflect.KClass import kotlin.script.experimental.api.* -import kotlin.script.experimental.jvm.JvmDependency -import kotlin.script.experimental.jvmhost.* - -class KJvmCompiledModule( - generationState: GenerationState -) : Serializable { - val compilerOutputFiles: Map = - generationState.factory.asList() - .associateTo(sortedMapOf()) { it.relativePath to it.asByteArray() } - - companion object { - @JvmStatic - private val serialVersionUID = 0L - } -} +import kotlin.script.experimental.jvmhost.getOrCreateActualClassloader class KJvmCompiledScript( sourceLocationId: String?, compilationConfiguration: ScriptCompilationConfiguration, private var scriptClassFQName: String, otherScripts: List> = emptyList(), - internal var compiledModule: KJvmCompiledModule? = null + internal var compiledModule: KJvmCompiledModule ) : CompiledScript, Serializable { private var _sourceLocationId: String? = sourceLocationId @@ -54,21 +38,7 @@ class KJvmCompiledScript( override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics> = try { // ensuring proper defaults are used val actualEvaluationConfiguration = scriptEvaluationConfiguration ?: ScriptEvaluationConfiguration() - val classLoader = actualEvaluationConfiguration[ScriptEvaluationConfiguration.jvm.actualClassLoader] - ?: run { - if (compiledModule == null) - return ResultWithDiagnostics.Failure( - "Unable to load class $scriptClassFQName: no compiled module is provided".asErrorDiagnostics(path = sourceLocationId) - ) - val baseClassLoader = actualEvaluationConfiguration[ScriptEvaluationConfiguration.jvm.baseClassLoader] - val dependencies = compilationConfiguration[ScriptCompilationConfiguration.dependencies] - ?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() } - // TODO: previous dependencies and classloaders should be taken into account here - val classLoaderWithDeps = - if (dependencies == null) baseClassLoader - else URLClassLoader(dependencies.toTypedArray(), baseClassLoader) - CompiledScriptClassLoader(classLoaderWithDeps, compiledModule!!.compilerOutputFiles) - } + val classLoader = getOrCreateActualClassloader(actualEvaluationConfiguration) val clazz = classLoader.loadClass(scriptClassFQName).kotlin clazz.asSuccess() @@ -82,14 +52,8 @@ class KJvmCompiledScript( ) } - // This method is exposed because the compilation configuration is not generally serializable (yet), but since it is supposed to - // be deserialized only from the cache, the configuration could be assigned from the cache.load method - fun setCompilationConfiguration(configuration: ScriptCompilationConfiguration) { - if (_compilationConfiguration != null) throw IllegalStateException("This method is applicable only in deserialization context") - _compilationConfiguration = configuration - } - private fun writeObject(outputStream: ObjectOutputStream) { + outputStream.writeObject(compilationConfiguration) outputStream.writeObject(sourceLocationId) outputStream.writeObject(otherScripts) outputStream.writeObject(compiledModule) @@ -98,15 +62,15 @@ class KJvmCompiledScript( @Suppress("UNCHECKED_CAST") private fun readObject(inputStream: ObjectInputStream) { - _compilationConfiguration = null + _compilationConfiguration = inputStream.readObject() as ScriptCompilationConfiguration _sourceLocationId = inputStream.readObject() as String? _otherScripts = inputStream.readObject() as List> - compiledModule = inputStream.readObject() as KJvmCompiledModule? + compiledModule = inputStream.readObject() as KJvmCompiledModuleInMemory scriptClassFQName = inputStream.readObject() as String } companion object { @JvmStatic - private val serialVersionUID = 1L + private val serialVersionUID = 2L } } \ No newline at end of file diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompilerImpl.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompilerImpl.kt index 2b769ccee70..051a3fb703f 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompilerImpl.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/impl/KJvmCompilerImpl.kt @@ -351,6 +351,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm sourceDependencies: List, getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration ): KJvmCompiledScript { + val module = makeCompiledModule(generationState) val scriptDependenciesStack = ArrayDeque() fun makeOtherScripts(script: KtScript): List> { @@ -368,7 +369,8 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm containingKtFile.virtualFile?.path, getScriptConfiguration(sourceFile), it.fqName.asString(), - makeOtherScripts(it) + makeOtherScripts(it), + module ) } } ?: emptyList() @@ -382,7 +384,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm getScriptConfiguration(ktScript.containingKtFile), ktScript.fqName.asString(), makeOtherScripts(ktScript), - KJvmCompiledModule(generationState) + module ) } @@ -566,4 +568,9 @@ internal class ScriptLightVirtualFile(name: String, private val _path: String?, override fun getPath(): String = _path ?: super.getPath() override fun getCanonicalPath(): String? = path -} \ No newline at end of file +} + +private fun makeCompiledModule(generationState: GenerationState) = KJvmCompiledModuleInMemory( + generationState.factory.asList() + .associateTo(sortedMapOf()) { it.relativePath to it.asByteArray() } +) diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt index ce31d7cdb68..76802cce22d 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt @@ -7,8 +7,11 @@ package kotlin.script.experimental.jvmhost +import java.net.URLClassLoader import kotlin.reflect.KClass import kotlin.script.experimental.api.* +import kotlin.script.experimental.jvm.JvmDependency +import kotlin.script.experimental.jvmhost.impl.KJvmCompiledScript import kotlin.script.experimental.util.PropertiesCollection interface JvmScriptEvaluationConfigurationKeys @@ -18,58 +21,84 @@ open class JvmScriptEvaluationConfigurationBuilder : PropertiesCollection.Builde companion object : JvmScriptEvaluationConfigurationBuilder() } +/** + * The base classloader to use for script classes loading + */ val JvmScriptEvaluationConfigurationKeys.baseClassLoader by PropertiesCollection.key(Thread.currentThread().contextClassLoader) -val JvmScriptEvaluationConfigurationKeys.actualClassLoader by PropertiesCollection.key() +/** + * Load script dependencies before evaluation, true by default + * If false, it is assumed that the all dependencies will be provided via baseClassLoader + */ +val JvmScriptEvaluationConfigurationKeys.loadDependencies by PropertiesCollection.key(true) + +internal val JvmScriptEvaluationConfigurationKeys.actualClassLoader by PropertiesCollection.key() + +internal val JvmScriptEvaluationConfigurationKeys.scriptsInstancesSharingMap by PropertiesCollection.key, EvaluationResult>>() val ScriptEvaluationConfigurationKeys.jvm get() = JvmScriptEvaluationConfigurationBuilder() +class JvmScriptEvaluationContext( + val classLoader: ClassLoader, + val scriptsInstancesSharingMap: MutableMap, EvaluationResult>? +) + open class BasicJvmScriptEvaluator : ScriptEvaluator { override suspend operator fun invoke( compiledScript: CompiledScript<*>, scriptEvaluationConfiguration: ScriptEvaluationConfiguration - ): ResultWithDiagnostics = - try { - compiledScript.getClass(scriptEvaluationConfiguration).onSuccess { scriptClass -> - // in the future, when (if) we'll stop to compile everything into constructor - // run as SAM - // return res + ): ResultWithDiagnostics = try { + val configuration = getConfigurationWithClassloader(compiledScript, scriptEvaluationConfiguration) - // for other scripts we need evaluation configuration with actualClassloader set, - // so they are loaded in the same classloader as the "main" script - val updatedEvalConfiguration = - if (scriptEvaluationConfiguration.containsKey(ScriptEvaluationConfiguration.jvm.actualClassLoader)) - scriptEvaluationConfiguration - else - ScriptEvaluationConfiguration(scriptEvaluationConfiguration) { - ScriptEvaluationConfiguration.jvm.actualClassLoader(scriptClass.java.classLoader) - } + compiledScript.getClass(configuration).onSuccess { scriptClass -> + // in the future, when (if) we'll stop to compile everything into constructor + // run as SAM + // return res - val sharedScripts = scriptEvaluationConfiguration[ScriptEvaluationConfiguration.scriptsInstancesSharingMap] + val sharedScripts = configuration[ScriptEvaluationConfiguration.jvm.scriptsInstancesSharingMap] - sharedScripts?.get(scriptClass)?.asSuccess() - ?: compiledScript.otherScripts.mapSuccess { - invoke(it, updatedEvalConfiguration) - }.onSuccess { importedScriptsEvalResults -> + sharedScripts?.get(scriptClass)?.asSuccess() + ?: compiledScript.otherScripts.mapSuccess { + invoke(it, configuration) + }.onSuccess { importedScriptsEvalResults -> - val refinedEvalConfiguration = - updatedEvalConfiguration[ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate] - ?.handler?.invoke(ScriptEvaluationConfigurationRefinementContext(compiledScript, updatedEvalConfiguration)) - ?.onFailure { - return@invoke ResultWithDiagnostics.Failure(it.reports) - } - ?.resultOrNull() - ?: updatedEvalConfiguration + val refinedEvalConfiguration = + configuration[ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate] + ?.handler?.invoke(ScriptEvaluationConfigurationRefinementContext(compiledScript, configuration)) + ?.onFailure { + return@invoke ResultWithDiagnostics.Failure(it.reports) + } + ?.resultOrNull() + ?: configuration - scriptClass.evalWithConfigAndOtherScriptsResults(refinedEvalConfiguration, importedScriptsEvalResults).let { - sharedScripts?.put(scriptClass, it) - ResultWithDiagnostics.Success(it) - } + scriptClass.evalWithConfigAndOtherScriptsResults(refinedEvalConfiguration, importedScriptsEvalResults).let { + sharedScripts?.put(scriptClass, it) + ResultWithDiagnostics.Success(it) } + } + } + } catch (e: Throwable) { + ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script", path = compiledScript.sourceLocationId)) + } + + private 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()) + } } - } catch (e: Throwable) { - ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script", path = compiledScript.sourceLocationId)) } private fun KClass<*>.evalWithConfigAndOtherScriptsResults( @@ -99,3 +128,32 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator { } } +internal fun KJvmCompiledScript<*>.getOrCreateActualClassloader(evaluationConfiguration: ScriptEvaluationConfiguration): ClassLoader = + evaluationConfiguration[ScriptEvaluationConfiguration.jvm.actualClassLoader] ?: run { + val baseClassLoader = evaluationConfiguration[ScriptEvaluationConfiguration.jvm.baseClassLoader] + val classLoaderWithDeps = + if (evaluationConfiguration[ScriptEvaluationConfiguration.jvm.loadDependencies] == false) baseClassLoader + else makeClassLoaderFromDependencies(baseClassLoader) + compiledModule.createClassLoader(classLoaderWithDeps) + } + +private fun CompiledScript<*>.makeClassLoaderFromDependencies(baseClassLoader: ClassLoader?): ClassLoader? { + val processedScripts = mutableSetOf>() + fun seq(res: Sequence>, script: CompiledScript<*>): Sequence> { + if (processedScripts.contains(script)) return res + processedScripts.add(script) + return script.otherScripts.asSequence().fold(res + script, ::seq) + } + + val dependencies = seq(emptySequence(), this).flatMap { script -> + script.compilationConfiguration[ScriptCompilationConfiguration.dependencies] + ?.asSequence() + ?.flatMap { dep -> + (dep as? JvmDependency)?.classpath?.asSequence()?.map { it.toURI().toURL() } ?: emptySequence() + } + ?: emptySequence() + }.distinct() + // TODO: previous dependencies and classloaders should be taken into account here + return if (dependencies.none()) baseClassLoader + else URLClassLoader(dependencies.toList().toTypedArray(), baseClassLoader) +} diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt index 95be84054f5..8260e5d313d 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt @@ -12,6 +12,7 @@ import java.util.jar.JarOutputStream import java.util.jar.Manifest import kotlin.script.experimental.api.* import kotlin.script.experimental.jvm.JvmDependency +import kotlin.script.experimental.jvmhost.impl.KJvmCompiledModuleInMemory import kotlin.script.experimental.jvmhost.impl.KJvmCompiledScript // TODO: generate execution code (main) @@ -24,8 +25,9 @@ open class BasicJvmScriptClassFilesGenerator(val outputDir: File) : ScriptEvalua ): ResultWithDiagnostics { try { if (compiledScript !is KJvmCompiledScript<*>) - return failure("Unsupported compiled script type ${compiledScript::class.qualifiedName}") - val module = compiledScript.compiledModule ?: return failure("Cannot generate classes: module is null") + return failure("Cannot generate classes: unsupported compiled script type $compiledScript") + val module = (compiledScript.compiledModule as? KJvmCompiledModuleInMemory) + ?: return failure("Cannot generate classes: unsupported module type ${compiledScript.compiledModule}") for ((path, bytes) in module.compilerOutputFiles) { File(outputDir, path).apply { if (!parentFile.isDirectory) { @@ -37,7 +39,7 @@ open class BasicJvmScriptClassFilesGenerator(val outputDir: File) : ScriptEvalua return ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Unit, scriptEvaluationConfiguration)) } catch (e: Throwable) { return ResultWithDiagnostics.Failure( - e.asDiagnostics("Error saving compiled script classes", path = compiledScript.sourceLocationId) + e.asDiagnostics("Cannot generate script classes: ${e.message}", path = compiledScript.sourceLocationId) ) } } @@ -52,8 +54,9 @@ open class BasicJvmScriptJarGenerator(val outputJar: File) : ScriptEvaluator { ): ResultWithDiagnostics { try { if (compiledScript !is KJvmCompiledScript<*>) - return failure("Unsupported compiled script type ${compiledScript::class.qualifiedName}") - val module = compiledScript.compiledModule ?: return failure("Cannot generate classes: module is null") + return failure("Cannot generate jar: unsupported compiled script type $compiledScript") + val module = (compiledScript.compiledModule as? KJvmCompiledModuleInMemory) + ?: return failure("Cannot generate jar: unsupported module type ${compiledScript.compiledModule}") val dependencies = compiledScript.compilationConfiguration[ScriptCompilationConfiguration.dependencies] ?.filterIsInstance() ?.flatMap { it.classpath } @@ -78,7 +81,7 @@ open class BasicJvmScriptJarGenerator(val outputJar: File) : ScriptEvaluator { return ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Unit, scriptEvaluationConfiguration)) } catch (e: Throwable) { return ResultWithDiagnostics.Failure( - e.asDiagnostics("Error saving compiled script jar", path = compiledScript.sourceLocationId) + e.asDiagnostics("Cannot generate script jar: ${e.message}", path = compiledScript.sourceLocationId) ) } } diff --git a/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt b/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt index 9a52b6b9e77..fbb2f249fd2 100644 --- a/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt +++ b/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt @@ -293,8 +293,11 @@ class ScriptingHostTest : TestCase() { Assert.assertNotNull(cachedScript) Assert.assertEquals(1, cache.retrievedScripts) - val compiledScriptClass = runBlocking { compiledScript!!.getClass(null).resultOrNull() } - val cachedScriptClass = runBlocking { cachedScript!!.getClass(null).resultOrNull() } + val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) } + val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) } + + val compiledScriptClass = compiledScriptClassRes.resultOrNull() + val cachedScriptClass = cachedScriptClassRes.resultOrNull() Assert.assertEquals(compiledScriptClass!!.qualifiedName, cachedScriptClass!!.qualifiedName) Assert.assertEquals(compiledScriptClass!!.supertypes, cachedScriptClass!!.supertypes) @@ -416,10 +419,8 @@ private fun ScriptCompilationConfiguration.Builder.makeSimpleConfigurationWithTe private fun File.readCompiledScript(scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*> { return inputStream().use { fs -> - ObjectInputStream(fs).use { os -> - (os.readObject() as KJvmCompiledScript<*>).apply { - setCompilationConfiguration(scriptCompilationConfiguration) - } + ObjectInputStream(fs).use { + it.readObject() as KJvmCompiledScript<*> } } }