diff --git a/Sources/OpenSwiftUICore/Data/Update.swift b/Sources/OpenSwiftUICore/Data/Update.swift index 509cc4ed2..0e5506483 100644 --- a/Sources/OpenSwiftUICore/Data/Update.swift +++ b/Sources/OpenSwiftUICore/Data/Update.swift @@ -100,7 +100,15 @@ package enum Update { depth -= 1 unlock() } - + + @inlinable + @inline(__always) + static func perform(_ body: () throws -> T) rethrows -> T { + begin() + defer { end() } + return try body() + } + package static func enqueueAction(_ action: @escaping () -> Void) { begin() actions.append(action) diff --git a/Sources/OpenSwiftUICore/Event/Event/EventBindingManager.swift b/Sources/OpenSwiftUICore/Event/Event/EventBindingManager.swift index c50305fc4..f69048d56 100644 --- a/Sources/OpenSwiftUICore/Event/Event/EventBindingManager.swift +++ b/Sources/OpenSwiftUICore/Event/Event/EventBindingManager.swift @@ -3,6 +3,7 @@ // OpenSwiftUICore // // Status: WIP +// ID: D63F4C292364B83D9F441CFC1A31B3F3 (SwiftUICore) import Foundation @@ -58,9 +59,18 @@ final public class EventBindingManager { preconditionFailure("TODO") } + private func sendDownstream(_ events: [EventID: any EventType]) -> Set { + preconditionFailure("TODO") + } + @discardableResult package func send(_ events: [EventID: any EventType]) -> Set { - preconditionFailure("TODO") + Update.locked { [weak self] in + guard let self else { + return [] + } + return sendDownstream(events) + } } package func send(_ event: E, id: Int) where E: EventType { diff --git a/Sources/OpenSwiftUICore/Event/Gesture/Gesture.swift b/Sources/OpenSwiftUICore/Event/Gesture/Gesture.swift index 049f68e50..cffedfc2f 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/Gesture.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/Gesture.swift @@ -93,7 +93,7 @@ private struct GestureBodyAccessor: BodyAccessor where Container: Ges @available(OpenSwiftUI_v1_0, *) extension Gesture where Value == Body.Value { - public static func _makeGesture( + nonisolated public static func _makeGesture( gesture: _GraphValue, inputs: _GestureInputs ) -> _GestureOutputs { diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift index 10c12ccf1..1e21f9af6 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift @@ -68,8 +68,7 @@ extension GestureDebug.Data: Defaultable { // MARK: - PrimitiveDebuggableGesture [6.5.4] -package protocol PrimitiveDebuggableGesture { -} +package protocol PrimitiveDebuggableGesture {} // MARK: - DebuggableGesturePhase [6.5.4] diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureDependency.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureDependency.swift index 1387b64b4..232d051cc 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureDependency.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureDependency.swift @@ -29,7 +29,7 @@ private struct DependentGesture: GestureModifier { var dependency: GestureDependency - static func _makeGesture( + nonisolated static func _makeGesture( modifier: _GraphValue, inputs: _GestureInputs, body: (_GestureInputs) -> _GestureOutputs diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureGraph.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureGraph.swift index b587ac937..36965cdd3 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureGraph.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureGraph.swift @@ -4,6 +4,8 @@ // // Status: WIP +import OpenGraphShims + // MARK: - GestureGraphDelegate [6.5.4] package protocol GestureGraphDelegate: AnyObject { @@ -13,67 +15,101 @@ package protocol GestureGraphDelegate: AnyObject { // MARK: - GestureGraph [6.5.4] [WIP] final package class GestureGraph: GraphHost, EventGraphHost, CustomStringConvertible { - package init(eventBindingManager: EventBindingManager) { + weak var rootResponder: AnyGestureResponder? + weak var delegate: GestureGraphDelegate? + package let eventBindingManager: EventBindingManager + @Attribute private var gestureTime: Time + @Attribute private var gestureEvents: [EventID: any EventType] + @Attribute private var inheritedPhase: _GestureInputs.InheritedPhase + @Attribute private var gestureResetSeed: UInt32 + @OptionalAttribute private var rootPhase: GesturePhase<()>? + @OptionalAttribute private var gestureDebug: GestureDebug.Data? + @OptionalAttribute private var gestureCategoryAttr: GestureCategory? + @OptionalAttribute private var gestureLabelAttr: String?? + @OptionalAttribute private var isCancellableAttr: Bool? + @OptionalAttribute private var requiredTapCountAttr: Int?? + @OptionalAttribute private var gestureDependencyAttr: GestureDependency? + @Attribute private var gesturePreferenceKeys: PreferenceKeys + var nextUpdateTime: Time + + init(rootResponder: AnyGestureResponder) { + self.rootResponder = rootResponder preconditionFailure("TODO") } - final package let eventBindingManager: EventBindingManager - - final package var description: String { - get { preconditionFailure("TODO") } + package var description: String { + "GestureGraph<\(rootResponder.map { String(describing: $0.gestureType) } ?? "nil")> \(self)" } - override final package func instantiateOutputs() { + override package func instantiateOutputs() { preconditionFailure("TODO") } - override final package func uninstantiateOutputs() { - preconditionFailure("TODO") + override package func uninstantiateOutputs() { + $rootPhase = nil + _ = gestureEvents + gestureEvents = [:] + inheritedPhase = .failed + gestureResetSeed = .zero + gesturePreferenceKeys = .init() + if let rootResponder { + rootResponder.resetGesture() + } } - override final package func timeDidChange() { - preconditionFailure("TODO") + override package func timeDidChange() { + nextUpdateTime = .infinity } - final package var responderNode: ResponderNode? { - get { preconditionFailure("TODO") } + package var responderNode: ResponderNode? { + rootResponder } - final package var focusedResponder: ResponderNode? { - get { preconditionFailure("TODO") } + package var focusedResponder: ResponderNode? { + guard let rootResponder, + let host = rootResponder.host, + let eventGraphHost = host.as(EventGraphHost.self) else { + return nil + } + return eventGraphHost.focusedResponder } - final package var nextGestureUpdateTime: Time { - get { preconditionFailure("TODO") } + package var nextGestureUpdateTime: Time { + nextUpdateTime } - final package func setInheritedPhase(_ phase: _GestureInputs.InheritedPhase) { - preconditionFailure("TODO") + package func setInheritedPhase(_ phase: _GestureInputs.InheritedPhase) { + inheritedPhase = phase } - final package func sendEvents( + package func sendEvents( _ events: [EventID: any EventType], rootNode: ResponderNode, at time: Time ) -> GesturePhase { + guard let rootResponder, rootResponder.isValid else { + return .failed + } preconditionFailure("TODO") } - final package func resetEvents() { - preconditionFailure("TODO") + package func resetEvents() { + uninstantiate(immediately: false) } - final package func enqueueAction(_ action: @escaping () -> Void) { - preconditionFailure("TODO") + package func enqueueAction(_ action: @escaping () -> Void) { + delegate?.enqueueAction(action) } - final package func gestureCategory() -> GestureCategory? { - preconditionFailure("TODO") + package func gestureCategory() -> GestureCategory? { + guard let rootResponder, rootResponder.isValid else { + return nil + } + return Update.perform { + instantiateIfNeeded() + return gestureCategoryAttr + } } - -// @objc deinit { -// preconditionFailure("TODO") -// } } extension GestureGraph { diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureModifier.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureModifier.swift index b7bdc6b5c..f17155bc6 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureModifier.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureModifier.swift @@ -2,7 +2,7 @@ // GestureModifier.swift // OpenSwiftUICore // -// Status: Blocked by makeDebuggableGesture +// Status: Complete package protocol GestureModifier { associatedtype Value @@ -33,10 +33,18 @@ package struct ModifierGesture: PrimitiveGesture package typealias Value = ContentModifier.Value package static func _makeGesture( - gesture: _GraphValue>, + gesture: _GraphValue, inputs: _GestureInputs ) -> _GestureOutputs { - preconditionFailure("TODO") + ContentModifier.makeDebuggableGesture( + modifier: gesture[offset: { .of(&$0.modifier) }], + inputs: inputs + ) { inputs in + Content.makeDebuggableGesture( + gesture: gesture[offset: { .of(&$0.content) }], + inputs: inputs + ) + } } } diff --git a/Sources/OpenSwiftUICore/Event/Gesture/GestureViewModifier.swift b/Sources/OpenSwiftUICore/Event/Gesture/GestureViewModifier.swift index 2a96ead12..cdbcf4e34 100644 --- a/Sources/OpenSwiftUICore/Event/Gesture/GestureViewModifier.swift +++ b/Sources/OpenSwiftUICore/Event/Gesture/GestureViewModifier.swift @@ -63,14 +63,14 @@ extension GestureViewModifier { body: @escaping (_Graph, _ViewInputs) -> _ViewOutputs ) -> _ViewOutputs { var outputs = body(_Graph(), inputs) - if inputs.preferences.contains(ViewRespondersKey.self) { + if inputs.preferences.requiresViewResponders { let filter = GestureFilter( children: outputs.viewResponders(), modifier: modifier.value, inputs: inputs, viewSubgraph: .current! ) - outputs.preferences[ViewRespondersKey.self] = Attribute(filter) + outputs.preferences.viewResponders = Attribute(filter) } let provider = inputs.gestureAccessibilityProvider provider.makeGesture( @@ -225,7 +225,7 @@ private class GestureResponder/*: AnyGestureResponder where Modifier: // MARK: - GestureAccessibilityProvider [6.5.4] package protocol GestureAccessibilityProvider { - static func makeGesture( + nonisolated static func makeGesture( mask: @autoclosure () -> Attribute, inputs: _ViewInputs, outputs: inout _ViewOutputs @@ -237,7 +237,7 @@ private struct GestureAccessibilityProviderKey: GraphInput { } struct EmptyGestureAccessibilityProvider: GestureAccessibilityProvider { - static func makeGesture( + nonisolated static func makeGesture( mask: @autoclosure () -> Attribute, inputs: _ViewInputs, outputs: inout _ViewOutputs @@ -259,17 +259,19 @@ extension _ViewInputs { } } -// MARK: - Optional: Gesture - -//extension Optional: Gesture where Wrapped: Gesture { -// public typealias Value = Wrapped.Value -// -// public static func _makeGesture( -// gesture: _GraphValue>, -// inputs: _GestureInputs -// ) -> _GestureOutputs { preconditionFailure("TODO") } -// -// public typealias Body = Never -//} -// -//extension Optional: PrimitiveGesture where Wrapped: Gesture {} +// MARK: - Optional: Gesture [WIP] + +extension Optional: Gesture where Wrapped: Gesture { + public typealias Value = Wrapped.Value + + nonisolated public static func _makeGesture( + gesture: _GraphValue>, + inputs: _GestureInputs + ) -> _GestureOutputs { + preconditionFailure("TODO") + } + + public typealias Body = Never +} + +extension Optional: PrimitiveGesture where Wrapped: Gesture {} diff --git a/Sources/OpenSwiftUICore/Event/Responder/ContentPathObserver.swift b/Sources/OpenSwiftUICore/Event/Responder/ContentPathObserver.swift new file mode 100644 index 000000000..1b2edc6fc --- /dev/null +++ b/Sources/OpenSwiftUICore/Event/Responder/ContentPathObserver.swift @@ -0,0 +1,60 @@ +// +// ContentPathObserver.swift +// OpenSwiftUICore +// +// Status: Complete + +@_spi(ForOpenSwiftUIOnly) +@available(OpenSwiftUI_v6_0, *) +public struct ContentPathChanges: OptionSet { + public var rawValue: UInt8 + + public init(rawValue: UInt8) { + self.rawValue = rawValue + } + + package static let data: ContentPathChanges = .init(rawValue: 1 << 0) + + package static let size: ContentPathChanges = .init(rawValue: 1 << 1) + + package static let transform: ContentPathChanges = .init(rawValue: 1 << 2) +} + +@_spi(ForOpenSwiftUIOnly) +@available(*, unavailable) +extension ContentPathChanges: Sendable {} + +@_spi(ForOpenSwiftUIOnly) +@available(OpenSwiftUI_v6_0, *) +public protocol ContentPathObserver: AnyObject { + func respondersDidChange( + for parent: ViewResponder + ) + + func contentPathDidChange( + for parent: ViewResponder, + changes: ContentPathChanges, + transform: (old: ViewTransform, new: ViewTransform), + finished: inout Bool + ) +} + +package protocol TrivialContentPathObserver: ContentPathObserver { + func contentPathDidChange(for parent: ViewResponder) +} + +extension TrivialContentPathObserver { + package func contentPathDidChange( + for parent: ViewResponder, + changes: ContentPathChanges, + transform: (old: ViewTransform, new: ViewTransform), + finished: inout Bool + ) { + contentPathDidChange(for: parent) + finished = true + } + + package func respondersDidChange(for parent: ViewResponder) { + contentPathDidChange(for: parent) + } +} diff --git a/Sources/OpenSwiftUICore/View/Responder/ContentResponder.swift b/Sources/OpenSwiftUICore/Event/Responder/ContentResponder.swift similarity index 100% rename from Sources/OpenSwiftUICore/View/Responder/ContentResponder.swift rename to Sources/OpenSwiftUICore/Event/Responder/ContentResponder.swift diff --git a/Sources/OpenSwiftUICore/View/Responder/ContentShapeKinds.swift b/Sources/OpenSwiftUICore/Event/Responder/ContentShapeKinds.swift similarity index 100% rename from Sources/OpenSwiftUICore/View/Responder/ContentShapeKinds.swift rename to Sources/OpenSwiftUICore/Event/Responder/ContentShapeKinds.swift diff --git a/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift b/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift index aa16566fd..0bad20fcb 100644 --- a/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift +++ b/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift @@ -55,7 +55,7 @@ open class ResponderNode { @available(*, unavailable) extension ResponderNode: Sendable {} -// MARK: - ResponderVisitorResult [6.5.4] [WIP] +// MARK: - ResponderVisitorResult [6.5.4] @_spi(ForOpenSwiftUIOnly) @available(OpenSwiftUI_v6_0, *) diff --git a/Sources/OpenSwiftUICore/Event/Responder/ViewResponder.swift b/Sources/OpenSwiftUICore/Event/Responder/ViewResponder.swift new file mode 100644 index 000000000..56457f115 --- /dev/null +++ b/Sources/OpenSwiftUICore/Event/Responder/ViewResponder.swift @@ -0,0 +1,198 @@ +// +// ViewResponder.swift +// OpenSwiftUICore +// +// Status: WIP +// ID: 5DC9CCF050AF89FBA971AEC7E32C63B6 (SwiftUICore) + +public import Foundation +import OpenGraphShims + +// MARK: - ViewRespondersKey [6.5.4] + +package struct ViewRespondersKey: PreferenceKey { + package static var defaultValue: [ViewResponder] { [] } + + package static var _includesRemovedValues: Bool { true } + + package static func reduce(value: inout Value, nextValue: () -> Value) { + value.append(contentsOf: nextValue()) + } +} + +extension PreferencesInputs { + @inline(__always) + var requiresViewResponders: Bool { + get { contains(ViewRespondersKey.self) } + set { + if newValue { + add(ViewRespondersKey.self) + } else { + remove(ViewRespondersKey.self) + } + } + } +} + +extension PreferencesOutputs { + @inline(__always) + var viewResponders: Attribute<[ViewResponder]>? { + get { self[ViewRespondersKey.self] } + set { self[ViewRespondersKey.self] = newValue } + } +} + +// MARK: - ViewResponder [6.5.4] [WIP] + +@_spi(ForOpenSwiftUIOnly) +@available(OpenSwiftUI_v6_0, *) +open class ViewResponder: ResponderNode, CustomStringConvertible/*, CustomRecursiveStringConvertible*/ { + final private(set) package weak var host: ViewGraphDelegate? = nil + + final package weak var parent: ViewResponder? = nil { + willSet { + guard let parent, newValue == nil else { + return + } + guard let host, let eventGraphHost = host.as(EventGraphHost.self) else { + return + } + eventGraphHost.eventBindingManager.willRemoveResponder(self) + resetGesture() + } + } + + override public init() { + host = ViewGraph.current.delegate + } + + override final public var nextResponder: ResponderNode? { parent } + + open var gestureContainer: AnyObject? { nil } + + open var opacity: Double { 1.0 } + + open var allowHitTesting: Bool { true } + + package struct ContainsPointsCache { + var storage: (key: UInt32?, value: ContainsPointsResult)? + + package init() { + storage = nil + } + + package mutating func fetch( + key: UInt32?, + _ body: () -> ContainsPointsResult + ) -> ContainsPointsResult { + guard let storage, let storageKey = storage.key, let key, storageKey == key else { + let result = body() + storage = (key, result) + return result + } + return storage.value + } + } + + package static let gestureContainmentPriority: Double = 16.0 + + public struct ContainsPointsOptions: OptionSet { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + package static let allowDisabledViews: ContainsPointsOptions = .init(rawValue: 1 << 0) + + package static let useZDistanceAsPriority: ContainsPointsOptions = .init(rawValue: 1 << 1) + + package static let disablePointCloudHitTesting: ContainsPointsOptions = .init(rawValue: 1 << 2) + + package static let allow3DResponders: ContainsPointsOptions = .init(rawValue: 1 << 3) + + package static let crossingServerIDBoundary: ContainsPointsOptions = .init(rawValue: 1 << 4) + + public static var platformDefault: ViewResponder.ContainsPointsOptions { [] } + } + + public struct ContainsPointsResult { + package var mask: BitVector64 + package var priority: Double + package var children: [ViewResponder] + } + + open func containsGlobalPoints( + _ points: [PlatformPoint], + cacheKey: UInt32?, + options: ContainsPointsOptions + ) -> ContainsPointsResult { + ContainsPointsResult(mask: .init(), priority: 0, children: children) + } + + open func addContentPath( + to path: inout Path, + kind: ContentShapeKinds, + in space: CoordinateSpace, + observer: (any ContentPathObserver)? + ) {} + + open func addObserver(_ observer: any ContentPathObserver) {} + + open var children: [ViewResponder] { [] } + + open var descriptionName: String { + // recursiveDescriptionName(Self.self) + preconditionFailure("TODO") + } + + public var description: String { + "node(\(self) \(descriptionName))" + } + + @inline(never) + final package func printTree(depth: Int = 0) { + // Log.eventDebug + preconditionFailure("TODO") + } + + open func extendPrintTree(string: inout String) {} +} + +private func indentString(_ depth: Int) -> String { + var result = "" + var depth = depth + while depth > 0 { + result.append("| ") + depth -= 1 + } + return result +} + +extension ViewGraph { + package static var eventGraphHost: (any EventGraphHost)? { + ViewGraph.current.delegate?.as(EventGraphHost.self) + } +} + +@_spi(ForOpenSwiftUIOnly) +@available(*, unavailable) +extension ViewResponder: Sendable {} + +@_spi(ForOpenSwiftUIOnly) +@available(*, unavailable) +extension ViewResponder.ContainsPointsOptions: Sendable {} + +// FIXME +package struct HitTestBindingModifier: ViewModifier, /*MultiViewModifier,*/ PrimitiveViewModifier { + nonisolated package static func _makeView( + modifier: _GraphValue, + inputs: _ViewInputs, + body: @escaping (_Graph, _ViewInputs) -> _ViewOutputs + ) -> _ViewOutputs { + // preconditionFailure("TODO") + return body(_Graph(), inputs) + } + + package typealias Body = Never +} diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift b/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift index 450287969..7b94cb5fc 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift @@ -38,7 +38,7 @@ package final class ViewGraph: GraphHost { inputs.preferences.add(DisplayList.Key.self) } if contains(.viewResponders) { - inputs.preferences.add(ViewRespondersKey.self) + inputs.preferences.requiresViewResponders = true } } } @@ -264,7 +264,7 @@ package final class ViewGraph: GraphHost { } } if requestedOutputs.contains(.viewResponders) { - _rootResponders = WeakAttribute(outputs.preferences[ViewRespondersKey.self]) + _rootResponders = WeakAttribute(outputs.preferences.viewResponders) } if requestedOutputs.contains(.layout) { _rootLayoutComputer = WeakAttribute(outputs.layoutComputer) diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift b/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift index e3e9c46e0..9a1472f29 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift @@ -349,11 +349,17 @@ package let hostingViewCoordinateSpace: CoordinateSpace.ID = .init() extension ViewRendererHost { package func sendTestEvents(_ events: [EventID : any EventType]) { - openSwiftUIUnimplementedWarning() + guard let eventGraphHost = self.as(EventGraphHost.self) else { + return + } + eventGraphHost.eventBindingManager.send(events) } package func resetTestEvents() { - openSwiftUIUnimplementedWarning() + guard let eventGraphHost = self.as(EventGraphHost.self) else { + return + } + eventGraphHost.eventBindingManager.reset(resetForwardedEventDispatchers: false) } } diff --git a/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift b/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift index 0b5a0b348..801b07c71 100644 --- a/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift +++ b/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift @@ -238,7 +238,7 @@ extension _ViewInputs { inputs.requestsLayoutComputer = false inputs.needsGeometry = false inputs.preferences.remove(DisplayList.Key.self) - inputs.preferences.remove(ViewRespondersKey.self) + inputs.preferences.requiresViewResponders = false return inputs } diff --git a/Sources/OpenSwiftUICore/View/Responder/ViewRespondersKey.swift b/Sources/OpenSwiftUICore/View/Responder/ViewRespondersKey.swift deleted file mode 100644 index 905214a09..000000000 --- a/Sources/OpenSwiftUICore/View/Responder/ViewRespondersKey.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// ViewRespondersKey.swift -// OpenSwiftUICore -// -// Audited for iOS 18.0 -// Status: Empty - -package struct ViewRespondersKey: PreferenceKey { - package static var defaultValue: [ViewResponder] { [] } - - package static var _includesRemovedValues: Bool { true } - - package static func reduce(value: inout Value, nextValue: () -> Value) { - value.append(contentsOf: nextValue()) - } -} - -// TODO - -@_spi(ForOpenSwiftUIOnly) -open class ViewResponder/*: ResponderNode, CustomStringConvertible, CustomRecursiveStringConvertible*/ { -} - -package struct HitTestBindingModifier: ViewModifier, /*MultiViewModifier,*/ PrimitiveViewModifier { - nonisolated package static func _makeView( - modifier: _GraphValue, - inputs: _ViewInputs, - body: @escaping (_Graph, _ViewInputs) -> _ViewOutputs - ) -> _ViewOutputs { - // preconditionFailure("TODO") - return body(_Graph(), inputs) - } - - package typealias Body = Never -}