diff --git a/Package.resolved b/Package.resolved index 22a45e95..1e114e42 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "7c61cf2fa8336371c9cc17d001d4e08e34b0f8b92c637a0c44f1b2cd08cd55b2", + "originHash" : "9749b5257cf4f28f086bdeac0424718c7ae499aeea22fdc45686fac00d8d561d", "pins" : [ { "identity" : "opengraph", @@ -7,7 +7,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenGraph", "state" : { "branch" : "main", - "revision" : "48ad5323175fbfdfde2287bbf26c3e5a861ae2bb" + "revision" : "58961e8c7fb7528a89dcd77a3a28a950f1791f1f" } }, { diff --git a/Sources/OpenSwiftUI/Core/Data/Boxes/MutableBox.swift b/Sources/OpenSwiftUI/Core/Data/Boxes/MutableBox.swift index 07fbca72..8b01805e 100644 --- a/Sources/OpenSwiftUI/Core/Data/Boxes/MutableBox.swift +++ b/Sources/OpenSwiftUI/Core/Data/Boxes/MutableBox.swift @@ -2,33 +2,38 @@ // MutableBox.swift // OpenSwiftUI // -// Audited for RELEASE_2021 +// Audited for RELEASE_2024 // Status: Complete @propertyWrapper -final class MutableBox { - private var value: A - - var wrappedValue: A { - get { value } - set { value = newValue } - } +final package class MutableBox { + final package var value: T - init(_ value: A) { + @inlinable + package init(_ value: T) { self.value = value } - init(wrappedValue value: A) { - self.value = value + @inlinable + convenience package init(wrappedValue value: T) { + self.init(value) } - - var projectedValue: MutableBox { + + @inlinable + final package var wrappedValue: T { + get { value } + set { value = newValue } + } + + @inlinable + final package var projectedValue: MutableBox { self } } -extension MutableBox: Equatable where A: Equatable { - static func == (lhs: MutableBox, rhs: MutableBox) -> Bool { +extension MutableBox: Equatable where T: Equatable { + @inlinable + package static func == (lhs: MutableBox, rhs: MutableBox) -> Bool { lhs.value == rhs.value } } diff --git a/Sources/OpenSwiftUI/Core/Data/Location/AnyLocation.swift b/Sources/OpenSwiftUI/Core/Data/Location/AnyLocation.swift index 6e128a31..425eb1db 100644 --- a/Sources/OpenSwiftUI/Core/Data/Location/AnyLocation.swift +++ b/Sources/OpenSwiftUI/Core/Data/Location/AnyLocation.swift @@ -5,11 +5,18 @@ // Audited for RELEASE_2021 // Status: Complete +/// The base type of all type-erased locations. @usableFromInline class AnyLocationBase {} +/// The base type of all type-erased locations with value-type Value. +/// It is annotated as `@unchecked Sendable` so that user types such as +/// `State`, and `SceneStorage` can be cleanly `Sendable`. However, it is +/// also the user types' responsibility to ensure that `get`, and `set` does +/// not access the graph concurrently (`get` should not be called while graph +/// is updating, for example). @usableFromInline -class AnyLocation: AnyLocationBase { +class AnyLocation: AnyLocationBase, @unchecked Sendable { var wasRead: Bool { get { fatalError() } set { fatalError() } diff --git a/Sources/OpenSwiftUI/Core/Data/Property/PropertyList.swift b/Sources/OpenSwiftUI/Core/Data/Property/PropertyList.swift index 080cad6e..bec1cb19 100644 --- a/Sources/OpenSwiftUI/Core/Data/Property/PropertyList.swift +++ b/Sources/OpenSwiftUI/Core/Data/Property/PropertyList.swift @@ -11,6 +11,7 @@ internal import OpenGraphShims // MARK: - PropertyList +/// A mutable container of key-value pairs @usableFromInline @frozen struct PropertyList: CustomStringConvertible { diff --git a/Sources/OpenSwiftUI/Core/View/CustomView.swift b/Sources/OpenSwiftUI/Core/View/CustomView.swift index 5fc9459e..c3e4f60a 100644 --- a/Sources/OpenSwiftUI/Core/View/CustomView.swift +++ b/Sources/OpenSwiftUI/Core/View/CustomView.swift @@ -15,6 +15,7 @@ extension View { let (body, buffer) = inputs.withMutateGraphInputs { inputs in makeBody(view: view, inputs: &inputs, fields: fields) } + // FIXME let outputs = _ViewDebug.makeView( view: body, inputs: inputs @@ -27,6 +28,19 @@ extension View { return outputs } + static func makeViewList(view: _GraphValue, inputs: _ViewListInputs) -> _ViewListOutputs { + let fields = DynamicPropertyCache.fields(of: Self.self) + var inputs = inputs + let (body, buffer) = inputs.withMutateGraphInputs { inputs in + makeBody(view: view, inputs: &inputs, fields: fields) + } + let outputs = Body.makeDebuggableViewList(view: body, inputs: inputs) + if let buffer { + buffer.traceMountedProperties(to: body, fields: fields) + } + return outputs + } + private static func makeBody( view: _GraphValue, inputs: inout _GraphInputs, diff --git a/Sources/OpenSwiftUI/Core/View/VariadicView/VariadicView_ImplicitRoot.swift b/Sources/OpenSwiftUI/Core/View/VariadicView/VariadicView_ImplicitRoot.swift index 1e0c6e5e..7e0ca869 100644 --- a/Sources/OpenSwiftUI/Core/View/VariadicView/VariadicView_ImplicitRoot.swift +++ b/Sources/OpenSwiftUI/Core/View/VariadicView/VariadicView_ImplicitRoot.swift @@ -18,7 +18,7 @@ package protocol _VariadicView_ImplicitRoot: _VariadicView_AnyImplicitRoot, _Var } extension _VariadicView_ImplicitRoot { - package func visitType(visitor: inout Visitor) { + package static func visitType(visitor: inout V) where V: _VariadicView_ImplicitRootVisitor { visitor.visit(type: Self.self) } } diff --git a/Sources/OpenSwiftUI/Core/View/View.swift b/Sources/OpenSwiftUI/Core/View/View.swift index 375042df..64cea50d 100644 --- a/Sources/OpenSwiftUI/Core/View/View.swift +++ b/Sources/OpenSwiftUI/Core/View/View.swift @@ -85,7 +85,7 @@ extension View { } public static func _makeViewList(view: _GraphValue, inputs: _ViewListInputs) -> _ViewListOutputs { - fatalError("TODO") + makeViewList(view: view, inputs: inputs) } public static func _viewListCount(inputs: _ViewListCountInputs) -> Int? { diff --git a/Sources/OpenSwiftUI/Core/View/View/ViewList.swift b/Sources/OpenSwiftUI/Core/View/View/ViewList.swift new file mode 100644 index 00000000..840d31d5 --- /dev/null +++ b/Sources/OpenSwiftUI/Core/View/View/ViewList.swift @@ -0,0 +1,483 @@ +// +// ViewList.swift +// OpenSwiftUI +// +// Audited for RELEASE_2021 +// Status: WIP +// ID: 70E71091E926A1B09B75AAEB38F5AA3F + +import Foundation +package import OpenGraphShims + +// MARK: - _ViewListInputs + +/// Input values to `View._makeViewList()`. +public struct _ViewListInputs { + package var base: _GraphInputs + package var implicitID: Int + + package struct Options: OptionSet { + package let rawValue: Int + + package init(rawValue: Int) { + self.rawValue = rawValue + } + + package static let canTransition: Options = Options(rawValue: 1 << 0) + package static let disableTransitions: Options = Options(rawValue: 1 << 1) + package static let requiresDepthAndSections: Options = Options(rawValue: 1 << 2) + package static let requiresNonEmptyGroupParent: Options = Options(rawValue: 1 << 3) + package static let isNonEmptyParent: Options = Options(rawValue: 1 << 4) + package static let resetHeaderStyleContext: Options = Options(rawValue: 1 << 5) + package static let resetFooterStyleContext: Options = Options(rawValue: 1 << 6) + package static let layoutPriorityIsTrait: Options = Options(rawValue: 1 << 7) + package static let requiresSections: Options = Options(rawValue: 1 << 8) + package static let tupleViewCreatesUnaryElements: Options = Options(rawValue: 1 << 9) + package static let previewContext: Options = Options(rawValue: 1 << 10) + package static let needsDynamicTraits: Options = Options(rawValue: 1 << 11) + package static let allowsNestedSections: Options = Options(rawValue: 1 << 12) + package static let sectionsConcatenateFooter: Options = Options(rawValue: 1 << 13) + package static let needsArchivedAnimationTraits: Options = Options(rawValue: 1 << 14) + package static let sectionsAreHierarchical: Options = Options(rawValue: 1 << 15) + } + + package var options: _ViewListInputs.Options + @OptionalAttribute var traits: ViewTraitCollection? + package var traitKeys: ViewTraitKeys? + + + // MARK: - base + + @inline(__always) + mutating func withMutateGraphInputs(_ body: (inout _GraphInputs) -> R) -> R { + body(&base) + } +} + +// MARK: - ViewListOutputs + +/// Output values from `View._makeViewList()`. +public struct _ViewListOutputs { + var views: Views + var nextImplicitID: Int + var staticCount: Int? + + enum Views { + case staticList(_ViewList_Elements) + case dynamicList(Attribute, ListModifier?) + } + + class ListModifier { + init() {} + + func apply(to: inout ViewList) { + // TODO + } + } + + private static func staticList(_ elements: _ViewList_Elements, inputs: _ViewListInputs, staticCount: Int) -> _ViewListOutputs { + fatalError("TODO") + } +} + +extension _ViewListOutputs { + @inline(__always) + static func emptyParentViewList(inputs: _ViewListInputs) -> _ViewListOutputs { + staticList(EmptyElements(), inputs: inputs, staticCount: 0) + } + + package static func nonEmptyParentViewList(inputs: _ViewListInputs) -> _ViewListOutputs { + fatalError("TODO") + } +} + +// MARK: - _ViewListCountInputs + +/// Input values to `View._viewListCount()`. +public struct _ViewListCountInputs { + var customInputs: PropertyList + var options: _ViewListInputs.Options + var baseOptions: _GraphInputs.Options + + subscript(_ type: Input.Type) -> Input.Value { + get { customInputs[type] } + set { customInputs[type] = newValue } + } + + mutating func append(_ value: Value, to type: Input.Type) where Input.Value == [Value] { + var values = self[type] + values.append(value) + self[type] = values + } + + mutating func popLast(_ type: Input.Type) -> Value? where Input.Value == [Value] { + var values = self[type] + guard let value = values.popLast() else { + return nil + } + self[type] = values + return value + } +} + +// MARK: - _ViewList_ID + +package struct _ViewList_ID { + var _index: Int32 + var implicitID: Int32 + private var explicitIDs: [Explicit] + + package class Views { + let isDataDependent: Bool + var endIndex: Int { fatalError() } + subscript(index: Int) -> _ViewList_ID { fatalError() } + func isEqual(to other: Views) -> Bool { fatalError() } + init(isDataDependent: Bool) { + self.isDataDependent = isDataDependent + } + // func withDataDependency() -> Views {} + } + + final class _Views: Views where Base: Equatable, Base: RandomAccessCollection, Base.Element == _ViewList_ID, Base.Index == Int { + let base: Base + + init(_ base: Base, isDataDependent: Bool) { + self.base = base + super.init(isDataDependent: isDataDependent) + } + override var endIndex: Int { + base.endIndex + } + + override subscript(index: Int) -> _ViewList_ID { + base[index] + } + + override func isEqual(to other: _ViewList_ID.Views) -> Bool { + guard let other = other as? Self else { return false } + return base == other.base + } + } + + final class JoinedViews: Views { + let views: [(views: Views, endOffset: Int)] + let count: Int + + init(_ views: [Views], isDataDependent: Bool) { + var offset = 0 + var result: [(views: Views, endOffset: Int)] = [] + for view in views { + offset += views.distance(from: 0, to: view.endIndex) + result.append((view, offset)) + } + self.views = result + count = offset + super.init(isDataDependent: isDataDependent) + } + + override var endIndex: Int { + views.endIndex + } + + override subscript(index: Int) -> _ViewList_ID { + fatalError("TODO") + } + + override func isEqual(to other: _ViewList_ID.Views) -> Bool { + fatalError("TODO") + } + } + + private struct Explicit: Equatable { + let id: AnyHashable + #if canImport(Darwin) + let owner: OGAttribute + #endif + let isUnary: Bool + } + + struct Canonical { + var _index: Int32 + var implicitID: Int32 + var explicitID: AnyHashable? + } + + #if canImport(Darwin) + mutating func bind(explicitID: AnyHashable, owner: OGAttribute, isUnary: Bool) { + explicitIDs.append(.init(id: explicitID, owner: owner, isUnary: isUnary)) + } + #endif +} + +// MARK: - IndirectMap + +#if OPENSWIFTUI_RELEASE_2024 +final package class IndirectAttributeMap { + final package let subgraph: Subgraph + final package var map: [AnyAttribute: AnyAttribute] + + package init(subgraph: Subgraph) { + self.subgraph = subgraph + self.map = [:] + } +} +#elseif OPENSWIFTUI_RELEASE_2021 +final package class _ViewList_IndirectMap { + final package let subgraph: OGSubgraph + + #if canImport(Darwin) + final package var map: [OGAttribute: OGAttribute] + #endif + + init(subgraph: OGSubgraph) { + self.subgraph = subgraph + #if canImport(Darwin) + self.map = [:] + #endif + } +} +#endif + +// MARK: - _ViewList_Elements + +package protocol _ViewList_Elements { + typealias Body = (_ViewInputs, @escaping Self.MakeElement) -> (_ViewOutputs?, Swift.Bool) + typealias MakeElement = (_ViewInputs) -> _ViewOutputs + #if OPENSWIFTUI_RELEASE_2024 + typealias Release = _ViewList_ReleaseElements + #elseif OPENSWIFTUI_RELEASE_2021 + typealias Release = () -> Void + #endif + + var count: Int { get } + + #if OPENSWIFTUI_RELEASE_2024 + func makeElements( + from start: inout Int, + inputs: _ViewInputs, + indirectMap: IndirectAttributeMap?, + body: Body + ) -> (_ViewOutputs?, Bool) + + func tryToReuseElement( + at index: Int, + by other: any _ViewList_Elements, + at otherIndex: Int, + indirectMap: IndirectAttributeMap, + testOnly: Bool + ) -> Bool + #elseif OPENSWIFTUI_RELEASE_2021 + func makeElements( + from start: inout Int, + inputs: _ViewInputs, + indirectMap: _ViewList_IndirectMap?, + body: Body + ) -> (_ViewOutputs?, Bool) + + func tryToReuseElement( + at index: Int, + by other: any _ViewList_Elements, + at otherIndex: Int, + indirectMap: _ViewList_IndirectMap, + testOnly: Bool + ) -> Bool + #endif + + func retain() -> Release +} + +extension _ViewList_Elements { + func retain() -> Release { + {} + } +} + +private struct EmptyElements: _ViewList_Elements { + var count: Int { 0 } + + func makeElements( + from start: inout Int, + inputs: _ViewInputs, + indirectMap: _ViewList_IndirectMap?, + body: Body + ) -> (_ViewOutputs?, Bool) { + return (nil, true) + } + + func tryToReuseElement( + at index: Int, + by other: any _ViewList_Elements, + at otherIndex: Int, + indirectMap: _ViewList_IndirectMap, + testOnly: Bool + ) -> Bool { + other is EmptyElements + } +} + +// TODO +private struct UnaryElements: _ViewList_Elements { + var body: Value + var baseInputs: _GraphInputs + + init(body: Value, baseInputs: _GraphInputs) { + self.body = body + self.baseInputs = baseInputs + } + + var count: Int { 1 } + + func makeElements( + from start: inout Int, + inputs: _ViewInputs, + indirectMap: _ViewList_IndirectMap?, + body: Body + ) -> (_ViewOutputs?, Bool) { + fatalError("TODO") + } + + func tryToReuseElement( + at index: Int, + by other: any _ViewList_Elements, + at otherIndex: Int, + indirectMap: _ViewList_IndirectMap, + testOnly: Bool + ) -> Bool { + fatalError("TODO") + } +} + +// MARK: - _ViewList_Subgraph + +class _ViewList_Subgraph { + let subgraph: OGSubgraph + private var refcount : UInt32 + + init(subgraph: OGSubgraph) { + self.subgraph = subgraph + self.refcount = 1 + } + + func invalidate() {} +} + +extension _ViewList_Subgraph { + var isValid: Bool { + guard refcount > 0 else { + return false + } + return subgraph.isValid + } + + func retain() { + refcount &+= 1 + } + + func release(isInserted: Bool) { + refcount &-= 1 + guard refcount == 0 else { + return + } + invalidate() + guard subgraph.isValid else { + return + } + subgraph.willInvalidate(isInserted: isInserted) + subgraph.invalidate() + } + + @inlinable + func wrapping(_ elements: _ViewList_Elements) -> _ViewList_Elements { + SubgraphElements(base: elements, subgraph: self) + } +} + +// TODO +private struct SubgraphElements: _ViewList_Elements { + let base: _ViewList_Elements + let subgraph: _ViewList_Subgraph + + var count: Int { + fatalError("TODO") + } + + func makeElements(from start: inout Int, inputs: _ViewInputs, indirectMap: _ViewList_IndirectMap?, body: (_ViewInputs, @escaping MakeElement) -> (_ViewOutputs?, Bool)) -> (_ViewOutputs?, Bool) { + fatalError("TODO") + } + + func tryToReuseElement(at index: Int, by other: any _ViewList_Elements, at otherIndex: Int, indirectMap: _ViewList_IndirectMap, testOnly: Bool) -> Bool { + fatalError("TODO") + } +} + +// MARK: - _ViewList_View + +package struct _ViewList_View { + var elements: _ViewList_Elements + var id: _ViewList_ID + var index: Int + var count: Int + var contentSubgraph: OGSubgraph +} + +// MARK: - _ViewList_Sublist + +struct _ViewList_Sublist { + var start: Int + var count: Int + var id: _ViewList_ID + var elements: _ViewList_Elements + var traits: ViewTraitCollection + var list: Attribute? +} + +struct _ViewList_SublistTransform { + var items: [any _ViewList_SublistTransform_Item] +} + + +protocol _ViewList_SublistTransform_Item { + func apply(sublist: inout _ViewList_Sublist) +} + +// MARK: - ViewList + +protocol ViewList { + func count(style: _ViewList_IteratorStyle) -> Int + func estimatedCount(style: _ViewList_IteratorStyle) -> Int + var traitKeys: ViewTraitKeys? { get } + var viewIDs: _ViewList_ID.Views? { get } + var traits: ViewTraitCollection { get } + func applyNodes(from index: inout Int, style: _ViewList_IteratorStyle, list: _GraphValue?, transform: inout _ViewList_SublistTransform, to body: (inout Int, _ViewList_IteratorStyle, _ViewList_Node, inout _ViewList_SublistTransform) -> Bool) -> Bool + func edit(forID id: _ViewList_ID, since transaction: TransactionID) -> _ViewList_Edit? + func firstOffset(forID id: OtherID, style: _ViewList_IteratorStyle) -> Int? where OtherID: Hashable +} + +// MARK: - ViewListVisitor + +protocol ViewListVisitor { + mutating func visit(view: _ViewList_View, traits: ViewTraitCollection) -> Bool +} + +// MARK: - _ViewList_IteratorStyle + +// TODO +struct _ViewList_IteratorStyle: Equatable { + var value: UInt + + func alignToPreviousGranularityMultiple(_ value: inout Int) { + fatalError("TODO") + } +} + +enum _ViewList_Edit: Equatable { + case inserted + case removed +} + +enum _ViewList_Node { + case list(any ViewList, Attribute?) + case sublist(_ViewList_Sublist) + // case group(_ViewList_Group) + // case section(_ViewList_Section) +} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewListCountInputs.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewListCountInputs.swift deleted file mode 100644 index 10f64ea2..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewListCountInputs.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// ViewListCountInputs.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: WIP - -/// Input values to `View._viewListCount()`. -public struct _ViewListCountInputs { - var customInputs: PropertyList - var options: _ViewListInputs.Options - var baseOptions: _GraphInputs.Options - - subscript(_ type: Input.Type) -> Input.Value { - get { customInputs[type] } - set { customInputs[type] = newValue } - } - - mutating func append(_ value: Value, to type: Input.Type) where Input.Value == [Value] { - var values = self[type] - values.append(value) - self[type] = values - } - - mutating func popLast(_ type: Input.Type) -> Value? where Input.Value == [Value] { - var values = self[type] - guard let value = values.popLast() else { - return nil - } - self[type] = values - return value - } -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewListInputs.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewListInputs.swift deleted file mode 100644 index 5feccda1..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewListInputs.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// ViewListInputs.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: WIP - -internal import OpenGraphShims - -/// Input values to `View._makeViewList()`. -public struct _ViewListInputs { - private var base: _GraphInputs - var implicitID: Int - var options: _ViewListInputs.Options - @OptionalAttribute var traits: ViewTraitCollection? - var traitKeys: ViewTraitKeys? - - package struct Options: OptionSet { - package init(rawValue: Int) { - self.rawValue = rawValue - } - - package let rawValue: Int - } - - // MARK: - base - - @inline(__always) - mutating func withMutateGraphInputs(_ body: (inout _GraphInputs) -> R) -> R { - body(&base) - } -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewListOutputs.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewListOutputs.swift deleted file mode 100644 index 78066438..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewListOutputs.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// ViewListOutputs.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: WIP - -internal import OpenGraphShims - -/// Output values from `View._makeViewList()`. -public struct _ViewListOutputs { - var views: Views - var nextImplicitID: Int - var staticCount: Int? - - enum Views { - case staticList(_ViewList_Elements) - case dynamicList(Attribute, ListModifier?) - } - - class ListModifier { - init() {} - - func apply(to: inout ViewList) { - // TODO - } - } -} - -// TODO -protocol ViewList { -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_Elements.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_Elements.swift deleted file mode 100644 index 058f4b79..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_Elements.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// ViewList_Elements.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: WIP - -protocol _ViewList_Elements { - var count: Int { get } - func makeElements( - from: inout Int, - inputs: _ViewInputs, - indirectMap: _ViewList_IndirectMap?, - body: (_ViewInputs, (_ViewInputs) -> _ViewOutputs) -> (_ViewOutputs?, Bool) - ) -> (_ViewOutputs?, Bool) - func tryToReuseElement(at: Int, by: _ViewList_Elements, at: Int, indirectMap: _ViewList_IndirectMap, testOnly: Bool) -> Bool - func retain() -> () -> Void -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_ID.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_ID.swift deleted file mode 100644 index 0f85667b..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_ID.swift +++ /dev/null @@ -1,12 +0,0 @@ -// ID: 70E71091E926A1B09B75AAEB38F5AA3F - -struct _ViewList_ID { - var _index: Int32 - var implicitID: Int32 - private var explicitIDs: [Explicit] -} - -extension _ViewList_ID { - private struct Explicit { - } -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_IndirectMap.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_IndirectMap.swift deleted file mode 100644 index 2cd7ca65..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_IndirectMap.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// ViewList_IndirectMap.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: WIP -// ID: 70E71091E926A1B09B75AAEB38F5AA3F - -internal import OpenGraphShims - -final class _ViewList_IndirectMap { - let subgraph: OGSubgraph - #if canImport(Darwin) - private var map: [OGAttribute: OGAttribute] - #endif - - init(subgraph: OGSubgraph) { - self.subgraph = subgraph - #if canImport(Darwin) - self.map = [:] - #endif - } -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_Subgraph.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_Subgraph.swift deleted file mode 100644 index 31c2ea09..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_Subgraph.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// ViewList_Subgraph.swift -// OpenSwiftUI -// -// Audited for RELEASE_2021 -// Status: WIP -// ID: 70E71091E926A1B09B75AAEB38F5AA3F - -internal import OpenGraphShims - -class _ViewList_Subgraph { - let subgraph: OGSubgraph - private var refcount : UInt32 - - init(subgraph: OGSubgraph) { - self.subgraph = subgraph - self.refcount = 1 // TODO - } - - func invalidate() {} -} - -extension _ViewList_Subgraph { - var isValid: Bool { - guard refcount > 0 else { - return false - } - return subgraph.isValid - } - - func retain() { - refcount &+= 1 - } - - func release(isInserted: Bool) { - refcount &-= 1 - guard refcount == 0 else { - return - } - invalidate() - guard subgraph.isValid else { - return - } - subgraph.willInvalidate(isInserted: isInserted) - subgraph.invalidate() - } -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_View.swift b/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_View.swift deleted file mode 100644 index f308db08..00000000 --- a/Sources/OpenSwiftUI/Core/View/ViewList/ViewList_View.swift +++ /dev/null @@ -1,9 +0,0 @@ -internal import OpenGraphShims - -struct _ViewList_View { - var elements: _ViewList_Elements - var id: _ViewList_ID - var index: Int - var count: Int - var contentSubgraph: OGSubgraph -} diff --git a/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitCollection.swift b/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitCollection.swift index e4b35858..de1cc979 100644 --- a/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitCollection.swift +++ b/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitCollection.swift @@ -6,7 +6,11 @@ // Status: WIP // ID: 9929B476764059557433A108298EE66F -struct ViewTraitCollection { +package struct ViewTraitCollection { + package init() { + self.storage = [] + } + private var storage: [any AnyViewTrait] private struct AnyTrait: AnyViewTrait { diff --git a/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitKeys.swift b/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitKeys.swift index 3f0d80b6..4d66ccf3 100644 --- a/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitKeys.swift +++ b/Sources/OpenSwiftUI/Core/View/ViewTrait/ViewTraitKeys.swift @@ -2,18 +2,34 @@ // ViewTraitKeys.swift // OpenSwiftUI // -// Audited for RELEASE_2021 +// Audited for RELEASE_2024 // Status: Complete -struct ViewTraitKeys { - var types: Set - var isDataDependent: Bool +package struct ViewTraitKeys { + package var types: Set + package var isDataDependent: Bool - mutating func insert(_ type: Key.Type) { - types.insert(ObjectIdentifier(type)) + package init() { + types = [] + isDataDependent = false } - func contains(_ type: Key.Type) -> Bool { + package func contains(_ type: T.Type) -> Bool where T: _ViewTraitKey{ types.contains(ObjectIdentifier(type)) } + + package mutating func insert(_ type: T.Type) where T: _ViewTraitKey { + types.insert(ObjectIdentifier(type)) + } + + package mutating func formUnion(_ other: ViewTraitKeys) { + types.formUnion(other.types) + isDataDependent = isDataDependent || other.isDataDependent + } + + package func withDataDependent() -> ViewTraitKeys { + var copy = self + copy.isDataDependent = true + return copy + } } diff --git a/Sources/OpenSwiftUI/Data/Model/State/State.swift b/Sources/OpenSwiftUI/Data/Model/State/State.swift index e2d9d611..16603c46 100644 --- a/Sources/OpenSwiftUI/Data/Model/State/State.swift +++ b/Sources/OpenSwiftUI/Data/Model/State/State.swift @@ -89,9 +89,11 @@ internal import OpenGraphShims @frozen @propertyWrapper public struct State { + /// The current or initial (if box == nil) value of the state @usableFromInline var _value: Value + /// The value's location, or nil if not yet known. @usableFromInline var _location: AnyLocation? diff --git a/Sources/OpenSwiftUI/Layout/LayoutFundamentals/Stack/HVStackLayout.swift b/Sources/OpenSwiftUI/Layout/LayoutFundamentals/Stack/HVStackLayout.swift index b8803a7c..7de5c9b3 100644 --- a/Sources/OpenSwiftUI/Layout/LayoutFundamentals/Stack/HVStackLayout.swift +++ b/Sources/OpenSwiftUI/Layout/LayoutFundamentals/Stack/HVStackLayout.swift @@ -57,8 +57,8 @@ public struct _VStackLayout { } extension _HStackLayout: _VariadicView_ImplicitRoot { - static var implicitRoot: _HStackLayout { _HStackLayout() } + package static var implicitRoot: _HStackLayout { _HStackLayout() } } extension _VStackLayout: _VariadicView_ImplicitRoot { - static var implicitRoot: _VStackLayout { _VStackLayout() } + package static var implicitRoot: _VStackLayout { _VStackLayout() } } diff --git a/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift b/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift index 06d2b7b4..765c8248 100644 --- a/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift +++ b/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift @@ -13,7 +13,18 @@ internal import OpenGraphShims // MARK: View and ViewModifier extension View { - static func makeDebuggableViewList( + @inline(__always) + nonisolated + package static func makeDebuggableView( + view: _GraphValue, + inputs: _ViewInputs + ) -> _ViewOutputs { + fatalError("TODO") + } + + @inline(__always) + nonisolated + package static func makeDebuggableViewList( view: _GraphValue, inputs: _ViewListInputs ) -> _ViewListOutputs { @@ -67,6 +78,8 @@ extension _ViewDebug { } } + // Fix -werror issue + // @available(*, deprecated, message: "To be refactored into View.makeDebuggableView") @inline(__always) static func makeView( view: _GraphValue, @@ -112,16 +125,21 @@ extension _ViewDebug { public init(rawValue: UInt32) { self.rawValue = rawValue } + + @inlinable + package init(_ property: Property) { + self.init(rawValue: 1 << property.rawValue) + } - public static let type = Properties(rawValue: 1 << Property.type.rawValue) - public static let value = Properties(rawValue: 1 << Property.value.rawValue) - public static let transform = Properties(rawValue: 1 << Property.transform.rawValue) - public static let position = Properties(rawValue: 1 << Property.position.rawValue) - public static let size = Properties(rawValue: 1 << Property.size.rawValue) - public static let environment = Properties(rawValue: 1 << Property.environment.rawValue) - public static let phase = Properties(rawValue: 1 << Property.phase.rawValue) - public static let layoutComputer = Properties(rawValue: 1 << Property.layoutComputer.rawValue) - public static let displayList = Properties(rawValue: 1 << Property.displayList.rawValue) + public static let type = Properties(.type) + public static let value = Properties(.value) + public static let transform = Properties(.transform) + public static let position = Properties(.position) + public static let size = Properties(.size) + public static let environment = Properties(.environment) + public static let phase = Properties(.phase) + public static let layoutComputer = Properties(.layoutComputer) + public static let displayList = Properties(.displayList) public static let all = Properties(rawValue: 0xFFFF_FFFF) } } diff --git a/Sources/OpenSwiftUI/View/Shape/Path/Path.swift b/Sources/OpenSwiftUI/View/Shape/Path/Path.swift index adbffa5b..4eb50cc3 100644 --- a/Sources/OpenSwiftUI/View/Shape/Path/Path.swift +++ b/Sources/OpenSwiftUI/View/Shape/Path/Path.swift @@ -328,8 +328,6 @@ extension Path { private func clearCache() { bounds.cache = nil } - #else - #error("Unimplemented") #endif } } diff --git a/Sources/OpenSwiftUI/View/Transaction/Transaction.swift b/Sources/OpenSwiftUI/View/Transaction/Transaction.swift index 07c1d0a6..fcd2141d 100644 --- a/Sources/OpenSwiftUI/View/Transaction/Transaction.swift +++ b/Sources/OpenSwiftUI/View/Transaction/Transaction.swift @@ -76,3 +76,7 @@ public func withTransaction( return try body() } } + +struct TransactionID { + var id: Int +} diff --git a/Sources/OpenSwiftUI/View/View/AnyView.swift b/Sources/OpenSwiftUI/View/View/AnyView.swift index 2806f8c4..7e0448b6 100644 --- a/Sources/OpenSwiftUI/View/View/AnyView.swift +++ b/Sources/OpenSwiftUI/View/View/AnyView.swift @@ -131,6 +131,7 @@ private final class AnyViewStorage: AnyViewStorageBase { ) -> _ViewOutputs { let child = AnyViewChild(info: container, uniqueId: uniqueId) let graphValue = _GraphValue(Attribute(child)) + // FIXME return _ViewDebug.makeView( view: graphValue, inputs: inputs @@ -141,12 +142,15 @@ private final class AnyViewStorage: AnyViewStorageBase { override func child() -> Value { view as! Value } - // TODO -// override func makeViewList( -// view: _GraphValue, -// inputs: _ViewListInputs -// ) -> _ViewListOutputs { -// } + override func makeViewList( + view: _GraphValue, + inputs: _ViewListInputs + ) -> _ViewListOutputs { + let childList = AnyViewChildList(view: view.value, id: id) + let childListAttribute = Attribute(childList) + childListAttribute.value = self.view + return V.makeDebuggableViewList(view: _GraphValue(childListAttribute), inputs: inputs) + } override func visitContent(_ visitor: inout Vistor) where Vistor : ViewVisitor { visitor.visit(view) @@ -230,8 +234,106 @@ extension AnyViewChild: CustomStringConvertible { var description: String { "\(V.self)" } } -// TODO -private struct AnyViewChildList { +private struct AnyViewChildList: StatefulRule, AsyncAttribute { + typealias Value = V + @Attribute var view: AnyView var id: UniqueID? + + func updateValue() { + guard let storage = view.storage as? AnyViewStorage, + storage.id == id else { + return + } + value = storage.view + return + } +} + +// TODO +private struct AnyViewList: StatefulRule, AsyncAttribute { + @Attribute var view: AnyView + let inputs: _ViewListInputs + let parentSubgraph: OGSubgraph + let allItems: MutableBox<[Unmanaged]> + var lastItem: Item? + + typealias Value = AnyView // FIXME + + func updateValue() { + fatalError("TODO") + } + + final class Item: _ViewList_Subgraph { + let type: Any.Type + #if canImport(Darwin) + let owner: OGAttribute + #endif + @Attribute var list: ViewList + let id: UniqueID + let isUnary: Bool + let allItems: MutableBox<[Unmanaged]> + + #if canImport(Darwin) + init(type: Any.Type, owner: OGAttribute, list: Attribute, id: UniqueID, isUnary: Bool, subgraph: OGSubgraph, allItems: MutableBox<[Unmanaged]>) { + self.type = type + self.owner = owner + _list = list + self.id = id + self.isUnary = isUnary + self.allItems = allItems + super.init(subgraph: subgraph) + allItems.wrappedValue.append(.passUnretained(self)) + } + #else + init(type: Any.Type, list: Attribute, id: UniqueID, isUnary: Bool, subgraph: OGSubgraph, allItems: MutableBox<[Unmanaged]>) { + self.type = type + _list = list + self.id = id + self.isUnary = isUnary + self.allItems = allItems + super.init(subgraph: subgraph) + allItems.wrappedValue.append(.passUnretained(self)) + } + #endif + + override func invalidate() { + for (index, item) in allItems.wrappedValue.enumerated() { + guard item == .passUnretained(self) else { + continue + } + allItems.wrappedValue.remove(at: index) + break + } + } + + func bindID(_ id: inout _ViewList_ID) { + #if canImport(Darwin) + id.bind(explicitID: AnyHashable(self.id), owner: owner, isUnary: isUnary) + #endif + } + } + + // TODO + struct WrappedList { + let base: ViewList + let item: Item + let lastID: UniqueID? + let lastTransaction: TransactionID + } + + // TODO + struct WrappedIDs/*: Sequence*/ { + let base: _ViewList_ID.Views + let item: Item + } + + struct Transform: _ViewList_SublistTransform_Item { + func apply(sublist: inout _ViewList_Sublist) { + item.bindID(&sublist.id) + sublist.elements = item.wrapping(sublist.elements) + } + + var item: Item + } } diff --git a/Sources/OpenSwiftUI/View/View/EmptyView.swift b/Sources/OpenSwiftUI/View/View/EmptyView.swift index c76344c7..17e9bbd5 100644 --- a/Sources/OpenSwiftUI/View/View/EmptyView.swift +++ b/Sources/OpenSwiftUI/View/View/EmptyView.swift @@ -3,9 +3,32 @@ // OpenSwiftUI // // Audited for RELEASE_2021 -// Status: WIP +// Status: Complete +/// A view that doesn't contain any content. +/// +/// You will rarely, if ever, need to create an `EmptyView` directly. Instead, +/// `EmptyView` represents the absence of a view. +/// +/// OpenSwiftUI uses `EmptyView` in situations where an OpenSwiftUI view type defines one +/// or more child views with generic parameters, and allows the child views to +/// be absent. When absent, the child view's type in the generic type parameter +/// is `EmptyView`. +/// +/// The following example creates an indeterminate ``ProgressView`` without +/// a label. The ``ProgressView`` type declares two generic parameters, +/// `Label` and `CurrentValueLabel`, for the types used by its subviews. +/// When both subviews are absent, like they are here, the resulting type is +/// `ProgressView`, as indicated by the example's output: +/// +/// let progressView = ProgressView() +/// print("\(type(of:progressView))") +/// // Prints: ProgressView +/// +@frozen public struct EmptyView: PrimitiveView { + /// Creates an empty view. + @inlinable public init() {} public static func _makeView(view: _GraphValue, inputs: _ViewInputs) -> _ViewOutputs { @@ -13,7 +36,10 @@ public struct EmptyView: PrimitiveView { } public static func _makeViewList(view: _GraphValue, inputs: _ViewListInputs) -> _ViewListOutputs { - fatalError("TODO") + guard inputs.options.contains(.isNonEmptyParent) else { + return _ViewListOutputs.emptyParentViewList(inputs: inputs) + } + return _ViewListOutputs.nonEmptyParentViewList(inputs: inputs) } public static func _viewListCount(inputs: _ViewListCountInputs) -> Int? {