Skip to content

Commit 38a7a56

Browse files
ddolovovSpace Team
authored andcommitted
KLIB compat tests, JS: Extract utilities for running a custom compiler
Extract `JsKlibTestSettings`, `CustomJsCompilerArtifacts` and `CustomJsCompiler` to make it possible to reuse them in different types of test runners. ^KT-78188
1 parent 261993b commit 38a7a56

File tree

2 files changed

+76
-62
lines changed

2 files changed

+76
-62
lines changed

js/js.tests/testFixtures/org/jetbrains/kotlin/js/test/ir/AbstractJsCompilerInvocationTest.kt

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
1010
import org.jetbrains.kotlin.cli.common.arguments.cliArgument
1111
import org.jetbrains.kotlin.cli.js.K2JSCompiler
1212
import org.jetbrains.kotlin.js.test.ir.AbstractJsCompilerInvocationTest.CompilerType
13+
import org.jetbrains.kotlin.js.test.klib.JsKlibTestSettings
1314
import org.jetbrains.kotlin.js.testOld.V8JsTestChecker
1415
import org.jetbrains.kotlin.klib.KlibCompilerEdition
1516
import org.jetbrains.kotlin.klib.KlibCompilerInvocationTestUtils
@@ -22,8 +23,6 @@ import org.junit.jupiter.api.AfterEach
2223
import java.io.ByteArrayOutputStream
2324
import java.io.File
2425
import java.io.PrintStream
25-
import java.lang.ref.SoftReference
26-
import java.net.URLClassLoader
2726
import kotlin.io.path.createTempDirectory
2827

2928
/**
@@ -59,72 +58,14 @@ private class ModuleDetails(val name: ModuleName, val outputDir: File) {
5958
constructor(dependency: Dependency) : this(dependency.moduleName, dependency.libraryFile.parentFile)
6059
}
6160

62-
private fun customCompilerCall(): (PrintStream, Array<String>) -> ExitCode {
63-
val customCompiler = JsKlibTestSettings.customJsCompiler
64-
65-
val compilerClass = Class.forName("org.jetbrains.kotlin.cli.js.K2JSCompiler", true, customCompiler.classLoader)
66-
val entryPoint = compilerClass.getMethod(
67-
"execFullPathsInMessages",
68-
PrintStream::class.java,
69-
Array<String>::class.java
70-
)
71-
72-
return { printStream: PrintStream, allCompilerArgs: Array<String> ->
73-
val result = entryPoint.invoke(compilerClass.getDeclaredConstructor().newInstance(), printStream, allCompilerArgs)
74-
ExitCode.valueOf(result.toString())
75-
}
61+
private fun customCompilerCall(): (PrintStream, Array<String>) -> ExitCode = { printStream: PrintStream, allCompilerArgs: Array<String> ->
62+
JsKlibTestSettings.customJsCompiler.callCompiler(args = allCompilerArgs, output = printStream)
7663
}
7764

7865
private fun currentCompilerCall() = { printStream: PrintStream, args: Array<String> ->
7966
K2JSCompiler().execFullPathsInMessages(printStream, args)
8067
}
8168

82-
internal class CustomJsCompiler(private val jsHome: CustomJsCompilerArtifacts) {
83-
private var softClassLoader: SoftReference<URLClassLoader>? = null
84-
val classLoader: URLClassLoader
85-
get() {
86-
return softClassLoader?.get() ?: synchronized(this) {
87-
softClassLoader?.get() ?: createClassLoader(jsHome).also {
88-
softClassLoader = SoftReference(it)
89-
}
90-
}
91-
}
92-
}
93-
94-
private fun createClassLoader(jsHome: CustomJsCompilerArtifacts): URLClassLoader {
95-
val jsClassPath = setOf(
96-
jsHome.compilerEmbeddable,
97-
jsHome.baseStdLib,
98-
)
99-
.map { it.toURI().toURL() }
100-
.toTypedArray()
101-
102-
return URLClassLoader(jsClassPath, null)
103-
.apply { setDefaultAssertionStatus(true) }
104-
}
105-
106-
internal class CustomJsCompilerArtifacts(val dir: File, version: String) {
107-
val compilerEmbeddable: File = dir.resolve("kotlin-compiler-embeddable-$version.jar")
108-
val baseStdLib: File = dir.resolve("kotlin-stdlib-$version.jar")
109-
val jsStdLib: File = dir.resolve("kotlin-stdlib-js-$version.klib")
110-
}
111-
112-
internal object JsKlibTestSettings {
113-
val customJsCompilerArtifacts by lazy {
114-
val location = System.getProperty("kotlin.internal.js.test.compat.customCompilerArtifactsDir")
115-
requireNotNull(location) { "Custom compiler location is not specified" }
116-
117-
val version = System.getProperty("kotlin.internal.js.test.compat.customCompilerVersion")
118-
requireNotNull(version) { "Custom compiler version is not specified" }
119-
120-
CustomJsCompilerArtifacts(File(location), version)
121-
}
122-
123-
val customJsCompiler by lazy {
124-
CustomJsCompiler(customJsCompilerArtifacts)
125-
}
126-
}
127-
12869
internal class JsCompilerInvocationTestConfiguration(
12970
override val buildDir: File,
13071
val compilerType: CompilerType,
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin.js.test.klib
7+
8+
import org.jetbrains.kotlin.cli.common.ExitCode
9+
import java.io.File
10+
import java.io.PrintStream
11+
import java.lang.ref.SoftReference
12+
import java.net.URLClassLoader
13+
14+
internal object JsKlibTestSettings {
15+
val customJsCompilerArtifacts: CustomJsCompilerArtifacts by lazy {
16+
val artifactsDir: String? = System.getProperty("kotlin.internal.js.test.compat.customCompilerArtifactsDir")
17+
requireNotNull(artifactsDir) { "Custom compiler location is not specified" }
18+
19+
val version: String? = System.getProperty("kotlin.internal.js.test.compat.customCompilerVersion")
20+
requireNotNull(version) { "Custom compiler version is not specified" }
21+
22+
CustomJsCompilerArtifacts(artifactsDir = File(artifactsDir), version)
23+
}
24+
25+
val customJsCompiler by lazy {
26+
CustomJsCompiler(customJsCompilerArtifacts)
27+
}
28+
}
29+
30+
internal class CustomJsCompilerArtifacts(artifactsDir: File, val version: String) {
31+
val compilerEmbeddable: File = artifactsDir.resolve("kotlin-compiler-embeddable-$version.jar")
32+
33+
val baseStdLib: File = artifactsDir.resolve("kotlin-stdlib-$version.jar")
34+
35+
val jsStdLib: File = artifactsDir.resolve("kotlin-stdlib-js-$version.klib")
36+
}
37+
38+
internal class CustomJsCompiler(private val customWebCompilerArtifacts: CustomJsCompilerArtifacts) {
39+
private var isolatedClassLoaderSoftRef: SoftReference<URLClassLoader>? = null
40+
41+
private fun getIsolatedClassLoader(): URLClassLoader = isolatedClassLoaderSoftRef?.get()
42+
?: synchronized(this) {
43+
isolatedClassLoaderSoftRef?.get()
44+
?: createIsolatedClassLoader(customWebCompilerArtifacts).also { isolatedClassLoaderSoftRef = SoftReference(it) }
45+
}
46+
47+
fun callCompiler(args: Array<String>, output: PrintStream): ExitCode {
48+
val isolatedClassLoader = getIsolatedClassLoader()
49+
50+
val compilerClass = Class.forName("org.jetbrains.kotlin.cli.js.K2JSCompiler", true, isolatedClassLoader)
51+
val entryPoint = compilerClass.getMethod(
52+
"execFullPathsInMessages",
53+
PrintStream::class.java,
54+
Array<String>::class.java
55+
)
56+
57+
val compilerInstance = compilerClass.getDeclaredConstructor().newInstance()
58+
val result = entryPoint.invoke(compilerInstance, output, args)
59+
60+
return ExitCode.valueOf(result.toString())
61+
}
62+
}
63+
64+
private fun createIsolatedClassLoader(customWebCompilerArtifacts: CustomJsCompilerArtifacts): URLClassLoader {
65+
val compilerClassPath = setOf(
66+
customWebCompilerArtifacts.compilerEmbeddable,
67+
customWebCompilerArtifacts.baseStdLib,
68+
)
69+
.map { it.toURI().toURL() }
70+
.toTypedArray()
71+
72+
return URLClassLoader(compilerClassPath, null).apply { setDefaultAssertionStatus(true) }
73+
}

0 commit comments

Comments
 (0)