Skip to content

Commit

Permalink
Add wasm target (#92)
Browse files Browse the repository at this point in the history
* Add kotlin wasmJs target

* Add wasm test strategy to GitHub action

* Fix to run wasm test tasks in ci
  • Loading branch information
xxfast committed Apr 29, 2024
1 parent 75ce1d6 commit e4fc084
Show file tree
Hide file tree
Showing 14 changed files with 1,009 additions and 34 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
{ target: windows, os: windows-latest, tasks: windowsTest, continueOnError: true }, # https://github.com/square/okio/issues/951
{ target: linux, os: ubuntu-latest, tasks: linuxTest, continueOnError: false },
{ target: js, os: ubuntu-latest, tasks: jsTest, continueOnError: false },
{ target: wasm, os: ubuntu-latest, tasks: wasmJsTest, continueOnError: false },
{ target: desktop, os: ubuntu-latest, tasks: desktopTest, continueOnError: false },
]
runs-on: ${{ matrix.config.os }}
Expand Down
2 changes: 0 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,3 @@ allprojects {
koverMerged {
enable()
}


4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ androidx-test-junit = "1.1.5"
junit = "4.13.2"
junit-jupiter="5.9.3"
kotlin = "1.9.22"
kotlinx-coroutines = "1.7.3"
kotlinx-coroutines = "1.8.0"
kotlinx-serialization = "1.6.2"
okio = "3.9.0"
turbine = "1.0.0"
turbine = "1.1.0"

[libraries]
agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
Expand Down
896 changes: 881 additions & 15 deletions kotlin-js-store/yarn.lock

Large diffs are not rendered by default.

33 changes: 31 additions & 2 deletions kstore-storage/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask

plugins {
kotlin("multiplatform")
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2"
Expand All @@ -10,15 +14,21 @@ kotlin {
browser()
}

@OptIn(ExperimentalWasmDsl::class)
wasmJs {
binaries.executable()
browser()
}

sourceSets {
val jsMain by getting {
val commonMain by getting {
dependencies {
implementation(project(":kstore"))
implementation(libs.kotlinx.serialization.json)
}
}

val jsTest by getting {
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test)
Expand All @@ -27,4 +37,23 @@ kotlin {
}
}

//
// TODO: https://youtrack.jetbrains.com/issue/KT-63014/Running-tests-with-wasmJs-in-1.9.20-requires-Chrome-Canary#focus=Comments-27-8321383.0-0
// The following is required to support the wasmJs target.
//
// Node.js Canary is set to 21.0.0-v8-canary20231019bd785be450
// as that is the last version to ship Windows binaries too.
//

rootProject.extensions.configure<NodeJsRootExtension> {
nodeVersion = "21.0.0-v8-canary20231019bd785be450"
nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary"
}

rootProject.tasks.withType<KotlinNpmInstallTask>().configureEach {
val flag = "--ignore-engines"

if (!args.contains(flag)) {
args.add(flag)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package io.github.xxfast.kstore.storage

import io.github.xxfast.kstore.DefaultJson
import io.github.xxfast.kstore.KStore
import kotlinx.browser.localStorage
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.w3c.dom.Storage

/**
* Creates a store with [StorageCodec]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.github.xxfast.kstore.storage

public expect abstract class Storage

internal expect operator fun Storage.get(key: String): String?

internal expect operator fun Storage.set(key: String, value: String)

internal expect fun Storage.remove(key: String)

internal expect fun Storage.delete()

public expect val localStorage: Storage
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@ package io.github.xxfast.kstore.storage

import io.github.xxfast.kstore.Codec
import io.github.xxfast.kstore.DefaultJson
import kotlinx.browser.localStorage
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
import org.w3c.dom.Storage
import org.w3c.dom.get
import org.w3c.dom.set

public inline fun <reified T : @Serializable Any> StorageCodec(
key: String,
Expand All @@ -30,7 +26,7 @@ public class StorageCodec<T : @Serializable Any>(
) : Codec<T> {
override suspend fun encode(value: T?) {
if (value != null) storage[key] = json.encodeToString(serializer, value)
else storage.removeItem(key)
else storage.remove(key)
}

override suspend fun decode(): T? = storage[key]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package io.github.xxfast.kstore.storage

import io.github.xxfast.kstore.DefaultJson
import kotlinx.browser.localStorage
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.SerializationException
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import org.w3c.dom.get
import org.w3c.dom.set
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertEquals
Expand All @@ -20,12 +16,12 @@ class StorageCodecTests {
get() = localStorage[KEY]?.let { DefaultJson.decodeFromString(it) }
set(value) {
if(value != null) { localStorage[KEY] = DefaultJson.encodeToString(value) }
else localStorage.clear()
else localStorage.delete()
}

@AfterTest
fun cleanUp() {
localStorage.clear()
localStorage.delete()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.github.xxfast.kstore.storage

import org.w3c.dom.Storage
import org.w3c.dom.get
import org.w3c.dom.set

public actual typealias Storage = Storage

internal actual operator fun Storage.get(key: String): String? = this[key]

internal actual operator fun Storage.set(key: String, value: String){
this[key] = value
}

internal actual fun Storage.remove(key: String) = this.removeItem(key)

internal actual fun Storage.delete() = this.clear()

public actual val localStorage: Storage = kotlinx.browser.localStorage
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.github.xxfast.kstore.storage

import org.w3c.dom.Storage
import org.w3c.dom.get
import org.w3c.dom.set

public actual typealias Storage = Storage

internal actual operator fun Storage.get(key: String): String? = this[key]

internal actual operator fun Storage.set(key: String, value: String){
this[key] = value
}

internal actual fun Storage.remove(key: String) = this.removeItem(key)

internal actual fun Storage.delete() = this.clear()

public actual val localStorage: Storage = kotlinx.browser.localStorage
34 changes: 34 additions & 0 deletions kstore/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask

plugins {
kotlin("multiplatform")
id("com.android.library")
Expand Down Expand Up @@ -51,6 +55,12 @@ kotlin {
nodejs()
}

@OptIn(ExperimentalWasmDsl::class)
wasmJs {
browser()
nodejs()
}

val macosX64 = macosX64()
val macosArm64 = macosArm64()
val iosArm64 = iosArm64()
Expand Down Expand Up @@ -116,6 +126,9 @@ kotlin {
val jsMain by getting
val jsTest by getting

val wasmJsMain by getting
val wasmJsTest by getting

val appleMain by creating {
dependsOn(commonMain)
}
Expand All @@ -133,3 +146,24 @@ kotlin {
val windowsTest by getting
}
}

//
// TODO: https://youtrack.jetbrains.com/issue/KT-63014/Running-tests-with-wasmJs-in-1.9.20-requires-Chrome-Canary#focus=Comments-27-8321383.0-0
// The following is required to support the wasmJs target.
//
// Node.js Canary is set to 21.0.0-v8-canary20231019bd785be450
// as that is the last version to ship Windows binaries too.
//

rootProject.extensions.configure<NodeJsRootExtension> {
nodeVersion = "21.0.0-v8-canary20231019bd785be450"
nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary"
}

rootProject.tasks.withType<KotlinNpmInstallTask>().configureEach {
val flag = "--ignore-engines"

if (!args.contains(flag)) {
args.add(flag)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.xxfast.kstore.utils

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

internal actual val StoreDispatcher: CoroutineDispatcher = Dispatchers.Default

0 comments on commit e4fc084

Please sign in to comment.