From e9d98194725115c1386f7648657c54ea182aa96a Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 25 Apr 2026 14:58:16 +0800 Subject: [PATCH 1/9] Add DanceUIGraph shim mode --- Package.swift | 31 ++++++++++- .../Attribute+Debug.swift | 2 +- .../OpenAttributeGraphShims/Graph+Debug.swift | 2 +- .../Metadata+Debug.swift | 4 ++ .../OpenAttributeGraphShims/OAGShims.swift | 53 ++++++++++++++++++- 5 files changed, 88 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 23b26e7f..f51ec1ec 100644 --- a/Package.swift +++ b/Package.swift @@ -145,6 +145,7 @@ let libraryEvolutionCondition = envBoolValue("LIBRARY_EVOLUTION", default: build let compatibilityTestCondition = envBoolValue("COMPATIBILITY_TEST", default: false) let useLocalDeps = envBoolValue("USE_LOCAL_DEPS") +let danceUIGraphCondition = envBoolValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH", default: false) let computeCondition = envBoolValue("OPENATTRIBUTESHIMS_COMPUTE", default: false) let attributeGraphCondition = envBoolValue("OPENATTRIBUTESHIMS_ATTRIBUTEGRAPH", default: false) @@ -221,6 +222,20 @@ if !(compatibilityTestCondition && buildForDarwinPlatform) { // MARK: - Extension extension Target { + func addDanceUIGraphSettings() { + dependencies.append( + .product(name: "DanceUIGraph", package: "DanceUIGraph-spm") + ) + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENATTRIBUTEGRAPH_DANCEUIGRAPH")) + self.swiftSettings = swiftSettings + + var linkerSettings = linkerSettings ?? [] + linkerSettings.append(.linkedLibrary("c++", .when(platforms: [.iOS]))) + linkerSettings.append(.linkedLibrary("z", .when(platforms: [.iOS]))) + self.linkerSettings = linkerSettings + } + func addAGSettings() { dependencies.append( .product(name: "AttributeGraph", package: "DarwinPrivateFrameworks") @@ -396,7 +411,21 @@ func setupDPFDependency() { } } -if computeCondition { +if danceUIGraphCondition { + let version = envStringValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH_VERSION", default: "0.1.0") + let danceUIGraphRepo: Package.Dependency + if useLocalDeps { + danceUIGraphRepo = Package.Dependency.package(path: "../DanceUIGraph-spm") + } else { + danceUIGraphRepo = Package.Dependency.package( + url: "https://github.com/OpenSwiftUIProject/DanceUIGraph-spm.git", + exact: Version(version)! + ) + } + package.dependencies.append(danceUIGraphRepo) + openAttributeGraphShimsTarget.addDanceUIGraphSettings() + package.platforms = [.iOS(.v13)] +} else if computeCondition { let computeBinary = envBoolValue("OPENATTRIBUTESHIMS_COMPUTE_USE_BINARY", default: false) if computeBinary { let version = envStringValue("OPENATTRIBUTESHIMS_COMPUTE_BINARY_VERSION", default: "0.1.0") diff --git a/Sources/OpenAttributeGraphShims/Attribute+Debug.swift b/Sources/OpenAttributeGraphShims/Attribute+Debug.swift index 52cda6a2..cf41e37a 100644 --- a/Sources/OpenAttributeGraphShims/Attribute+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Attribute+Debug.swift @@ -2,7 +2,7 @@ // Attribute+Debug.swift // OpenAttributeGraphShims -#if canImport(Darwin) && DEBUG // Compiler crash for Darwin + release and non-Darwin build +#if canImport(Darwin) && DEBUG && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH // Compiler crash for Darwin + release and non-Darwin build // Use 4 spaces instead of \t for bettern test case expect private let tab = " " diff --git a/Sources/OpenAttributeGraphShims/Graph+Debug.swift b/Sources/OpenAttributeGraphShims/Graph+Debug.swift index 6ff803dc..7be140f7 100644 --- a/Sources/OpenAttributeGraphShims/Graph+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Graph+Debug.swift @@ -2,7 +2,7 @@ // Graph+Debug.swift // OpenAttributeGraphShims -#if canImport(Darwin) +#if canImport(Darwin) && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH #if OPENATTRIBUTEGRAPH_COMPUTE extension Graph { diff --git a/Sources/OpenAttributeGraphShims/Metadata+Debug.swift b/Sources/OpenAttributeGraphShims/Metadata+Debug.swift index b11c56d8..faabd4a9 100644 --- a/Sources/OpenAttributeGraphShims/Metadata+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Metadata+Debug.swift @@ -4,6 +4,8 @@ import Foundation +#if !OPENATTRIBUTEGRAPH_DANCEUIGRAPH + @_spi(Debug) extension Metadata { public struct Option { @@ -95,3 +97,5 @@ extension Int { "0x\(String(format: "%X", self))" } } + +#endif diff --git a/Sources/OpenAttributeGraphShims/OAGShims.swift b/Sources/OpenAttributeGraphShims/OAGShims.swift index aa9bf058..f99fcaef 100644 --- a/Sources/OpenAttributeGraphShims/OAGShims.swift +++ b/Sources/OpenAttributeGraphShims/OAGShims.swift @@ -21,7 +21,10 @@ public struct AttributeGraphVendor: RawRepresentable, Hashable, CaseIterable { /// An incremental computation library for Swift by @jcmosc public static let compute = AttributeGraphVendor(rawValue: "dev.incrematic.compute") - public static var allCases: [AttributeGraphVendor] { [.oag, .ag, .compute] } + /// ByteDance DanceUIGraph. + public static let danceUIGraph = AttributeGraphVendor(rawValue: "com.bytedance.danceui.graph") + + public static var allCases: [AttributeGraphVendor] { [.oag, .ag, .compute, .danceUIGraph] } } #if OPENATTRIBUTEGRAPH_COMPUTE @@ -79,6 +82,54 @@ extension CachedValueOptions { public let attributeGraphVendor = AttributeGraphVendor.compute +#elseif OPENATTRIBUTEGRAPH_DANCEUIGRAPH + +@_exported public import DanceUIRuntime +@_exported public import DanceUIGraph + +public typealias AnyAttribute = DGAttribute +public typealias AnyWeakAttribute = DGWeakAttribute +public typealias Graph = DGGraphRef +public typealias GraphContext = DGGraphContextRef +public typealias Metadata = DGTypeID +public typealias OAGAttributeInfo = DGAttributeInfo +public typealias OAGCachedValueOptions = DGGraphCachedValueOptions +public typealias OAGChangedValueFlags = DGChangedValueFlags +public typealias OAGInputOptions = DGInputOptions +public typealias OAGValue = DGGraphValue +public typealias OAGValueOptions = DGValueOptions +public typealias SearchOptions = DGSearchOptions +public typealias Subgraph = DGSubgraphRef +public typealias TupleType = DGTupleType +public typealias UnsafeMutableTuple = DGUnsafeMutableTuple +public typealias UnsafeTuple = DGUnsafeTuple +public typealias UniqueID = DGUniqueID +public typealias ValueState = DGValueState +public typealias _AttributeType = _DGAttributeType +public typealias _AttributeVTable = _DGAttributeVTable +public typealias _OAGClosureStorage = DGClosureStorage + +extension AnyAttribute { + public typealias Flags = DGAttributeFlags +} + +extension Graph { + public static func resetProfile() { + reset() + } + + public func resetProfile() { + reset() + } +} + +extension Subgraph { + public typealias Flags = AnyAttribute.Flags + public typealias ChildFlags = AnyAttribute.Flags +} + +public let attributeGraphVendor = AttributeGraphVendor.danceUIGraph + #elseif OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH @_exported public import AttributeGraph From 708fe221504fc99ceb081bcae336412f405fddb3 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 25 Apr 2026 16:01:27 +0800 Subject: [PATCH 2/9] Use DanceUIGraph 0.0.1 by default --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index f51ec1ec..c5ecf8fa 100644 --- a/Package.swift +++ b/Package.swift @@ -412,7 +412,7 @@ func setupDPFDependency() { } if danceUIGraphCondition { - let version = envStringValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH_VERSION", default: "0.1.0") + let version = envStringValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH_VERSION", default: "0.0.1") let danceUIGraphRepo: Package.Dependency if useLocalDeps { danceUIGraphRepo = Package.Dependency.package(path: "../DanceUIGraph-spm") From d76f333cfbba1a6e5d0174da2b07afdf2a55078d Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Apr 2026 14:52:16 +0800 Subject: [PATCH 3/9] Add DanceUIGraph shim dependency mode --- Package.resolved | 2 +- Package.swift | 48 +++++++++++-------- .../Attribute+DebugTests.swift | 2 +- .../MetadataDebugTests.swift | 4 ++ .../GraphEnvironmentTrait.swift | 18 +++++++ 5 files changed, 52 insertions(+), 22 deletions(-) diff --git a/Package.resolved b/Package.resolved index 82465d4c..6f549f34 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "dee0d2efee07a0e54cf03403184cd73e1e83885c57adb6d0fb794470857b1c1e", + "originHash" : "09ae01ad49c002f33e5be89781b71faff1cd16e69a42bd5adbed665314e65ed3", "pins" : [ { "identity" : "swift-numerics", diff --git a/Package.swift b/Package.swift index c5ecf8fa..c87ed7d5 100644 --- a/Package.swift +++ b/Package.swift @@ -226,16 +226,20 @@ extension Target { dependencies.append( .product(name: "DanceUIGraph", package: "DanceUIGraph-spm") ) - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENATTRIBUTEGRAPH_DANCEUIGRAPH")) - self.swiftSettings = swiftSettings + addDanceUIGraphSwiftSettings() var linkerSettings = linkerSettings ?? [] - linkerSettings.append(.linkedLibrary("c++", .when(platforms: [.iOS]))) - linkerSettings.append(.linkedLibrary("z", .when(platforms: [.iOS]))) + linkerSettings.append(.linkedLibrary("c++", .when(platforms: [.iOS, .macOS]))) + linkerSettings.append(.linkedLibrary("z", .when(platforms: [.iOS, .macOS]))) self.linkerSettings = linkerSettings } + func addDanceUIGraphSwiftSettings() { + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENATTRIBUTEGRAPH_DANCEUIGRAPH")) + self.swiftSettings = swiftSettings + } + func addAGSettings() { dependencies.append( .product(name: "AttributeGraph", package: "DarwinPrivateFrameworks") @@ -411,21 +415,7 @@ func setupDPFDependency() { } } -if danceUIGraphCondition { - let version = envStringValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH_VERSION", default: "0.0.1") - let danceUIGraphRepo: Package.Dependency - if useLocalDeps { - danceUIGraphRepo = Package.Dependency.package(path: "../DanceUIGraph-spm") - } else { - danceUIGraphRepo = Package.Dependency.package( - url: "https://github.com/OpenSwiftUIProject/DanceUIGraph-spm.git", - exact: Version(version)! - ) - } - package.dependencies.append(danceUIGraphRepo) - openAttributeGraphShimsTarget.addDanceUIGraphSettings() - package.platforms = [.iOS(.v13)] -} else if computeCondition { +if computeCondition { let computeBinary = envBoolValue("OPENATTRIBUTESHIMS_COMPUTE_USE_BINARY", default: false) if computeBinary { let version = envStringValue("OPENATTRIBUTESHIMS_COMPUTE_BINARY_VERSION", default: "0.1.0") @@ -449,6 +439,24 @@ if danceUIGraphCondition { } openAttributeGraphShimsTarget.addComputeSettings() package.platforms = [.iOS(.v18), .macOS(.v15), .macCatalyst(.v18), .tvOS(.v18), .watchOS(.v10), .visionOS(.v2)] +} else if danceUIGraphCondition { + let danceUIGraphBinaryRepo: Package.Dependency + if useLocalDeps { + danceUIGraphBinaryRepo = Package.Dependency.package(path: "../DanceUIGraph-spm") + } else { + let version: Version = envStringValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH_BINARY_VERSION").flatMap { + Version($0) + } ?? "0.0.2" + danceUIGraphBinaryRepo = Package.Dependency.package( + url: "https://github.com/OpenSwiftUIProject/DanceUIGraph-spm.git", + exact: version + ) + } + package.dependencies.append(danceUIGraphBinaryRepo) + openAttributeGraphShimsTarget.addDanceUIGraphSettings() + openAttributeGraphShimsTestsTarget.addDanceUIGraphSwiftSettings() + package.targets.append(openAttributeGraphShimsTestsTarget) + package.platforms = [.iOS(.v13), .macOS(.v10_15)] } else if attributeGraphCondition, buildForDarwinPlatform { setupDPFDependency() openAttributeGraphShimsTarget.addAGSettings() diff --git a/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift b/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift index 8a5e6b50..759df733 100644 --- a/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift +++ b/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift @@ -2,7 +2,7 @@ // Attribute+DebugTests.swift // OpenAttributeGraphShimsTests -#if canImport(Darwin) && DEBUG +#if canImport(Darwin) && DEBUG && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH import OpenAttributeGraphShims import Testing diff --git a/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift b/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift index 2da05cd7..1ec190b1 100644 --- a/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift +++ b/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift @@ -2,6 +2,8 @@ // MetadataDebugTests.swift // OpenAttributeGraphShimsTests +#if !OPENATTRIBUTEGRAPH_DANCEUIGRAPH + @_spi(Debug) import OpenAttributeGraphShims import Testing @@ -67,3 +69,5 @@ extension Int { "0x\(String(format: "%X", self))" } } + +#endif diff --git a/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift b/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift index a3e871de..aeb6b65e 100644 --- a/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift +++ b/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift @@ -5,7 +5,11 @@ public import Testing public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { + #if OPENATTRIBUTEGRAPH_DANCEUIGRAPH + private static let sharedGraph = DGGraphCreate() + #else private static let sharedGraph = Graph() + #endif private static let semaphore = AsyncSemaphore(value: 1) @MainActor @@ -16,6 +20,19 @@ public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { ) async throws { await Self.semaphore.wait() defer { Self.semaphore.signal() } + #if OPENATTRIBUTEGRAPH_DANCEUIGRAPH + let graph = DGGraphCreateShared(Self.sharedGraph) + let subgraph = DGSubgraphCreate(graph) + let oldSubgraph = Subgraph.current + + Subgraph.current = subgraph + defer { + Subgraph.current = oldSubgraph + subgraph.invalidate() + graph.invalidate() + } + try await function() + #else let graph = Graph(shared: Self.sharedGraph) let subgraph = Subgraph(graph: graph) let oldSubgraph = Subgraph.current @@ -23,6 +40,7 @@ public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { Subgraph.current = subgraph try await function() Subgraph.current = oldSubgraph + #endif } public var isRecursive: Bool { From 503c559d2e97f964c2fe5dd88c8fd129f8785180 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Apr 2026 15:20:41 +0800 Subject: [PATCH 4/9] Remove DanceUIGraph-specific shim tests --- Package.resolved | 2 +- Package.swift | 12 ++++++------ .../Attribute+Debug.swift | 2 +- .../OpenAttributeGraphShims/Graph+Debug.swift | 2 +- .../Metadata+Debug.swift | 4 ---- .../Attribute+DebugTests.swift | 2 +- .../MetadataDebugTests.swift | 4 ---- .../GraphEnvironmentTrait.swift | 18 ------------------ 8 files changed, 10 insertions(+), 36 deletions(-) diff --git a/Package.resolved b/Package.resolved index 6f549f34..b0860d83 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "09ae01ad49c002f33e5be89781b71faff1cd16e69a42bd5adbed665314e65ed3", + "originHash" : "6f1bc3c594b00da912a3dda25a2aab758ff9dff337b9474048e78f9a76ed819a", "pins" : [ { "identity" : "swift-numerics", diff --git a/Package.swift b/Package.swift index c87ed7d5..5b1d8c2d 100644 --- a/Package.swift +++ b/Package.swift @@ -234,12 +234,6 @@ extension Target { self.linkerSettings = linkerSettings } - func addDanceUIGraphSwiftSettings() { - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENATTRIBUTEGRAPH_DANCEUIGRAPH")) - self.swiftSettings = swiftSettings - } - func addAGSettings() { dependencies.append( .product(name: "AttributeGraph", package: "DarwinPrivateFrameworks") @@ -261,6 +255,12 @@ extension Target { linkerSettings.append(.linkedLibrary("swiftDemangle", .when(platforms: .darwinPlatforms))) self.linkerSettings = linkerSettings } + + func addDanceUIGraphSwiftSettings() { + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENATTRIBUTEGRAPH_DANCEUIGRAPH")) + self.swiftSettings = swiftSettings + } } extension [Platform] { diff --git a/Sources/OpenAttributeGraphShims/Attribute+Debug.swift b/Sources/OpenAttributeGraphShims/Attribute+Debug.swift index cf41e37a..52cda6a2 100644 --- a/Sources/OpenAttributeGraphShims/Attribute+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Attribute+Debug.swift @@ -2,7 +2,7 @@ // Attribute+Debug.swift // OpenAttributeGraphShims -#if canImport(Darwin) && DEBUG && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH // Compiler crash for Darwin + release and non-Darwin build +#if canImport(Darwin) && DEBUG // Compiler crash for Darwin + release and non-Darwin build // Use 4 spaces instead of \t for bettern test case expect private let tab = " " diff --git a/Sources/OpenAttributeGraphShims/Graph+Debug.swift b/Sources/OpenAttributeGraphShims/Graph+Debug.swift index 7be140f7..6ff803dc 100644 --- a/Sources/OpenAttributeGraphShims/Graph+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Graph+Debug.swift @@ -2,7 +2,7 @@ // Graph+Debug.swift // OpenAttributeGraphShims -#if canImport(Darwin) && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH +#if canImport(Darwin) #if OPENATTRIBUTEGRAPH_COMPUTE extension Graph { diff --git a/Sources/OpenAttributeGraphShims/Metadata+Debug.swift b/Sources/OpenAttributeGraphShims/Metadata+Debug.swift index faabd4a9..b11c56d8 100644 --- a/Sources/OpenAttributeGraphShims/Metadata+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Metadata+Debug.swift @@ -4,8 +4,6 @@ import Foundation -#if !OPENATTRIBUTEGRAPH_DANCEUIGRAPH - @_spi(Debug) extension Metadata { public struct Option { @@ -97,5 +95,3 @@ extension Int { "0x\(String(format: "%X", self))" } } - -#endif diff --git a/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift b/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift index 759df733..8a5e6b50 100644 --- a/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift +++ b/Tests/OpenAttributeGraphShimsTests/Attribute+DebugTests.swift @@ -2,7 +2,7 @@ // Attribute+DebugTests.swift // OpenAttributeGraphShimsTests -#if canImport(Darwin) && DEBUG && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH +#if canImport(Darwin) && DEBUG import OpenAttributeGraphShims import Testing diff --git a/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift b/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift index 1ec190b1..2da05cd7 100644 --- a/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift +++ b/Tests/OpenAttributeGraphShimsTests/MetadataDebugTests.swift @@ -2,8 +2,6 @@ // MetadataDebugTests.swift // OpenAttributeGraphShimsTests -#if !OPENATTRIBUTEGRAPH_DANCEUIGRAPH - @_spi(Debug) import OpenAttributeGraphShims import Testing @@ -69,5 +67,3 @@ extension Int { "0x\(String(format: "%X", self))" } } - -#endif diff --git a/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift b/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift index aeb6b65e..a3e871de 100644 --- a/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift +++ b/Tests/OpenAttributeGraphTestsSupport/GraphEnvironmentTrait.swift @@ -5,11 +5,7 @@ public import Testing public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { - #if OPENATTRIBUTEGRAPH_DANCEUIGRAPH - private static let sharedGraph = DGGraphCreate() - #else private static let sharedGraph = Graph() - #endif private static let semaphore = AsyncSemaphore(value: 1) @MainActor @@ -20,19 +16,6 @@ public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { ) async throws { await Self.semaphore.wait() defer { Self.semaphore.signal() } - #if OPENATTRIBUTEGRAPH_DANCEUIGRAPH - let graph = DGGraphCreateShared(Self.sharedGraph) - let subgraph = DGSubgraphCreate(graph) - let oldSubgraph = Subgraph.current - - Subgraph.current = subgraph - defer { - Subgraph.current = oldSubgraph - subgraph.invalidate() - graph.invalidate() - } - try await function() - #else let graph = Graph(shared: Self.sharedGraph) let subgraph = Subgraph(graph: graph) let oldSubgraph = Subgraph.current @@ -40,7 +23,6 @@ public struct GraphEnvironmentTrait: TestTrait, TestScoping, SuiteTrait { Subgraph.current = subgraph try await function() Subgraph.current = oldSubgraph - #endif } public var isRecursive: Bool { From d882f6d776ffcb455447a5ce53fae1f64d6555f7 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Apr 2026 15:31:06 +0800 Subject: [PATCH 5/9] Split shim adapters by vendor --- .../Adapter/AttributeGraph.swift | 21 +++ .../Adapter/Compute.swift | 58 +++++++++ .../Adapter/DanceUIGraph.swift | 53 ++++++++ .../OpenAttributeGraphShims/OAGShims.swift | 121 +----------------- 4 files changed, 133 insertions(+), 120 deletions(-) create mode 100644 Sources/OpenAttributeGraphShims/Adapter/AttributeGraph.swift create mode 100644 Sources/OpenAttributeGraphShims/Adapter/Compute.swift create mode 100644 Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift diff --git a/Sources/OpenAttributeGraphShims/Adapter/AttributeGraph.swift b/Sources/OpenAttributeGraphShims/Adapter/AttributeGraph.swift new file mode 100644 index 00000000..83dd5d09 --- /dev/null +++ b/Sources/OpenAttributeGraphShims/Adapter/AttributeGraph.swift @@ -0,0 +1,21 @@ +// +// AttributeGraph.swift +// OpenAttributeGraphShims + +#if OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH + +@_exported public import AttributeGraph +#if os(iOS) && !targetEnvironment(simulator) +@_exported public import _AttributeGraphDeviceSwiftShims +#endif + +public typealias OAGAttributeInfo = AGAttributeInfo +public typealias OAGCachedValueOptions = AGCachedValueOptions +public typealias OAGChangedValueFlags = AGChangedValueFlags +public typealias OAGInputOptions = AGInputOptions +public typealias OAGValue = AGValue +public typealias OAGValueOptions = AGValueOptions + +public let attributeGraphVendor = AttributeGraphVendor.ag + +#endif diff --git a/Sources/OpenAttributeGraphShims/Adapter/Compute.swift b/Sources/OpenAttributeGraphShims/Adapter/Compute.swift new file mode 100644 index 00000000..c57a0d3f --- /dev/null +++ b/Sources/OpenAttributeGraphShims/Adapter/Compute.swift @@ -0,0 +1,58 @@ +// +// Compute.swift +// OpenAttributeGraphShims + +#if OPENATTRIBUTEGRAPH_COMPUTE + +@_exported public import Compute + +public typealias OAGAttributeInfo = AGAttributeInfo +public typealias OAGCachedValueOptions = CachedValueOptions +public typealias OAGChangedValueFlags = AGChangedValueFlags +public typealias OAGInputOptions = AGInputOptions +public typealias OAGValue = AGChangedValue +public typealias OAGValueOptions = AGValueOptions + +extension AnyAttribute { + public typealias Flags = Subgraph.Flags + + public var subgraph2: Subgraph? { nil } +} + +extension Subgraph { + public typealias ChildFlags = AnyAttribute.Flags +} + +extension Graph { + public static func startProfiling() { + startProfiling(nil) + } + + public static func stopProfiling() { + stopProfiling(nil) + } + + public func startProfiling() { + Self.startProfiling(self) + } + + public func stopProfiling() { + Self.stopProfiling(self) + } + + public func resetProfile() { + // TODO: placeholder + } +} + +extension _AttributeBody { + public typealias Flags = _AttributeType.Flags +} + +extension CachedValueOptions { + public static var _1: CachedValueOptions = .unprefetched +} + +public let attributeGraphVendor = AttributeGraphVendor.compute + +#endif diff --git a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift new file mode 100644 index 00000000..b2ef4b56 --- /dev/null +++ b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift @@ -0,0 +1,53 @@ +// +// DanceUIGraph.swift +// OpenAttributeGraphShims + +#if OPENATTRIBUTEGRAPH_DANCEUIGRAPH + +@_exported public import DanceUIRuntime +@_exported public import DanceUIGraph + +public typealias AnyAttribute = DGAttribute +public typealias AnyWeakAttribute = DGWeakAttribute +public typealias Graph = DGGraphRef +public typealias GraphContext = DGGraphContextRef +public typealias Metadata = DGTypeID +public typealias OAGAttributeInfo = DGAttributeInfo +public typealias OAGCachedValueOptions = DGGraphCachedValueOptions +public typealias OAGChangedValueFlags = DGChangedValueFlags +public typealias OAGInputOptions = DGInputOptions +public typealias OAGValue = DGGraphValue +public typealias OAGValueOptions = DGValueOptions +public typealias SearchOptions = DGSearchOptions +public typealias Subgraph = DGSubgraphRef +public typealias TupleType = DGTupleType +public typealias UnsafeMutableTuple = DGUnsafeMutableTuple +public typealias UnsafeTuple = DGUnsafeTuple +public typealias UniqueID = DGUniqueID +public typealias ValueState = DGValueState +public typealias _AttributeType = _DGAttributeType +public typealias _AttributeVTable = _DGAttributeVTable +public typealias _OAGClosureStorage = DGClosureStorage + +extension AnyAttribute { + public typealias Flags = DGAttributeFlags +} + +extension Graph { + public static func resetProfile() { + reset() + } + + public func resetProfile() { + reset() + } +} + +extension Subgraph { + public typealias Flags = AnyAttribute.Flags + public typealias ChildFlags = AnyAttribute.Flags +} + +public let attributeGraphVendor = AttributeGraphVendor.danceUIGraph + +#endif diff --git a/Sources/OpenAttributeGraphShims/OAGShims.swift b/Sources/OpenAttributeGraphShims/OAGShims.swift index f99fcaef..7cd1d419 100644 --- a/Sources/OpenAttributeGraphShims/OAGShims.swift +++ b/Sources/OpenAttributeGraphShims/OAGShims.swift @@ -27,126 +27,7 @@ public struct AttributeGraphVendor: RawRepresentable, Hashable, CaseIterable { public static var allCases: [AttributeGraphVendor] { [.oag, .ag, .compute, .danceUIGraph] } } -#if OPENATTRIBUTEGRAPH_COMPUTE - -@_exported public import Compute -public typealias OAGAttributeInfo = AGAttributeInfo -public typealias OAGCachedValueOptions = CachedValueOptions -public typealias OAGChangedValueFlags = AGChangedValueFlags -public typealias OAGInputOptions = AGInputOptions -public typealias OAGValue = AGChangedValue -public typealias OAGValueOptions = AGValueOptions - -extension AnyAttribute { - public typealias Flags = Subgraph.Flags -} - -extension AnyAttribute { - public var subgraph2: Subgraph? { nil } -} - - -extension Subgraph { - public typealias ChildFlags = AnyAttribute.Flags -} - -extension Graph { - public static func startProfiling() { - startProfiling(nil) - } - - public static func stopProfiling() { - stopProfiling(nil) - } - - public func startProfiling() { - Self.startProfiling(self) - } - - public func stopProfiling() { - Self.stopProfiling(self) - } - - public func resetProfile() { - // TODO: placeholder - } -} - -extension _AttributeBody { - public typealias Flags = _AttributeType.Flags -} - -extension CachedValueOptions { - public static var _1: CachedValueOptions = .unprefetched -} - -public let attributeGraphVendor = AttributeGraphVendor.compute - -#elseif OPENATTRIBUTEGRAPH_DANCEUIGRAPH - -@_exported public import DanceUIRuntime -@_exported public import DanceUIGraph - -public typealias AnyAttribute = DGAttribute -public typealias AnyWeakAttribute = DGWeakAttribute -public typealias Graph = DGGraphRef -public typealias GraphContext = DGGraphContextRef -public typealias Metadata = DGTypeID -public typealias OAGAttributeInfo = DGAttributeInfo -public typealias OAGCachedValueOptions = DGGraphCachedValueOptions -public typealias OAGChangedValueFlags = DGChangedValueFlags -public typealias OAGInputOptions = DGInputOptions -public typealias OAGValue = DGGraphValue -public typealias OAGValueOptions = DGValueOptions -public typealias SearchOptions = DGSearchOptions -public typealias Subgraph = DGSubgraphRef -public typealias TupleType = DGTupleType -public typealias UnsafeMutableTuple = DGUnsafeMutableTuple -public typealias UnsafeTuple = DGUnsafeTuple -public typealias UniqueID = DGUniqueID -public typealias ValueState = DGValueState -public typealias _AttributeType = _DGAttributeType -public typealias _AttributeVTable = _DGAttributeVTable -public typealias _OAGClosureStorage = DGClosureStorage - -extension AnyAttribute { - public typealias Flags = DGAttributeFlags -} - -extension Graph { - public static func resetProfile() { - reset() - } - - public func resetProfile() { - reset() - } -} - -extension Subgraph { - public typealias Flags = AnyAttribute.Flags - public typealias ChildFlags = AnyAttribute.Flags -} - -public let attributeGraphVendor = AttributeGraphVendor.danceUIGraph - -#elseif OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH - -@_exported public import AttributeGraph -#if os(iOS) && !targetEnvironment(simulator) -@_exported public import _AttributeGraphDeviceSwiftShims -#endif -public typealias OAGAttributeInfo = AGAttributeInfo -public typealias OAGCachedValueOptions = AGCachedValueOptions -public typealias OAGChangedValueFlags = AGChangedValueFlags -public typealias OAGInputOptions = AGInputOptions -public typealias OAGValue = AGValue -public typealias OAGValueOptions = AGValueOptions - -public let attributeGraphVendor = AttributeGraphVendor.ag - -#else - +#if !OPENATTRIBUTEGRAPH_COMPUTE && !OPENATTRIBUTEGRAPH_DANCEUIGRAPH && !OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH @_exported import OpenAttributeGraph public let attributeGraphVendor = AttributeGraphVendor.oag #endif From cde607a58494b304b1a60232a4008a532fdfecfd Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Apr 2026 20:54:24 +0800 Subject: [PATCH 6/9] Bump DG version --- Package.resolved | 2 +- Package.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index b0860d83..097bf37a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "6f1bc3c594b00da912a3dda25a2aab758ff9dff337b9474048e78f9a76ed819a", + "originHash" : "434e8483d5d838dea7f4fc046575d87bd29c861c96803ba4e3aad7d819308bbc", "pins" : [ { "identity" : "swift-numerics", diff --git a/Package.swift b/Package.swift index 5b1d8c2d..c95bea30 100644 --- a/Package.swift +++ b/Package.swift @@ -446,7 +446,7 @@ if computeCondition { } else { let version: Version = envStringValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH_BINARY_VERSION").flatMap { Version($0) - } ?? "0.0.2" + } ?? "0.0.3" danceUIGraphBinaryRepo = Package.Dependency.package( url: "https://github.com/OpenSwiftUIProject/DanceUIGraph-spm.git", exact: version From 50c08ed7c9fdbc5911f2ff3ab6e7616e3ba3302d Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Apr 2026 23:12:18 +0800 Subject: [PATCH 7/9] Add DanceUIGraph adapter shims --- Package.resolved | 10 +- Package.swift | 13 + .../OpenAttributeGraphDanceUIGraphShims.m | 177 ++ .../OpenAttributeGraphDanceUIGraphShims.h | 61 + .../Adapter/DanceUIGraph.swift | 1808 ++++++++++++++++- .../Attribute+Debug.swift | 9 + 6 files changed, 2061 insertions(+), 17 deletions(-) create mode 100644 Sources/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.m create mode 100644 Sources/OpenAttributeGraphDanceUIGraphShims/include/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.h diff --git a/Package.resolved b/Package.resolved index 097bf37a..9ebc7699 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "434e8483d5d838dea7f4fc046575d87bd29c861c96803ba4e3aad7d819308bbc", + "originHash" : "04b6edb35915a23279d904347c869df8edbee1e1773569e49acfaedb7d8a6f1b", "pins" : [ { - "identity" : "swift-numerics", + "identity" : "danceuigraph-spm", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-numerics", + "location" : "https://github.com/OpenSwiftUIProject/DanceUIGraph-spm.git", "state" : { - "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2", - "version" : "1.1.1" + "revision" : "bda6c5a83d93abf18d07d2e586e6caaf7e034e2b", + "version" : "0.0.3" } } ], diff --git a/Package.swift b/Package.swift index c95bea30..3a26ce3e 100644 --- a/Package.swift +++ b/Package.swift @@ -226,6 +226,9 @@ extension Target { dependencies.append( .product(name: "DanceUIGraph", package: "DanceUIGraph-spm") ) + dependencies.append( + .target(name: "OpenAttributeGraphDanceUIGraphShims") + ) addDanceUIGraphSwiftSettings() var linkerSettings = linkerSettings ?? [] @@ -333,6 +336,15 @@ let openAttributeGraphShimsTarget = Target.target( cxxSettings: sharedCxxSettings, swiftSettings: sharedSwiftSettings ) +let openAttributeGraphDanceUIGraphShimsTarget = Target.target( + name: "OpenAttributeGraphDanceUIGraphShims", + dependencies: [ + .product(name: "DanceUIGraph", package: "DanceUIGraph-spm"), + ], + path: "Sources/OpenAttributeGraphDanceUIGraphShims", + publicHeadersPath: "include", + cSettings: sharedCSettings +) // MARK: - Test Targets @@ -453,6 +465,7 @@ if computeCondition { ) } package.dependencies.append(danceUIGraphBinaryRepo) + package.targets.append(openAttributeGraphDanceUIGraphShimsTarget) openAttributeGraphShimsTarget.addDanceUIGraphSettings() openAttributeGraphShimsTestsTarget.addDanceUIGraphSwiftSettings() package.targets.append(openAttributeGraphShimsTestsTarget) diff --git a/Sources/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.m b/Sources/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.m new file mode 100644 index 00000000..2875a5f4 --- /dev/null +++ b/Sources/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.m @@ -0,0 +1,177 @@ +#include + +void * _Nullable OAGDanceUIGraphGetContext(DanceUIGraphRef graph) SWIFT_CC(swift) { + return DanceUIGraphGetContext(graph); +} + +void OAGDanceUIGraphSetContext(DanceUIGraphRef graph, void * _Nullable context) SWIFT_CC(swift) { + DanceUIGraphSetContext(graph, context); +} + +DanceUIGraphAttribute OAGDanceUIGraphGetCurrentAttribute(void) SWIFT_CC(swift) { + return DanceUIGraphGetCurrentAttribute(); +} + +bool OAGDanceUIGraphCurrentAttributeWasModified(void) SWIFT_CC(swift) { + return DanceUIGraphCurrentAttributeWasModified(); +} + +DanceUIGraphAttribute OAGDanceUIGraphCurrentAttributeUpdatedReason(void) SWIFT_CC(swift) { + return DanceUIGraphCurrentAttributeUpdatedReason(); +} + +void *OAGDanceUIGraphClearUpdate(void) SWIFT_CC(swift) { + return DanceUIGraphClearUpdate(); +} + +void OAGDanceUIGraphSetUpdate(void *update) SWIFT_CC(swift) { + DanceUIGraphSetUpdate(update); +} + +DanceUIGraphAttribute OAGDanceUIGraphCreateAttribute(DanceUIGraphTypeIndex typeID, const void *attribute, const void * _Nullable value) SWIFT_CC(swift) { + return DanceUIGraphCreateAttribute(typeID, (void *)attribute, (void *)value); +} + +DanceUIGraphValue OAGDanceUIGraphGetValue(DanceUIGraphAttribute attribute, DanceUIGraphInputOptions options, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + return DanceUIGraphGetValue(attribute, (DanceUIGraphValueOptions)options, metadata); +} + +bool OAGDanceUIGraphSetValue(DanceUIGraphAttribute attribute, const void *value, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + return DanceUIGraphSetValue(attribute, value, metadata); +} + +DanceUIGraphValue OAGDanceUIGraphGetInputValue(DanceUIGraphAttribute destinationAttribute, DanceUIGraphAttribute inputAttribute, DanceUIGraphInputOptions options, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + return DanceUIGraphGetInputValue(destinationAttribute, inputAttribute, (DanceUIGraphValueOptions)options, metadata); +} + +const void * _Nullable OAGDanceUIGraphGetOutputValue(const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + return DanceUIGraphGetOutputValue(metadata); +} + +void OAGDanceUIGraphSetOutputValue(const void *value, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + DanceUIGraphSetOutputValue((void *)value, metadata); +} + +void OAGDanceUIGraphWithUpdate(DanceUIGraphAttribute attribute, void (*updateCallback)(void *ctx SWIFT_CONTEXT) SWIFT_CC(swift), const void *updateCallbackContext) SWIFT_CC(swift) { + DanceUIGraphWithUpdate(attribute, updateCallback, updateCallbackContext); +} + +DanceUIGraphAttribute OAGDanceUIGraphCreateOffsetAttribute(DanceUIGraphAttribute attribute, int offset) SWIFT_CC(swift) { + return DanceUIGraphCreateOffsetAttribute(attribute, (uint32_t)offset); +} + +DanceUIGraphAttribute OAGDanceUIGraphCreateOffsetAttribute2(DanceUIGraphAttribute attribute, int offset, int size) SWIFT_CC(swift) { + return DanceUIGraphCreateOffsetAttribute2(attribute, (uint32_t)offset, (uint32_t)size); +} + +DanceUIGraphAttribute OAGDanceUIGraphCreateIndirectAttribute(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphCreateIndirectAttribute(attribute); +} + +DanceUIGraphAttribute OAGDanceUIGraphCreateIndirectAttribute2(DanceUIGraphAttribute attribute, uint32_t size) SWIFT_CC(swift) { + return DanceUIGraphCreateIndirectAttribute2(attribute, size); +} + +DanceUIGraphAttribute OAGDanceUIGraphGetIndirectAttribute(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphGetIndirectAttribute(attribute); +} + +void OAGDanceUIGraphSetIndirectAttribute(DanceUIGraphAttribute attribute, DanceUIGraphAttribute source) SWIFT_CC(swift) { + DanceUIGraphSetIndirectAttribute(attribute, source); +} + +DanceUIGraphAttribute OAGDanceUIGraphGetIndirectDependency(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphGetIndirectDependency(attribute); +} + +void OAGDanceUIGraphSetIndirectDependency(DanceUIGraphAttribute attribute, DanceUIGraphAttribute dependency) SWIFT_CC(swift) { + DanceUIGraphSetIndirectDependency(attribute, dependency); +} + +DanceUIGraphWeakAttribute OAGDanceUIGraphCreateWeakAttribute(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphCreateWeakAttribute(attribute); +} + +DanceUIGraphAttribute OAGDanceUIGraphWeakAttributeGetAttribute(DanceUIGraphWeakAttribute weakAttribute) SWIFT_CC(swift) { + return DanceUIGraphWeakAttributeGetAttribute(weakAttribute); +} + +DanceUIGraphWeakValue OAGDanceUIGraphGetWeakValue(DanceUIGraphWeakAttribute weakAttribute, DanceUIGraphInputOptions options, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + return DanceUIGraphGetWeakValue(weakAttribute, (DanceUIGraphValueOptions)options, metadata); +} + +DanceUIGraphAttributeInfo OAGDanceUIGraphGetAttributeInfo(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphGetAttributeInfo(attribute); +} + +void OAGDanceUIGraphMutateAttribute(DanceUIGraphAttribute attribute, const DanceUIGraphSwiftMetadata *metadata, bool invalidate, void (*mutateBody)(void *ctx SWIFT_CONTEXT, void *attribute) SWIFT_CC(swift), const void *mutateBodyContext) SWIFT_CC(swift) { + DanceUIGraphMutateAttribute(attribute, metadata, invalidate, mutateBody, mutateBodyContext); +} + +void OAGDanceUIGraphVerifyType(DanceUIGraphAttribute attribute, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift) { + DanceUIGraphVerifyType(attribute, metadata); +} + +void OAGDanceUIGraphAddInput(DanceUIGraphAttribute toAttribute, DanceUIGraphAttribute fromAttribute, DanceUIGraphInputOptions inputOptions) SWIFT_CC(swift) { + DanceUIGraphAddInput(toAttribute, fromAttribute, inputOptions); +} + +void OAGDanceUIGraphInvalidateAllValues(DanceUIGraphRef graph) SWIFT_CC(swift) { + DanceUIGraphInvalidateAllValues(graph); +} + +void OAGDanceUIGraphInvalidateValue(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + DanceUIGraphInvalidateValue(attribute); +} + +bool OAGDanceUIGraphHasValue(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphHasValue(attribute); +} + +void OAGDanceUIGraphUpdateValue(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + DanceUIGraphUpdateValue(attribute); +} + +DanceUIGraphValueState OAGDanceUIGraphGetValueState(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphGetValueState(attribute); +} + +bool OAGDanceUIGraphSearch(DanceUIGraphAttribute rootAttribute, DanceUIGraphSearchOptions options, bool (*body)(void *ctx SWIFT_CONTEXT, DanceUIGraphAttribute attribute) SWIFT_CC(swift), const void *bodyContext) SWIFT_CC(swift) { + return DanceUIGraphSearch(rootAttribute, options, body, bodyContext); +} + +DanceUIGraphAttributeFlags OAGDanceUIGraphGetFlags(DanceUIGraphAttribute attribute) SWIFT_CC(swift) { + return DanceUIGraphGetFlags(attribute); +} + +void OAGDanceUIGraphSetFlags(DanceUIGraphAttribute attribute, DanceUIGraphAttributeFlags flags) SWIFT_CC(swift) { + DanceUIGraphSetFlags(attribute, flags); +} + +const void *OAGDanceUIGraphReadCachedAttribute(uintptr_t hashValue, const DanceUIGraphSwiftMetadata *selfMetadata, const void *attributeBody, const DanceUIGraphSwiftMetadata *valueMetadata, DanceUIGraphCachedValueOptions valueOptions, DanceUIGraphAttribute attribute, DanceUIGraphChangedValueFlags *changedValueFlags, DanceUIGraphTypeIndex (*body)(void *ctx SWIFT_CONTEXT, DanceUIGraphContextRef) SWIFT_CC(swift), const void *bodyContext) SWIFT_CC(swift) { + return DanceUIGraphReadCachedAttribute(hashValue, selfMetadata, attributeBody, valueMetadata, valueOptions, attribute, changedValueFlags, body, bodyContext); +} + +const void * _Nullable OAGDanceUIGraphReadCachedAttributeIfExists(uintptr_t hashValue, const DanceUIGraphSwiftMetadata *selfMetadata, const void *attributeBody, const DanceUIGraphSwiftMetadata *valueMetadata, DanceUIGraphCachedValueOptions valueOptions, DanceUIGraphAttribute attribute, DanceUIGraphChangedValueFlags *changedValueFlags) SWIFT_CC(swift) { + return DanceUIGraphReadCachedAttributeIfExists(hashValue, selfMetadata, attributeBody, valueMetadata, valueOptions, attribute, changedValueFlags); +} + +void OAGDanceUISubgraphSetCurrent(DanceUISubgraphRef _Nullable subgraph) SWIFT_CC(swift) { + DanceUISubgraphSetCurrent(subgraph); +} + +DanceUISubgraphRef _Nullable OAGDanceUISubgraphGetCurrent(void) SWIFT_CC(swift) { + return DanceUISubgraphGetCurrent(); +} + +DanceUIGraphContextRef _Nullable OAGDanceUISubgraphGetCurrentGraphContext(void) SWIFT_CC(swift) { + return DanceUISubgraphGetCurrentGraphContext(); +} + +void OAGDanceUISubgraphApply(DanceUISubgraphRef subgraph, DanceUIGraphAttributeFlags flags, void (*applyBody)(void *ctx SWIFT_CONTEXT, DanceUIGraphAttribute attribute) SWIFT_CC(swift), const void *applyBodyContext) SWIFT_CC(swift) { + DanceUISubgraphApply(subgraph, flags, applyBody, applyBodyContext); +} + +bool OAGDanceUISubgraphIntersects(DanceUISubgraphRef subgraph, DanceUIGraphAttributeFlags flags) SWIFT_CC(swift) { + return DanceUISubgraphIntersects(subgraph, flags); +} diff --git a/Sources/OpenAttributeGraphDanceUIGraphShims/include/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.h b/Sources/OpenAttributeGraphDanceUIGraphShims/include/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.h new file mode 100644 index 00000000..305dca2f --- /dev/null +++ b/Sources/OpenAttributeGraphDanceUIGraphShims/include/OpenAttributeGraphDanceUIGraphShims/OpenAttributeGraphDanceUIGraphShims.h @@ -0,0 +1,61 @@ +#ifndef OpenAttributeGraphDanceUIGraphShims_h +#define OpenAttributeGraphDanceUIGraphShims_h + +#include +#include + +#include +#include +#include + +DANCE_UI_ASSUME_NONNULL_BEGIN + +void * _Nullable OAGDanceUIGraphGetContext(DanceUIGraphRef graph) SWIFT_CC(swift); +void OAGDanceUIGraphSetContext(DanceUIGraphRef graph, void * _Nullable context) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphGetCurrentAttribute(void) SWIFT_CC(swift); +bool OAGDanceUIGraphCurrentAttributeWasModified(void) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphCurrentAttributeUpdatedReason(void) SWIFT_CC(swift); +void *OAGDanceUIGraphClearUpdate(void) SWIFT_CC(swift); +void OAGDanceUIGraphSetUpdate(void *update) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphCreateAttribute(DanceUIGraphTypeIndex typeID, const void *attribute, const void * _Nullable value) SWIFT_CC(swift); +DanceUIGraphValue OAGDanceUIGraphGetValue(DanceUIGraphAttribute attribute, DanceUIGraphInputOptions options, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +bool OAGDanceUIGraphSetValue(DanceUIGraphAttribute attribute, const void *value, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +DanceUIGraphValue OAGDanceUIGraphGetInputValue(DanceUIGraphAttribute destinationAttribute, DanceUIGraphAttribute inputAttribute, DanceUIGraphInputOptions options, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +const void * _Nullable OAGDanceUIGraphGetOutputValue(const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +void OAGDanceUIGraphSetOutputValue(const void *value, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +void OAGDanceUIGraphWithUpdate(DanceUIGraphAttribute attribute, void (*updateCallback)(void *ctx SWIFT_CONTEXT) SWIFT_CC(swift), const void *updateCallbackContext) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphCreateOffsetAttribute(DanceUIGraphAttribute attribute, int offset) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphCreateOffsetAttribute2(DanceUIGraphAttribute attribute, int offset, int size) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphCreateIndirectAttribute(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphCreateIndirectAttribute2(DanceUIGraphAttribute attribute, uint32_t size) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphGetIndirectAttribute(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +void OAGDanceUIGraphSetIndirectAttribute(DanceUIGraphAttribute attribute, DanceUIGraphAttribute source) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphGetIndirectDependency(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +void OAGDanceUIGraphSetIndirectDependency(DanceUIGraphAttribute attribute, DanceUIGraphAttribute dependency) SWIFT_CC(swift); +DanceUIGraphWeakAttribute OAGDanceUIGraphCreateWeakAttribute(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +DanceUIGraphAttribute OAGDanceUIGraphWeakAttributeGetAttribute(DanceUIGraphWeakAttribute weakAttribute) SWIFT_CC(swift); +DanceUIGraphWeakValue OAGDanceUIGraphGetWeakValue(DanceUIGraphWeakAttribute weakAttribute, DanceUIGraphInputOptions options, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +DanceUIGraphAttributeInfo OAGDanceUIGraphGetAttributeInfo(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +void OAGDanceUIGraphMutateAttribute(DanceUIGraphAttribute attribute, const DanceUIGraphSwiftMetadata *metadata, bool invalidate, void (*mutateBody)(void *ctx SWIFT_CONTEXT, void *attribute) SWIFT_CC(swift), const void *mutateBodyContext) SWIFT_CC(swift); +void OAGDanceUIGraphVerifyType(DanceUIGraphAttribute attribute, const DanceUIGraphSwiftMetadata *metadata) SWIFT_CC(swift); +void OAGDanceUIGraphAddInput(DanceUIGraphAttribute toAttribute, DanceUIGraphAttribute fromAttribute, DanceUIGraphInputOptions inputOptions) SWIFT_CC(swift); +void OAGDanceUIGraphInvalidateAllValues(DanceUIGraphRef graph) SWIFT_CC(swift); +void OAGDanceUIGraphInvalidateValue(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +bool OAGDanceUIGraphHasValue(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +void OAGDanceUIGraphUpdateValue(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +DanceUIGraphValueState OAGDanceUIGraphGetValueState(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +bool OAGDanceUIGraphSearch(DanceUIGraphAttribute rootAttribute, DanceUIGraphSearchOptions options, bool (*body)(void *ctx SWIFT_CONTEXT, DanceUIGraphAttribute attribute) SWIFT_CC(swift), const void *bodyContext) SWIFT_CC(swift); +DanceUIGraphAttributeFlags OAGDanceUIGraphGetFlags(DanceUIGraphAttribute attribute) SWIFT_CC(swift); +void OAGDanceUIGraphSetFlags(DanceUIGraphAttribute attribute, DanceUIGraphAttributeFlags flags) SWIFT_CC(swift); +const void *OAGDanceUIGraphReadCachedAttribute(uintptr_t hashValue, const DanceUIGraphSwiftMetadata *selfMetadata, const void *attributeBody, const DanceUIGraphSwiftMetadata *valueMetadata, DanceUIGraphCachedValueOptions valueOptions, DanceUIGraphAttribute attribute, DanceUIGraphChangedValueFlags *changedValueFlags, DanceUIGraphTypeIndex (*body)(void *ctx SWIFT_CONTEXT, DanceUIGraphContextRef) SWIFT_CC(swift), const void *bodyContext) SWIFT_CC(swift); +const void * _Nullable OAGDanceUIGraphReadCachedAttributeIfExists(uintptr_t hashValue, const DanceUIGraphSwiftMetadata *selfMetadata, const void *attributeBody, const DanceUIGraphSwiftMetadata *valueMetadata, DanceUIGraphCachedValueOptions valueOptions, DanceUIGraphAttribute attribute, DanceUIGraphChangedValueFlags *changedValueFlags) SWIFT_CC(swift); + +void OAGDanceUISubgraphSetCurrent(DanceUISubgraphRef _Nullable subgraph) SWIFT_CC(swift); +DanceUISubgraphRef _Nullable OAGDanceUISubgraphGetCurrent(void) SWIFT_CC(swift); +DanceUIGraphContextRef _Nullable OAGDanceUISubgraphGetCurrentGraphContext(void) SWIFT_CC(swift); +void OAGDanceUISubgraphApply(DanceUISubgraphRef subgraph, DanceUIGraphAttributeFlags flags, void (*applyBody)(void *ctx SWIFT_CONTEXT, DanceUIGraphAttribute attribute) SWIFT_CC(swift), const void *applyBodyContext) SWIFT_CC(swift); +bool OAGDanceUISubgraphIntersects(DanceUISubgraphRef subgraph, DanceUIGraphAttributeFlags flags) SWIFT_CC(swift); + +DANCE_UI_ASSUME_NONNULL_END + +#endif diff --git a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift index b2ef4b56..ba76b9ce 100644 --- a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift +++ b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift @@ -6,10 +6,11 @@ @_exported public import DanceUIRuntime @_exported public import DanceUIGraph +@_exported public import Foundation +import Darwin -public typealias AnyAttribute = DGAttribute -public typealias AnyWeakAttribute = DGWeakAttribute -public typealias Graph = DGGraphRef +public typealias AttributeBodyVisitor = DanceUIGraph.AttributeBodyVisitor +public typealias ComparisonMode = DGComparisonMode public typealias GraphContext = DGGraphContextRef public typealias Metadata = DGTypeID public typealias OAGAttributeInfo = DGAttributeInfo @@ -17,35 +18,1818 @@ public typealias OAGCachedValueOptions = DGGraphCachedValueOptions public typealias OAGChangedValueFlags = DGChangedValueFlags public typealias OAGInputOptions = DGInputOptions public typealias OAGValue = DGGraphValue -public typealias OAGValueOptions = DGValueOptions +public typealias OAGValueOptions = DGInputOptions +public typealias OAGWeakValue = DGGraphWeakValue +public typealias ObservedAttribute = DanceUIGraph.ObservedAttribute +public typealias PointerOffset = DanceUIGraph.PointerOffset public typealias SearchOptions = DGSearchOptions -public typealias Subgraph = DGSubgraphRef public typealias TupleType = DGTupleType public typealias UnsafeMutableTuple = DGUnsafeMutableTuple public typealias UnsafeTuple = DGUnsafeTuple -public typealias UniqueID = DGUniqueID +public typealias UniqueID = UInt public typealias ValueState = DGValueState +public typealias _AttributeBody = DanceUIGraph._AttributeBody public typealias _AttributeType = _DGAttributeType public typealias _AttributeVTable = _DGAttributeVTable public typealias _OAGClosureStorage = DGClosureStorage +public typealias DescriptionOption = DanceUIGraphDescriptionOption +public typealias Signature = UnsafePointer +public typealias AttributeUpdateBlock = () -> (UnsafeMutableRawPointer, AnyAttribute) -> Void -extension AnyAttribute { - public typealias Flags = DGAttributeFlags +@frozen +public struct OAGAttributeFlags: OptionSet, Hashable, Sendable { + public let rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } +} + +private extension DGAttributeFlags { + init(_ flags: OAGAttributeFlags) { + self.init(rawValue: flags.rawValue) + } +} + +private extension OAGAttributeFlags { + init(_ flags: DGAttributeFlags) { + self.init(rawValue: flags.rawValue) + } } -extension Graph { +@_silgen_name("OAGDanceUIGraphGetContext") +private func OAGDGGraphGetContext(_ graph: DGGraphRef) -> UnsafeMutableRawPointer? + +@_silgen_name("OAGDanceUIGraphSetContext") +private func OAGDGGraphSetContext(_ graph: DGGraphRef, _ context: UnsafeMutableRawPointer?) + +@_silgen_name("OAGDanceUIGraphGetCurrentAttribute") +private func OAGDGGraphGetCurrentAttribute() -> DGAttribute + +@_silgen_name("OAGDanceUIGraphCurrentAttributeWasModified") +private func OAGDGGraphCurrentAttributeWasModified() -> Bool + +@_silgen_name("OAGDanceUIGraphCurrentAttributeUpdatedReason") +private func OAGDGGraphCurrentAttributeUpdatedReason() -> DGAttribute + +@_silgen_name("OAGDanceUIGraphClearUpdate") +private func OAGDGGraphClearUpdate() -> UnsafeRawPointer + +@_silgen_name("OAGDanceUIGraphSetUpdate") +private func OAGDGGraphSetUpdate(_ oldUpdate: UnsafeRawPointer) + +@_silgen_name("OAGDanceUIGraphCreateAttribute") +private func OAGDGGraphCreateAttribute( + _ typeIndex: DGGraphTypeIndex, + _ body: UnsafeRawPointer, + _ value: UnsafeRawPointer? +) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphGetValue") +private func OAGDGGraphGetValue( + _ attribute: DGAttribute, + _ options: DGInputOptions, + _ valueType: Any.Type +) -> DGGraphValue + +@_silgen_name("OAGDanceUIGraphSetValue") +@discardableResult +private func OAGDGGraphSetValue( + _ attribute: DGAttribute, + _ value: UnsafeRawPointer, + _ type: Any.Type +) -> Bool + +@_silgen_name("OAGDanceUIGraphGetInputValue") +private func OAGDGGraphGetInputValue( + _ destinationAttribute: DGAttribute, + _ inputAttribute: DGAttribute, + _ options: DGInputOptions, + _ valueType: Any.Type +) -> DGGraphValue + +@_silgen_name("OAGDanceUIGraphGetOutputValue") +private func OAGDGGraphGetOutputValue() -> UnsafePointer? + +@_silgen_name("OAGDanceUIGraphSetOutputValue") +private func OAGDGGraphSetOutputValue(_ valuePtr: UnsafePointer) + +@_silgen_name("OAGDanceUIGraphWithUpdate") +private func OAGDGGraphWithUpdate(_ attribute: DGAttribute, _ body: () -> Void) + +@_silgen_name("OAGDanceUIGraphCreateOffsetAttribute") +private func OAGDGGraphCreateOffsetAttribute(_ attribute: DGAttribute, _ offset: Int) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphCreateOffsetAttribute2") +private func OAGDGGraphCreateOffsetAttribute2(_ attribute: DGAttribute, _ offset: Int, _ size: Int) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphCreateIndirectAttribute") +private func OAGDGGraphCreateIndirectAttribute(_ attribute: DGAttribute) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphCreateIndirectAttribute2") +private func OAGDGGraphCreateIndirectAttribute2(_ attribute: DGAttribute, _ size: UInt32) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphGetIndirectAttribute") +private func OAGDGGraphGetIndirectAttribute(_ attribute: DGAttribute) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphSetIndirectAttribute") +private func OAGDGGraphSetIndirectAttribute(_ attribute: DGAttribute, _ source: DGAttribute) + +@_silgen_name("OAGDanceUIGraphGetIndirectDependency") +private func OAGDGGraphGetIndirectDependency(_ attribute: DGAttribute) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphSetIndirectDependency") +private func OAGDGGraphSetIndirectDependency(_ attribute: DGAttribute, _ dependency: DGAttribute) + +@_silgen_name("OAGDanceUIGraphCreateWeakAttribute") +private func OAGDGGraphCreateWeakAttribute(_ attribute: DGAttribute) -> DGWeakAttribute + +@_silgen_name("OAGDanceUIGraphWeakAttributeGetAttribute") +private func OAGDGGraphWeakAttributeGetAttribute(_ weakAttribute: DGWeakAttribute) -> DGAttribute + +@_silgen_name("OAGDanceUIGraphGetWeakValue") +private func OAGDGGraphGetWeakValue( + _ weakAttribute: DGWeakAttribute, + _ options: DGInputOptions, + _ valueType: Any.Type +) -> DGGraphWeakValue + +@_silgen_name("OAGDanceUIGraphGetAttributeInfo") +private func OAGDGGraphGetAttributeInfo(_ attribute: DGAttribute) -> DGAttributeInfo + +@_silgen_name("OAGDanceUIGraphMutateAttribute") +private func OAGDGGraphMutateAttribute( + _ attribute: DGAttribute, + _ type: Any.Type, + _ invalidate: Bool, + _ body: (UnsafeMutableRawPointer) -> Void +) + +@_silgen_name("OAGDanceUIGraphVerifyType") +private func OAGDGGraphVerifyType(_ attribute: DGAttribute, _ type: Any.Type) + +@_silgen_name("OAGDanceUIGraphAddInput") +private func OAGDGGraphAddInput(_ toAttribute: DGAttribute, _ fromAttribute: DGAttribute, _ options: DGInputOptions) + +@_silgen_name("OAGDanceUIGraphInvalidateAllValues") +private func OAGDGGraphInvalidateAllValues(_ graph: DGGraphRef) + +@_silgen_name("OAGDanceUIGraphInvalidateValue") +private func OAGDGGraphInvalidateValue(_ attribute: DGAttribute) + +@_silgen_name("OAGDanceUIGraphHasValue") +private func OAGDGGraphHasValue(_ attribute: DGAttribute) -> Bool + +@_silgen_name("OAGDanceUIGraphUpdateValue") +private func OAGDGGraphUpdateValue(_ attribute: DGAttribute) + +@_silgen_name("OAGDanceUIGraphGetValueState") +private func OAGDGGraphGetValueState(_ attribute: DGAttribute) -> DGValueState + +@_silgen_name("OAGDanceUIGraphSearch") +private func OAGDGGraphSearch( + attribute: DGAttribute, + options: DGSearchOptions, + body: (DGAttribute) -> Bool +) -> Bool + +@_silgen_name("OAGDanceUIGraphGetFlags") +private func OAGDGGraphGetFlags(_ attribute: DGAttribute) -> DGAttributeFlags + +@_silgen_name("OAGDanceUIGraphSetFlags") +private func OAGDGGraphSetFlags(_ attribute: DGAttribute, _ flags: DGAttributeFlags) + +@_silgen_name("OAGDanceUIGraphReadCachedAttribute") +private func OAGDGGraphReadCachedAttribute( + _ hashValue: Int, + _ selfType: Any.Type, + _ attributeBody: UnsafeRawPointer, + _ valueType: Any.Type, + _ valueOptions: DGGraphCachedValueOptions, + _ attribute: DGAttribute, + _ flags: UnsafeMutablePointer, + _ body: (DGGraphContextRef) -> DGGraphTypeIndex +) -> UnsafeRawPointer + +@_silgen_name("OAGDanceUIGraphReadCachedAttributeIfExists") +private func OAGDGGraphReadCachedAttributeIfExists( + _ hashValue: Int, + _ selfType: Any.Type, + _ attributeBody: UnsafeRawPointer, + _ valueType: Any.Type, + _ valueOptions: DGGraphCachedValueOptions, + _ attribute: DGAttribute, + _ flags: UnsafeMutablePointer +) -> UnsafeRawPointer? + +@_silgen_name("OAGDanceUISubgraphSetCurrent") +private func OAGDGSubgraphSetCurrent(_ subgraph: DGSubgraphRef?) + +@_silgen_name("OAGDanceUISubgraphGetCurrent") +private func OAGDGSubgraphGetCurrent() -> DGSubgraphRef? + +@_silgen_name("OAGDanceUISubgraphGetCurrentGraphContext") +private func OAGDGSubgraphGetCurrentGraphContext() -> DGGraphContextRef? + +@_silgen_name("OAGDanceUISubgraphApply") +private func OAGDGSubgraphApply(_ subgraph: DGSubgraphRef, _ flags: DGAttributeFlags, _ body: (DGAttribute) -> Void) + +@_silgen_name("OAGDanceUISubgraphIntersects") +private func OAGDGSubgraphIntersects(_ subgraph: DGSubgraphRef, _ flags: DGAttributeFlags) -> Bool + +// MARK: - Graph + +@frozen +public struct Graph: Hashable { + public var base: DGGraphRef + + public init() { + base = DGGraphCreate() + } + + public init(shared graph: Graph) { + base = DGGraphCreateShared(graph.base) + } + + public init(_ base: DGGraphRef) { + self.base = base + } + + public typealias CounterQueryType = DGGraphQueryType + + public struct TraceOptions: OptionSet, Sendable { + public let rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + } + + public static func == (lhs: Graph, rhs: Graph) -> Bool { + lhs.base === rhs.base + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(base)) + } + + public static var current: Graph { + AnyAttribute.current!.graph + } + + public var context: UnsafeRawPointer? { + get { OAGDGGraphGetContext(base).map(UnsafeRawPointer.init) } + nonmutating set { OAGDGGraphSetContext(base, newValue.map(UnsafeMutableRawPointer.init(mutating:))) } + } + + public static func typeIndex( + ctx: GraphContext, + body: _AttributeBody.Type, + valueType: Metadata, + flags: _AttributeType.Flags, + update: AttributeUpdateBlock + ) -> DGGraphTypeIndex { + DGGraphRef.typeIndex( + ctx: ctx, + body: body, + valueType: valueType, + flags: flags + ) { + let update = update() + return { pointer, attribute in + update(pointer, AnyAttribute(attribute)) + } + } + } + + public static func withoutUpdate(_ body: () -> Value) -> Value { + DGGraphRef.withoutUpdate(body) + } + + public func withoutSubgraphInvalidation(_ body: () -> Value) -> Value { + let previousDeferring = DGGraphBeginDeferringSubgraphInvalidation(base) + defer { + DGGraphEndDeferringSubgraphInvalidation(base, previousDeferring: previousDeferring) + } + return body() + } + + public func withDeadline(_: UInt64, _: () -> Value) -> Value { + fatalError("OAGDanceUIGraph deadline-scoped updates are not available through OpenAttributeGraphShims") + } + + public func onInvalidation(_ callback: @escaping (AnyAttribute) -> Void) { + base.onInvalidation { callback(AnyAttribute($0)) } + } + + public func onUpdate(_ callback: @escaping () -> Void) { + base.onUpdate(callback) + } + + public func withMainThreadHandler(_ handler: (() -> Void) -> Void, do body: () -> Void) { + base.withMainThreadHandler(handler, do: body) + } + + public func invalidateAllValues() { + OAGDGGraphInvalidateAllValues(base) + } + + public func invalidate() { + base.invalidate() + } + + public func setNeedsUpdate() { + DGGraphSetNeedsUpdate(base) + } + + public func counter(for query: CounterQueryType) -> UInt64 { + switch query { + case []: + 0 + case .transactionCounter: + UInt64(base.transactionCounter) + case .updateCounter: + UInt64(base.updateCounter) + case .changeCounter: + 0 + case .internTypes: + UInt64(base.internTypes) + case .uniqueID: + UInt64(base.graphIdentity) + case .isUpdating: + base.isUpdating ? 1 : 0 + case .hasCurrentUpdate: + base.hasCurrentUpdate ? 1 : 0 + case .contextNeedsUpdate, .graphNeedsUpdate: + 0 + case .mainUpdates: + UInt64(base.mainUpdates) + default: + 0 + } + } + + public var mainUpdates: Int { + numericCast(counter(for: .mainThreadUpdates)) + } + + public static func outputValue() -> UnsafePointer? { + OAGDGGraphGetOutputValue() + } + + public static func setOutputValue(_ value: UnsafePointer) { + OAGDGGraphSetOutputValue(value) + } + + public static func anyInputsChanged(excluding excludedInputs: [AnyAttribute]) -> Bool { + DGGraphRef.anyInputsChanged(excludedInputs.map(\.base)) + } + public static func resetProfile() { - reset() + DGGraphRef.reset() + } + + public static func startProfiling() { + DGGraphRef.startProfiling() + } + + public static func stopProfiling() { + DGGraphRef.stopProfiling() } public func resetProfile() { - reset() + base.reset() + } + + public static func startTracing(_ graph: Graph?, options _: TraceOptions?) { + graph?.base.startProfiling() + } + + public static func stopTracing(_ graph: Graph?) { + graph?.base.stopProfiling() + } + + public func startProfiling() { + base.startProfiling() } + + public func stopProfiling() { + base.stopProfiling() + } + + public func archiveJSON(name: String?) { + if let name { + name.withCString { base.archiveJSON(name: $0) } + } else { + let nilName: UnsafePointer? = nil + base.archiveJSON(name: nilName) + } + } + + public static func archiveJSON(name: UnsafePointer?) { + DGGraphRef.current.archiveJSON(name: name) + } + + public static var descriptionFormatDictionary: CFString { + DanceUIGraphDescriptionFormatKind.graphDictionary.rawValue as CFString + } + + public static var descriptionFormatDot: CFString { + DanceUIGraphDescriptionFormatKind.graphDot.rawValue as CFString + } + + public static var descriptionAllGraphs: CFString { + DescriptionOption.allGraphs.rawValue as CFString + } + + public static func description(_ graph: Graph?, options: NSDictionary) -> Any? { + var danceOptions: [DescriptionOption: Any] = [:] + for (key, value) in options { + guard let option = key as? DescriptionOption else { + continue + } + danceOptions[option] = value + } + return DanceUIGraphDescription(graph?.base, danceOptions) + } +} + +public func === (lhs: Graph, rhs: Graph) -> Bool { + lhs == rhs } -extension Subgraph { +public func !== (lhs: Graph, rhs: Graph) -> Bool { + !(lhs == rhs) +} + +extension Graph.CounterQueryType { + public static var nodes: Self { [] } + public static var transactions: Self { .transactionCounter } + public static var updates: Self { .updateCounter } + public static var changes: Self { .changeCounter } + public static var contextID: Self { .internTypes } + public static var graphID: Self { .uniqueID } + public static var contextThreadUpdating: Self { .isUpdating } + public static var threadUpdating: Self { .hasCurrentUpdate } + public static var needsUpdate: Self { .graphNeedsUpdate } + public static var mainThreadUpdates: Self { .mainUpdates } + public static var createdNodes: Self { [] } + public static var subgraphs: Self { Self(rawValue: 0) } + public static var createdSubgraphs: Self { Self(rawValue: 0) } +} + +// MARK: - Subgraph + +public final class Subgraph: Hashable { + public var base: DGSubgraphRef + + public init(_ base: DGSubgraphRef) { + self.base = base + } + + public init(graph: Graph) { + base = DGSubgraphCreate(graph.base) + } + + public init(graph: Graph, attribute: AnyAttribute) { + base = DGSubgraphCreate2(graph.base, attribute.base) + } + public typealias Flags = AnyAttribute.Flags public typealias ChildFlags = AnyAttribute.Flags + + public static func == (lhs: Subgraph, rhs: Subgraph) -> Bool { + lhs.base === rhs.base + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(base)) + } + + public static var current: Subgraph? { + get { OAGDGSubgraphGetCurrent().map(Subgraph.init) } + set { OAGDGSubgraphSetCurrent(newValue?.base) } + } + + public static var currentGraphContext: GraphContext? { + OAGDGSubgraphGetCurrentGraphContext() + } + + public var graph: Graph { + Graph(base.graph) + } + + public var isValid: Bool { + base.isValid + } + + public func apply(_ body: () -> Value) -> Value { + base.apply(body) + } + + public func forEach(_ flags: Flags, _ callback: (AnyAttribute) -> Void) { + OAGDGSubgraphApply(base, DGAttributeFlags(flags)) { callback(AnyAttribute($0)) } + } + + public func addChild(_ child: Subgraph) { + base.add(child: child.base) + } + + public func addChild(_ child: Subgraph, tag _: UInt8) { + addChild(child) + } + + public func removeChild(_ child: Subgraph) { + base.remove(child: child.base) + } + + @discardableResult + public func addObserver(_ observer: @escaping () -> Void) -> Int { + Int(base.add(observer: observer).rawValue) + } + + public func removeObserver(_ observerID: Int) { + base.remove(observer: DGUniqueID(rawValue: Int64(observerID))) + } + + public func isAncestor(of other: Subgraph) -> Bool { + base.isAncestor(other.base) + } + + public func isDirty(flags: Flags) -> Bool { + base.isDirty(UInt64(flags.rawValue)) + } + + public func update(flags: Flags) { + base.update(DGAttributeFlags(flags)) + } + + public func intersects(flags: Flags) -> Bool { + OAGDGSubgraphIntersects(base, DGAttributeFlags(flags)) + } + + public func invalidate() { + base.invalidate() + } + + public var index: UInt32 { + get { 0 } + set { DGSubgraphSetIndex(base, newValue) } + } + + public static var shouldRecordTree: Bool { + get { DGSubgraphRef.shouldRecordTree } + set { DGSubgraphRef.shouldRecordTree = newValue } + } + + public static func setShouldRecordTree(_ flag: Bool = true) { + shouldRecordTree = flag + } + + public static func beginTreeElement(value: Attribute, flags: UInt32) { + DGSubgraphRef.beginTreeElement(value: DanceUIGraph.Attribute(identifier: value.identifier.base), flags: flags) + } + + public static func addTreeValue(_ attribute: Attribute, forKey key: UnsafePointer, flags: UInt32) { + DGSubgraphRef.addTreeValue(DanceUIGraph.Attribute(identifier: attribute.identifier.base), forKey: key, flags: flags) + } + + public static func endTreeElement(value: Attribute) { + DGSubgraphRef.endTreeElement(value: DanceUIGraph.Attribute(identifier: value.identifier.base)) + } +} + +public func === (lhs: Subgraph, rhs: Subgraph) -> Bool { + lhs == rhs +} + +public func !== (lhs: Subgraph, rhs: Subgraph) -> Bool { + !(lhs == rhs) +} + +// MARK: - Attributes + +@frozen +public struct AnyAttribute: RawRepresentable, Hashable, CustomStringConvertible, CustomDebugStringConvertible { + public typealias RawValue = UInt32 + public typealias Flags = OAGAttributeFlags + + public var base: DGAttribute + + public init(rawValue: UInt32) { + base = DGAttribute(rawValue: rawValue) + } + + public init(_ base: DGAttribute) { + self.base = base + } + + public init(_ attribute: Attribute) { + base = attribute.identifier.base + } + + public var rawValue: UInt32 { + base.rawValue + } + + public static var `nil`: AnyAttribute { + AnyAttribute(DGAttribute.nil) + } + + public static var current: AnyAttribute? { + let current = OAGDGGraphGetCurrentAttribute() + return current == .nil ? nil : AnyAttribute(current) + } + + public static var currentWasModified: Bool { + OAGDGGraphCurrentAttributeWasModified() + } + + public var graph: Graph { + Graph(base.graph) + } + + public var subgraph: Subgraph { + Subgraph(base.subgraph) + } + + public var subgraph2: Subgraph? { + base == .nil ? nil : subgraph + } + + public var source: AnyAttribute { + get { AnyAttribute(OAGDGGraphGetIndirectAttribute(base)) } + nonmutating set { OAGDGGraphSetIndirectAttribute(base, newValue.base) } + } + + public var indirectDependency: AnyAttribute? { + get { + let dependency = OAGDGGraphGetIndirectDependency(base) + return dependency == .nil ? nil : AnyAttribute(dependency) + } + nonmutating set { + OAGDGGraphSetIndirectDependency(base, newValue?.base ?? .nil) + } + } + + public var info: OAGAttributeInfo { + OAGDGGraphGetAttributeInfo(base) + } + + public var flags: Flags { + get { OAGAttributeFlags(OAGDGGraphGetFlags(base)) } + nonmutating set { OAGDGGraphSetFlags(base, DGAttributeFlags(newValue)) } + } + + public var hasValue: Bool { + OAGDGGraphHasValue(base) + } + + public func unsafeCast(to _: Value.Type) -> Attribute { + Attribute(identifier: self) + } + + public func unsafeOffset(at offset: Int) -> AnyAttribute { + create(offset: offset) + } + + public func create(offset: Int, size: UInt32 = 0) -> AnyAttribute { + if size == 0 { + AnyAttribute(OAGDGGraphCreateOffsetAttribute(base, offset)) + } else { + AnyAttribute(OAGDGGraphCreateOffsetAttribute2(base, offset, Int(size))) + } + } + + public func createIndirect() -> AnyAttribute { + AnyAttribute(OAGDGGraphCreateIndirectAttribute(base)) + } + + public func createIndirect(size: UInt64) -> AnyAttribute { + AnyAttribute(OAGDGGraphCreateIndirectAttribute2(base, UInt32(size))) + } + + public func updateValue() { + OAGDGGraphUpdateValue(base) + } + + public func prefetchValue() { + updateValue() + } + + public func invalidateValue() { + OAGDGGraphInvalidateValue(base) + } + + public var valueState: ValueState { + OAGDGGraphGetValueState(base) + } + + public func addInput(_ attribute: AnyAttribute, options: OAGInputOptions = [], token _: Int) { + OAGDGGraphAddInput(base, attribute.base, options) + } + + public func addInput(_ attribute: Attribute, options: OAGInputOptions = [], token: Int) { + addInput(attribute.identifier, options: options, token: token) + } + + public func setFlags(_ newFlags: Flags, mask: Flags) { + flags = flags.subtracting(mask).union(newFlags.intersection(mask)) + } + + public func visitBody(_ visitor: inout Visitor) where Visitor: AttributeBodyVisitor { + base.visitBody(&visitor) + } + + public func mutateBody(as type: Value.Type, invalidating: Bool, _ body: (inout Value) -> Void) { + OAGDGGraphMutateAttribute(base, type, invalidating) { value in + body(&value.assumingMemoryBound(to: Value.self).pointee) + } + } + + public func breadthFirstSearch(options: SearchOptions = [], _ body: (AnyAttribute) -> Bool) -> Bool { + OAGDGGraphSearch(attribute: base, options: options) { body(AnyAttribute($0)) } + } + + public var _bodyType: Any.Type { + base._bodyType.type + } + + public var _bodyPointer: UnsafeRawPointer { + info.body + } + + public var valueType: Any.Type { + base.valueType.type + } + + public var description: String { + "#\(rawValue)" + } + + public var debugDescription: String { + base.debugDescription + } + + public static func == (lhs: AnyAttribute, rhs: AnyAttribute) -> Bool { + lhs.base == rhs.base + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(base) + } +} + +@frozen +@propertyWrapper +@dynamicMemberLookup +public struct Attribute: Hashable, Equatable, CustomStringConvertible { + public var identifier: AnyAttribute + + public init(identifier: AnyAttribute) { + self.identifier = identifier + } + + public init(_ attribute: Attribute) { + self = attribute + } + + public init(value: Value) { + self = withUnsafePointer(to: value) { valuePointer in + withUnsafePointer(to: External()) { bodyPointer in + Attribute(body: bodyPointer, value: valuePointer, flags: .external) { + External._update + } + } + } + } + + public init(type _: Value.Type) { + self = withUnsafePointer(to: External()) { bodyPointer in + Attribute(body: bodyPointer, value: nil, flags: .external) { + External._update + } + } + } + + public init( + body: UnsafePointer, + value: UnsafePointer?, + flags: _AttributeType.Flags = [], + update: AttributeUpdateBlock + ) { + guard let context = Subgraph.currentGraphContext else { + fatalError("attempting to create attribute with no subgraph: \(Value.self)") + } + let index = Graph.typeIndex( + ctx: context, + body: Body.self, + valueType: Metadata(Value.self), + flags: flags, + update: update + ) + identifier = AnyAttribute(OAGDGGraphCreateAttribute(index, body, value)) + } + + public var wrappedValue: Value { + unsafeAddress { + OAGDGGraphGetValue(identifier.base, [], Value.self) + .value_ptr + .assumingMemoryBound(to: Value.self) + } + nonmutating set { _ = setValue(newValue) } + } + + public var projectedValue: Attribute { + get { self } + set { self = newValue } + } + + public subscript(dynamicMember keyPath: KeyPath) -> Attribute { + self[keyPath: keyPath] + } + + public subscript(keyPath keyPath: KeyPath) -> Attribute { + if let offset = MemoryLayout.offset(of: keyPath) { + return unsafeOffset(at: offset, as: Member.self) + } else { + return Attribute(Focus(root: self, keyPath: keyPath)) + } + } + + public subscript(offset body: (inout Value) -> PointerOffset) -> Attribute { + unsafeOffset(at: PointerOffset.offset(body).byteOffset, as: Member.self) + } + + public func unsafeCast(to _: OtherValue.Type) -> Attribute { + Attribute(identifier: identifier) + } + + public func unsafeOffset(at offset: Int, as _: Member.Type) -> Attribute { + Attribute( + identifier: identifier.create( + offset: offset, + size: numericCast(MemoryLayout.size) + ) + ) + } + + public func applying(offset: PointerOffset) -> Attribute { + unsafeOffset(at: offset.byteOffset, as: Member.self) + } + + public func visitBody(_ visitor: inout Body) { + identifier.visitBody(&visitor) + } + + public func mutateBody(as type: V.Type, invalidating: Bool, _ body: (inout V) -> Void) { + identifier.mutateBody(as: type, invalidating: invalidating, body) + } + + public func breadthFirstSearch(options: SearchOptions = [], _ body: (AnyAttribute) -> Bool) -> Bool { + identifier.breadthFirstSearch(options: options, body) + } + + public var graph: Graph { + identifier.graph + } + + public var subgraph: Subgraph { + identifier.subgraph + } + + public var value: Value { + unsafeAddress { + OAGDGGraphGetValue(identifier.base, [], Value.self) + .value_ptr + .assumingMemoryBound(to: Value.self) + } + nonmutating set { _ = setValue(newValue) } + } + + public var valueState: ValueState { + identifier.valueState + } + + public func valueAndFlags(options: OAGValueOptions = []) -> (value: Value, flags: OAGChangedValueFlags) { + let value = OAGDGGraphGetValue(identifier.base, options, Value.self) + return ( + value.value_ptr.assumingMemoryBound(to: Value.self).pointee, + value.changed_value_flags + ) + } + + public func changedValue(options: OAGValueOptions = []) -> (value: Value, changed: Bool) { + let result = valueAndFlags(options: options) + return (result.value, result.flags.contains(.changed)) + } + + public func setValue(_ value: Value) -> Bool { + withUnsafePointer(to: value) { valuePointer in + OAGDGGraphSetValue(identifier.base, valuePointer, Value.self) + } + } + + public var hasValue: Bool { + identifier.hasValue + } + + public func updateValue() { + identifier.updateValue() + } + + public func prefetchValue() { + identifier.prefetchValue() + } + + public func invalidateValue() { + identifier.invalidateValue() + } + + public func validate() { + OAGDGGraphVerifyType(identifier.base, Value.self) + } + + public func addInput(_ attribute: AnyAttribute, options: OAGInputOptions = [], token: Int) { + identifier.addInput(attribute, options: options, token: token) + } + + public func addInput(_ attribute: Attribute, options: OAGInputOptions = [], token: Int) { + identifier.addInput(attribute.identifier, options: options, token: token) + } + + public typealias Flags = AnyAttribute.Flags + + public var flags: Flags { + get { identifier.flags } + nonmutating set { identifier.flags = newValue } + } + + public func setFlags(_ newFlags: Flags, mask: Flags) { + identifier.setFlags(newFlags, mask: mask) + } + + public var description: String { + identifier.description + } +} + +extension Attribute { + public init(_ rule: R) where R.Value == Value { + self = withUnsafePointer(to: rule) { pointer in + Attribute(body: pointer, value: nil) { R._update } + } + } + + public init(_ rule: R) where R.Value == Value { + self = withUnsafePointer(to: rule) { pointer in + Attribute(body: pointer, value: nil) { R._update } + } + } +} + +// MARK: - Weak and optional attributes + +@frozen +public struct AnyWeakAttribute: Hashable, CustomStringConvertible, CustomDebugStringConvertible { + public struct Details: Hashable { + public var identifier: AnyAttribute + public var seed: UInt32 + + public init(identifier: AnyAttribute, seed: UInt32) { + self.identifier = identifier + self.seed = seed + } + } + + public var base: DGWeakAttribute + + public init(_ attribute: AnyAttribute?) { + base = OAGDGGraphCreateWeakAttribute(attribute?.base ?? .nil) + } + + public init(_ attribute: AnyAttribute) { + self.init(Optional(attribute)) + } + + public init(_details: Details) { + base = OAGDGGraphCreateWeakAttribute(_details.identifier.base) + } + + public init(_ weakAttribute: WeakAttribute) { + base = weakAttribute.base.base + } + + public init(base: DGWeakAttribute) { + self.base = base + } + + public var _details: Details { + Details(identifier: attribute ?? .nil, seed: base.subgraph_id) + } + + public var details: Details { + _details + } + + public var attribute: AnyAttribute? { + get { + let attribute = OAGDGGraphWeakAttributeGetAttribute(base) + return attribute == .nil ? nil : AnyAttribute(attribute) + } + set { + base = OAGDGGraphCreateWeakAttribute(newValue?.base ?? .nil) + } + } + + public func unsafeCast(to _: Value.Type) -> WeakAttribute { + WeakAttribute(base: self) + } + + public static func == (lhs: AnyWeakAttribute, rhs: AnyWeakAttribute) -> Bool { + lhs._details == rhs._details + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(_details) + } + + public var description: String { + attribute?.description ?? "nil" + } + + public var debugDescription: String { + base.debugDescription + } +} + +@frozen +@propertyWrapper +@dynamicMemberLookup +public struct WeakAttribute: Hashable, CustomStringConvertible { + public var base: AnyWeakAttribute + + public init(base: AnyWeakAttribute) { + self.base = base + } + + public init() { + base = AnyWeakAttribute(nil) + } + + public init(_ attribute: Attribute) { + base = AnyWeakAttribute(attribute.identifier) + } + + public init(_ attribute: Attribute?) { + base = AnyWeakAttribute(attribute?.identifier) + } + + public var wrappedValue: Value? { + OAGDGGraphGetWeakValue(base.base, [], Value.self) + .value_ptr? + .assumingMemoryBound(to: Value.self) + .pointee + } + + public var projectedValue: Attribute? { + get { attribute } + set { attribute = newValue } + _modify { yield &attribute } + } + + public subscript(dynamicMember keyPath: KeyPath) -> Attribute? { + attribute?[keyPath: keyPath] + } + + public var attribute: Attribute? { + get { base.attribute?.unsafeCast(to: Value.self) } + set { base.attribute = newValue?.identifier } + } + + public var value: Value? { + wrappedValue + } + + public func changedValue(options: OAGValueOptions = []) -> (value: Value, changed: Bool)? { + let value = OAGDGGraphGetWeakValue(base.base, options, Value.self) + guard let pointer = value.value_ptr else { + return nil + } + return ( + pointer.assumingMemoryBound(to: Value.self).pointee, + value.changed_value_flags.contains(.changed) + ) + } + + public var description: String { + base.description + } +} + +@frozen +public struct AnyOptionalAttribute: Hashable, CustomStringConvertible, CustomDebugStringConvertible { + public var identifier: AnyAttribute + + public init() { + identifier = .nil + } + + public init(_ attribute: AnyAttribute) { + identifier = attribute + } + + public init(_ attribute: AnyAttribute?) { + identifier = attribute ?? .nil + } + + public init(_ weakAttribute: AnyWeakAttribute) { + identifier = weakAttribute.attribute ?? .nil + } + + public init(_ attribute: OptionalAttribute) { + self = attribute.base + } + + public static var current: AnyOptionalAttribute { + AnyOptionalAttribute(AnyAttribute(OAGDGGraphGetCurrentAttribute())) + } + + public var attribute: AnyAttribute? { + get { identifier == .nil ? nil : identifier } + set { identifier = newValue ?? .nil } + } + + public func map(_ body: (AnyAttribute) -> Value) -> Value? { + if let attribute { + body(attribute) + } else { + nil + } + } + + public func unsafeCast(to _: Value.Type) -> OptionalAttribute { + OptionalAttribute(base: self) + } + + public var description: String { + attribute?.description ?? "nil" + } + + public var debugDescription: String { + description + } +} + +@frozen +@propertyWrapper +@dynamicMemberLookup +public struct OptionalAttribute: Hashable, CustomStringConvertible { + public var base: AnyOptionalAttribute + + public init() { + base = AnyOptionalAttribute() + } + + public init(base: AnyOptionalAttribute) { + self.base = base + } + + public init(_ attribute: Attribute) { + base = AnyOptionalAttribute(attribute.identifier) + } + + public init(_ attribute: Attribute?) { + base = AnyOptionalAttribute(attribute?.identifier) + } + + public init(_ weakAttribute: WeakAttribute) { + base = AnyOptionalAttribute(weakAttribute.base) + } + + public var attribute: Attribute? { + get { base.attribute?.unsafeCast(to: Value.self) } + set { base.attribute = newValue?.identifier } + } + + public var value: Value? { + attribute?.value + } + + public func changedValue(options: OAGValueOptions = []) -> (value: Value, changed: Bool)? { + attribute?.changedValue(options: options) + } + + public func map(_ body: (Attribute) -> OtherValue) -> OtherValue? { + if let attribute { + body(attribute) + } else { + nil + } + } + + public var wrappedValue: Value? { + value + } + + public var projectedValue: Attribute? { + get { attribute } + set { attribute = newValue } + _modify { yield &attribute } + } + + public subscript(dynamicMember keyPath: KeyPath) -> Attribute? { + attribute?[keyPath: keyPath] + } + + public var description: String { + attribute?.description ?? "nil" + } +} + +// MARK: - Rule contexts + +@frozen +public struct AnyRuleContext: Equatable { + public var attribute: AnyAttribute + + public static var current: AnyRuleContext { + AnyRuleContext(attribute: AnyAttribute.current!) + } + + public static var wasModified: Bool { + AnyAttribute.currentWasModified + } + + public static var updateReason: AnyAttribute? { + let reason = OAGDGGraphCurrentAttributeUpdatedReason() + return reason == .nil ? nil : AnyAttribute(reason) + } + + public init(attribute: AnyAttribute) { + self.attribute = attribute + } + + public init(_ attribute: AnyAttribute) { + self.attribute = attribute + } + + public init(_ optionalAttribute: AnyOptionalAttribute) { + attribute = optionalAttribute.identifier + } + + public init(_ context: RuleContext) { + attribute = context.attribute.identifier + } + + public subscript(attribute: Attribute) -> Value { + unsafeAddress { + OAGDGGraphGetInputValue(self.attribute.base, attribute.identifier.base, [], Value.self) + .value_ptr + .assumingMemoryBound(to: Value.self) + } + } + + public subscript(weakAttribute: WeakAttribute) -> Value? { + weakAttribute.attribute.map { self[$0] } + } + + public subscript(optionalAttribute: OptionalAttribute) -> Value? { + optionalAttribute.attribute.map { self[$0] } + } + + public func valueAndFlags( + of input: Attribute, + options: OAGValueOptions = [] + ) -> (value: Value, flags: OAGChangedValueFlags) { + let value = OAGDGGraphGetInputValue(attribute.base, input.identifier.base, options, Value.self) + return ( + value.value_ptr.assumingMemoryBound(to: Value.self).pointee, + value.changed_value_flags + ) + } + + public func changedValue(of input: Attribute, options: OAGValueOptions = []) -> (value: Value, changed: Bool) { + let result = valueAndFlags(of: input, options: options) + return (result.value, result.flags.contains(.changed)) + } + + public func update(body: () -> Void) { + OAGDGGraphWithUpdate(attribute.base, body) + } + + public func unsafeCast(to _: Value.Type) -> RuleContext { + RuleContext(attribute: Attribute(identifier: attribute)) + } +} + +@frozen +public struct RuleContext: Equatable { + public var attribute: Attribute + + public init(attribute: Attribute) { + self.attribute = attribute + } + + public subscript(attribute: Attribute) -> OtherValue { + unsafeAddress { + OAGDGGraphGetInputValue(self.attribute.identifier.base, attribute.identifier.base, [], OtherValue.self) + .value_ptr + .assumingMemoryBound(to: OtherValue.self) + } + } + + public subscript(weakAttribute: WeakAttribute) -> OtherValue? { + weakAttribute.attribute.map { self[$0] } + } + + public subscript(optionalAttribute: OptionalAttribute) -> OtherValue? { + optionalAttribute.attribute.map { self[$0] } + } + + public var value: Value { + unsafeAddress { Graph.outputValue()! } + nonmutating set { + withUnsafePointer(to: newValue) { value in + Graph.setOutputValue(value) + } + } + } + + public var hasValue: Bool { + let valuePointer: UnsafePointer? = Graph.outputValue() + return valuePointer != nil + } + + public func valueAndFlags( + of input: Attribute, + options: OAGValueOptions = [] + ) -> (value: OtherValue, flags: OAGChangedValueFlags) { + let value = OAGDGGraphGetInputValue(attribute.identifier.base, input.identifier.base, options, OtherValue.self) + return ( + value.value_ptr.assumingMemoryBound(to: OtherValue.self).pointee, + value.changed_value_flags + ) + } + + public func changedValue(of input: Attribute, options: OAGValueOptions = []) -> (value: OtherValue, changed: Bool) { + let result = valueAndFlags(of: input, options: options) + return (result.value, result.flags.contains(.changed)) + } + + public func update(body: () -> Void) { + OAGDGGraphWithUpdate(attribute.identifier.base, body) + } +} + +// MARK: - Rules + +public protocol Rule: _AttributeBody { + associatedtype Value + static var initialValue: Value? { get } + var value: Value { get } +} + +extension Rule { + public static var initialValue: Value? { nil } + + public static func _update(_ pointer: UnsafeMutableRawPointer, attribute _: AnyAttribute) { + let rule = pointer.assumingMemoryBound(to: Self.self) + let value = rule.pointee.value + withUnsafePointer(to: value) { value in + Graph.setOutputValue(value) + } + } + + public static func _updateDefault(_: UnsafeMutableRawPointer) { + guard let initialValue else { + return + } + withUnsafePointer(to: initialValue) { value in + Graph.setOutputValue(value) + } + } + + public var attribute: Attribute { + Attribute(identifier: AnyAttribute.current!) + } + + public var context: RuleContext { + RuleContext(attribute: attribute) + } + + public var optionalValue: Value? { + (Graph.outputValue() as UnsafePointer?)?.pointee + } +} + +extension Rule where Self: Hashable { + public func cachedValue(options: OAGCachedValueOptions = [], owner: AnyAttribute?) -> Value { + cachedValue(options, owner: owner) + } + + public func cachedValue(_ options: OAGCachedValueOptions = [], owner: AnyAttribute?) -> Value { + withUnsafePointer(to: self) { pointer in + var flags = OAGChangedValueFlags() + let value = OAGDGGraphReadCachedAttribute( + hashValue, + Self.self, + pointer, + Value.self, + options, + owner?.base ?? .nil, + &flags + ) { context in + Graph.typeIndex( + ctx: context, + body: Self.self, + valueType: Metadata(Value.self), + flags: Self.flags, + update: { Self._update } + ) + } + return value.assumingMemoryBound(to: Value.self).pointee + } + } + + public func cachedValueIfExists(options: OAGCachedValueOptions = [], owner: AnyAttribute?) -> Value? { + cachedValueIfExists(options, owner: owner) + } + + public func cachedValueIfExists(_ options: OAGCachedValueOptions = [], owner: AnyAttribute?) -> Value? { + withUnsafePointer(to: self) { pointer in + var flags = OAGChangedValueFlags() + let value = OAGDGGraphReadCachedAttributeIfExists( + hashValue, + Self.self, + pointer, + Value.self, + options, + owner?.base ?? .nil, + &flags + ) + return value?.assumingMemoryBound(to: Value.self).pointee + } + } +} + +public protocol StatefulRule: _AttributeBody { + associatedtype Value + static var initialValue: Value? { get } + mutating func updateValue() +} + +extension StatefulRule { + public static var initialValue: Value? { nil } + + public static func _update(_ pointer: UnsafeMutableRawPointer, attribute _: AnyAttribute) { + pointer.assumingMemoryBound(to: Self.self) + .pointee + .updateValue() + } + + public static func _updateDefault(_: UnsafeMutableRawPointer) { + guard let initialValue else { + return + } + withUnsafePointer(to: initialValue) { value in + Graph.setOutputValue(value) + } + } + + public var attribute: Attribute { + Attribute(identifier: AnyAttribute.current!) + } + + public var context: RuleContext { + RuleContext(attribute: attribute) + } + + public var value: Value { + unsafeAddress { Graph.outputValue()! } + nonmutating set { context.value = newValue } + } + + public var hasValue: Bool { + context.hasValue + } + + public var optionalValue: Value? { + (Graph.outputValue() as UnsafePointer?)?.pointee + } +} + +@frozen +public struct External: _AttributeBody, CustomStringConvertible { + public init() {} + + public static func _update(_: UnsafeMutableRawPointer, attribute: AnyAttribute) { + let value = Attribute(identifier: attribute).value + withUnsafePointer(to: value) { value in + Graph.setOutputValue(value) + } + } + + public static var flags: _AttributeType.Flags { + .external + } + + public var description: String { + "External<\(Value.self)>" + } +} + +@frozen +public struct Focus: Rule { + public var root: Attribute + public var keyPath: KeyPath + + public init(root: Attribute, keyPath: KeyPath) { + self.root = root + self.keyPath = keyPath + } + + public var value: Value { + root.value[keyPath: keyPath] + } +} + +@frozen +public struct Map: Rule { + public var source: Attribute + public var body: (Source) -> Value + + public init(_ source: Attribute, _ body: @escaping (Source) -> Value) { + self.source = source + self.body = body + } + + public init(_ source: Attribute, body: @escaping (Source) -> Value) { + self.init(source, body) + } + + public var value: Value { + body(source.value) + } +} + +@frozen +@propertyWrapper +@dynamicMemberLookup +public struct IndirectAttribute: Hashable, Equatable { + public var identifier: AnyAttribute + + public var source: Attribute { + get { Attribute(identifier: identifier.source) } + nonmutating set { identifier.source = newValue.identifier } + } + + public var dependency: AnyAttribute? { + get { identifier.indirectDependency } + nonmutating set { identifier.indirectDependency = newValue } + } + + public var wrappedValue: Value { + get { Attribute(identifier: identifier).value } + nonmutating set { Attribute(identifier: identifier).value = newValue } + } + + public var projectedValue: Attribute { + Attribute(identifier: identifier) + } + + public subscript(dynamicMember keyPath: KeyPath) -> Attribute { + Attribute(identifier: identifier)[keyPath: keyPath] + } + + public init(source: Attribute) { + identifier = source.identifier.createIndirect(size: UInt64(MemoryLayout.size)) + } + + public func changedValue(options: OAGValueOptions = []) -> (value: Value, changed: Bool) { + Attribute(identifier: identifier).changedValue(options: options) + } + + public func valueAndFlags(options: OAGValueOptions = []) -> (value: Value, flags: OAGChangedValueFlags) { + Attribute(identifier: identifier).valueAndFlags(options: options) + } +} + +// MARK: - Runtime helpers + +private func dgComparisonOptions(_ options: ComparisonOptions) -> DGComparisonMode { + let mode = options.rawValue & ComparisonOptions.comparisonModeMask.rawValue + var result: DGComparisonMode + switch mode { + case ComparisonOptions.comparisonModeIndirect.rawValue: + result = .indirect + case ComparisonOptions.comparisonModeEquatableUnlessPOD.rawValue: + result = .equatableUnlessPOD + case ComparisonOptions.comparisonModeEquatableAlways.rawValue: + result = .equatableAlways + default: + result = .bitwise + } + result.insert(.asynchronous) + return result +} + +public struct ComparisonOptions: OptionSet { + public let rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + + public init(mode: ComparisonMode) { + switch mode { + case .indirect: + self = .comparisonModeIndirect + case .equatableUnlessPOD: + self = .comparisonModeEquatableUnlessPOD + case .equatableAlways: + self = .comparisonModeEquatableAlways + default: + self = .comparisonModeBitwise + } + } + + public static let comparisonModeBitwise: ComparisonOptions = [] + public static let comparisonModeIndirect = ComparisonOptions(rawValue: 1) + public static let comparisonModeEquatableUnlessPOD = ComparisonOptions(rawValue: 2) + public static let comparisonModeEquatableAlways = ComparisonOptions(rawValue: 3) + public static let comparisonModeMask = ComparisonOptions(rawValue: 0xff) + public static let copyOnWrite = ComparisonOptions(rawValue: 1 << 8) + public static let fetchLayoutsSynchronously = ComparisonOptions(rawValue: 1 << 9) + public static let traceCompareFailed = ComparisonOptions(rawValue: 1 << 31) +} + +public func compareValues(_ lhs: Value, _ rhs: Value, mode: ComparisonMode = .equatableAlways) -> Bool { + compareValues(lhs, rhs, options: [.init(mode: mode), .copyOnWrite]) +} + +public func compareValues(_ lhs: Value, _ rhs: Value, options: ComparisonOptions) -> Bool { + DGCompareValues(lhs: lhs, rhs: rhs, options: dgComparisonOptions(options)) +} + +public func makeUniqueID() -> UniqueID { + UInt(DGMakeUniqueID().rawValue) +} + +public func withUnsafeTuple(of type: TupleType, count: Int, _ body: (UnsafeMutableTuple) -> Void) { + DanceUIGraph.withUnsafeTuple(of: type.type, count: count) { tuple in + body(tuple) + } +} + +extension TupleType { + public func elementType(at index: Int) -> Metadata { + Metadata(getElementType(at: index)) + } + + public func type(at index: Int) -> Any.Type { + getElementType(at: index) + } + + public func elementOffset(at index: Int) -> Int { + offset(at: index) + } + + public func elementOffset(at index: Int, type: Metadata) -> Int { + func project(_: T.Type) -> Int { + offset(at: index, as: T.self) + } + return _openExistential(type.type, do: project) + } + + public func elementSize(at index: Int) -> Int { + MemoryLayout.size(ofValue: getElementType(at: index)) + } +} + +extension Metadata { + public func enumTag(_ value: UnsafeRawPointer) -> UInt32 { + getEnumTag(value: value) + } + + public func projectEnumData(_ value: UnsafeMutableRawPointer) { + _ = value + } + + public func injectEnumTag(tag: UInt32, _ value: UnsafeMutableRawPointer) { + _ = tag + _ = value + } + + public var descriptor: UnsafeRawPointer? { + nominalDescriptor + } +} + +extension UnsafePointer where Pointee == DanceUIGraphTypeSignature { + public var bytes: ( + UInt8, UInt8, UInt8, UInt8, UInt8, + UInt8, UInt8, UInt8, UInt8, UInt8, + UInt8, UInt8, UInt8, UInt8, UInt8, + UInt8, UInt8, UInt8, UInt8, UInt8 + ) { + var signature = pointee + let bytes = withUnsafeBytes(of: &signature) { buffer in + Array(buffer.prefix(20)) + } + return ( + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], + bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], + bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], + bytes[15], bytes[16], bytes[17], bytes[18], bytes[19] + ) + } +} + +// MARK: - Option compatibility + +extension AnyAttribute.Flags { + public static var all: Self { + Self(rawValue: ~0) + } +} + +extension ComparisonMode { + public static var bitwise: Self { [] } + public static var indirect: Self { .pod } + public static var equatableUnlessPOD: Self { .inline } + public static var equatableAlways: Self { .equatable } +} + +extension OAGChangedValueFlags { + public static var changed: Self { .updated } + public static var requiresMainThread: Self { .requiresMainHandler } +} + +extension OAGInputOptions { + public static var inputOptionsUnprefetched: Self { Self(rawValue: 1 << 0) } + public static var inputOptionsSyncMainRef: Self { Self(rawValue: 1 << 1) } + public static var inputOptionsMask: Self { Self(rawValue: 0x03) } +} + +extension OAGValueOptions { + public static var incrementGraphVersion: Self { Self(rawValue: 1 << 2) } +} + +extension OAGCachedValueOptions { + public static var _1: Self { .withoutPrefetching } + public static var _2: Self { Self(rawValue: 1 << 1) } + public static var _4: Self { Self(rawValue: 1 << 2) } + public static var _8: Self { Self(rawValue: 1 << 3) } + public static var _16: Self { Self(rawValue: 1 << 4) } +} + +extension SearchOptions { + public static var searchInputs: Self { .backwards } + public static var searchOutputs: Self { .forwards } + public static var traverseGraphContexts: Self { Self(rawValue: 1 << 2) } +} + +extension ValueState { + public static var dirty: Self { .isDirty } + public static var pending: Self { .isPending } + public static var updating: Self { .isUpdating } + public static var valueExists: Self { .hasValue } + public static var mainThread: Self { .requiresMainThreadFromOutput } + public static var mainRef: Self { .attributeIsMainReference } + public static var requiresMainThread: Self { .requiresMainThreadFromInput } + public static var selfModified: Self { .wasModified } +} + +extension _AttributeType { + public typealias Flags = DGAttributeTypeFlags +} + +extension _AttributeBody { + public typealias Flags = _AttributeType.Flags +} + +extension _AttributeType.Flags { + public static var comparisonModeBitwise: Self { Self(rawValue: 0) } + public static var comparisonModeIndirect: Self { Self(rawValue: 1) } + public static var comparisonModeEquatableUnlessPOD: Self { Self(rawValue: 2) } + public static var comparisonModeEquatableAlways: Self { Self(rawValue: 3) } + public static var comparisonModeMask: Self { Self(rawValue: 0x03) } + public static var mainThread: Self { .threadMain } + public static var asyncThread: Self { .threadAsync } + public static var external: Self { .valueIndirect } +} + +extension Metadata.ApplyOptions { + public static var enumerateClassFields: Self { .heap } + public static var continueAfterUnknownField: Self { .continueWhenUnknown } + public static var enumerateEnumCases: Self { .allowVisitEnum } +} + +extension DescriptionOption { + public static var maxFrames: Self { + .stackMaxFrames + } } public let attributeGraphVendor = AttributeGraphVendor.danceUIGraph diff --git a/Sources/OpenAttributeGraphShims/Attribute+Debug.swift b/Sources/OpenAttributeGraphShims/Attribute+Debug.swift index 52cda6a2..209991df 100644 --- a/Sources/OpenAttributeGraphShims/Attribute+Debug.swift +++ b/Sources/OpenAttributeGraphShims/Attribute+Debug.swift @@ -22,6 +22,13 @@ extension Attribute: Swift.CustomDebugStringConvertible { } } +#if OPENATTRIBUTEGRAPH_DANCEUIGRAPH +extension AnyAttribute { + func _debugDescription(indent: Int) -> String { + "\(String(repeating: tab, count: indent))\(debugDescription)" + } +} +#else extension AnyAttribute: Swift.CustomDebugStringConvertible { public var debugDescription: String { _debugDescription(indent: 0) @@ -89,3 +96,5 @@ extension AnyAttribute: Swift.CustomDebugStringConvertible { } } #endif + +#endif From 5e2a9d81fea17bc83b3d03cfc2b221de3b39c27c Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 27 Apr 2026 00:24:10 +0800 Subject: [PATCH 8/9] Fix OAGAttributeFlags --- .../Adapter/DanceUIGraph.swift | 31 ++++--------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift index ba76b9ce..f641a199 100644 --- a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift +++ b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift @@ -36,26 +36,7 @@ public typealias DescriptionOption = DanceUIGraphDescriptionOption public typealias Signature = UnsafePointer public typealias AttributeUpdateBlock = () -> (UnsafeMutableRawPointer, AnyAttribute) -> Void -@frozen -public struct OAGAttributeFlags: OptionSet, Hashable, Sendable { - public let rawValue: UInt32 - - public init(rawValue: UInt32) { - self.rawValue = rawValue - } -} - -private extension DGAttributeFlags { - init(_ flags: OAGAttributeFlags) { - self.init(rawValue: flags.rawValue) - } -} - -private extension OAGAttributeFlags { - init(_ flags: DGAttributeFlags) { - self.init(rawValue: flags.rawValue) - } -} +public typealias OAGAttributeFlags = DGAttributeFlags @_silgen_name("OAGDanceUIGraphGetContext") private func OAGDGGraphGetContext(_ graph: DGGraphRef) -> UnsafeMutableRawPointer? @@ -528,7 +509,7 @@ public final class Subgraph: Hashable { } public func forEach(_ flags: Flags, _ callback: (AnyAttribute) -> Void) { - OAGDGSubgraphApply(base, DGAttributeFlags(flags)) { callback(AnyAttribute($0)) } + OAGDGSubgraphApply(base, flags) { callback(AnyAttribute($0)) } } public func addChild(_ child: Subgraph) { @@ -561,11 +542,11 @@ public final class Subgraph: Hashable { } public func update(flags: Flags) { - base.update(DGAttributeFlags(flags)) + base.update(flags) } public func intersects(flags: Flags) -> Bool { - OAGDGSubgraphIntersects(base, DGAttributeFlags(flags)) + OAGDGSubgraphIntersects(base, flags) } public func invalidate() { @@ -677,8 +658,8 @@ public struct AnyAttribute: RawRepresentable, Hashable, CustomStringConvertible, } public var flags: Flags { - get { OAGAttributeFlags(OAGDGGraphGetFlags(base)) } - nonmutating set { OAGDGGraphSetFlags(base, DGAttributeFlags(newValue)) } + get { OAGDGGraphGetFlags(base) } + nonmutating set { OAGDGGraphSetFlags(base, newValue) } } public var hasValue: Bool { From 718fceffc1b84ea2fb701d6f9e145cec029c6119 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 27 Apr 2026 00:56:14 +0800 Subject: [PATCH 9/9] Update graph --- .../Adapter/DanceUIGraph.swift | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift index f641a199..07f98b0a 100644 --- a/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift +++ b/Sources/OpenAttributeGraphShims/Adapter/DanceUIGraph.swift @@ -4,10 +4,10 @@ #if OPENATTRIBUTEGRAPH_DANCEUIGRAPH +// FIXME: Runtime crash to be fixed in OpenSwiftUI + @_exported public import DanceUIRuntime @_exported public import DanceUIGraph -@_exported public import Foundation -import Darwin public typealias AttributeBodyVisitor = DanceUIGraph.AttributeBodyVisitor public typealias ComparisonMode = DGComparisonMode @@ -220,9 +220,8 @@ private func OAGDGSubgraphIntersects(_ subgraph: DGSubgraphRef, _ flags: DGAttri // MARK: - Graph -@frozen -public struct Graph: Hashable { - public var base: DGGraphRef +public final class Graph: Hashable { + let base: DGGraphRef public init() { base = DGGraphCreate() @@ -232,7 +231,7 @@ public struct Graph: Hashable { base = DGGraphCreateShared(graph.base) } - public init(_ base: DGGraphRef) { + init(_ base: DGGraphRef) { self.base = base } @@ -260,7 +259,7 @@ public struct Graph: Hashable { public var context: UnsafeRawPointer? { get { OAGDGGraphGetContext(base).map(UnsafeRawPointer.init) } - nonmutating set { OAGDGGraphSetContext(base, newValue.map(UnsafeMutableRawPointer.init(mutating:))) } + set { OAGDGGraphSetContext(base, newValue.map(UnsafeMutableRawPointer.init(mutating:))) } } public static func typeIndex( @@ -436,11 +435,11 @@ public struct Graph: Hashable { } public func === (lhs: Graph, rhs: Graph) -> Bool { - lhs == rhs + lhs.base === rhs.base } public func !== (lhs: Graph, rhs: Graph) -> Bool { - !(lhs == rhs) + lhs.base !== rhs.base } extension Graph.CounterQueryType {