From 03e9a14081c2c3912b9be6ccc553b8639009ae03 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 13:04:40 +0800 Subject: [PATCH 1/3] Update missing parts of _VariadicView.Children --- .../View/VariadicView_Children.swift | 76 +++++++++++++++---- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/Sources/OpenSwiftUICore/View/VariadicView_Children.swift b/Sources/OpenSwiftUICore/View/VariadicView_Children.swift index e04cb5df9..564eae31a 100644 --- a/Sources/OpenSwiftUICore/View/VariadicView_Children.swift +++ b/Sources/OpenSwiftUICore/View/VariadicView_Children.swift @@ -2,14 +2,14 @@ // VariadicView_Children.swift // OpenSwiftUICore // -// Audited for 6.0.87 +// Audited for 6.5.4 // Status: WIP // ID: 52A2FFECFBCF37BFFEED558E33EBD1E3 (?) // ID: 9B09D1820E97ECBB666F7560EA2A2D2C (?) package import OpenAttributeGraphShims -// MARK: - _VariadicView.Children + View [WIP] +// MARK: - _VariadicView.Children + View @available(OpenSwiftUI_v1_0, *) extension _VariadicView.Children: View, MultiView, PrimitiveView { @@ -34,25 +34,26 @@ extension _VariadicView.Children: View, MultiView, PrimitiveView { @Attribute var children: _VariadicView.Children var value: Value { - _openSwiftUIUnimplementedFailure() + ForEach(children) { $0 } } } } -// MARK: - _VariadicView.Children + RandomAccessCollection [WIP] +// MARK: - _VariadicView.Children + RandomAccessCollection @available(OpenSwiftUI_v1_0, *) extension _VariadicView.Children: RandomAccessCollection { + public struct Element: PrimitiveView, UnaryView, Identifiable { var view: ViewList.View var traits: ViewTraitCollection public var id: AnyHashable { - _openSwiftUIUnimplementedFailure() - + view.viewID } - public func id(as _: ID.Type = ID.self) -> ID? where ID : Hashable { - _openSwiftUIUnimplementedFailure() + + public func id(as _: ID.Type = ID.self) -> ID? where ID: Hashable { + view.id.primaryExplicitID.flatMap{ $0.as(type: ID.self) } } /// The value of each trait associated with the view. Changing @@ -63,20 +64,52 @@ extension _VariadicView.Children: RandomAccessCollection { } public static func _makeView(view: _GraphValue, inputs: _ViewInputs) -> _ViewOutputs { - _openSwiftUIUnimplementedFailure() + ViewList.View._makeView( + view: view[\.view], + inputs: inputs + ) } } - public var startIndex: Int { - _openSwiftUIUnimplementedFailure() - } + public var startIndex: Int { .zero } - public var endIndex: Int { - _openSwiftUIUnimplementedFailure() - } + public var endIndex: Int { Update.ensure { list.count } } public subscript(index: Int) -> Element { - _openSwiftUIUnimplementedFailure() + var element: Element? + Update.ensure { + var start = index + var transform = transform + list.applySublists( + from: &start, + list: nil, + transform: &transform + ) { sublist in + let index = sublist.start + let count = sublist.count + if index < count { + element = Element( + view: .init( + elements: sublist.elements, + id: sublist.id, + index: index, + count: count, + contentSubgraph: contentSubgraph + ), + traits: sublist.traits + ) + } + return index >= count + } + } + guard let element else { + Log.internalError("Accessing invalid variadic view child at index %d", index) + return Element( + view: .init(emptyViewID: index), + traits: .init() + ) + } + return element } } @@ -142,6 +175,16 @@ package struct _ViewList_View: PrimitiveView, View, UnaryView { var count: Int var contentSubgraph: Subgraph? + @inline(__always) + init(emptyViewID implicitID: Int) { + self.elements = EmptyViewListElements() + self.releaseElements = nil + self.id = .init(implicitID: implicitID) + self.index = .zero + self.count = .zero + self.contentSubgraph = nil + } + package init( elements: any ViewList.Elements, id: ViewList.ID, @@ -150,6 +193,7 @@ package struct _ViewList_View: PrimitiveView, View, UnaryView { contentSubgraph: Subgraph ) { self.elements = elements + releaseElements = elements.retain() self.id = id self.index = index self.count = count From f38178ae1f9b5d800b5126344d467867b8599ac9 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 13:06:58 +0800 Subject: [PATCH 2/3] Update folder structure --- .../OpenSwiftUICore/View/{ => VariadicView}/VariadicView.swift | 0 .../VariadicViewChildren.swift} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Sources/OpenSwiftUICore/View/{ => VariadicView}/VariadicView.swift (100%) rename Sources/OpenSwiftUICore/View/{VariadicView_Children.swift => VariadicView/VariadicViewChildren.swift} (99%) diff --git a/Sources/OpenSwiftUICore/View/VariadicView.swift b/Sources/OpenSwiftUICore/View/VariadicView/VariadicView.swift similarity index 100% rename from Sources/OpenSwiftUICore/View/VariadicView.swift rename to Sources/OpenSwiftUICore/View/VariadicView/VariadicView.swift diff --git a/Sources/OpenSwiftUICore/View/VariadicView_Children.swift b/Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift similarity index 99% rename from Sources/OpenSwiftUICore/View/VariadicView_Children.swift rename to Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift index 564eae31a..bcf8610f7 100644 --- a/Sources/OpenSwiftUICore/View/VariadicView_Children.swift +++ b/Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift @@ -1,5 +1,5 @@ // -// VariadicView_Children.swift +// VariadicViewChildren.swift // OpenSwiftUICore // // Audited for 6.5.4 From a76e9487d54d543605e1580e2d785c0cbe086710 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 26 Oct 2025 13:17:21 +0800 Subject: [PATCH 3/3] Split ViewListView --- .../View/Input/ViewListView.swift | 233 ++++++++++++++++++ .../VariadicView/VariadicViewChildren.swift | 229 +---------------- 2 files changed, 235 insertions(+), 227 deletions(-) create mode 100644 Sources/OpenSwiftUICore/View/Input/ViewListView.swift diff --git a/Sources/OpenSwiftUICore/View/Input/ViewListView.swift b/Sources/OpenSwiftUICore/View/Input/ViewListView.swift new file mode 100644 index 000000000..990edd9a5 --- /dev/null +++ b/Sources/OpenSwiftUICore/View/Input/ViewListView.swift @@ -0,0 +1,233 @@ +// +// ViewListView.swift +// OpenSwiftUICore +// +// Audited for 6.0.87 +// Status: WIP +// ID: 52A2FFECFBCF37BFFEED558E33EBD1E3 (?) +// ID: 9B09D1820E97ECBB666F7560EA2A2D2C (?) + +package import OpenAttributeGraphShims + +// MARK: - ViewListVisitor + +package protocol ViewListVisitor { + mutating func visit(view: ViewList.View, traits: ViewTraitCollection) -> Bool +} + +// MARK: - ViewList.Backing [WIP] + +extension ViewList { + package typealias Backing = _ViewList_Backing +} + +package struct _ViewList_Backing { + package var children: _VariadicView.Children + + package var viewCount: Swift.Int { + children.list.count + } + + package init(_ children: _VariadicView.Children) { + self.children = children + } + + package func visitViews(applying v: inout V, from start: inout Int) -> Bool where V: ViewListVisitor { + Update.ensure { + children.list.applySublists(from: &start, list: nil) { sublist in + _openSwiftUIUnimplementedFailure() + } + } + } +} + +extension ViewList.Backing { + package func visitAll(applying v: inout V) where V: ViewListVisitor { + _openSwiftUIUnimplementedFailure() + } + + package func visitViews(applying v: inout V, from start: Int) where V: ViewListVisitor { + _openSwiftUIUnimplementedFailure() + } +} + +extension ViewList.Backing { + package var ids: [AnyHashable] { + _openSwiftUIUnimplementedFailure() + } +} + +// MARK: - _ViewList.View + +extension ViewList { + package typealias View = _ViewList_View +} + +package struct _ViewList_View: PrimitiveView, View, UnaryView { + var elements: any ViewList.Elements + var releaseElements: ViewList.Elements.Release? + package var id: ViewList.ID + var index: Int + var count: Int + var contentSubgraph: Subgraph? + + @inline(__always) + init(emptyViewID implicitID: Int) { + self.elements = EmptyViewListElements() + self.releaseElements = nil + self.id = .init(implicitID: implicitID) + self.index = .zero + self.count = .zero + self.contentSubgraph = nil + } + + package init( + elements: any ViewList.Elements, + id: ViewList.ID, + index: Int, + count: Int, + contentSubgraph: Subgraph + ) { + self.elements = elements + releaseElements = elements.retain() + self.id = id + self.index = index + self.count = count + self.contentSubgraph = contentSubgraph + } + + package var elementID: ViewList.ID { + id.elementID(at: index) + } + + package var reuseIdentifier: Int { + elementID.reuseIdentifier + } + + package var viewID: AnyHashable { + let canonicalID = elementID.canonicalID + if count == 1, !canonicalID.requiresImplicitID { + return canonicalID.explicitID!.anyHashable + } else { + return AnyHashable(canonicalID) + } + } + + nonisolated package static func _makeView( + view: _GraphValue, + inputs: _ViewInputs + ) -> _ViewOutputs { + let outputs = inputs.makeIndirectOutputs() + let placeholderInfo = PlaceholderInfo( + placeholder: view.value, + inputs: inputs, + outputs: outputs + ) + let attribute = Attribute(placeholderInfo) + outputs.setIndirectDependency(attribute.identifier) + return outputs + } +} + +// MARK: - PlaceholderInfo [WIP] + +private struct PlaceholderInfo: StatefulRule, ObservedAttribute, AsyncAttribute { + @Attribute var placeholder: ViewList.View + let inputs: _ViewInputs + let outputs: _ViewOutputs + let parentSubgraph: Subgraph + var lastSubgraph: Subgraph? + var lastRelease: ViewList.Elements.Release? + var secondaryRelease: ViewList.Elements.Release? + var lastElements: (any ViewList.Elements)? + var lastMap: IndirectAttributeMap? + var contentObserver: (Subgraph, Int)? + var lastPhase: Attribute<_GraphInputs.Phase>? + + init(placeholder: Attribute, inputs: _ViewInputs, outputs: _ViewOutputs) { + self._placeholder = placeholder + self.inputs = inputs + self.outputs = outputs + // FIXME: The Subgraph.current call on the init default value or the call site will trigger a compiler crash (SIL -> IR) on Release build + // We workaround it by setting it to .current here + self.parentSubgraph = .current! + } + + struct Value { + var id: ViewList.ID + var seed: UInt32 + var index: Int + } + + func makeItem(placeholder: ViewList.View, seed: UInt32) -> Value { + _openSwiftUIUnimplementedFailure() + } + + mutating func reuseItem(info: inout Value, placeholder: ViewList.View) -> Bool { + guard let lastElements, + lastElements.tryToReuseElement( + at: info.index, + by: placeholder.elements, + at: placeholder.index, + indirectMap: lastMap!, + testOnly: false + ) + else { + ReuseTrace.traceReuseInvalidSubgraphFailure(ViewList.View.self) + return false + } + lastPhase!.mutateBody( + as: PlaceholderViewPhase.self, + invalidating: true + ) { phase in + phase.resetDelta &+= 1 + } + secondaryRelease = placeholder.elements.retain() + info.id = placeholder.id + info.index = placeholder.index + return true + } + + mutating func eraseItem() { + outputs.detachIndirectOutputs() + if let lastSubgraph { + lastSubgraph.willInvalidate(isInserted: true) + lastSubgraph.invalidate() + self.lastSubgraph = nil + } + if let contentObserver { + // TODO: OSubgraphRemoveObserver + // contentObserver.0.removeObserver(contentObserver.1) + self.contentObserver = nil + } + lastRelease = nil + secondaryRelease = nil + lastElements = nil + lastMap = nil + lastPhase = nil + } + + mutating func updateValue() { + _openSwiftUIUnimplementedFailure() + } + + func destroy() { + if let contentObserver { + // TODO: OSubgraphRemoveObserver + // contentObserver.0.removeObserver(contentObserver.1) + } + } +} + +private struct PlaceholderViewPhase: Rule, AsyncAttribute { + @Attribute var phase1: _GraphInputs.Phase + @Attribute var phase2: _GraphInputs.Phase + var resetDelta: UInt32 + + var value: _GraphInputs.Phase { + var result = phase1 + result.merge(phase2) + result.resetSeed &+= resetDelta + return result + } +} diff --git a/Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift b/Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift index bcf8610f7..d681fd328 100644 --- a/Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift +++ b/Sources/OpenSwiftUICore/View/VariadicView/VariadicViewChildren.swift @@ -3,11 +3,9 @@ // OpenSwiftUICore // // Audited for 6.5.4 -// Status: WIP -// ID: 52A2FFECFBCF37BFFEED558E33EBD1E3 (?) -// ID: 9B09D1820E97ECBB666F7560EA2A2D2C (?) +// Status: Complete -package import OpenAttributeGraphShims +import OpenAttributeGraphShims // MARK: - _VariadicView.Children + View @@ -112,226 +110,3 @@ extension _VariadicView.Children: RandomAccessCollection { return element } } - -// MARK: - ViewListVisitor - -package protocol ViewListVisitor { - mutating func visit(view: ViewList.View, traits: ViewTraitCollection) -> Bool -} - -// MARK: - ViewList.Backing [WIP] - -extension ViewList { - package typealias Backing = _ViewList_Backing -} - -package struct _ViewList_Backing { - package var children: _VariadicView.Children - - package var viewCount: Swift.Int { - children.list.count - } - - package init(_ children: _VariadicView.Children) { - self.children = children - } - - package func visitViews(applying v: inout V, from start: inout Int) -> Bool where V: ViewListVisitor { - Update.ensure { - children.list.applySublists(from: &start, list: nil) { sublist in - _openSwiftUIUnimplementedFailure() - } - } - } -} - -extension ViewList.Backing { - package func visitAll(applying v: inout V) where V: ViewListVisitor { - _openSwiftUIUnimplementedFailure() - } - - package func visitViews(applying v: inout V, from start: Int) where V: ViewListVisitor { - _openSwiftUIUnimplementedFailure() - } -} - -extension ViewList.Backing { - package var ids: [AnyHashable] { - _openSwiftUIUnimplementedFailure() - } -} - -// MARK: - _ViewList.View - -extension ViewList { - package typealias View = _ViewList_View -} - -package struct _ViewList_View: PrimitiveView, View, UnaryView { - var elements: any ViewList.Elements - var releaseElements: ViewList.Elements.Release? - package var id: ViewList.ID - var index: Int - var count: Int - var contentSubgraph: Subgraph? - - @inline(__always) - init(emptyViewID implicitID: Int) { - self.elements = EmptyViewListElements() - self.releaseElements = nil - self.id = .init(implicitID: implicitID) - self.index = .zero - self.count = .zero - self.contentSubgraph = nil - } - - package init( - elements: any ViewList.Elements, - id: ViewList.ID, - index: Int, - count: Int, - contentSubgraph: Subgraph - ) { - self.elements = elements - releaseElements = elements.retain() - self.id = id - self.index = index - self.count = count - self.contentSubgraph = contentSubgraph - } - - package var elementID: ViewList.ID { - id.elementID(at: index) - } - - package var reuseIdentifier: Int { - elementID.reuseIdentifier - } - - package var viewID: AnyHashable { - let canonicalID = elementID.canonicalID - if count == 1, !canonicalID.requiresImplicitID { - return canonicalID.explicitID!.anyHashable - } else { - return AnyHashable(canonicalID) - } - } - - nonisolated package static func _makeView( - view: _GraphValue, - inputs: _ViewInputs - ) -> _ViewOutputs { - let outputs = inputs.makeIndirectOutputs() - let placeholderInfo = PlaceholderInfo( - placeholder: view.value, - inputs: inputs, - outputs: outputs - ) - let attribute = Attribute(placeholderInfo) - outputs.setIndirectDependency(attribute.identifier) - return outputs - } -} - -// MARK: - PlaceholderInfo [WIP] - -private struct PlaceholderInfo: StatefulRule, ObservedAttribute, AsyncAttribute { - @Attribute var placeholder: ViewList.View - let inputs: _ViewInputs - let outputs: _ViewOutputs - let parentSubgraph: Subgraph - var lastSubgraph: Subgraph? - var lastRelease: ViewList.Elements.Release? - var secondaryRelease: ViewList.Elements.Release? - var lastElements: (any ViewList.Elements)? - var lastMap: IndirectAttributeMap? - var contentObserver: (Subgraph, Int)? - var lastPhase: Attribute<_GraphInputs.Phase>? - - init(placeholder: Attribute, inputs: _ViewInputs, outputs: _ViewOutputs) { - self._placeholder = placeholder - self.inputs = inputs - self.outputs = outputs - // FIXME: The Subgraph.current call on the init default value or the call site will trigger a compiler crash (SIL -> IR) on Release build - // We workaround it by setting it to .current here - self.parentSubgraph = .current! - } - - struct Value { - var id: ViewList.ID - var seed: UInt32 - var index: Int - } - - func makeItem(placeholder: ViewList.View, seed: UInt32) -> Value { - _openSwiftUIUnimplementedFailure() - } - - mutating func reuseItem(info: inout Value, placeholder: ViewList.View) -> Bool { - guard let lastElements, - lastElements.tryToReuseElement( - at: info.index, - by: placeholder.elements, - at: placeholder.index, - indirectMap: lastMap!, - testOnly: false - ) - else { - ReuseTrace.traceReuseInvalidSubgraphFailure(ViewList.View.self) - return false - } - lastPhase!.mutateBody( - as: PlaceholderViewPhase.self, - invalidating: true - ) { phase in - phase.resetDelta &+= 1 - } - secondaryRelease = placeholder.elements.retain() - info.id = placeholder.id - info.index = placeholder.index - return true - } - - mutating func eraseItem() { - outputs.detachIndirectOutputs() - if let lastSubgraph { - lastSubgraph.willInvalidate(isInserted: true) - lastSubgraph.invalidate() - self.lastSubgraph = nil - } - if let contentObserver { - // TODO: OSubgraphRemoveObserver - // contentObserver.0.removeObserver(contentObserver.1) - self.contentObserver = nil - } - lastRelease = nil - secondaryRelease = nil - lastElements = nil - lastMap = nil - lastPhase = nil - } - - mutating func updateValue() { - _openSwiftUIUnimplementedFailure() - } - - func destroy() { - if let contentObserver { - // TODO: OSubgraphRemoveObserver - // contentObserver.0.removeObserver(contentObserver.1) - } - } -} - -private struct PlaceholderViewPhase: Rule, AsyncAttribute { - @Attribute var phase1: _GraphInputs.Phase - @Attribute var phase2: _GraphInputs.Phase - var resetDelta: UInt32 - - var value: _GraphInputs.Phase { - var result = phase1 - result.merge(phase2) - result.resetSeed &+= resetDelta - return result - } -}