Skip to content

Commit cbfdc34

Browse files
Update for JSKit 0.11.1, add async task modifier (#457)
I've also moved sources in `TokamakDemo` directory into their respective subdirectories for easier navigation. * Update for JSKit 0.11.0, add async `task` modifier * Add back new file locations to `NativeDemo` * Add compiler `#if` check to `TaskDemo` * Update to JavaScriptKit 0.11.1 * Restrict `TaskDemo` with `compiler(>=5.5)` check * Replace `compiler` with `swift` in some places * Revert "Replace `compiler` with `swift` in some places" This reverts commit 534784c. * Use Xcode 13.2 on GitHub Actions hosts * Find `TokamakPackageTests` in the build directory * Fix macOS tests bundle path * Make `task` modifier available only on macOS Monterey * Revert "Use Xcode 13.2 on GitHub Actions hosts" This reverts commit 63d044f. * Revert "Fix macOS tests bundle path" This reverts commit 3ccbc98. * Revert "Find `TokamakPackageTests` in the build directory" This reverts commit 68c845b. * Use `canImport(Concurrency)` as an ultimate check * Use `compiler(>=5.5) && canImport(Concurrency)` * Clarify new browser version requirements in `README.md` * Account for `_Concurrency` naming * Update `README.md` * Update README.md Co-authored-by: ezraberch <49635435+ezraberch@users.noreply.github.com>
1 parent a5a05b4 commit cbfdc34

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+442
-225
lines changed

NativeDemo/TokamakDemo.xcodeproj/project.pbxproj

+244-174
Large diffs are not rendered by default.

Package.resolved

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"repositoryURL": "https://github.com/swiftwasm/JavaScriptKit.git",
77
"state": {
88
"branch": null,
9-
"revision": "b19e7c8b10a2750ed47753e31ed13613171f3294",
10-
"version": "0.10.1"
9+
"revision": "309e63c03d8116210ad0437f5d1f09a26d4de48b",
10+
"version": "0.11.1"
1111
}
1212
},
1313
{
@@ -24,8 +24,8 @@
2424
"repositoryURL": "https://github.com/swiftwasm/OpenCombineJS.git",
2525
"state": {
2626
"branch": null,
27-
"revision": "eaf324ce78710f53b52fb82e9a8de4693633e33a",
28-
"version": "0.1.1"
27+
"revision": "f1f1799ddbb9876a0ef8c5700a3b78d352d0b969",
28+
"version": "0.1.2"
2929
}
3030
},
3131
{

Package.swift

+28-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,31 @@
44

55
import PackageDescription
66

7+
var tokamakDOMDependencies: [Target.Dependency] = [
8+
"TokamakCore",
9+
"TokamakStaticHTML",
10+
.product(
11+
name: "OpenCombineShim",
12+
package: "OpenCombine"
13+
),
14+
.product(
15+
name: "JavaScriptKit",
16+
package: "JavaScriptKit",
17+
condition: .when(platforms: [.wasi])
18+
),
19+
"OpenCombineJS",
20+
]
21+
22+
#if compiler(>=5.5) && (canImport(Concurrency) || canImport(_Concurrency))
23+
tokamakDOMDependencies.append(
24+
.product(
25+
name: "JavaScriptEventLoop",
26+
package: "JavaScriptKit",
27+
condition: .when(platforms: [.wasi])
28+
)
29+
)
30+
#endif
31+
732
let package = Package(
833
name: "Tokamak",
934
platforms: [
@@ -51,15 +76,15 @@ let package = Package(
5176
// .package(url: /* package url */, from: "1.0.0"),
5277
.package(
5378
url: "https://github.com/swiftwasm/JavaScriptKit.git",
54-
.upToNextMinor(from: "0.10.0")
79+
.upToNextMinor(from: "0.11.1")
5580
),
5681
.package(
5782
url: "https://github.com/OpenCombine/OpenCombine.git",
5883
from: "0.12.0"
5984
),
6085
.package(
6186
url: "https://github.com/swiftwasm/OpenCombineJS.git",
62-
.upToNextMinor(from: "0.1.1")
87+
.upToNextMinor(from: "0.1.2")
6388
),
6489
.package(
6590
name: "Benchmark",
@@ -152,20 +177,7 @@ let package = Package(
152177
),
153178
.target(
154179
name: "TokamakDOM",
155-
dependencies: [
156-
"TokamakCore",
157-
"TokamakStaticHTML",
158-
.product(
159-
name: "OpenCombineShim",
160-
package: "OpenCombine"
161-
),
162-
.product(
163-
name: "JavaScriptKit",
164-
package: "JavaScriptKit",
165-
condition: .when(platforms: [.wasi])
166-
),
167-
"OpenCombineJS",
168-
]
180+
dependencies: tokamakDOMDependencies
169181
),
170182
.executableTarget(
171183
name: "TokamakDemo",

README.md

+17-4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2021 Tokamak contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#if compiler(>=5.5) && (canImport(Concurrency) || canImport(_Concurrency))
16+
17+
public extension View {
18+
func task(
19+
priority: TaskPriority = .userInitiated,
20+
_ action: @escaping @Sendable () async -> ()
21+
) -> some View {
22+
var task: Task<(), Never>?
23+
return onAppear {
24+
task = Task(priority: priority, operation: action)
25+
}
26+
.onDisappear {
27+
task?.cancel()
28+
}
29+
}
30+
}
31+
32+
#endif

Sources/TokamakCore/Shapes/Path/PathLayout.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ public extension Path {
223223

224224
func applying(_ transform: CGAffineTransform) -> Path {
225225
guard transform != .identity else { return self }
226-
let elements = self.elements.map { transform.transform(element: $0) }
226+
let elements = elements.map { transform.transform(element: $0) }
227227
let box = _PathBox(elements: elements)
228228
return Path(storage: .path(box), sizing: .fixed)
229229
}

Sources/TokamakDOM/DOMNode.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ extension AnyHTML {
6060
additionalAttributes: [HTMLAttribute: String],
6161
transaction: Transaction
6262
) {
63-
let attributes = self.attributes.merging(additionalAttributes, uniquingKeysWith: +)
63+
let attributes = attributes.merging(additionalAttributes, uniquingKeysWith: +)
6464

6565
dom.applyAttributes(attributes, with: transaction)
6666

@@ -109,7 +109,9 @@ final class DOMNode: Target {
109109
func reinstall(_ listeners: [String: Listener]) {
110110
for (event, jsClosure) in self.listeners {
111111
_ = ref.removeEventListener!(event, jsClosure)
112+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
112113
jsClosure.release()
114+
#endif
113115
}
114116
self.listeners = [:]
115117

Sources/TokamakDOM/DOMRenderer.swift

+8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ import OpenCombineJS
2020
@_spi(TokamakCore) import TokamakCore
2121
import TokamakStaticHTML
2222

23+
#if compiler(>=5.5) && (canImport(Concurrency) || canImport(_Concurrency))
24+
import JavaScriptEventLoop
25+
#endif
26+
2327
public typealias Sanitizers = TokamakStaticHTML.Sanitizers
2428

2529
extension EnvironmentValues {
@@ -87,6 +91,10 @@ final class DOMRenderer: Renderer {
8791
rootRef = ref
8892
appendRootStyle(ref)
8993

94+
#if compiler(>=5.5) && (canImport(Concurrency) || canImport(_Concurrency))
95+
JavaScriptEventLoop.installGlobalExecutor()
96+
#endif
97+
9098
let scheduler = JSScheduler()
9199
self.scheduler = scheduler
92100
reconciler = StackReconciler(

Sources/TokamakDOM/Views/Canvas/Canvas.swift

+8-8
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ struct _Canvas<Symbols: View>: View {
6262
HTML("canvas", [
6363
"style": "width: 100%; height: 100%;",
6464
])
65-
._domRef($coordinator.canvas)
66-
.onAppear { draw(in: proxy.size) }
67-
._onUpdate {
68-
// Cancel the previous animation loop.
69-
if let currentDrawLoop = coordinator.currentDrawLoop {
70-
_ = JSObject.global.cancelAnimationFrame!(currentDrawLoop)
71-
}
72-
draw(in: proxy.size)
65+
._domRef($coordinator.canvas)
66+
.onAppear { draw(in: proxy.size) }
67+
._onUpdate {
68+
// Cancel the previous animation loop.
69+
if let currentDrawLoop = coordinator.currentDrawLoop {
70+
_ = JSObject.global.cancelAnimationFrame!(currentDrawLoop)
7371
}
72+
draw(in: proxy.size)
73+
}
7474
}
7575
}
7676

Sources/TokamakDemo/ButtonStyleDemo.swift Sources/TokamakDemo/Buttons/ButtonStyleDemo.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ public struct ButtonStyleDemo: View {
7575
Text("Label").padding(.leading, 5)
7676
}
7777
})
78-
.buttonStyle(
79-
PressedButtonStyle(pressedColor: Color.red)
80-
)
78+
.buttonStyle(
79+
PressedButtonStyle(pressedColor: Color.red)
80+
)
8181
if #available(iOS 15.0, macOS 12.0, *) {
8282
Button("Prominent") {}
8383
.buttonStyle(BorderedProminentButtonStyle())
File renamed without changes.
File renamed without changes.

Sources/TokamakDemo/URLHashDemo.swift Sources/TokamakDemo/DOM/URLHashDemo.swift

+2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ private final class HashState: ObservableObject {
3636

3737
deinit {
3838
window.onhashchange = .undefined
39+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
3940
onHashChange.release()
41+
#endif
4042
}
4143
}
4244

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2021 Tokamak contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import TokamakShim
16+
17+
struct ShadowDemo: View {
18+
var body: some View {
19+
Color.red.frame(width: 60, height: 60, alignment: .center)
20+
.shadow(color: .black, radius: 5, x: 0, y: 10)
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2021 Tokamak contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#if os(WASI) && compiler(>=5.5) && (canImport(Concurrency) || canImport(_Concurrency))
16+
import JavaScriptKit
17+
import TokamakDOM
18+
19+
private let jsFetch = JSObject.global.fetch.function!
20+
private func fetch(_ url: String) -> JSPromise {
21+
JSPromise(jsFetch(url).object!)!
22+
}
23+
24+
private struct Response: Decodable {
25+
let uuid: String
26+
}
27+
28+
struct TaskDemo: View {
29+
@State private var response: Result<Response, Error>?
30+
31+
var body: some View {
32+
VStack {
33+
switch response {
34+
case let .success(response):
35+
Text("Fetched UUID is \(response.uuid)")
36+
case let .failure(error):
37+
Text("Error is \(error)")
38+
default:
39+
Text("Response not available yet")
40+
}
41+
42+
Button("Fetch new UUID asynchronously") {
43+
response = nil
44+
Task { await fetchResponse() }
45+
}
46+
}.task {
47+
await fetchResponse()
48+
}
49+
}
50+
51+
func fetchResponse() async {
52+
do {
53+
let fetchResult = try await fetch("https://httpbin.org/uuid").value
54+
let json = try await JSPromise(fetchResult.json().object!)!.value
55+
response = Result { try JSValueDecoder().decode(Response.self, from: json) }
56+
} catch {
57+
response = .failure(error)
58+
}
59+
}
60+
}
61+
#endif

Sources/TokamakDemo/ShadowDemo.swift

-8
This file was deleted.

Sources/TokamakDemo/TextDemo.swift Sources/TokamakDemo/Text/TextDemo.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ struct TextDemo: View {
5353
.heavy,
5454
.black,
5555
], id: \.self) { weight in
56-
Text("a")
57-
.fontWeight(weight)
56+
Text("a")
57+
.fontWeight(weight)
5858
}
5959
}
6060
VStack {

Sources/TokamakDemo/TokamakDemo.swift

+3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ struct TokamakDemoView: View {
133133
}
134134
Section(header: Text("Modifiers")) {
135135
NavItem("Shadow", destination: ShadowDemo())
136+
#if os(WASI) && compiler(>=5.5) && (canImport(Concurrency) || canImport(_Concurrency))
137+
NavItem("Task", destination: TaskDemo())
138+
#endif
136139
}
137140
Section(header: Text("Selectors")) {
138141
NavItem("DatePicker", destination: DatePickerDemo())

0 commit comments

Comments
 (0)