From 8cc066069385eff4c4fcc38eb6d00e466ba772a3 Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Mon, 31 Jul 2023 14:27:09 +0200 Subject: [PATCH] [Wasm] Wasi stdlib implementation KT-56608 --- libraries/stdlib/wasm/build.gradle.kts | 29 +- .../stdlib/wasm/builtins/kotlin/Throwable.kt | 48 +-- .../stdlib/wasm/internal/ExceptionHelpers.kt | 8 + .../stdlib/wasm/internal/ExternalWrapper.kt | 21 + .../kotlin/wasm/internal/WasmInstructions.kt | 10 +- .../wasm/js/builtins/kotlin/Throwable.kt | 52 +++ .../wasm => js}/internal/ExceptionHelpers.kt | 4 +- .../wasm => js}/internal/ExternalWrapper.kt | 17 +- .../wasm/js/internal/WasmInstructions.kt | 17 + .../wasm/{ => js}/src/kotlin/Dynamic.kt | 0 .../wasm/{ => js}/src/kotlin/JsInterop.kt | 0 .../stdlib/wasm/{ => js}/src/kotlin/io.kt | 6 +- .../wasm/{ => js}/src/kotlin/js/JsAny.kt | 0 .../wasm/{ => js}/src/kotlin/js/JsArray.kt | 0 .../wasm/{ => js}/src/kotlin/js/JsBoolean.kt | 0 .../wasm/{ => js}/src/kotlin/js/JsNumber.kt | 0 .../{ => js}/src/kotlin/js/JsReference.kt | 0 .../wasm/{ => js}/src/kotlin/js/JsString.kt | 0 .../wasm/{ => js}/src/kotlin/js/Promise.kt | 0 .../{ => js}/src/kotlin/js/annotations.kt | 0 .../wasm/{ => js}/src/kotlin/js/core.kt | 0 .../js/src/kotlin/random/PlatformRandom.kt | 12 + .../wasm/{ => js}/src/kotlin/time/Duration.kt | 1 - .../{ => js}/src/kotlin/time/TimeSources.kt | 0 .../wasm/{ => js}/src/kotlin/w3cSupport.kt | 0 .../src/kotlinx/browser/declarations.kt | 0 .../wasm/{ => js}/src/kotlinx/dom/Builders.kt | 0 .../wasm/{ => js}/src/kotlinx/dom/Classes.kt | 0 .../wasm/{ => js}/src/kotlinx/dom/Dom.kt | 0 .../{ => js}/src/kotlinx/dom/ItemArrayLike.kt | 0 .../{ => js}/src/kotlinx/dom/Mutations.kt | 0 .../{ => js}/src/org.w3c/org.khronos.webgl.kt | 0 .../src/org.w3c/org.w3c.css.masking.kt | 0 .../src/org.w3c/org.w3c.dom.clipboard.kt | 0 .../{ => js}/src/org.w3c/org.w3c.dom.css.kt | 0 .../src/org.w3c/org.w3c.dom.encryptedmedia.kt | 0 .../src/org.w3c/org.w3c.dom.events.kt | 0 .../wasm/{ => js}/src/org.w3c/org.w3c.dom.kt | 0 .../src/org.w3c/org.w3c.dom.mediacapture.kt | 0 .../src/org.w3c/org.w3c.dom.mediasource.kt | 0 .../src/org.w3c/org.w3c.dom.parsing.kt | 0 .../src/org.w3c/org.w3c.dom.pointerevents.kt | 0 .../{ => js}/src/org.w3c/org.w3c.dom.svg.kt | 0 .../{ => js}/src/org.w3c/org.w3c.dom.url.kt | 0 .../{ => js}/src/org.w3c/org.w3c.fetch.kt | 0 .../{ => js}/src/org.w3c/org.w3c.files.kt | 0 .../src/org.w3c/org.w3c.notifications.kt | 0 .../src/org.w3c/org.w3c.performance.kt | 0 .../{ => js}/src/org.w3c/org.w3c.workers.kt | 0 .../wasm/{ => js}/src/org.w3c/org.w3c.xhr.kt | 0 .../stdlib/wasm/src/kotlin/Serializable.kt | 8 + .../wasm/src/kotlin/random/PlatformRandom.kt | 6 - .../wasm/test/unsafe/MemoryAllocationTest.kt | 11 - .../wasm/{test => testJs}/js/AsyncTest.kt | 5 + .../testJs/unsafe/MemoryAllocationJsTest.kt | 18 + .../wasm/wasi/builtins/kotlin/Throwable.kt | 36 ++ .../stdlib/wasm/wasi/src/kotlin/WasiError.kt | 398 ++++++++++++++++++ libraries/stdlib/wasm/wasi/src/kotlin/io.kt | 98 +++++ .../wasi/src/kotlin/random/PlatformRandom.kt | 36 ++ .../wasm/wasi/src/kotlin/time/Duration.kt | 19 + .../wasm/wasi/src/kotlin/time/TimeSources.kt | 60 +++ 61 files changed, 817 insertions(+), 103 deletions(-) create mode 100644 libraries/stdlib/wasm/internal/ExceptionHelpers.kt create mode 100644 libraries/stdlib/wasm/internal/ExternalWrapper.kt create mode 100644 libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt rename libraries/stdlib/wasm/{internal/kotlin/wasm => js}/internal/ExceptionHelpers.kt (92%) rename libraries/stdlib/wasm/{internal/kotlin/wasm => js}/internal/ExternalWrapper.kt (96%) create mode 100644 libraries/stdlib/wasm/js/internal/WasmInstructions.kt rename libraries/stdlib/wasm/{ => js}/src/kotlin/Dynamic.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/JsInterop.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/io.kt (87%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/JsAny.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/JsArray.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/JsBoolean.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/JsNumber.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/JsReference.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/JsString.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/Promise.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/annotations.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/js/core.kt (100%) create mode 100644 libraries/stdlib/wasm/js/src/kotlin/random/PlatformRandom.kt rename libraries/stdlib/wasm/{ => js}/src/kotlin/time/Duration.kt (96%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/time/TimeSources.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlin/w3cSupport.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlinx/browser/declarations.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlinx/dom/Builders.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlinx/dom/Classes.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlinx/dom/Dom.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlinx/dom/ItemArrayLike.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/kotlinx/dom/Mutations.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.khronos.webgl.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.css.masking.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.clipboard.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.css.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.encryptedmedia.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.events.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.mediacapture.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.mediasource.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.parsing.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.pointerevents.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.svg.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.dom.url.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.fetch.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.files.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.notifications.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.performance.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.workers.kt (100%) rename libraries/stdlib/wasm/{ => js}/src/org.w3c/org.w3c.xhr.kt (100%) create mode 100644 libraries/stdlib/wasm/src/kotlin/Serializable.kt rename libraries/stdlib/wasm/{test => testJs}/js/AsyncTest.kt (86%) create mode 100644 libraries/stdlib/wasm/testJs/unsafe/MemoryAllocationJsTest.kt create mode 100644 libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt create mode 100644 libraries/stdlib/wasm/wasi/src/kotlin/WasiError.kt create mode 100644 libraries/stdlib/wasm/wasi/src/kotlin/io.kt create mode 100644 libraries/stdlib/wasm/wasi/src/kotlin/random/PlatformRandom.kt create mode 100644 libraries/stdlib/wasm/wasi/src/kotlin/time/Duration.kt create mode 100644 libraries/stdlib/wasm/wasi/src/kotlin/time/TimeSources.kt diff --git a/libraries/stdlib/wasm/build.gradle.kts b/libraries/stdlib/wasm/build.gradle.kts index bf4541514d4..c9b85b0ee1e 100644 --- a/libraries/stdlib/wasm/build.gradle.kts +++ b/libraries/stdlib/wasm/build.gradle.kts @@ -1,4 +1,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCompile +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetAttribute import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink @@ -81,14 +83,20 @@ kotlin { @Suppress("DEPRECATION") @OptIn(org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl::class) wasm("wasm") { - d8() + nodejs() + } + + fun KotlinSourceSet.addWasmMainDirs() { + kotlin.srcDirs("builtins", "internal", "runtime", "src", "stubs") + kotlin.srcDirs("$rootDir/libraries/stdlib/native-wasm/src") + kotlin.srcDirs(files(builtInsSources.map { it.destinationDir })) } sourceSets { named("wasmMain") { - kotlin.srcDirs("builtins", "internal", "runtime", "src", "stubs") - kotlin.srcDirs("$rootDir/libraries/stdlib/native-wasm/src") - kotlin.srcDirs(files(builtInsSources.map { it.destinationDir })) + addWasmMainDirs() +// kotlin.srcDirs("js/builtins/kotlin", "js/internal", "js/src/kotlin", "js/src/kotlinx", "js/src/org.w3c") + kotlin.srcDirs("wasi/builtins/kotlin", "wasi/internal", "wasi/src/kotlin", "wasi/src/kotlinx") } named("commonMain") { @@ -153,8 +161,17 @@ val compileTestDevelopmentExecutableKotlinWasm = tasks.named("co (this as KotlinCompile<*>).kotlinOptions.freeCompilerArgs += listOf("-Xwasm-enable-array-range-checks") } -val runtimeElements by configurations.creating {} -val apiElements by configurations.creating {} +val runtimeElements by configurations.creating { + attributes { + attributes.attribute(KotlinWasmTargetAttribute.wasmTargetAttribute, KotlinWasmTargetAttribute.js) + } +} + +val apiElements by configurations.creating { + attributes { + attributes.attribute(KotlinWasmTargetAttribute.wasmTargetAttribute, KotlinWasmTargetAttribute.js) + } +} publish(sbom = false) { pom.packaging = "klib" diff --git a/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt b/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt index ca47635834f..50919e6a08a 100644 --- a/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt @@ -3,50 +3,4 @@ * 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 - -import kotlin.wasm.internal.ExternalInterfaceType -import kotlin.wasm.internal.getSimpleName -import kotlin.wasm.internal.jsToKotlinStringAdapter - -/** - * The base class for all errors and exceptions. Only instances of this class can be thrown or caught. - * - * @param message the detail message string. - * @param cause the cause of this throwable. - */ -public open class Throwable(open val message: String?, open val cause: kotlin.Throwable?) { - constructor(message: String?) : this(message, null) - - constructor(cause: Throwable?) : this(cause?.toString(), cause) - - constructor() : this(null, null) - - internal val jsStack: ExternalInterfaceType = captureStackTrace() - - private var _stack: String? = null - internal val stack: String - get() { - var value = _stack - if (value == null) { - value = jsToKotlinStringAdapter(jsStack).removePrefix("Error\n") - _stack = value - } - - return value - } - - internal var suppressedExceptionsList: MutableList? = null - - /** - * Returns the short description of this throwable consisting of the exception class name - * followed by the exception message if it is not null. - */ - public override fun toString(): String { - val s = getSimpleName(this.typeInfo) - return if (message != null) s + ": " + message.toString() else s - } -} - -private fun captureStackTrace(): ExternalInterfaceType = - js("new Error().stack") +package kotlin \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/ExceptionHelpers.kt b/libraries/stdlib/wasm/internal/ExceptionHelpers.kt new file mode 100644 index 00000000000..b4219a2e01d --- /dev/null +++ b/libraries/stdlib/wasm/internal/ExceptionHelpers.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2022 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/LICENSE.txt file. + */ + +package kotlin.wasm.internal + +internal var isNotFirstWasmExportCall: Boolean = false \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/ExternalWrapper.kt b/libraries/stdlib/wasm/internal/ExternalWrapper.kt new file mode 100644 index 00000000000..5c04d203b7c --- /dev/null +++ b/libraries/stdlib/wasm/internal/ExternalWrapper.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2021 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/LICENSE.txt file. + */ + +package kotlin.wasm.internal + +@Suppress("UNUSED_PARAMETER") +@ExcludedFromCodegen +/* +* Compiler generates inplace next code: +* ``` +* block (result anyref) { +* local.get 0 +* extern.internalize +* br_on_cast_fail 0000_0011b 0 (type any) (type $kotlin.Any) +* return +* } +* ``` +*/ +internal fun returnArgumentIfItIsKotlinAny(): Unit = implementedAsIntrinsic \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt index ddc71351011..98dbcbb9fb4 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 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/LICENSE.txt file. */ @@ -9,8 +9,6 @@ package kotlin.wasm.internal -import kotlin.wasm.internal.ExternalInterfaceType - @WasmOp(WasmOp.UNREACHABLE) internal fun wasm_unreachable(): Nothing = implementedAsIntrinsic @@ -495,10 +493,4 @@ internal fun wasm_i64_popcnt(a: Long): Long = @PublishedApi @WasmOp(WasmOp.I64_CTZ) internal fun wasm_i64_ctz(a: Long): Long = - implementedAsIntrinsic - -// Reference type operators - -@WasmOp(WasmOp.REF_IS_NULL) -internal external fun wasm_externref_is_null(a: ExternalInterfaceType?): Boolean = implementedAsIntrinsic \ No newline at end of file diff --git a/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt b/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt new file mode 100644 index 00000000000..ca47635834f --- /dev/null +++ b/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2022 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/LICENSE.txt file. + */ + +package kotlin + +import kotlin.wasm.internal.ExternalInterfaceType +import kotlin.wasm.internal.getSimpleName +import kotlin.wasm.internal.jsToKotlinStringAdapter + +/** + * The base class for all errors and exceptions. Only instances of this class can be thrown or caught. + * + * @param message the detail message string. + * @param cause the cause of this throwable. + */ +public open class Throwable(open val message: String?, open val cause: kotlin.Throwable?) { + constructor(message: String?) : this(message, null) + + constructor(cause: Throwable?) : this(cause?.toString(), cause) + + constructor() : this(null, null) + + internal val jsStack: ExternalInterfaceType = captureStackTrace() + + private var _stack: String? = null + internal val stack: String + get() { + var value = _stack + if (value == null) { + value = jsToKotlinStringAdapter(jsStack).removePrefix("Error\n") + _stack = value + } + + return value + } + + internal var suppressedExceptionsList: MutableList? = null + + /** + * Returns the short description of this throwable consisting of the exception class name + * followed by the exception message if it is not null. + */ + public override fun toString(): String { + val s = getSimpleName(this.typeInfo) + return if (message != null) s + ": " + message.toString() else s + } +} + +private fun captureStackTrace(): ExternalInterfaceType = + js("new Error().stack") diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt b/libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt similarity index 92% rename from libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt rename to libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt index 893899e0680..241d9a27639 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt +++ b/libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt @@ -18,6 +18,4 @@ private fun throwJsError(message: String?, wasmTypeName: String?, stack: Externa internal fun throwAsJsException(t: Throwable): Nothing { throwJsError(t.message, getSimpleName(t.typeInfo), t.jsStack) -} - -internal var isNotFirstWasmExportCall: Boolean = false \ No newline at end of file +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt b/libraries/stdlib/wasm/js/internal/ExternalWrapper.kt similarity index 96% rename from libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt rename to libraries/stdlib/wasm/js/internal/ExternalWrapper.kt index afc5eb0a0e7..044a892f03c 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt +++ b/libraries/stdlib/wasm/js/internal/ExternalWrapper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 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/LICENSE.txt file. */ @@ -145,21 +145,6 @@ private fun Any.asWasmExternRef(): ExternalInterfaceType = internal fun isNullish(ref: ExternalInterfaceType?): Boolean = js("ref == null") -@Suppress("UNUSED_PARAMETER") -@ExcludedFromCodegen -/* -* Compiler generates inplace next code: -* ``` -* block (result anyref) { -* local.get 0 -* extern.internalize -* br_on_cast_fail 0000_0011b 0 (type any) (type $kotlin.Any) -* return -* } -* ``` -*/ -internal fun returnArgumentIfItIsKotlinAny(): Unit = implementedAsIntrinsic - internal fun externRefToAny(ref: ExternalInterfaceType): Any? { // TODO rewrite it so to get something like: // block { diff --git a/libraries/stdlib/wasm/js/internal/WasmInstructions.kt b/libraries/stdlib/wasm/js/internal/WasmInstructions.kt new file mode 100644 index 00000000000..e0ffed318a7 --- /dev/null +++ b/libraries/stdlib/wasm/js/internal/WasmInstructions.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2023 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/LICENSE.txt file. + */ + +@file:ExcludedFromCodegen +@file:Suppress("unused", "NON_ABSTRACT_FUNCTION_WITH_NO_BODY", "INLINE_CLASS_IN_EXTERNAL_DECLARATION", "UNUSED_PARAMETER") + + +package kotlin.wasm.internal + +import kotlin.wasm.internal.ExternalInterfaceType + +// Reference type operators + +@WasmOp(WasmOp.REF_IS_NULL) +internal external fun wasm_externref_is_null(a: ExternalInterfaceType?): Boolean diff --git a/libraries/stdlib/wasm/src/kotlin/Dynamic.kt b/libraries/stdlib/wasm/js/src/kotlin/Dynamic.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/Dynamic.kt rename to libraries/stdlib/wasm/js/src/kotlin/Dynamic.kt diff --git a/libraries/stdlib/wasm/src/kotlin/JsInterop.kt b/libraries/stdlib/wasm/js/src/kotlin/JsInterop.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/JsInterop.kt rename to libraries/stdlib/wasm/js/src/kotlin/JsInterop.kt diff --git a/libraries/stdlib/wasm/src/kotlin/io.kt b/libraries/stdlib/wasm/js/src/kotlin/io.kt similarity index 87% rename from libraries/stdlib/wasm/src/kotlin/io.kt rename to libraries/stdlib/wasm/js/src/kotlin/io.kt index 4a058a9475f..96aa45e8598 100644 --- a/libraries/stdlib/wasm/src/kotlin/io.kt +++ b/libraries/stdlib/wasm/js/src/kotlin/io.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 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/LICENSE.txt file. */ @@ -37,6 +37,4 @@ public actual fun print(message: Any?) { public actual fun readln(): String = throw UnsupportedOperationException("readln is not supported in Kotlin/WASM") @SinceKotlin("1.6") -public actual fun readlnOrNull(): String? = throw UnsupportedOperationException("readlnOrNull is not supported in Kotlin/WASM") - -internal actual interface Serializable \ No newline at end of file +public actual fun readlnOrNull(): String? = throw UnsupportedOperationException("readlnOrNull is not supported in Kotlin/WASM") \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/js/JsAny.kt b/libraries/stdlib/wasm/js/src/kotlin/js/JsAny.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/JsAny.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/JsAny.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/JsArray.kt b/libraries/stdlib/wasm/js/src/kotlin/js/JsArray.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/JsArray.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/JsArray.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/JsBoolean.kt b/libraries/stdlib/wasm/js/src/kotlin/js/JsBoolean.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/JsBoolean.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/JsBoolean.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/JsNumber.kt b/libraries/stdlib/wasm/js/src/kotlin/js/JsNumber.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/JsNumber.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/JsNumber.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/JsReference.kt b/libraries/stdlib/wasm/js/src/kotlin/js/JsReference.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/JsReference.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/JsReference.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/JsString.kt b/libraries/stdlib/wasm/js/src/kotlin/js/JsString.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/JsString.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/JsString.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/Promise.kt b/libraries/stdlib/wasm/js/src/kotlin/js/Promise.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/Promise.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/Promise.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/annotations.kt b/libraries/stdlib/wasm/js/src/kotlin/js/annotations.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/annotations.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/annotations.kt diff --git a/libraries/stdlib/wasm/src/kotlin/js/core.kt b/libraries/stdlib/wasm/js/src/kotlin/js/core.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/js/core.kt rename to libraries/stdlib/wasm/js/src/kotlin/js/core.kt diff --git a/libraries/stdlib/wasm/js/src/kotlin/random/PlatformRandom.kt b/libraries/stdlib/wasm/js/src/kotlin/random/PlatformRandom.kt new file mode 100644 index 00000000000..e2a7749d26b --- /dev/null +++ b/libraries/stdlib/wasm/js/src/kotlin/random/PlatformRandom.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 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/LICENSE.txt file. + */ + +package kotlin.random + +private fun initialSeed(): Int = + js("((Math.random() * Math.pow(2, 32)) | 0)") + +internal actual fun defaultPlatformRandom(): Random = + Random(initialSeed()) \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/time/Duration.kt b/libraries/stdlib/wasm/js/src/kotlin/time/Duration.kt similarity index 96% rename from libraries/stdlib/wasm/src/kotlin/time/Duration.kt rename to libraries/stdlib/wasm/js/src/kotlin/time/Duration.kt index 03edf9e9b48..d4690d62551 100644 --- a/libraries/stdlib/wasm/src/kotlin/time/Duration.kt +++ b/libraries/stdlib/wasm/js/src/kotlin/time/Duration.kt @@ -23,7 +23,6 @@ internal actual fun formatToExactDecimals(value: Double, decimals: Int): String } else { val pow = (10.0).pow(decimals) round(abs(value) * pow) / pow * sign(value) - round(abs(value) * pow) / pow * sign(value) } return if (abs(rounded) < 1e21) { // toFixed switches to scientific format after 1e21 diff --git a/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt b/libraries/stdlib/wasm/js/src/kotlin/time/TimeSources.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt rename to libraries/stdlib/wasm/js/src/kotlin/time/TimeSources.kt diff --git a/libraries/stdlib/wasm/src/kotlin/w3cSupport.kt b/libraries/stdlib/wasm/js/src/kotlin/w3cSupport.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlin/w3cSupport.kt rename to libraries/stdlib/wasm/js/src/kotlin/w3cSupport.kt diff --git a/libraries/stdlib/wasm/src/kotlinx/browser/declarations.kt b/libraries/stdlib/wasm/js/src/kotlinx/browser/declarations.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlinx/browser/declarations.kt rename to libraries/stdlib/wasm/js/src/kotlinx/browser/declarations.kt diff --git a/libraries/stdlib/wasm/src/kotlinx/dom/Builders.kt b/libraries/stdlib/wasm/js/src/kotlinx/dom/Builders.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlinx/dom/Builders.kt rename to libraries/stdlib/wasm/js/src/kotlinx/dom/Builders.kt diff --git a/libraries/stdlib/wasm/src/kotlinx/dom/Classes.kt b/libraries/stdlib/wasm/js/src/kotlinx/dom/Classes.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlinx/dom/Classes.kt rename to libraries/stdlib/wasm/js/src/kotlinx/dom/Classes.kt diff --git a/libraries/stdlib/wasm/src/kotlinx/dom/Dom.kt b/libraries/stdlib/wasm/js/src/kotlinx/dom/Dom.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlinx/dom/Dom.kt rename to libraries/stdlib/wasm/js/src/kotlinx/dom/Dom.kt diff --git a/libraries/stdlib/wasm/src/kotlinx/dom/ItemArrayLike.kt b/libraries/stdlib/wasm/js/src/kotlinx/dom/ItemArrayLike.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlinx/dom/ItemArrayLike.kt rename to libraries/stdlib/wasm/js/src/kotlinx/dom/ItemArrayLike.kt diff --git a/libraries/stdlib/wasm/src/kotlinx/dom/Mutations.kt b/libraries/stdlib/wasm/js/src/kotlinx/dom/Mutations.kt similarity index 100% rename from libraries/stdlib/wasm/src/kotlinx/dom/Mutations.kt rename to libraries/stdlib/wasm/js/src/kotlinx/dom/Mutations.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.khronos.webgl.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.khronos.webgl.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.khronos.webgl.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.khronos.webgl.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.css.masking.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.css.masking.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.css.masking.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.css.masking.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.clipboard.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.clipboard.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.clipboard.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.clipboard.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.css.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.css.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.css.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.css.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.encryptedmedia.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.encryptedmedia.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.encryptedmedia.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.encryptedmedia.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.events.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.events.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.events.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.events.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.mediacapture.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.mediacapture.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.mediacapture.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.mediacapture.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.mediasource.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.mediasource.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.mediasource.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.mediasource.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.parsing.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.parsing.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.parsing.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.parsing.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.pointerevents.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.pointerevents.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.pointerevents.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.pointerevents.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.svg.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.svg.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.svg.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.svg.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.url.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.url.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.dom.url.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.dom.url.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.fetch.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.fetch.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.fetch.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.fetch.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.files.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.files.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.files.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.files.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.notifications.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.notifications.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.notifications.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.notifications.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.performance.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.performance.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.performance.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.performance.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.workers.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.workers.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.workers.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.workers.kt diff --git a/libraries/stdlib/wasm/src/org.w3c/org.w3c.xhr.kt b/libraries/stdlib/wasm/js/src/org.w3c/org.w3c.xhr.kt similarity index 100% rename from libraries/stdlib/wasm/src/org.w3c/org.w3c.xhr.kt rename to libraries/stdlib/wasm/js/src/org.w3c/org.w3c.xhr.kt diff --git a/libraries/stdlib/wasm/src/kotlin/Serializable.kt b/libraries/stdlib/wasm/src/kotlin/Serializable.kt new file mode 100644 index 00000000000..cde7b7ce3b3 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/Serializable.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2023 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/LICENSE.txt file. + */ + +package kotlin.io + +internal actual interface Serializable \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt b/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt index 149f9873099..87454ca7ece 100644 --- a/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt +++ b/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt @@ -5,11 +5,5 @@ package kotlin.random -private fun initialSeed(): Int = - js("((Math.random() * Math.pow(2, 32)) | 0)") - -internal actual fun defaultPlatformRandom(): Random = - Random(initialSeed()) - internal actual fun doubleFromParts(hi26: Int, low27: Int): Double = (hi26.toLong().shl(27) + low27) / (1L shl 53).toDouble() diff --git a/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt b/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt index d4563cca4c6..9397ef0654e 100644 --- a/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt +++ b/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt @@ -3,9 +3,6 @@ package test.wasm.unsafe import kotlin.wasm.unsafe.* import kotlin.test.* -private fun jsConcatStrings(a: String, b: String): String = - js("a + b") - @OptIn(UnsafeWasmMemoryApi::class) class MemoryAllocationTest { val pageSize = 65_536 @@ -128,14 +125,6 @@ class MemoryAllocationTest { assertTrue(max1 < min1_1) } - @Test - fun testJsIntropInsideAllocations() { - withScopedMemoryAllocator { allocator -> - assertEquals(jsConcatStrings("str1", "str2"), "str1str2") - allocator.allocate(10) - } - } - @Test fun testNestedAllocatorThrows() { var leakedAllocator1: MemoryAllocator? = null diff --git a/libraries/stdlib/wasm/test/js/AsyncTest.kt b/libraries/stdlib/wasm/testJs/js/AsyncTest.kt similarity index 86% rename from libraries/stdlib/wasm/test/js/AsyncTest.kt rename to libraries/stdlib/wasm/testJs/js/AsyncTest.kt index 9d929ffc5f6..0948138129c 100644 --- a/libraries/stdlib/wasm/test/js/AsyncTest.kt +++ b/libraries/stdlib/wasm/testJs/js/AsyncTest.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2010-2023 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/LICENSE.txt file. + */ + package test.js import kotlin.js.* diff --git a/libraries/stdlib/wasm/testJs/unsafe/MemoryAllocationJsTest.kt b/libraries/stdlib/wasm/testJs/unsafe/MemoryAllocationJsTest.kt new file mode 100644 index 00000000000..d5547353256 --- /dev/null +++ b/libraries/stdlib/wasm/testJs/unsafe/MemoryAllocationJsTest.kt @@ -0,0 +1,18 @@ +package test.wasm.unsafe + +import kotlin.wasm.unsafe.* +import kotlin.test.* + +private fun jsConcatStrings(a: String, b: String): String = + js("a + b") + +@OptIn(UnsafeWasmMemoryApi::class) +class MemoryAllocationJsTest { + @Test + fun testJsIntropInsideAllocations() { + withScopedMemoryAllocator { allocator -> + assertEquals(jsConcatStrings("str1", "str2"), "str1str2") + allocator.allocate(10) + } + } +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt b/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt new file mode 100644 index 00000000000..12156b91a45 --- /dev/null +++ b/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2022 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/LICENSE.txt file. + */ + +package kotlin + +import kotlin.wasm.internal.getSimpleName + +/** + * The base class for all errors and exceptions. Only instances of this class can be thrown or caught. + * + * @param message the detail message string. + * @param cause the cause of this throwable. + */ +public open class Throwable(open val message: String?, open val cause: kotlin.Throwable?) { + constructor(message: String?) : this(message, null) + + constructor(cause: Throwable?) : this(cause?.toString(), cause) + + constructor() : this(null, null) + + //TODO: Investigate possibility to make WASI stack discoverable (KT-60965) + internal val stack: String get() = "" + + internal var suppressedExceptionsList: MutableList? = null + + /** + * Returns the short description of this throwable consisting of the exception class name + * followed by the exception message if it is not null. + */ + public override fun toString(): String { + val s = getSimpleName(this.typeInfo) + return if (message != null) s + ": " + message.toString() else s + } +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/wasi/src/kotlin/WasiError.kt b/libraries/stdlib/wasm/wasi/src/kotlin/WasiError.kt new file mode 100644 index 00000000000..ead5bbbac80 --- /dev/null +++ b/libraries/stdlib/wasm/wasi/src/kotlin/WasiError.kt @@ -0,0 +1,398 @@ +/* + * Copyright 2010-2023 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/LICENSE.txt file. + */ + +package kotlin.wasm + +/** + * [WASI Error codes for preview1](https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md) + */ +internal enum class WasiErrorCode { + /** + * No error occurred. System call completed successfully. + */ + SUCCESS, + + /** + * Argument list too long. + */ + _2BIG, + + /** + * Permission denied. + */ + ACCES, + + /** + * Address in use. + */ + ADDRINUSE, + + /** + * Address not available. + */ + ADDRNOTAVAIL, + + /** + * Address family not supported. + */ + AFNOSUPPORT, + + /** + * Resource unavailable, or operation would block. + */ + AGAIN, + + /** + * Connection already in progress. + */ + ALREADY, + + /** + * Bad file descriptor. + */ + BADF, + + /** + * Bad message. + */ + BADMSG, + + /** + * Device or resource busy. + */ + BUSY, + + /** + * Operation canceled. + */ + CANCELED, + + /** + * No child processes. + */ + CHILD, + + /** + * Connection aborted. + */ + CONNABORTED, + + /** + * Connection refused. + */ + CONNREFUSED, + + /** + * Connection reset. + */ + CONNRESET, + + /** + * Resource deadlock would occur. + */ + DEADLK, + + /** + * Destination address required. + */ + DESTADDRREQ, + + /** + * Mathematics argument out of domain of function. + */ + DOM, + + /** + * Reserved. + */ + DQUOT, + + /** + * File exists. + */ + EXIST, + + /** + * Bad address. + */ + FAULT, + + /** + * File too large. + */ + FBIG, + + /** + * Host is unreachable. + */ + HOSTUNREACH, + + /** + * Identifier removed. + */ + IDRM, + + /** + * Illegal byte sequence. + */ + ILSEQ, + + /** + * Operation in progress. + */ + INPROGRESS, + + /** + * Interrupted function. + */ + INTR, + + /** + * Invalid argument. + */ + INVAL, + + /** + * I/O error. + */ + IO, + + /** + * Socket is connected. + */ + ISCONN, + + /** + * Is a directory. + */ + ISDIR, + + /** + * Too many levels of symbolic links. + */ + LOOP, + + /** + * File descriptor value too large. + */ + MFILE, + + /** + * Too many links. + */ + MLINK, + + /** + * Message too large. + */ + MSGSIZE, + + /** + * Reserved. + */ + MULTIHOP, + + /** + * Filename too long. + */ + NAMETOOLONG, + + /** + * Network is down. + */ + NETDOWN, + + /** + * Connection aborted by network. + */ + NETRESET, + + /** + * Network unreachable. + */ + NETUNREACH, + + /** + * Too many files open in system. + */ + NFILE, + + /** + * No buffer space available. + */ + NOBUFS, + + /** + * No such device. + */ + NODEV, + + /** + * No such file or directory. + */ + NOENT, + + /** + * Executable file format error. + */ + NOEXEC, + + /** + * No locks available. + */ + NOLCK, + + /** + * Reserved. + */ + NOLINK, + + /** + * Not enough space. + */ + NOMEM, + + /** + * No message of the desired type. + */ + NOMSG, + + /** + * Protocol not available. + */ + NOPROTOOPT, + + /** + * No space left on device. + */ + NOSPC, + + /** + * Function not supported. + */ + NOSYS, + + /** + * The socket is not connected. + */ + NOTCONN, + + /** + * Not a directory or a symbolic link to a directory. + */ + NOTDIR, + + /** + * Directory not empty. + */ + NOTEMPTY, + + /** + * State not recoverable. + */ + NOTRECOVERABLE, + + /** + * Not a socket. + */ + NOTSOCK, + + /** + * Not supported, or operation not supported on socket. + */ + NOTSUP, + + /** + * Inappropriate I/O control operation. + */ + NOTTY, + + /** + * No such device or address. + */ + NXIO, + + /** + * Value too large to be stored in data type. + */ + OVERFLOW, + + /** + * Previous owner died. + */ + OWNERDEAD, + + /** + * Operation not permitted. + */ + PERM, + + /** + * Broken pipe. + */ + PIPE, + + /** + * Protocol error. + */ + PROTO, + + /** + * Protocol not supported. + */ + PROTONOSUPPORT, + + /** + * Protocol wrong type for socket. + */ + PROTOTYPE, + + /** + * Result too large. + */ + RANGE, + + /** + * Read-only file system. + */ + ROFS, + + /** + * Invalid seek. + */ + SPIPE, + + /** + * No such process. + */ + SRCH, + + /** + * Reserved. + */ + STALE, + + /** + * Connection timed out. + */ + TIMEDOUT, + + /** + * Text file busy. + */ + TXTBSY, + + /** + * Cross-device link. + */ + XDEV, + + /** + * Extension: Capabilities insufficient. + */ + NOTCAPABLE, +} + +internal class WasiError(val error: WasiErrorCode) : Throwable(message = "WASI call failed with $error") diff --git a/libraries/stdlib/wasm/wasi/src/kotlin/io.kt b/libraries/stdlib/wasm/wasi/src/kotlin/io.kt new file mode 100644 index 00000000000..49460fa6292 --- /dev/null +++ b/libraries/stdlib/wasm/wasi/src/kotlin/io.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2020 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/LICENSE.txt file. + */ + +package kotlin.io + +import kotlin.wasm.WasiError +import kotlin.wasm.WasiErrorCode +import kotlin.wasm.WasmImport +import kotlin.wasm.unsafe.MemoryAllocator +import kotlin.wasm.unsafe.withScopedMemoryAllocator + +private const val STDOUT = 1 +private const val STDERR = 2 + +/** + * Write to a file descriptor. Note: This is similar to `writev` in POSIX. + */ +@WasmImport("wasi_snapshot_preview1", "fd_write") +private external fun wasiRawFdWrite(descriptor: Int, scatterPtr: Int, scatterSize: Int, errorPtr: Int): Int + +internal fun wasiPrintImpl( + allocator: MemoryAllocator, + data: ByteArray?, + newLine: Boolean, + useErrorStream: Boolean +) { + val dataSize = data?.size ?: 0 + val memorySize = dataSize + (if (newLine) 1 else 0) + if (memorySize == 0) return + + val ptr = allocator.allocate(memorySize) + if (data != null) { + var currentPtr = ptr + for (el in data) { + currentPtr.storeByte(el) + currentPtr += 1 + } + } + if (newLine) { + (ptr + dataSize).storeByte(0x0A) + } + + val scatterPtr = allocator.allocate(8) + (scatterPtr + 0).storeInt(ptr.address.toInt()) + (scatterPtr + 4).storeInt(memorySize) + + val rp0 = allocator.allocate(4) + + val ret = + wasiRawFdWrite( + descriptor = if (useErrorStream) STDERR else STDOUT, + scatterPtr = scatterPtr.address.toInt(), + scatterSize = 1, + errorPtr = rp0.address.toInt() + ) + + if (ret != 0) { + throw WasiError(WasiErrorCode.values()[ret]) + } +} + +private fun printImpl(message: String?, useErrorStream: Boolean, newLine: Boolean) { + withScopedMemoryAllocator { allocator -> + wasiPrintImpl( + allocator = allocator, + data = message?.encodeToByteArray(), + newLine = newLine, + useErrorStream = useErrorStream, + ) + } +} + +internal fun printError(error: String?) { + printImpl(error, useErrorStream = true, newLine = false) +} + +/** Prints the line separator to the standard output stream. */ +public actual fun println() { + printImpl(null, useErrorStream = false, newLine = true) +} + +/** Prints the given [message] and the line separator to the standard output stream. */ +public actual fun println(message: Any?) { + printImpl(message?.toString(), useErrorStream = false, newLine = true) +} + +/** Prints the given [message] to the standard output stream. */ +public actual fun print(message: Any?) { + printImpl(message?.toString(), useErrorStream = false, newLine = false) +} + +@SinceKotlin("1.6") +public actual fun readln(): String = TODO("wasi") + +@SinceKotlin("1.6") +public actual fun readlnOrNull(): String? = TODO("wasi") \ No newline at end of file diff --git a/libraries/stdlib/wasm/wasi/src/kotlin/random/PlatformRandom.kt b/libraries/stdlib/wasm/wasi/src/kotlin/random/PlatformRandom.kt new file mode 100644 index 00000000000..55758085736 --- /dev/null +++ b/libraries/stdlib/wasm/wasi/src/kotlin/random/PlatformRandom.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2020 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/LICENSE.txt file. + */ + +package kotlin.random + +import kotlin.wasm.WasiError +import kotlin.wasm.WasiErrorCode +import kotlin.wasm.WasmImport +import kotlin.wasm.unsafe.withScopedMemoryAllocator + +/** + * Write high-quality random data into a buffer. This function blocks when the implementation is + * unable to immediately provide sufficient high-quality random data. This function may execute + * slowly, so when large mounts of random data are required, it's advisable to use this function to + * seed a pseudo-random number generator, rather than to provide the random data directly. + */ +@WasmImport("wasi_snapshot_preview1", "random_get") +//TODO: Better to use 64-bit Long as a seed if possible. (KT-60962) +internal external fun wasiRawRandomGet(address: Int, size: Int): Int + +private fun wasiRandomGet(): Int { + withScopedMemoryAllocator { allocator -> + val memory = allocator.allocate(Int.SIZE_BYTES) + val ret = wasiRawRandomGet(memory.address.toInt(), Int.SIZE_BYTES) + return if (ret == 0) { + memory.loadInt() + } else { + throw WasiError(WasiErrorCode.values()[ret]) + } + } +} + +internal actual fun defaultPlatformRandom(): Random = + Random(wasiRandomGet()) \ No newline at end of file diff --git a/libraries/stdlib/wasm/wasi/src/kotlin/time/Duration.kt b/libraries/stdlib/wasm/wasi/src/kotlin/time/Duration.kt new file mode 100644 index 00000000000..af80d8851ca --- /dev/null +++ b/libraries/stdlib/wasm/wasi/src/kotlin/time/Duration.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2022 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/LICENSE.txt file. + */ + +package kotlin.time + +import kotlin.math.fdlibm.__ieee754_pow + +internal actual fun formatToExactDecimals(value: Double, decimals: Int): String { + // TODO Make correct implementation (KT-60964) + val pow = __ieee754_pow(10.0, decimals.toDouble()) + val round = kotlin.math.fdlibm.rint(value * pow) + return (round / pow).toString() +} + +internal actual fun formatUpToDecimals(value: Double, decimals: Int): String = TODO("Wasi Implement") + +internal actual inline val durationAssertionsEnabled: Boolean get() = true \ No newline at end of file diff --git a/libraries/stdlib/wasm/wasi/src/kotlin/time/TimeSources.kt b/libraries/stdlib/wasm/wasi/src/kotlin/time/TimeSources.kt new file mode 100644 index 00000000000..f1cdefb2498 --- /dev/null +++ b/libraries/stdlib/wasm/wasi/src/kotlin/time/TimeSources.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2022 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/LICENSE.txt file. + */ + +package kotlin.time + +import kotlin.time.Duration.Companion.nanoseconds +import kotlin.time.TimeSource.Monotonic.ValueTimeMark +import kotlin.wasm.WasiError +import kotlin.wasm.WasiErrorCode +import kotlin.wasm.WasmImport +import kotlin.wasm.unsafe.Pointer +import kotlin.wasm.unsafe.withScopedMemoryAllocator + +private const val MONOTONIC = 1 + +/** + * Return the time value of a clock. Note: This is similar to `clock_gettime` in POSIX. + */ +@WasmImport("wasi_snapshot_preview1", "clock_time_get") +private external fun wasiRawClockTimeGet(clockId: Int, precision: Long, resultPtr: Int): Int + +private fun clockTimeGet(): Long = withScopedMemoryAllocator { allocator -> + val rp0 = allocator.allocate(8) + val ret = wasiRawClockTimeGet( + clockId = MONOTONIC, + precision = 1, + resultPtr = rp0.address.toInt() + ) + if (ret == 0) { + (Pointer(rp0.address.toInt().toUInt())).loadLong() + } else { + throw WasiError(WasiErrorCode.values()[ret]) + } +} + +@SinceKotlin("1.3") +//TODO: Try use implementation of K/JVM since it uses a Long nanosecond counter similar to System.nanoTime (KT-60963) +internal actual object MonotonicTimeSource : TimeSource.WithComparableMarks { + actual override fun markNow(): ValueTimeMark = + ValueTimeMark(clockTimeGet()) + + actual fun elapsedFrom(timeMark: ValueTimeMark): Duration = + (clockTimeGet() - timeMark.reading).nanoseconds + + actual fun adjustReading(timeMark: ValueTimeMark, duration: Duration): ValueTimeMark = + ValueTimeMark(timeMark.reading + duration.toLong(DurationUnit.NANOSECONDS)) + + actual fun differenceBetween(one: ValueTimeMark, another: ValueTimeMark): Duration { + val ms1 = one.reading + val ms2 = another.reading + return if (ms1 == ms2) Duration.ZERO else (ms1 - ms2).nanoseconds + } + + override fun toString(): String = "WASI monotonic time source" +} + +@Suppress("ACTUAL_WITHOUT_EXPECT") // visibility +internal actual typealias ValueTimeMarkReading = Long \ No newline at end of file