Browse Source

Introduce wasmJsBrowserDistribution task (#5375)

## Testing
Clone https://github.com/Schahen/ComposeWebApp and run 
```
 ./gradlew  :composeApp: composeCompatibilityBrowserDistribution
```

## Release Notes
### Features - Web
- Introduce composeCompatibilityBrowserDistribution task. This task
combines two prod distributions - for js and for wasm in such way so
that if modern require features are not supported by the consumer
browser, application switch to js mode.

---------

Co-authored-by: Oleksandr Karpovich <a.n.karpovich@gmail.com>
Co-authored-by: Konstantin Tskhovrebov <konstantin.tskhovrebov@jetbrains.com>
pull/5377/head v1.9.0+dev2724
Shagen Ogandzhanian 5 months ago committed by GitHub
parent
commit
64200ba5e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt
  2. 3
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt
  3. 173
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/tasks/WebCompatibilityTask.kt
  4. 66
      gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/CompatibilityDistributionTest.kt
  5. 1
      gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt
  6. 1
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/.yarnrc
  7. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/build.gradle.kts
  8. 56
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/build.gradle.kts
  9. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/jsMain/kotlin/org/example/project/Platform.kt
  10. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/wasmJsMain/kotlin/org/example/project/Platform.kt
  11. 9
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/kotlin/Greeting.kt
  12. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/kotlin/Platform.kt
  13. 5
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/kotlin/main.kt
  14. 13
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/resources/index.html
  15. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/resources/styles.css
  16. 6
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/gradle/libs.versions.toml
  17. 41
      gradle-plugins/compose/src/test/test-projects/application/webJsWasm/settings.gradle.kts
  18. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/build.gradle.kts
  19. 56
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/build.gradle.kts
  20. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webJsMain/kotlin/org/example/project/Platform.kt
  21. 9
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/kotlin/Greeting.kt
  22. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/kotlin/Platform.kt
  23. 5
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/kotlin/main.kt
  24. 13
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/resources/index.html
  25. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/resources/styles.css
  26. 7
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webWasmMain/kotlin/org/example/project/Platform.kt
  27. 6
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/gradle/libs.versions.toml
  28. 41
      gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/settings.gradle.kts

3
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt

@ -27,6 +27,7 @@ import org.jetbrains.compose.resources.ResourcesExtension @@ -27,6 +27,7 @@ import org.jetbrains.compose.resources.ResourcesExtension
import org.jetbrains.compose.resources.configureComposeResources
import org.jetbrains.compose.web.WebExtension
import org.jetbrains.compose.web.internal.configureWeb
import org.jetbrains.compose.web.tasks.configureWebCompatibility
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
internal val composeVersion get() = ComposeBuildConfig.composeVersion
@ -52,6 +53,8 @@ abstract class ComposePlugin : Plugin<Project> { @@ -52,6 +53,8 @@ abstract class ComposePlugin : Plugin<Project> {
project.configureComposeResources(resourcesExtension)
project.configureWebCompatibility()
project.afterEvaluate {
configureDesktop(project, desktopExtension)
project.configureWeb(composeExtension)

3
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt

@ -10,7 +10,6 @@ import org.gradle.api.artifacts.Configuration @@ -10,7 +10,6 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.artifacts.UnresolvedDependency
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Copy
import org.gradle.language.jvm.tasks.ProcessResources
@ -21,9 +20,7 @@ import org.jetbrains.compose.internal.utils.file @@ -21,9 +20,7 @@ import org.jetbrains.compose.internal.utils.file
import org.jetbrains.compose.internal.utils.registerTask
import org.jetbrains.compose.web.WebExtension
import org.jetbrains.compose.web.tasks.UnpackSkikoWasmRuntimeTask
import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import org.jetbrains.kotlin.gradle.tasks.IncrementalSyncTask
internal fun Project.configureWeb(
composeExt: ComposeExtension,

173
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/tasks/WebCompatibilityTask.kt

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
package org.jetbrains.compose.web.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID
import org.jetbrains.compose.internal.mppExt
import org.jetbrains.compose.internal.utils.clearDirs
import org.jetbrains.compose.internal.utils.joinLowerCamelCase
import org.jetbrains.compose.internal.utils.registerTask
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
import java.io.File
import javax.inject.Inject
abstract class WebCompatibilityTask : DefaultTask() {
@get:Inject
internal abstract val fileOperations: FileSystemOperations
@get:OutputDirectory
abstract val outputDir: DirectoryProperty
@get:InputFiles
abstract val jsDistFiles: ConfigurableFileCollection
@get:InputFiles
abstract val wasmDistFiles: ConfigurableFileCollection
@get:Input
@get:Optional
abstract val jsOutputName: Property<String>
@get:Input
@get:Optional
abstract val wasmOutputName: Property<String>
@TaskAction
fun run() {
val prefix = "origin"
val jsAppFileName = jsOutputName.get()
val jsAppRenamed = joinLowerCamelCase(prefix, "js", jsAppFileName)
val wasmAppFileName = wasmOutputName.get()
val wasmAppRenamed = joinLowerCamelCase(prefix, "wasm", wasmAppFileName)
fileOperations.clearDirs(outputDir)
fileOperations.copy { copySpec ->
copySpec.duplicatesStrategy = DuplicatesStrategy.WARN
copySpec.from(jsDistFiles) {
it.rename { name ->
when (name) {
jsAppFileName -> jsAppRenamed
"${jsAppFileName}.map" -> "${jsAppRenamed}.map"
else -> name
}
}
}
copySpec.from(wasmDistFiles) {
it.rename { name ->
when (name) {
wasmAppFileName -> wasmAppRenamed
"${wasmAppFileName}.map" -> "${wasmAppRenamed}.map"
else -> name
}
}
}
copySpec.into(outputDir)
}
val fallbackResolverCode = """
const simpleWasmModule = new Uint8Array([
0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 95,
1, 120, 0, 96, 0, 0, 3, 3, 2, 1, 1, 10,
14, 2, 6, 0, 6, 64, 25, 11, 11, 5, 0, 208,
112, 26, 11, 0, 45, 4, 110, 97, 109, 101, 1, 15,
2, 0, 5, 102, 117, 110, 99, 48, 1, 5, 102, 117,
110, 99, 49, 4, 8, 1, 0, 5, 116, 121, 112, 101,
48, 10, 11, 1, 0, 1, 0, 6, 102, 105, 101, 108,
100, 48
]);
const hasSupportOfAllRequiredWasmFeatures = () =>
typeof WebAssembly !== "undefined" &&
typeof WebAssembly?.validate === "function" &&
WebAssembly.validate(simpleWasmModule);
const createScript = (src) => {
const script = document.createElement("script");
script.src = src;
script.type = "application/javascript";
return script;
}
if (hasSupportOfAllRequiredWasmFeatures()) {
document.body.appendChild(createScript('$wasmAppRenamed'));
} else {
document.body.appendChild(createScript('$jsAppRenamed'));
}
""".trimIndent()
val outputDir = outputDir.get().asFile
File(outputDir, jsAppFileName).writeText(fallbackResolverCode)
File(outputDir, wasmAppFileName).writeText(fallbackResolverCode)
}
}
private fun Project.registerWebCompatibilityTask(mppPlugin: KotlinMultiplatformExtension) =
registerTask<WebCompatibilityTask>("composeCompatibilityBrowserDistribution") {
group = "compose"
description =
"This task combines both js and wasm distributions into one so that wasm application fallback to js target if modern wasm feature are not supported"
val webProductionDist = layout.buildDirectory.dir("dist/composeWebCompatibility/productionExecutable")
outputDir.set(webProductionDist)
mppPlugin.targets.withType(KotlinJsIrTarget::class.java).configureEach { target ->
if (target.platformType == KotlinPlatformType.wasm) {
wasmOutputName.set(
tasks.named(
"${target.name}BrowserProductionWebpack",
KotlinWebpack::class.java
).flatMap { it.mainOutputFileName }
)
wasmDistFiles.from(
tasks.named("${target.name}BrowserDistribution").map { it.outputs.files }
)
} else if (target.platformType == KotlinPlatformType.js) {
jsOutputName.set(
tasks.named(
"${target.name}BrowserProductionWebpack",
KotlinWebpack::class.java
).flatMap { it.mainOutputFileName }
)
jsDistFiles.from(
tasks.named("${target.name}BrowserDistribution").map { it.outputs.files }
)
}
onlyIf {
val hasBothDistributions = !jsDistFiles.isEmpty && !wasmDistFiles.isEmpty
val hasBothOutputs = jsOutputName.orNull != null && wasmOutputName.orNull != null
if (!hasBothDistributions) {
logger.lifecycle("Task ${this.name} skipped: no js and wasm distributions found, both are required for compatibility")
} else if (!hasBothOutputs) {
logger.lifecycle("Task ${this.name} skipped: no js and wasm output names specified")
}
hasBothDistributions && hasBothOutputs
}
}
}
internal fun Project.configureWebCompatibility() {
plugins.withId(KOTLIN_MPP_PLUGIN_ID) {
project.registerWebCompatibilityTask(mppExt)
}
}

66
gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/CompatibilityDistributionTest.kt

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package org.jetbrains.compose.test.tests.integration
import org.gradle.internal.impldep.junit.framework.TestCase.assertTrue
import org.jetbrains.compose.test.utils.GradlePluginTestBase
import org.jetbrains.compose.test.utils.checkExists
import org.jetbrains.compose.test.utils.checks
import org.junit.jupiter.api.Test
import kotlin.test.assertContentEquals
class CompatibilityDistributionTest : GradlePluginTestBase() {
@Test
fun testWebJsWasm() = with(
testProject(
"application/webJsWasm",
testEnvironment = defaultTestEnvironment.copy()
)
) {
gradle(":composeApp:composeCompatibilityBrowserDistribution").checks {
check.taskSuccessful(":composeApp:composeCompatibilityBrowserDistribution")
check.taskSuccessful(":composeApp:jsBrowserDistribution")
check.taskSuccessful(":composeApp:wasmJsBrowserDistribution")
file("./composeApp/build/dist/composeWebCompatibility/productionExecutable").apply {
checkExists()
assertTrue(isDirectory)
val distributionFiles = listFiles()!!.map { it.name }.toList().sorted()
assertTrue(distributionFiles.any { it.endsWith(".wasm") })
assertContentEquals(distributionFiles.filter { !it.endsWith(".wasm") }, listOf(
"composeApp.js", "composeResources", "index.html", "originJsComposeApp.js", "originJsComposeApp.js.map", "originWasmComposeApp.js", "originWasmComposeApp.js.map", "styles.css"
))
}
}
}
@Test
fun testWebJsWasmNonStandard() = with(
testProject(
"application/webJsWasmNonStandard",
testEnvironment = defaultTestEnvironment.copy()
)
) {
gradle(":composeApp:composeCompatibilityBrowserDistribution").checks {
check.taskSuccessful(":composeApp:composeCompatibilityBrowserDistribution")
check.taskSuccessful(":composeApp:webJsBrowserDistribution")
check.taskSuccessful(":composeApp:webWasmBrowserDistribution")
file("./composeApp/build/dist/composeWebCompatibility/productionExecutable").apply {
checkExists()
assertTrue(isDirectory)
val distributionFiles = listFiles()!!.map { it.name }.toList().sorted()
assertTrue(distributionFiles.any { it.endsWith(".wasm") })
println(distributionFiles.filter { !it.endsWith(".wasm") }.sorted().joinToString(", ") { "\"$it\"" })
assertContentEquals(distributionFiles.filter { !it.endsWith(".wasm") }, listOf(
"composeApp.js", "composeResources", "index.html", "originJsComposeApp.js", "originJsComposeApp.js.map", "originWasmComposeApp.js", "originWasmComposeApp.js.map", "styles.css"
))
}
}
}
}

1
gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt

@ -24,6 +24,7 @@ import java.net.SocketTimeoutException @@ -24,6 +24,7 @@ import java.net.SocketTimeoutException
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.thread
import kotlin.test.assertContentEquals
import kotlin.test.assertFalse
class GradlePluginTest : GradlePluginTestBase() {

1
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/.yarnrc

@ -0,0 +1 @@ @@ -0,0 +1 @@
--install.mutex network

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/build.gradle.kts

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
plugins {
// this is necessary to avoid the plugins to be loaded multiple times
// in each subproject's classloader
id("org.jetbrains.kotlin.multiplatform") apply false
id("org.jetbrains.compose") apply false
id("org.jetbrains.kotlin.plugin.compose") apply false
}

56
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/build.gradle.kts

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
plugins {
id("org.jetbrains.kotlin.multiplatform")
id("org.jetbrains.compose")
id("org.jetbrains.kotlin.plugin.compose")
}
kotlin {
js(IR) {
outputModuleName.set("composeApp")
browser {
commonWebpackConfig {
outputFileName = "composeApp.js"
}
}
binaries.executable()
}
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
outputModuleName.set("composeApp")
browser {
val rootDirPath = project.rootDir.path
val projectDirPath = project.projectDir.path
commonWebpackConfig {
outputFileName = "composeApp.js"
}
}
binaries.executable()
}
// Simple task that prints "Hello World" to the console
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
}
val webMain by creating {
resources.setSrcDirs(resources.srcDirs)
dependsOn(commonMain.get())
}
val jsMain by getting {
dependsOn(webMain)
}
val wasmJsMain by getting {
dependsOn(webMain)
}
}
}

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/jsMain/kotlin/org/example/project/Platform.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package org.example.project
private class JsPlatform : Platform {
override val name: String = "Web with Kotlin/JS"
}
actual fun getPlatform(): Platform = JsPlatform()

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/wasmJsMain/kotlin/org/example/project/Platform.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package org.example.project
private class WasmPlatform : Platform {
override val name: String = "Web with Kotlin/Wasm"
}
actual fun getPlatform(): Platform = WasmPlatform()

9
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/kotlin/Greeting.kt

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
package org.example.project
class Greeting {
private val platform = getPlatform()
fun greet(): String {
return "Hello, ${platform.name}!"
}
}

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/kotlin/Platform.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package org.example.project
interface Platform {
val name: String
}
expect fun getPlatform(): Platform

5
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/kotlin/main.kt

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
package org.example.project
fun main() {
println(Greeting().greet())
}

13
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/resources/index.html

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KotlinProject</title>
<link type="text/css" rel="stylesheet" href="styles.css">
</head>
<body>
</body>
<script type="application/javascript" src="composeApp.js"></script>
</html>

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/composeApp/src/webMain/resources/styles.css

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}

6
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/gradle/libs.versions.toml

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
[versions]
androidx-lifecycle = "2.9.1"
[libraries]
androidx-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }

41
gradle-plugins/compose/src/test/test-projects/application/webJsWasm/settings.gradle.kts

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
rootProject.name = "WebJsMain"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
plugins {
id("org.jetbrains.kotlin.multiplatform") version "KOTLIN_VERSION_PLACEHOLDER"
id("org.jetbrains.kotlin.plugin.compose") version "KOTLIN_VERSION_PLACEHOLDER"
id("org.jetbrains.compose") version "COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER"
}
repositories {
mavenLocal()
google {
mavenContent {
includeGroupAndSubgroups("androidx")
includeGroupAndSubgroups("com.android")
includeGroupAndSubgroups("com.google")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
mavenLocal()
maven {
url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
google {
mavenContent {
includeGroupAndSubgroups("androidx")
includeGroupAndSubgroups("com.android")
includeGroupAndSubgroups("com.google")
}
}
mavenCentral()
}
}
include(":composeApp")

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/build.gradle.kts

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
plugins {
// this is necessary to avoid the plugins to be loaded multiple times
// in each subproject's classloader
id("org.jetbrains.kotlin.multiplatform") apply false
id("org.jetbrains.compose") apply false
id("org.jetbrains.kotlin.plugin.compose") apply false
}

56
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/build.gradle.kts

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
plugins {
id("org.jetbrains.kotlin.multiplatform")
id("org.jetbrains.compose")
id("org.jetbrains.kotlin.plugin.compose")
}
kotlin {
js(name = "webJs", IR) {
outputModuleName.set("composeApp")
browser {
commonWebpackConfig {
outputFileName = "composeApp.js"
}
}
binaries.executable()
}
@OptIn(ExperimentalWasmDsl::class)
wasmJs(name = "webWasm") {
outputModuleName.set("composeApp")
browser {
val rootDirPath = project.rootDir.path
val projectDirPath = project.projectDir.path
commonWebpackConfig {
outputFileName = "composeApp.js"
}
}
binaries.executable()
}
// Simple task that prints "Hello World" to the console
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
}
val webMain by creating {
resources.setSrcDirs(resources.srcDirs)
dependsOn(commonMain.get())
}
val webJsMain by getting {
dependsOn(webMain)
}
val webWasmMain by getting {
dependsOn(webMain)
}
}
}

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webJsMain/kotlin/org/example/project/Platform.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package org.example.project
private class JsPlatform : Platform {
override val name: String = "Web with Kotlin/JS"
}
actual fun getPlatform(): Platform = JsPlatform()

9
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/kotlin/Greeting.kt

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
package org.example.project
class Greeting {
private val platform = getPlatform()
fun greet(): String {
return "Hello, ${platform.name}!"
}
}

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/kotlin/Platform.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package org.example.project
interface Platform {
val name: String
}
expect fun getPlatform(): Platform

5
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/kotlin/main.kt

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
package org.example.project
fun main() {
println(Greeting().greet())
}

13
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/resources/index.html

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KotlinProject</title>
<link type="text/css" rel="stylesheet" href="styles.css">
</head>
<body>
</body>
<script type="application/javascript" src="composeApp.js"></script>
</html>

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webMain/resources/styles.css

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}

7
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/composeApp/src/webWasmMain/kotlin/org/example/project/Platform.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package org.example.project
private class WasmPlatform : Platform {
override val name: String = "Web with Kotlin/Wasm"
}
actual fun getPlatform(): Platform = WasmPlatform()

6
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/gradle/libs.versions.toml

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
[versions]
androidx-lifecycle = "2.9.1"
[libraries]
androidx-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }

41
gradle-plugins/compose/src/test/test-projects/application/webJsWasmNonStandard/settings.gradle.kts

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
rootProject.name = "WebJsMain"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement {
plugins {
id("org.jetbrains.kotlin.multiplatform") version "KOTLIN_VERSION_PLACEHOLDER"
id("org.jetbrains.kotlin.plugin.compose") version "KOTLIN_VERSION_PLACEHOLDER"
id("org.jetbrains.compose") version "COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER"
}
repositories {
mavenLocal()
google {
mavenContent {
includeGroupAndSubgroups("androidx")
includeGroupAndSubgroups("com.android")
includeGroupAndSubgroups("com.google")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
mavenLocal()
maven {
url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
google {
mavenContent {
includeGroupAndSubgroups("androidx")
includeGroupAndSubgroups("com.android")
includeGroupAndSubgroups("com.google")
}
}
mavenCentral()
}
}
include(":composeApp")
Loading…
Cancel
Save