Skip to content

Commit 2725652

Browse files
committed
Add Wasm WASI target
1 parent 375cef8 commit 2725652

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

core/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ kotlin {
129129
}
130130
}
131131

132+
wasmWasi {
133+
nodejs()
134+
}
135+
132136
@OptIn(ExperimentalKotlinGradlePluginApi::class)
133137
compilerOptions {
134138
freeCompilerArgs.add("-Xexpect-actual-classes")
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2019-2024 JetBrains s.r.o. and contributors.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.datetime.internal
7+
8+
import kotlinx.datetime.Instant
9+
import kotlin.wasm.WasmImport
10+
import kotlin.wasm.unsafe.UnsafeWasmMemoryApi
11+
import kotlin.wasm.unsafe.withScopedMemoryAllocator
12+
13+
/**
14+
* Return the time value of a clock. Note: This is similar to `clock_gettime` in POSIX.
15+
*/
16+
@WasmImport("wasi_snapshot_preview1", "clock_time_get")
17+
private external fun wasiRawClockTimeGet(clockId: Int, precision: Long, resultPtr: Int): Int
18+
19+
private const val CLOCKID_REALTIME = 0
20+
21+
@OptIn(UnsafeWasmMemoryApi::class)
22+
private fun clockTimeGet(): Long = withScopedMemoryAllocator { allocator ->
23+
val rp0 = allocator.allocate(8)
24+
val ret = wasiRawClockTimeGet(
25+
clockId = CLOCKID_REALTIME,
26+
precision = 1,
27+
resultPtr = rp0.address.toInt()
28+
)
29+
if (ret == 0) {
30+
rp0.loadLong()
31+
} else {
32+
error("WASI call failed with $ret")
33+
}
34+
}
35+
36+
internal actual fun currentTime(): Instant = clockTimeGet().let { time ->
37+
// Instant.MAX and Instant.MIN are never going to be exceeded using just the Long number of nanoseconds
38+
Instant(time.floorDiv(NANOS_PER_ONE.toLong()), time.mod(NANOS_PER_ONE.toLong()).toInt())
39+
}
40+
41+
internal actual fun currentSystemDefaultZone(): Pair<String, TimeZoneRules?> =
42+
throw UnsupportedOperationException("WASI platform does not support system timezone obtaining")
43+
44+
internal actual val systemTzdb: TimeZoneDatabase = TzdbOnData()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2019-2023 JetBrains s.r.o. and contributors.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.datetime.internal
7+
8+
import kotlinx.datetime.IllegalTimeZoneException
9+
10+
@RequiresOptIn
11+
internal annotation class InternalDateTimeApi
12+
13+
/*
14+
This is internal API which is not intended to use on user-side.
15+
*/
16+
@InternalDateTimeApi
17+
public interface TimeZonesProvider {
18+
public fun zoneDataByName(name: String): ByteArray
19+
public fun getTimeZones(): Set<String>
20+
}
21+
22+
/*
23+
This is internal API which is not intended to use on user-side.
24+
*/
25+
@InternalDateTimeApi
26+
public fun initializeTimeZonesProvider(provider: TimeZonesProvider) {
27+
check(timeZonesProvider != provider) { "TimeZone database redeclaration" }
28+
timeZonesProvider = provider
29+
}
30+
31+
@InternalDateTimeApi
32+
private var timeZonesProvider: TimeZonesProvider? = null
33+
34+
internal class TzdbOnData: TimeZoneDatabase {
35+
override fun rulesForId(id: String): TimeZoneRules {
36+
@OptIn(InternalDateTimeApi::class)
37+
val data = timeZonesProvider?.zoneDataByName(id)
38+
?: throw IllegalTimeZoneException("TimeZones are not supported")
39+
return readTzFile(data).toTimeZoneRules()
40+
}
41+
42+
override fun availableTimeZoneIds(): Set<String> =
43+
@OptIn(InternalDateTimeApi::class)
44+
timeZonesProvider?.getTimeZones() ?: emptySet()
45+
}

serialization/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ kotlin {
5858
}
5959
}
6060

61+
wasmWasi {
62+
nodejs {
63+
}
64+
}
65+
6166
sourceSets.all {
6267
val suffixIndex = name.indexOfLast { it.isUpperCase() }
6368
val targetName = name.substring(0, suffixIndex)
@@ -103,6 +108,9 @@ kotlin {
103108
}
104109
}
105110

111+
val wasmWasiMain by getting
112+
val wasmWasiTest by getting
113+
106114
val nativeMain by getting
107115
val nativeTest by getting
108116
}

0 commit comments

Comments
 (0)