Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ gradle-app.setting
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
/.idea/
/kotlin-js-store/
/kotlin-js-store/
/.kotlin/
18 changes: 14 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
@file:OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)

plugins {
kotlin("multiplatform") version "2.2.0"
kotlin("multiplatform") version "2.2.20-Beta2"
`maven-publish`
signing
}
Expand Down Expand Up @@ -39,13 +39,23 @@ if (!versionSuffix.isNullOrBlank()) {
}

kotlin {
@OptIn(ExperimentalWasmDsl::class)
compilerOptions {
optIn.add("kotlin.js.ExperimentalWasmJsInterop")
}

js {
nodejs()
}

wasmJs {
nodejs()
}

applyDefaultHierarchyTemplate()

sourceSets {
val wasmJsTest by getting {
val commonMain by getting
val webTest by getting {
dependencies {
implementation(kotlin("test"))
}
Expand Down
8 changes: 4 additions & 4 deletions generator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ task("downloadIDL", JavaExec::class) {
dependsOn("build")
}

task("generateWasmStdlibFromIDL", JavaExec::class) {
mainClass = "org.jetbrains.kotlin.tools.dukat.LaunchWasmKt"
task("generateStdlibFromIDL", JavaExec::class) {
mainClass = "org.jetbrains.kotlin.tools.dukat.LaunchBrowserKt"
classpath = sourceSets["main"].runtimeClasspath
dependsOn("build")
systemProperty("line.separator", "\n")
}

task("generateWasmJsUtils", JavaExec::class) {
mainClass.set("org.jetbrains.kotlin.generators.wasm.js.GenerateKt")
task("generateUtils", JavaExec::class) {
mainClass.set("org.jetbrains.kotlin.generators.helpers.GenerateKt")
classpath = sourceSets["main"].runtimeClasspath
dependsOn("build")
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.tools.dukat.wasm.translateIdlToSourceSet
import java.io.File

fun main() {
val outputDirectory = "../src/wasmJsMain/kotlin/org.w3c/"
val outputDirectory = "../src/webMain/kotlin/org.w3c/"
val input = "../idl/org.w3c.dom.idl"

val sourceSet = translateIdlToSourceSet(input)
Expand Down
8 changes: 3 additions & 5 deletions generator/src/main/kotlin/dukat/wasm/convertToModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,7 @@ private class IdlFileConverter(
SUPPRESS_UNUSED_PARAMETER_ANNOTATION
),
body = BlockStatementModel(
listOf(
ExpressionStatementModel(callJsFunction("return obj[${key.name}];"))
)
listOf(ReturnStatementModel(callJsFunction("obj[${key.name}]")))
),
visibilityModifier = VisibilityModifierModel.INTERNAL,
comment = null,
Expand Down Expand Up @@ -555,8 +553,8 @@ private class IdlFileConverter(

fun IDLDictionaryDeclaration.generateFunctionBody(): List<StatementModel> =
listOf<StatementModel>(
ExpressionStatementModel(
callJsFunction("return { ${members.joinToString { it.name }} };")
ReturnStatementModel(
callJsFunction("({ ${members.joinToString(", ") { "${it.name}: ${it.name}" }} })")
)
)

Expand Down
108 changes: 93 additions & 15 deletions generator/src/main/kotlin/helpers/generate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package org.jetbrains.kotlin.generators.wasm.js
package org.jetbrains.kotlin.generators.helpers

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

fun generatePublicStdlibFunctions() {
FileWriter(File("../src/wasmJsMain/kotlin/arrayCopy.kt")).use { writer: FileWriter ->
val conversions = listOf(
Conversion("Byte", "Int8"),
Conversion("UByte", "Uint8", isUnsigned = true),
Conversion("Short", "Int16"),
Conversion("UShort", "Uint16", isUnsigned = true),
Conversion("Int", "Int32"),
Conversion("UInt", "Uint32", isUnsigned = true),
Conversion("Float", "Float32"),
Conversion("Double", "Float64")
)

FileWriter(File("../src/webMain/kotlin/arrayCopy.kt")).use { writer: FileWriter ->
with(writer) {
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))
appendLine("package org.khronos.webgl")

conversions.forEach { (ktType, jsType, isUnsigned) ->
appendExpectConversionsForType(ktType, jsType, isUnsigned)
}
}
}
FileWriter(File("../src/jsMain/kotlin/arrayCopy.js.kt")).use { writer: FileWriter ->
with(writer) {
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))

appendLine("package org.khronos.webgl")

conversions.forEach { (ktType, jsType, isUnsigned) ->
appendJsConversionsForType(ktType, jsType, isUnsigned)
}
}
}
FileWriter(File("../src/wasmJsMain/kotlin/arrayCopy.wasm.kt")).use { writer: FileWriter ->
with(writer) {
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))
appendLine("package org.khronos.webgl")

appendConversionsForType("Byte", "Int8")
appendConversionsForType("UByte", "Uint8", isUnsigned = true)
appendConversionsForType("Short", "Int16")
appendConversionsForType("UShort", "Uint16", isUnsigned = true)
appendConversionsForType("Int", "Int32")
appendConversionsForType("UInt", "Uint32", isUnsigned = true)
appendConversionsForType("Float", "Float32")
appendConversionsForType("Double", "Float64")
conversions.forEach { (ktType, jsType, isUnsigned) ->
appendWasmConversionsForType(ktType, jsType, isUnsigned)
}
}
}
}

private fun FileWriter.appendConversionsForType(

private fun FileWriter.appendExpectConversionsForType(
ktType: String,
jsType: String,
isUnsigned: Boolean = false,
) {
val kotlinArrayType = "${ktType}Array"
val jsArrayType = "${jsType}Array"

appendLine()
appendLine("/** Returns a new [$kotlinArrayType] containing all the elements of this [$jsArrayType]. */")
if (isUnsigned) {
appendLine("@ExperimentalUnsignedTypes")
}
appendLine("public expect fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType")
appendLine()
appendLine("/** Returns a new [$jsArrayType] containing all the elements of this [$kotlinArrayType]. */")
if (isUnsigned) {
appendLine("@ExperimentalUnsignedTypes")
}
appendLine("public expect fun $kotlinArrayType.to$jsArrayType(): $jsArrayType")
}


private fun FileWriter.appendJsConversionsForType(
ktType: String,
jsType: String,
isUnsigned: Boolean = false,
) {
val kotlinArrayType = "${ktType}Array"
val jsArrayType = "${jsType}Array"

appendLine()
appendLine("/** Returns a new [$kotlinArrayType] containing all the elements of this [$jsArrayType]. */")
if (isUnsigned) {
appendLine("@ExperimentalUnsignedTypes")
}
appendLine("public actual inline fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType =")
appendLine(" unsafeCast<$kotlinArrayType>()")

appendLine()
appendLine("/** Returns a new [$jsArrayType] containing all the elements of this [$kotlinArrayType]. */")
if (isUnsigned) {
appendLine("@ExperimentalUnsignedTypes")
}
appendLine("public actual inline fun $kotlinArrayType.to$jsArrayType(): $jsArrayType =")
appendLine(" unsafeCast<$jsArrayType>()")
}

private fun FileWriter.appendWasmConversionsForType(
ktType: String,
jsType: String,
isUnsigned: Boolean = false,
Expand All @@ -46,7 +121,7 @@ private fun FileWriter.appendConversionsForType(
if (isUnsigned) {
appendLine("@ExperimentalUnsignedTypes")
}
appendLine("public fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType =")
appendLine("public actual fun $jsArrayType.to$kotlinArrayType(): $kotlinArrayType =")
if (isUnsigned) {
appendLine(" $kotlinArrayType(this.length) { this[it].to$ktType() }")
} else {
Expand All @@ -58,7 +133,7 @@ private fun FileWriter.appendConversionsForType(
if (isUnsigned) {
appendLine("@ExperimentalUnsignedTypes")
}
appendLine("public fun $kotlinArrayType.to$jsArrayType(): $jsArrayType {")
appendLine("public actual fun $kotlinArrayType.to$jsArrayType(): $jsArrayType {")
appendLine(" val result = $jsArrayType(this.size)")
appendLine(" for (index in this.indices) {")
if (isUnsigned) {
Expand All @@ -73,7 +148,7 @@ private fun FileWriter.appendConversionsForType(
}

fun generateTests() {
FileWriter(File("../src/wasmJsTest/kotlin/arrayCopyTest.kt")).use { writer: FileWriter ->
FileWriter(File("../src/webtest/kotlin/arrayCopyTest.kt")).use { writer: FileWriter ->
with(writer) {
appendLine(getHeader(seeDetailsAt = "generator/src/main/kotlin/helpers/generate.kt"))

Expand Down Expand Up @@ -146,4 +221,7 @@ private fun FileWriter.appendTestFunction(
appendLine(" testJsRoundTrip($ktArrayOf(0.to$ktType(), (-42).to$ktType(), $ktType.MIN_VALUE, $ktType.MAX_VALUE))")
appendLine(" testJsRoundTrip($kotlinArrayType(1000) { it.to$ktType() })")
appendLine(" }")
}
}

data class Conversion(val jsType: String, val ktType: String, val isUnsigned: Boolean = false)
data class InteropCorrespondence(val interopType: String, val wasmType: String, val jsType: String)
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pluginManagement {
gradlePluginPortal()
}
plugins {
kotlin("multiplatform").version("2.2.0")
kotlin("multiplatform").version("2.2.20-Beta2")
}
}

Expand Down
80 changes: 80 additions & 0 deletions src/jsMain/kotlin/arrayCopy.js.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/

// NOTE: THIS FILE IS AUTO-GENERATED, DO NOT EDIT!
// See generator/src/main/kotlin/helpers/generate.kt for details


package org.khronos.webgl

/** Returns a new [ByteArray] containing all the elements of this [Int8Array]. */
public actual inline fun Int8Array.toByteArray(): ByteArray =
unsafeCast<ByteArray>()

/** Returns a new [Int8Array] containing all the elements of this [ByteArray]. */
public actual inline fun ByteArray.toInt8Array(): Int8Array =
unsafeCast<Int8Array>()

/** Returns a new [UByteArray] containing all the elements of this [Uint8Array]. */
@ExperimentalUnsignedTypes
public actual inline fun Uint8Array.toUByteArray(): UByteArray =
unsafeCast<UByteArray>()

/** Returns a new [Uint8Array] containing all the elements of this [UByteArray]. */
@ExperimentalUnsignedTypes
public actual inline fun UByteArray.toUint8Array(): Uint8Array =
unsafeCast<Uint8Array>()

/** Returns a new [ShortArray] containing all the elements of this [Int16Array]. */
public actual inline fun Int16Array.toShortArray(): ShortArray =
unsafeCast<ShortArray>()

/** Returns a new [Int16Array] containing all the elements of this [ShortArray]. */
public actual inline fun ShortArray.toInt16Array(): Int16Array =
unsafeCast<Int16Array>()

/** Returns a new [UShortArray] containing all the elements of this [Uint16Array]. */
@ExperimentalUnsignedTypes
public actual inline fun Uint16Array.toUShortArray(): UShortArray =
unsafeCast<UShortArray>()

/** Returns a new [Uint16Array] containing all the elements of this [UShortArray]. */
@ExperimentalUnsignedTypes
public actual inline fun UShortArray.toUint16Array(): Uint16Array =
unsafeCast<Uint16Array>()

/** Returns a new [IntArray] containing all the elements of this [Int32Array]. */
public actual inline fun Int32Array.toIntArray(): IntArray =
unsafeCast<IntArray>()

/** Returns a new [Int32Array] containing all the elements of this [IntArray]. */
public actual inline fun IntArray.toInt32Array(): Int32Array =
unsafeCast<Int32Array>()

/** Returns a new [UIntArray] containing all the elements of this [Uint32Array]. */
@ExperimentalUnsignedTypes
public actual inline fun Uint32Array.toUIntArray(): UIntArray =
unsafeCast<UIntArray>()

/** Returns a new [Uint32Array] containing all the elements of this [UIntArray]. */
@ExperimentalUnsignedTypes
public actual inline fun UIntArray.toUint32Array(): Uint32Array =
unsafeCast<Uint32Array>()

/** Returns a new [FloatArray] containing all the elements of this [Float32Array]. */
public actual inline fun Float32Array.toFloatArray(): FloatArray =
unsafeCast<FloatArray>()

/** Returns a new [Float32Array] containing all the elements of this [FloatArray]. */
public actual inline fun FloatArray.toFloat32Array(): Float32Array =
unsafeCast<Float32Array>()

/** Returns a new [DoubleArray] containing all the elements of this [Float64Array]. */
public actual inline fun Float64Array.toDoubleArray(): DoubleArray =
unsafeCast<DoubleArray>()

/** Returns a new [Float64Array] containing all the elements of this [DoubleArray]. */
public actual inline fun DoubleArray.toFloat64Array(): Float64Array =
unsafeCast<Float64Array>()
Loading