From 107d81f27bc27dcdffc3e51b882881f3881276af Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Mon, 29 Jul 2024 11:24:57 -0400 Subject: [PATCH] Revert "Remove Wasm JS support (#2207)" This reverts commit 3bc9242a9543f2131225d6bde5a9c09860c0c4bf. --- CHANGELOG.md | 2 +- .../buildsupport/RedwoodBuildPlugin.kt | 2 + redwood-compose/api/redwood-compose.klib.api | 2 +- .../api/redwood-layout-api.klib.api | 2 +- .../api/redwood-layout-compose.klib.api | 2 +- .../api/redwood-layout-modifiers.klib.api | 2 +- .../api/redwood-layout-testing.klib.api | 2 +- .../api/redwood-layout-widget.klib.api | 2 +- .../api/redwood-lazylayout-api.klib.api | 2 +- .../api/redwood-lazylayout-compose.klib.api | 2 +- .../api/redwood-lazylayout-testing.klib.api | 2 +- .../api/redwood-lazylayout-widget.klib.api | 2 +- .../api/redwood-leak-detector.klib.api | 2 +- redwood-leak-detector/build.gradle | 12 ++++++ .../redwood/leaks/ConcurrentMutableList.kt | 39 +++++++++++++++++++ .../kotlin/app/cash/redwood/leaks/Gc.kt | 36 +++++++++++++++++ .../app/cash/redwood/leaks/WeakReference.kt | 37 ++++++++++++++++++ .../app/cash/redwood/leaks/delayForGc.kt | 28 +++++++++++++ .../api/redwood-protocol-guest.klib.api | 2 +- .../api/redwood-protocol-host.klib.api | 2 +- .../api/redwood-protocol.klib.api | 2 +- redwood-runtime/api/redwood-runtime.klib.api | 2 +- .../kotlin/app/cash/redwood/ui/density.kt | 18 +++++++++ redwood-testing/api/redwood-testing.klib.api | 2 +- .../api/redwood-widget-compose.klib.api | 2 +- .../api/redwood-widget-testing.klib.api | 2 +- redwood-widget/api/redwood-widget.klib.api | 2 +- 27 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/ConcurrentMutableList.kt create mode 100644 redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/Gc.kt create mode 100644 redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/WeakReference.kt create mode 100644 redwood-leak-detector/src/wasmJsTest/kotlin/app/cash/redwood/leaks/delayForGc.kt create mode 100644 redwood-runtime/src/wasmJsMain/kotlin/app/cash/redwood/ui/density.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3416f611ed..a29a2ef8e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ New: - Nothing yet! Changed: -- Removed Wasm JS targets for common Redwood modules. They are causing CI problems, and we're not ready for Wasm anyway. +- Nothing yet! Fixed: - Nothing yet! diff --git a/build-support/src/main/kotlin/app/cash/redwood/buildsupport/RedwoodBuildPlugin.kt b/build-support/src/main/kotlin/app/cash/redwood/buildsupport/RedwoodBuildPlugin.kt index 4bd89373bf..41fac481b6 100644 --- a/build-support/src/main/kotlin/app/cash/redwood/buildsupport/RedwoodBuildPlugin.kt +++ b/build-support/src/main/kotlin/app/cash/redwood/buildsupport/RedwoodBuildPlugin.kt @@ -302,6 +302,7 @@ private class RedwoodBuildExtensionImpl(private val project: Project) : RedwoodB iosTargets() modifiedGroup[JsTests, NodeJs].applyTo(js()) jvm() + wasmJs().nodejs() } // Needed for lint in downstream Android projects to analyze this dependency. project.plugins.apply("com.android.lint") @@ -313,6 +314,7 @@ private class RedwoodBuildExtensionImpl(private val project: Project) : RedwoodB iosTargets() modifiedGroup[JsTests, NodeJs].applyTo(js()) jvm() + wasmJs().nodejs() } } Tooling -> { diff --git a/redwood-compose/api/redwood-compose.klib.api b/redwood-compose/api/redwood-compose.klib.api index 54650daccb..6a7021400d 100644 --- a/redwood-compose/api/redwood-compose.klib.api +++ b/redwood-compose/api/redwood-compose.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Alias: ios => [iosArm64, iosSimulatorArm64, iosX64] // Rendering settings: // - Signature version: 2 diff --git a/redwood-layout-api/api/redwood-layout-api.klib.api b/redwood-layout-api/api/redwood-layout-api.klib.api index 58162e1229..afc878af94 100644 --- a/redwood-layout-api/api/redwood-layout-api.klib.api +++ b/redwood-layout-api/api/redwood-layout-api.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-layout-compose/api/redwood-layout-compose.klib.api b/redwood-layout-compose/api/redwood-layout-compose.klib.api index f7fd5a8343..e73035eb1a 100644 --- a/redwood-layout-compose/api/redwood-layout-compose.klib.api +++ b/redwood-layout-compose/api/redwood-layout-compose.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-layout-modifiers/api/redwood-layout-modifiers.klib.api b/redwood-layout-modifiers/api/redwood-layout-modifiers.klib.api index 6abacfeb67..deb13e07fc 100644 --- a/redwood-layout-modifiers/api/redwood-layout-modifiers.klib.api +++ b/redwood-layout-modifiers/api/redwood-layout-modifiers.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-layout-testing/api/redwood-layout-testing.klib.api b/redwood-layout-testing/api/redwood-layout-testing.klib.api index dd0a895ad9..19b0f256b0 100644 --- a/redwood-layout-testing/api/redwood-layout-testing.klib.api +++ b/redwood-layout-testing/api/redwood-layout-testing.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-layout-widget/api/redwood-layout-widget.klib.api b/redwood-layout-widget/api/redwood-layout-widget.klib.api index f61c11d6f2..ffe7bd3853 100644 --- a/redwood-layout-widget/api/redwood-layout-widget.klib.api +++ b/redwood-layout-widget/api/redwood-layout-widget.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-lazylayout-api/api/redwood-lazylayout-api.klib.api b/redwood-lazylayout-api/api/redwood-lazylayout-api.klib.api index ebc4890077..94e7810b93 100644 --- a/redwood-lazylayout-api/api/redwood-lazylayout-api.klib.api +++ b/redwood-lazylayout-api/api/redwood-lazylayout-api.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-lazylayout-compose/api/redwood-lazylayout-compose.klib.api b/redwood-lazylayout-compose/api/redwood-lazylayout-compose.klib.api index 9bc991ec52..d29619e0b8 100644 --- a/redwood-lazylayout-compose/api/redwood-lazylayout-compose.klib.api +++ b/redwood-lazylayout-compose/api/redwood-lazylayout-compose.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-lazylayout-testing/api/redwood-lazylayout-testing.klib.api b/redwood-lazylayout-testing/api/redwood-lazylayout-testing.klib.api index cd0c56b963..bb3889ec03 100644 --- a/redwood-lazylayout-testing/api/redwood-lazylayout-testing.klib.api +++ b/redwood-lazylayout-testing/api/redwood-lazylayout-testing.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-lazylayout-widget/api/redwood-lazylayout-widget.klib.api b/redwood-lazylayout-widget/api/redwood-lazylayout-widget.klib.api index 1cd63198c7..7f350c9a49 100644 --- a/redwood-lazylayout-widget/api/redwood-lazylayout-widget.klib.api +++ b/redwood-lazylayout-widget/api/redwood-lazylayout-widget.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-leak-detector/api/redwood-leak-detector.klib.api b/redwood-leak-detector/api/redwood-leak-detector.klib.api index 93922d6700..0efecb4448 100644 --- a/redwood-leak-detector/api/redwood-leak-detector.klib.api +++ b/redwood-leak-detector/api/redwood-leak-detector.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-leak-detector/build.gradle b/redwood-leak-detector/build.gradle index ce9a36f01e..2a0ce94910 100644 --- a/redwood-leak-detector/build.gradle +++ b/redwood-leak-detector/build.gradle @@ -18,6 +18,18 @@ kotlin { } } } + wasmJs { + nodejs { + testTask { + useMocha { + // We use up to 10s of wall clock time to test leaks. + timeout = '15s' + // Required for access to V8 GC function. + nodeJsArgs.add('--expose-gc') + } + } + } + } sourceSets { commonMain { diff --git a/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/ConcurrentMutableList.kt b/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/ConcurrentMutableList.kt new file mode 100644 index 0000000000..2a3a43a794 --- /dev/null +++ b/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/ConcurrentMutableList.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@file:Suppress("NOTHING_TO_INLINE") + +package app.cash.redwood.leaks + +internal actual typealias ConcurrentMutableList = ArrayList + +internal actual inline fun concurrentMutableListOf(): ConcurrentMutableList { + return arrayListOf() +} + +internal actual inline operator fun ConcurrentMutableList.plusAssign(element: T) { + add(element) +} + +internal actual inline fun ConcurrentMutableList.removeIf(predicate: (element: T) -> Boolean) { + var i = 0 + while (i < size) { + if (predicate(get(i))) { + removeAt(i) + } else { + i++ + } + } +} diff --git a/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/Gc.kt b/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/Gc.kt new file mode 100644 index 0000000000..678760833e --- /dev/null +++ b/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/Gc.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package app.cash.redwood.leaks + +private external val globalThis: GlobalThis + +private external class GlobalThis { + fun hasOwnProperty(name: String): Boolean + fun gc() +} + +internal actual fun detectGc(): Gc { + if (globalThis.hasOwnProperty("gc")) { + return GlobalThisGc() + } + return Gc.None +} + +private class GlobalThisGc : Gc { + override suspend fun collect() { + globalThis.gc() + } +} diff --git a/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/WeakReference.kt b/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/WeakReference.kt new file mode 100644 index 0000000000..c4e6bf2fb2 --- /dev/null +++ b/redwood-leak-detector/src/wasmJsMain/kotlin/app/cash/redwood/leaks/WeakReference.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@file:Suppress("NOTHING_TO_INLINE") + +package app.cash.redwood.leaks + +internal actual inline fun hasWeakReference(): Boolean { + return true +} + +internal actual class WeakReference +private constructor( + private val real: WeakRef>, +) { + actual constructor(referred: T) : this(WeakRef(referred.toJsReference())) + + actual fun get(): T? { + return real.deref()?.get() + } +} + +private external class WeakRef(reference: T) { + fun deref(): T? +} diff --git a/redwood-leak-detector/src/wasmJsTest/kotlin/app/cash/redwood/leaks/delayForGc.kt b/redwood-leak-detector/src/wasmJsTest/kotlin/app/cash/redwood/leaks/delayForGc.kt new file mode 100644 index 0000000000..ff2742f3be --- /dev/null +++ b/redwood-leak-detector/src/wasmJsTest/kotlin/app/cash/redwood/leaks/delayForGc.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package app.cash.redwood.leaks + +import kotlin.time.Duration +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext + +internal actual suspend fun delayForGc(duration: Duration) { + // Force a wall clock delay for JS Gc. + withContext(Dispatchers.Default) { + delay(duration) + } +} diff --git a/redwood-protocol-guest/api/redwood-protocol-guest.klib.api b/redwood-protocol-guest/api/redwood-protocol-guest.klib.api index 38939bb436..7d559c09da 100644 --- a/redwood-protocol-guest/api/redwood-protocol-guest.klib.api +++ b/redwood-protocol-guest/api/redwood-protocol-guest.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-protocol-host/api/redwood-protocol-host.klib.api b/redwood-protocol-host/api/redwood-protocol-host.klib.api index 96c18ae145..327e90bef7 100644 --- a/redwood-protocol-host/api/redwood-protocol-host.klib.api +++ b/redwood-protocol-host/api/redwood-protocol-host.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-protocol/api/redwood-protocol.klib.api b/redwood-protocol/api/redwood-protocol.klib.api index 9caf13558c..f44fa18db3 100644 --- a/redwood-protocol/api/redwood-protocol.klib.api +++ b/redwood-protocol/api/redwood-protocol.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-runtime/api/redwood-runtime.klib.api b/redwood-runtime/api/redwood-runtime.klib.api index bc01a56ee8..88c29a8fa7 100644 --- a/redwood-runtime/api/redwood-runtime.klib.api +++ b/redwood-runtime/api/redwood-runtime.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Alias: ios => [iosArm64, iosSimulatorArm64, iosX64] // Rendering settings: // - Signature version: 2 diff --git a/redwood-runtime/src/wasmJsMain/kotlin/app/cash/redwood/ui/density.kt b/redwood-runtime/src/wasmJsMain/kotlin/app/cash/redwood/ui/density.kt new file mode 100644 index 0000000000..4d3a7460d3 --- /dev/null +++ b/redwood-runtime/src/wasmJsMain/kotlin/app/cash/redwood/ui/density.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package app.cash.redwood.ui + +internal actual const val DENSITY_MULTIPLIER = 1.0 diff --git a/redwood-testing/api/redwood-testing.klib.api b/redwood-testing/api/redwood-testing.klib.api index 6871c1def2..59d10afb37 100644 --- a/redwood-testing/api/redwood-testing.klib.api +++ b/redwood-testing/api/redwood-testing.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-widget-compose/api/redwood-widget-compose.klib.api b/redwood-widget-compose/api/redwood-widget-compose.klib.api index d6bde99cb8..55b6bcb0d5 100644 --- a/redwood-widget-compose/api/redwood-widget-compose.klib.api +++ b/redwood-widget-compose/api/redwood-widget-compose.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-widget-testing/api/redwood-widget-testing.klib.api b/redwood-widget-testing/api/redwood-widget-testing.klib.api index 7c7c38a184..7b2326ccc7 100644 --- a/redwood-widget-testing/api/redwood-widget-testing.klib.api +++ b/redwood-widget-testing/api/redwood-widget-testing.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/redwood-widget/api/redwood-widget.klib.api b/redwood-widget/api/redwood-widget.klib.api index ce12f8e6b8..6d65845e96 100644 --- a/redwood-widget/api/redwood-widget.klib.api +++ b/redwood-widget/api/redwood-widget.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, wasmJs] // Alias: ios => [iosArm64, iosSimulatorArm64, iosX64] // Rendering settings: // - Signature version: 2