From c5be89bf31037f2d176728586eb093a63e316cd9 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 25 Feb 2024 20:52:55 +0800 Subject: [PATCH 1/4] Bump watchOS target and fix available issue --- Package.swift | 2 +- Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift | 2 -- .../AppStructure/AppOrganization/TODO/AppGraph.swift | 1 - .../AppOrganization/TODO/OpenSwiftUIApplication.swift | 2 -- .../InputEvents/KeyboardShortcut/EventModifiers.swift | 1 - Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift | 1 - 6 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Package.swift b/Package.swift index 6ba620d1..4394801b 100644 --- a/Package.swift +++ b/Package.swift @@ -70,7 +70,7 @@ let package = Package( .macOS(.v10_15), .macCatalyst(.v13), .tvOS(.v13), - .watchOS(.v6), + .watchOS(.v7), // WKApplicationMain is available for watchOS 7.0+ .visionOS(.v1), ], products: [ diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift index 24c10cc0..c65d1699 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift @@ -67,7 +67,6 @@ /// } /// } /// -@available(watchOS 7.0, *) public protocol App { /// The type of scene representing the content of the app. /// @@ -108,7 +107,6 @@ public protocol App { init() } -@available(watchOS 7.0, *) extension App { /// Initializes and runs the app. /// diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift index 24e01b95..eb24a14a 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift @@ -8,7 +8,6 @@ // ID: A363922CEBDF47986D9772B903C8737A #if canImport(Darwin) -@available(watchOS 7.0, *) final class AppGraph: GraphHost { init(app _: some App) {} diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift index 7d4beff2..54dc1d88 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift @@ -31,7 +31,6 @@ private final class OpenSwiftUIApplication: NSApplication { import Foundation #endif -@available(watchOS 7.0, *) func runApp(_ app: some App) -> Never { #if canImport(Darwin) let graph = AppGraph(app: app) @@ -42,7 +41,6 @@ func runApp(_ app: some App) -> Never { KitRendererCommon() } -@available(watchOS 7.0, *) private func KitRendererCommon() -> Never { let argc = CommandLine.argc let argv = CommandLine.unsafeArgv diff --git a/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift b/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift index a5e86552..b8c060b7 100644 --- a/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift +++ b/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift @@ -6,7 +6,6 @@ // Lastest Version: iOS 15.5 // Status: Complete -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct EventModifiers: OptionSet { public let rawValue: Int public init(rawValue: Int) { diff --git a/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift b/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift index ab100719..36651fb1 100644 --- a/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift +++ b/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift @@ -53,7 +53,6 @@ extension View { } } -@available(iOS 13.0, *) extension View { @inline(__always) func defaultFont(_ font: Font?) -> some View { From 8a145a4370e40da9a138d4b2edc3a69ca8d25223 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 25 Feb 2024 23:49:16 +0800 Subject: [PATCH 2/4] Update AppGraph --- .../AppOrganization/Graph/AppGraph.swift | 67 +++++++++++++++++++ .../Profile/FinishLaunchTestAction.swift | 30 +++++++++ .../AppOrganization/TODO/AppGraph.swift | 21 ------ .../TODO/FallbackDelegateBox.swift | 7 +- .../OpenSwiftUI/Test/_PerformanceTest.swift | 12 +++- .../include/OpenSwiftUI_SPI.h | 10 ++- 6 files changed, 119 insertions(+), 28 deletions(-) create mode 100644 Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift create mode 100644 Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift delete mode 100644 Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift new file mode 100644 index 00000000..107b10eb --- /dev/null +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift @@ -0,0 +1,67 @@ +// +// AppGraph.swift +// OpenSwiftUI +// +// Created by Kyle on 2023/9/22. +// Lastest Version: iOS 15.5 +// Status: WIP +// ID: A363922CEBDF47986D9772B903C8737A + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif os(WASI) +import WASILibc +#endif + +final class AppGraph: GraphHost { + static var shared: AppGraph? = nil + static var delegateBox: AnyFallbackDelegateBox? = nil + + private struct LaunchProfileOptions: OptionSet { + let rawValue: Int32 + + static var enable: LaunchProfileOptions { .init(rawValue: 1 << 1) } + } + + private lazy var launchProfileOptions: LaunchProfileOptions = { + let env = getenv("SWIFTUI_PROFILE_LAUNCH") + if let env { + return .init(rawValue: atoi(env)) + } else { + return [] + } + }() + + var didCollectLaunchProfile: Bool = false + + init(app _: some App) {} + + func extendedLaunchTestName() -> String? { nil } + + func startProfilingIfNecessary() { + guard !didCollectLaunchProfile else { + return + } + + if launchProfileOptions.contains(.enable) { + // AGGraphStartProfiling + } + } + + func stopProfilingIfNecessary() { + guard !didCollectLaunchProfile else { + return + } + didCollectLaunchProfile = true + + if launchProfileOptions.contains(.enable) { + // AGGraphStopProfiling + } + + if launchProfileOptions.rawValue != 0 { + // AGGraphArchiveJSON + } + } +} diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift new file mode 100644 index 00000000..3ff6e264 --- /dev/null +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift @@ -0,0 +1,30 @@ +// +// FinishLaunchTestAction.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/25. +// Lastest Version: iOS 15.5 +// Status: Complete + +#if os(iOS) +import UIKit +#elseif os(macOS) +import AppKit +#endif + +struct FinishLaunchTestAction { + func callAsFunction() { + AppGraph.shared?.stopProfilingIfNecessary() + #if os(iOS) + UIApplication.shared.finishedTest(UIApplication.shared._launchTestName()) + #else + fatalError("Unimplemented for other platform") + #endif + } +} + +extension EnvironmentValues { + var finishLaunchTest: FinishLaunchTestAction { + FinishLaunchTestAction() + } +} diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift deleted file mode 100644 index eb24a14a..00000000 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// AppGraph.swift -// OpenSwiftUI -// -// Created by Kyle on 2023/9/22. -// Lastest Version: iOS 15.5 -// Status: WIP -// ID: A363922CEBDF47986D9772B903C8737A - -#if canImport(Darwin) -final class AppGraph: GraphHost { - init(app _: some App) {} - - static var shared: AppGraph? = nil - static var delegateBox: AnyFallbackDelegateBox? = nil - - func extendedLaunchTestName() -> String? { nil } - - func startProfilingIfNecessary() {} -} -#endif diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift index c5912477..e120cc68 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift @@ -6,7 +6,6 @@ // Lastest Version: iOS 15.5 // Status: WIP -#if canImport(Darwin) import Foundation #if OPENSWIFTUI_OPENCOMBINE import OpenCombine @@ -39,6 +38,10 @@ class FallbackDelegateBox: AnyFallbackDelegateBox { } override var delegate: NSObject? { + // FIXME: error: constructing an object of class type 'Delegate' with a metatype value must use a 'required' initializer + #if !canImport(Darwin) + return nil + #else switch storage { case let .type(type): let delegate = type.init() @@ -47,6 +50,6 @@ class FallbackDelegateBox: AnyFallbackDelegateBox { case let .instance(delegate): return delegate } + #endif } } -#endif diff --git a/Sources/OpenSwiftUI/Test/_PerformanceTest.swift b/Sources/OpenSwiftUI/Test/_PerformanceTest.swift index 76a19e4b..1c08019d 100644 --- a/Sources/OpenSwiftUI/Test/_PerformanceTest.swift +++ b/Sources/OpenSwiftUI/Test/_PerformanceTest.swift @@ -35,24 +35,30 @@ extension _BenchmarkHost { public func _started(test: _PerformanceTest) { #if os(iOS) UIApplication.shared.startedTest(test.name) + #elseif os(macOS) + NSApplication.shared.startedTest(test.name) #else - fatalError("TODO") + fatalError("Unimplemented for other platform") #endif } public func _finished(test: _PerformanceTest) { #if os(iOS) UIApplication.shared.finishedTest(test.name) + #elseif os(macOS) + NSApplication.shared.finishedTest(test.name) #else - fatalError("TODO") + fatalError("Unimplemented for other platform") #endif } public func _failed(test: _PerformanceTest) { #if os(iOS) UIApplication.shared.failedTest(test.name, withFailure: nil) + #elseif os(macOS) + NSApplication.shared.failedTest(test.name, withFailure: nil) #else - fatalError("TODO") + fatalError("Unimplemented for other platform") #endif } } diff --git a/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h b/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h index 5ca9230a..200a61c0 100644 --- a/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h +++ b/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h @@ -14,9 +14,15 @@ - (void)startedTest:(nullable NSString *)name; - (void)finishedTest:(nullable NSString *)name; - (void)failedTest:(nullable NSString *)name withFailure:(nullable NSError*)failure; +- (nullable NSString *)_launchTestName; +@end +#elif __has_include() +#import +@interface NSApplication (OpenSwiftUI_SPI) +- (void)startedTest:(nullable NSString *)name; +- (void)finishedTest:(nullable NSString *)name; +- (void)failedTest:(nullable NSString *)name withFailure:(nullable NSError*)failure; @end -#else - #endif #endif /* OpenSwiftUI_SPI_h */ From bc0b3c79369ddb43862631e62a878bcd68a081d1 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 26 Feb 2024 00:47:59 +0800 Subject: [PATCH 3/4] Update OpenGraph to add profile support --- Package.resolved | 2 +- .../AppOrganization/Graph/AppGraph.swift | 22 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Package.resolved b/Package.resolved index 4ba7be1f..484f7fae 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,7 +6,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenGraph", "state" : { "branch" : "main", - "revision" : "6133e9f737077b5c75ff33dee1c2c969cb5d91b4" + "revision" : "45bd9b86eb917e1bd56ead3ef51ca82beca94a70" } }, { diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift index 107b10eb..e0d489d7 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift @@ -14,6 +14,7 @@ import Glibc #elseif os(WASI) import WASILibc #endif +internal import OpenGraphShims final class AppGraph: GraphHost { static var shared: AppGraph? = nil @@ -21,12 +22,11 @@ final class AppGraph: GraphHost { private struct LaunchProfileOptions: OptionSet { let rawValue: Int32 - - static var enable: LaunchProfileOptions { .init(rawValue: 1 << 1) } + static var profile: LaunchProfileOptions { .init(rawValue: 1 << 1) } } private lazy var launchProfileOptions: LaunchProfileOptions = { - let env = getenv("SWIFTUI_PROFILE_LAUNCH") + let env = getenv("OPENSWIFTUI_PROFILE_LAUNCH") if let env { return .init(rawValue: atoi(env)) } else { @@ -44,9 +44,8 @@ final class AppGraph: GraphHost { guard !didCollectLaunchProfile else { return } - - if launchProfileOptions.contains(.enable) { - // AGGraphStartProfiling + if launchProfileOptions.contains(.profile) { + OGGraph.startProfiling() } } @@ -55,13 +54,12 @@ final class AppGraph: GraphHost { return } didCollectLaunchProfile = true - - if launchProfileOptions.contains(.enable) { - // AGGraphStopProfiling + if launchProfileOptions.contains(.profile) { + OGGraph.stopProfiling() } - - if launchProfileOptions.rawValue != 0 { - // AGGraphArchiveJSON + if !launchProfileOptions.isEmpty { + // /tmp/graph.ag-gzon + OGGraph.archiveJSON(name: nil) } } } From b4f10420ce30ff398b11be5232de56e34333bbd7 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 26 Feb 2024 02:10:26 +0800 Subject: [PATCH 4/4] Add GraphDelegate and update App related --- .../AppOrganization/Graph/AppGraph.swift | 10 ++++- .../TODO/OpenSwiftUIApplication.swift | 4 +- .../Internal/Graph/GraphDelegate.swift | 13 ++++++ .../Internal/Graph/GraphHost.swift | 43 ++++++++++++++++--- 4 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift index e0d489d7..e3931b6a 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift @@ -35,8 +35,16 @@ final class AppGraph: GraphHost { }() var didCollectLaunchProfile: Bool = false + + // TODO + init(app: some App) { + let data = GraphHost.Data() + super.init(data: data) + } - init(app _: some App) {} + // MARK: - Override Methods + + // MARK: - Profile related func extendedLaunchTestName() -> String? { nil } diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift index 54dc1d88..d34fd4ae 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift @@ -32,12 +32,10 @@ import Foundation #endif func runApp(_ app: some App) -> Never { - #if canImport(Darwin) let graph = AppGraph(app: app) graph.startProfilingIfNecessary() -// graph.instantiate() + graph.instantiate() AppGraph.shared = graph - #endif KitRendererCommon() } diff --git a/Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift new file mode 100644 index 00000000..0ab76dbe --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift @@ -0,0 +1,13 @@ +// +// GraphDelegate.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/26. +// Lastest Version: iOS 15.5 +// Status: Complete + +protocol GraphDelegate: AnyObject { + func updateGraph(body: (GraphHost) -> V) -> V + func graphDidChange() + func preferencesDidChange() +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift index fab39cfc..476179ec 100644 --- a/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift @@ -3,21 +3,50 @@ internal import OpenGraphShims class GraphHost { - -// var data: Data -// var isInstantiated: Swift.Bool + var data: Data + var isInstantiated: Bool // var hostPreferenceValues: OptionalAttribute // var lastHostPreferencesSeed: VersionSeed -// var pendingTransactions: [SwiftUI.(AsyncTransaction in _30C09FF16BC95EC5173809B57186CAC3)] +// var pendingTransactions: [AsyncTransaction] // var inTransaction: Bool // var continuations: [() -> ()] // var mayDeferUpdate: Bool // var removedState: RemovedState + // FIXME static var isUpdating = false + + // private static let shared = OGGraphCreate() + // MARK: - non final methods -// private static let shared = OGGraphCreate() + init(data: Data) { + self.data = data + isInstantiated = false + // TODO + } + + func invalidate() { + // TODO + } + + var graphDelegate: GraphDelegate? { nil } + var parentHost: GraphHost? { nil } + func instantiateOutputs() {} + func uninstantiateOutputs() {} + func timeDidChange() {} + func isHiddenForReuseDidChange() {} + + // MARK: - final methods + + final func instantiate() { + guard !isInstantiated else { + return + } + graphDelegate?.updateGraph { _ in } + instantiateOutputs() + isInstantiated = true + } } // MARK: - GraphHost.Data @@ -40,6 +69,10 @@ extension GraphHost { @Attribute var transaction: Transaction var inputs: _GraphInputs + + init() { + fatalError("TODO") + } } }