Skip to content

Commit a39765a

Browse files
Artem.KobzarArtem.Kobzar
Artem.Kobzar
authored and
Artem.Kobzar
committed
Setup a common sourceSet in between wasmJs and JS targets to publish both variants from the single source
1 parent f7d2ddc commit a39765a

38 files changed

+457
-206
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ gradle-app.setting
1313
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
1414
# gradle/wrapper/gradle-wrapper.properties
1515
/.idea/
16-
/kotlin-js-store/
16+
/kotlin-js-store/
17+
/.kotlin/

build.gradle.kts

+32-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
12
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
3+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon
24

35
plugins {
4-
kotlin("multiplatform") version "1.9.24"
6+
kotlin("multiplatform") version "2.1.10"
57
`maven-publish`
68
signing
79
}
@@ -26,6 +28,7 @@ afterEvaluate {
2628

2729
repositories {
2830
mavenCentral()
31+
mavenLocal()
2932
}
3033

3134
val artifactId = "kotlinx-browser"
@@ -39,16 +42,43 @@ if (!versionSuffix.isNullOrBlank()) {
3942
}
4043

4144
kotlin {
45+
js()
46+
4247
@OptIn(ExperimentalWasmDsl::class)
4348
wasmJs {
4449
nodejs()
4550
}
4651

4752
sourceSets {
48-
val wasmJsTest by getting {
53+
val commonMain by getting
54+
val commonTest by getting
55+
val browserMain by creating {
56+
dependsOn(commonMain)
57+
}
58+
val browserTest by creating {
59+
dependsOn(commonTest)
4960
dependencies {
5061
implementation(kotlin("test"))
5162
}
5263
}
64+
val jsMain by getting {
65+
dependsOn(browserMain)
66+
dependencies {
67+
implementation(kotlin("wasm-js-interop", "0.0.1-SNAPSHOT"))
68+
}
69+
}
70+
val jsTest by getting {
71+
dependsOn(browserTest)
72+
}
73+
val wasmJsMain by getting {
74+
dependsOn(browserMain)
75+
}
76+
val wasmJsTest by getting {
77+
dependsOn(browserTest)
78+
}
5379
}
80+
}
81+
82+
tasks.withType<KotlinCompileCommon>().configureEach {
83+
enabled = false
5484
}

generator/build.gradle.kts

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ task("downloadIDL", JavaExec::class) {
1818
dependsOn("build")
1919
}
2020

21-
task("generateWasmStdlibFromIDL", JavaExec::class) {
22-
mainClass = "org.jetbrains.kotlin.tools.dukat.LaunchWasmKt"
21+
task("generateStdlibFromIDL", JavaExec::class) {
22+
mainClass = "org.jetbrains.kotlin.tools.dukat.LaunchBrowserKt"
2323
classpath = sourceSets["main"].runtimeClasspath
2424
dependsOn("build")
2525
systemProperty("line.separator", "\n")
2626
}
2727

28-
task("generateWasmJsUtils", JavaExec::class) {
29-
mainClass.set("org.jetbrains.kotlin.generators.wasm.js.GenerateKt")
28+
task("generateUtils", JavaExec::class) {
29+
mainClass.set("org.jetbrains.kotlin.generators.helpers.GenerateKt")
3030
classpath = sourceSets["main"].runtimeClasspath
3131
dependsOn("build")
3232
}

generator/src/main/kotlin/dukat/launchWasm.kt renamed to generator/src/main/kotlin/dukat/launchBrowser.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.tools.dukat.wasm.translateIdlToSourceSet
1111
import java.io.File
1212

1313
fun main() {
14-
val outputDirectory = "../src/wasmJsMain/kotlin/org.w3c/"
14+
val outputDirectory = "../src/browserMain/kotlin/org.w3c/"
1515
val input = "../idl/org.w3c.dom.idl"
1616

1717
val sourceSet = translateIdlToSourceSet(input)

generator/src/main/kotlin/dukat/wasm/convertToModel.kt

+3-5
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,7 @@ private class IdlFileConverter(
380380
SUPPRESS_UNUSED_PARAMETER_ANNOTATION
381381
),
382382
body = BlockStatementModel(
383-
listOf(
384-
ExpressionStatementModel(callJsFunction("return obj[${key.name}];"))
385-
)
383+
listOf(ReturnStatementModel(callJsFunction("obj[${key.name}]")))
386384
),
387385
visibilityModifier = VisibilityModifierModel.INTERNAL,
388386
comment = null,
@@ -555,8 +553,8 @@ private class IdlFileConverter(
555553

556554
fun IDLDictionaryDeclaration.generateFunctionBody(): List<StatementModel> =
557555
listOf<StatementModel>(
558-
ExpressionStatementModel(
559-
callJsFunction("return { ${members.joinToString { it.name }} };")
556+
ReturnStatementModel(
557+
callJsFunction("({ ${members.joinToString(", ") { "${it.name}: ${it.name}" }} })")
560558
)
561559
)
562560

generator/src/main/kotlin/helpers/generate.kt

+93-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
44
*/
55

6-
package org.jetbrains.kotlin.generators.wasm.js
6+
package org.jetbrains.kotlin.generators.helpers
77

88
import org.jetbrains.kotlin.tools.dukat.getHeader
99
import java.io.File
@@ -15,25 +15,100 @@ fun main() {
1515
}
1616

1717
fun generatePublicStdlibFunctions() {
18-
FileWriter(File("../src/wasmJsMain/kotlin/arrayCopy.kt")).use { writer: FileWriter ->
18+
val conversions = listOf(
19+
Conversion("Byte", "Int8"),
20+
Conversion("UByte", "Uint8", isUnsigned = true),
21+
Conversion("Short", "Int16"),
22+
Conversion("UShort", "Uint16", isUnsigned = true),
23+
Conversion("Int", "Int32"),
24+
Conversion("UInt", "Uint32", isUnsigned = true),
25+
Conversion("Float", "Float32"),
26+
Conversion("Double", "Float64")
27+
)
28+
29+
FileWriter(File("../src/browserMain/kotlin/arrayCopy.kt")).use { writer: FileWriter ->
1930
with(writer) {
2031
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))
32+
appendLine("package org.khronos.webgl")
2133

34+
conversions.forEach { (ktType, jsType, isUnsigned) ->
35+
appendExpectConversionsForType(ktType, jsType, isUnsigned)
36+
}
37+
}
38+
}
39+
FileWriter(File("../src/jsMain/kotlin/arrayCopy.js.kt")).use { writer: FileWriter ->
40+
with(writer) {
41+
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))
42+
43+
appendLine("package org.khronos.webgl")
44+
45+
conversions.forEach { (ktType, jsType, isUnsigned) ->
46+
appendJsConversionsForType(ktType, jsType, isUnsigned)
47+
}
48+
}
49+
}
50+
FileWriter(File("../src/wasmJsMain/kotlin/arrayCopy.wasm.kt")).use { writer: FileWriter ->
51+
with(writer) {
52+
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))
2253
appendLine("package org.khronos.webgl")
2354

24-
appendConversionsForType("Byte", "Int8")
25-
appendConversionsForType("UByte", "Uint8", isUnsigned = true)
26-
appendConversionsForType("Short", "Int16")
27-
appendConversionsForType("UShort", "Uint16", isUnsigned = true)
28-
appendConversionsForType("Int", "Int32")
29-
appendConversionsForType("UInt", "Uint32", isUnsigned = true)
30-
appendConversionsForType("Float", "Float32")
31-
appendConversionsForType("Double", "Float64")
55+
conversions.forEach { (ktType, jsType, isUnsigned) ->
56+
appendWasmConversionsForType(ktType, jsType, isUnsigned)
57+
}
3258
}
3359
}
3460
}
3561

36-
private fun FileWriter.appendConversionsForType(
62+
63+
private fun FileWriter.appendExpectConversionsForType(
64+
ktType: String,
65+
jsType: String,
66+
isUnsigned: Boolean = false,
67+
) {
68+
val kotlinArrayType = "${ktType}Array"
69+
val jsArrayType = "${jsType}Array"
70+
71+
appendLine()
72+
appendLine("/** Returns a new [$kotlinArrayType] containing all the elements of this [$jsArrayType]. */")
73+
if (isUnsigned) {
74+
appendLine("@ExperimentalUnsignedTypes")
75+
}
76+
appendLine("public expect fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType")
77+
appendLine()
78+
appendLine("/** Returns a new [$jsArrayType] containing all the elements of this [$kotlinArrayType]. */")
79+
if (isUnsigned) {
80+
appendLine("@ExperimentalUnsignedTypes")
81+
}
82+
appendLine("public expect fun $kotlinArrayType.to$jsArrayType(): $jsArrayType")
83+
}
84+
85+
86+
private fun FileWriter.appendJsConversionsForType(
87+
ktType: String,
88+
jsType: String,
89+
isUnsigned: Boolean = false,
90+
) {
91+
val kotlinArrayType = "${ktType}Array"
92+
val jsArrayType = "${jsType}Array"
93+
94+
appendLine()
95+
appendLine("/** Returns a new [$kotlinArrayType] containing all the elements of this [$jsArrayType]. */")
96+
if (isUnsigned) {
97+
appendLine("@ExperimentalUnsignedTypes")
98+
}
99+
appendLine("public actual inline fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType =")
100+
appendLine(" unsafeCast<$kotlinArrayType>()")
101+
102+
appendLine()
103+
appendLine("/** Returns a new [$jsArrayType] containing all the elements of this [$kotlinArrayType]. */")
104+
if (isUnsigned) {
105+
appendLine("@ExperimentalUnsignedTypes")
106+
}
107+
appendLine("public actual inline fun $kotlinArrayType.to$jsArrayType(): $jsArrayType =")
108+
appendLine(" unsafeCast<$jsArrayType>()")
109+
}
110+
111+
private fun FileWriter.appendWasmConversionsForType(
37112
ktType: String,
38113
jsType: String,
39114
isUnsigned: Boolean = false,
@@ -46,7 +121,7 @@ private fun FileWriter.appendConversionsForType(
46121
if (isUnsigned) {
47122
appendLine("@ExperimentalUnsignedTypes")
48123
}
49-
appendLine("public fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType =")
124+
appendLine("public actual fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType =")
50125
if (isUnsigned) {
51126
appendLine(" $kotlinArrayType(this.length) { this[it].to$ktType() }")
52127
} else {
@@ -58,7 +133,7 @@ private fun FileWriter.appendConversionsForType(
58133
if (isUnsigned) {
59134
appendLine("@ExperimentalUnsignedTypes")
60135
}
61-
appendLine("public fun $kotlinArrayType.to$jsArrayType(): $jsArrayType {")
136+
appendLine("public actual fun $kotlinArrayType.to$jsArrayType(): $jsArrayType {")
62137
appendLine(" val result = $jsArrayType(this.size)")
63138
appendLine(" for (index in this.indices) {")
64139
if (isUnsigned) {
@@ -73,7 +148,7 @@ private fun FileWriter.appendConversionsForType(
73148
}
74149

75150
fun generateTests() {
76-
FileWriter(File("../src/wasmJsTest/kotlin/arrayCopyTest.kt")).use { writer: FileWriter ->
151+
FileWriter(File("../src/browserTest/kotlin/arrayCopyTest.kt")).use { writer: FileWriter ->
77152
with(writer) {
78153
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))
79154

@@ -146,4 +221,7 @@ private fun FileWriter.appendTestFunction(
146221
appendLine(" testJsRoundTrip($ktArrayOf(0.to$ktType(), (-42).to$ktType(), $ktType.MIN_VALUE, $ktType.MAX_VALUE))")
147222
appendLine(" testJsRoundTrip($kotlinArrayType(1000) { it.to$ktType() })")
148223
appendLine(" }")
149-
}
224+
}
225+
226+
data class Conversion(val jsType: String, val ktType: String, val isUnsigned: Boolean = false)
227+
data class InteropCorrespondence(val interopType: String, val wasmType: String, val jsType: String)

settings.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pluginManagement {
33
gradlePluginPortal()
44
}
55
plugins {
6-
kotlin("multiplatform").version("1.9.23")
6+
kotlin("multiplatform").version("2.1.10")
77
}
88
}
99

src/browserMain/kotlin/arrayCopy.kt

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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 file.
4+
*/
5+
6+
// NOTE: THIS FILE IS AUTO-GENERATED, DO NOT EDIT!
7+
// See generator/src/main/kotlin/helpers/generate.kt for details
8+
9+
10+
package org.khronos.webgl
11+
12+
/** Returns a new [ByteArray] containing all the elements of this [Int8Array]. */
13+
public expect fun Int8Array.toByteArray(): ByteArray
14+
15+
/** Returns a new [Int8Array] containing all the elements of this [ByteArray]. */
16+
public expect fun ByteArray.toInt8Array(): Int8Array
17+
18+
/** Returns a new [UByteArray] containing all the elements of this [Uint8Array]. */
19+
@ExperimentalUnsignedTypes
20+
public expect fun Uint8Array.toUByteArray(): UByteArray
21+
22+
/** Returns a new [Uint8Array] containing all the elements of this [UByteArray]. */
23+
@ExperimentalUnsignedTypes
24+
public expect fun UByteArray.toUint8Array(): Uint8Array
25+
26+
/** Returns a new [ShortArray] containing all the elements of this [Int16Array]. */
27+
public expect fun Int16Array.toShortArray(): ShortArray
28+
29+
/** Returns a new [Int16Array] containing all the elements of this [ShortArray]. */
30+
public expect fun ShortArray.toInt16Array(): Int16Array
31+
32+
/** Returns a new [UShortArray] containing all the elements of this [Uint16Array]. */
33+
@ExperimentalUnsignedTypes
34+
public expect fun Uint16Array.toUShortArray(): UShortArray
35+
36+
/** Returns a new [Uint16Array] containing all the elements of this [UShortArray]. */
37+
@ExperimentalUnsignedTypes
38+
public expect fun UShortArray.toUint16Array(): Uint16Array
39+
40+
/** Returns a new [IntArray] containing all the elements of this [Int32Array]. */
41+
public expect fun Int32Array.toIntArray(): IntArray
42+
43+
/** Returns a new [Int32Array] containing all the elements of this [IntArray]. */
44+
public expect fun IntArray.toInt32Array(): Int32Array
45+
46+
/** Returns a new [UIntArray] containing all the elements of this [Uint32Array]. */
47+
@ExperimentalUnsignedTypes
48+
public expect fun Uint32Array.toUIntArray(): UIntArray
49+
50+
/** Returns a new [Uint32Array] containing all the elements of this [UIntArray]. */
51+
@ExperimentalUnsignedTypes
52+
public expect fun UIntArray.toUint32Array(): Uint32Array
53+
54+
/** Returns a new [FloatArray] containing all the elements of this [Float32Array]. */
55+
public expect fun Float32Array.toFloatArray(): FloatArray
56+
57+
/** Returns a new [Float32Array] containing all the elements of this [FloatArray]. */
58+
public expect fun FloatArray.toFloat32Array(): Float32Array
59+
60+
/** Returns a new [DoubleArray] containing all the elements of this [Float64Array]. */
61+
public expect fun Float64Array.toDoubleArray(): DoubleArray
62+
63+
/** Returns a new [Float64Array] containing all the elements of this [DoubleArray]. */
64+
public expect fun DoubleArray.toFloat64Array(): Float64Array

0 commit comments

Comments
 (0)