diff --git a/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingViewBase.swift b/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingViewBase.swift index 20fa036a7..4c1842a35 100644 --- a/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingViewBase.swift +++ b/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingViewBase.swift @@ -915,28 +915,23 @@ final package class DisplayLink: NSObject { if nextThread != currentThread, let oldLink = self.link { if nextThread == .async { Self.asyncPending = true - if Self.asyncRunloop == nil { - let threadName = "org.OpenSwiftUIProject.OpenSwiftUI.AsyncRenderer" - while true { - if Self.asyncThread == nil { // FIXME: - let thread = Thread( - target: DisplayLink.self, - selector: #selector(DisplayLink.asyncThread(with:)), - object: nil - ) - thread.qualityOfService = .userInteractive - thread.name = threadName - guard _NSThreadStart(thread) else { - cancelAsyncRendering() - break - } - Self.asyncThread = thread - } - Update.wait() - guard Self.asyncRunloop == nil else { + while Self.asyncRunloop == nil { + if Self.asyncThread == nil { + let thread = Thread( + target: DisplayLink.self, + selector: #selector(DisplayLink.asyncThread(with:)), + object: nil + ) + thread.qualityOfService = .userInteractive + thread.name = "org.OpenSwiftUIProject.OpenSwiftUI.AsyncRenderer" + guard _NSThreadStart(thread) else { + cancelAsyncRendering() break } + Self.asyncThread = thread } + Update.wait() + Self.asyncPending = true } } if nextThread != currentThread { diff --git a/Sources/OpenSwiftUICore/Data/DynamicProperty/UnsafeHeterogeneousBuffer.swift b/Sources/OpenSwiftUICore/Data/DynamicProperty/UnsafeHeterogeneousBuffer.swift index fba3f6e7f..f636950fd 100644 --- a/Sources/OpenSwiftUICore/Data/DynamicProperty/UnsafeHeterogeneousBuffer.swift +++ b/Sources/OpenSwiftUICore/Data/DynamicProperty/UnsafeHeterogeneousBuffer.swift @@ -2,16 +2,17 @@ // UnsafeHeterogeneousBuffer.swift // OpenSwiftUICore // -// Audited for 6.0.87 +// Audited for 6.5.4 // Status: Complete // ID: 568350FE259575B5E1AAA52AD722AAAC (SwiftUICore) package struct UnsafeHeterogeneousBuffer: Collection { - var buf: UnsafeMutableRawPointer! - var available: Int32 - var _count: Int32 + private var buf: UnsafeMutableRawPointer! + private var available: Int32 + private var _count: Int32 package typealias VTable = _UnsafeHeterogeneousBuffer_VTable + package typealias Element = _UnsafeHeterogeneousBuffer_Element package struct Index: Equatable, Comparable { @@ -34,11 +35,13 @@ package struct UnsafeHeterogeneousBuffer: Collection { } package var count: Int { Int(_count) } + package var isEmpty: Bool { _count == 0 } package var startIndex: Index { Index(index: 0, offset: 0) } + package var endIndex: Index { Index(index: _count, offset: 0) } @@ -113,7 +116,13 @@ package struct UnsafeHeterogeneousBuffer: Collection { } package func formIndex(after index: inout Index) { - index = self.index(after: index) + let item = self[index].item.pointee + index.index &+= 1 + if index.index == _count { + index.offset = 0 + } else { + index.offset &+= item.size + } } package func index(after index: Index) -> Index { @@ -137,14 +146,13 @@ package struct UnsafeHeterogeneousBuffer: Collection { @discardableResult package mutating func append(_ value: T, vtable: VTable.Type) -> Index { + defer { _count += 1 } let bytes = (MemoryLayout.size + MemoryLayout.size + 0xf) & ~0xf let pointer = allocate(bytes) let element = _UnsafeHeterogeneousBuffer_Element(item: pointer.assumingMemoryBound(to: Item.self)) element.item.initialize(to: Item(vtable: vtable, size: Int32(bytes), flags: 0)) element.body(as: T.self).initialize(to: value) - let index = Index(index: _count, offset: Int32(pointer - buf)) - _count += 1 - return index + return Index(index: _count, offset: Int32(pointer - buf)) } } diff --git a/Sources/OpenSwiftUICore/Graph/GraphHost.swift b/Sources/OpenSwiftUICore/Graph/GraphHost.swift index eae54ab0a..142658187 100644 --- a/Sources/OpenSwiftUICore/Graph/GraphHost.swift +++ b/Sources/OpenSwiftUICore/Graph/GraphHost.swift @@ -496,17 +496,17 @@ extension GraphHost { } package final func finishTransactionUpdate(in subgraph: Subgraph, postUpdate: (_ again: Bool) -> Void = { _ in }) { - var count = 0 + var counter = 0 repeat { - let currentContinuations = continuations + let oldContinuations = continuations continuations = [] - for currentContinuation in currentContinuations { - currentContinuation() + for continuation in oldContinuations { + continuation() } - count &+= 1 + counter &+= 1 subgraph.update(flags: .transactional) postUpdate(!continuations.isEmpty) - } while count != 8 && !continuations.isEmpty + } while counter != 8 && !continuations.isEmpty inTransaction = false } } diff --git a/Sources/OpenSwiftUICore/Render/DisplayList/DisplayListViewRenderer.swift b/Sources/OpenSwiftUICore/Render/DisplayList/DisplayListViewRenderer.swift index 8970cf90b..41e0c0912 100644 --- a/Sources/OpenSwiftUICore/Render/DisplayList/DisplayListViewRenderer.swift +++ b/Sources/OpenSwiftUICore/Render/DisplayList/DisplayListViewRenderer.swift @@ -120,6 +120,16 @@ extension DisplayList { maxVersion: DisplayList.Version, environment: DisplayList.ViewRenderer.Environment ) -> Time + + @_silgen_name("OpenSwiftUITestStub_DisplayListViewRendererRenderAsync") + package func swiftUI_renderAsync( + to list: DisplayList, + time: Time, + nextTime: Time, + targetTimestamp: Time?, + version: DisplayList.Version, + maxVersion: DisplayList.Version + ) -> Time? #endif package func render( @@ -138,7 +148,14 @@ extension DisplayList { return time + maxInterval } - package func renderAsync(to list: DisplayList, time: Time, nextTime: Time, targetTimestamp: Time?, version: DisplayList.Version, maxVersion: DisplayList.Version) -> Time? { + package func renderAsync( + to list: DisplayList, + time: Time, + nextTime: Time, + targetTimestamp: Time?, + version: DisplayList.Version, + maxVersion: DisplayList.Version + ) -> Time? { guard !configChanged, let renderer else { return nil } diff --git a/Sources/OpenSwiftUICore/Util/AttributeGraphAdditions.swift b/Sources/OpenSwiftUICore/Util/AttributeGraphAdditions.swift index 23c1fb71f..19c0e32c9 100644 --- a/Sources/OpenSwiftUICore/Util/AttributeGraphAdditions.swift +++ b/Sources/OpenSwiftUICore/Util/AttributeGraphAdditions.swift @@ -171,17 +171,21 @@ extension Attribute { } package func allowsAsyncUpdate() -> Bool { - _openSwiftUIUnimplementedFailure() + !valueState.contains([.dirty, .mainThread]) } } extension WeakAttribute { package var uncheckedIdentifier: Attribute { - get { _openSwiftUIUnimplementedFailure() } + #if OPENSWIFTUI_ANY_ATTRIBUTE_FIX + _openSwiftUIUnimplementedFailure() + #else + Attribute(identifier: AnyWeakAttribute(self)._details.identifier) + #endif } package func allowsAsyncUpdate() -> Bool { - _openSwiftUIUnimplementedFailure() + attribute.map { $0.allowsAsyncUpdate() } ?? false } } diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift b/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift index e29d0548a..4c3b476e4 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift @@ -375,6 +375,8 @@ extension ViewGraph { } } +// MARK: - ViewGraph + Update [6.5.4] + extension ViewGraph { package var updateRequiredMainThread: Bool { graph.mainUpdates != mainUpdates @@ -384,11 +386,31 @@ extension ViewGraph { beginNextUpdate(at: time) updateOutputs(async: false) } - + package func updateOutputsAsync(at time: Time) -> (list: DisplayList, version: DisplayList.Version)? { beginNextUpdate(at: time) - _openSwiftUIUnimplementedWarning() - return nil + guard _rootDisplayList.allowsAsyncUpdate(), + hostPreferenceValues.allowsAsyncUpdate(), + sizeThatFitsObservers.isEmpty || _rootLayoutComputer.allowsAsyncUpdate() + else { + return nil + } + for feature in features { + guard let allowsAsyncUpdate = feature.allowsAsyncUpdate(graph: self) else { + feature.skipsAsyncUpdate = true + continue + } + feature.skipsAsyncUpdate = false + guard allowsAsyncUpdate else { + return nil + } + } + var result: (DisplayList, DisplayList.Version)? + graph.withMainThreadHandler(Update.syncMain) { + updateOutputs(async: true) + result = displayList() + } + return result } package func displayList() -> (DisplayList, DisplayList.Version) { @@ -400,68 +422,59 @@ extension ViewGraph { data.updateSeed &+= 1 mainUpdates = graph.mainUpdates } - - // FIXME - private func updateOutputs(async: Bool) { - instantiateIfNeeded() - data.transactionSeed &+= 1 - // let oldCachedSizeThatFits = cachedSizeThatFits - + private func updateOutputs(async: Bool) { var preferencesChanged = false - var observedSizeThatFitsChanged = false - var updatedOutputs: Outputs = [] - - var counter1 = 0 + var featuresChanged = false + var sizeThatFitsChanged = false + var counter = 0 repeat { - counter1 &+= 1 - inTransaction = true - var counter2 = 0 - repeat { - let conts = continuations - continuations = [] - for continuation in conts { - continuation() + counter &+= 1 + instantiateIfNeeded() + startTransactionUpdate() + finishTransactionUpdate(in: globalSubgraph) + if updatePreferences() { + preferencesChanged = true + } + if sizeThatFitsObservers.needsUpdate(graph: self) { + sizeThatFitsChanged = true + } + for feature in features { + guard !async || !feature.skipsAsyncUpdate else { + continue } - counter2 &+= 1 - data.globalSubgraph.update(flags: .transactional) - } while (continuations.count != 0 && counter2 != 8) - inTransaction = false - preferencesChanged = preferencesChanged || updatePreferences() - observedSizeThatFitsChanged = observedSizeThatFitsChanged || updateObservedSizeThatFits() - updatedOutputs.formUnion(updateRequestedOutputs()) - } while (needsTransaction && counter1 != 8) -// guard preferencesChanged || observedSizeThatFitsChanged || !updatedOutputs.isEmpty || needsFocusUpdate else { -// return -// } -// if Thread.isMainThread { -// if preferencesChanged { -// delegate?.preferencesDidChange() -// } -// if observedSizeThatFitsChanged { -// sizeThatFitsObserver?.callback(oldCachedSizeThatFits, self.cachedSizeThatFits) -// } -// if !requestedOutputs.isEmpty { -//// delegate?.outputsDidChange(outputs: updatedOutputs) -// } -// if needsFocusUpdate { -// needsFocusUpdate = false -//// delegate?.focusDidChange() -// } -// } else { -// _openSwiftUIUnimplementedFailure() -// } -// mainUpdates &-= 1 - } - - private func updateObservedSizeThatFits() -> Bool { - // TODO - return false - } - - private func updateRequestedOutputs() -> Outputs { - // TODO - return [] + if feature.needsUpdate { + featuresChanged = true + } else if feature.needsUpdate(graph: self) { + feature.needsUpdate = true + featuresChanged = true + } + } + } while (needsTransaction && counter != 8) + guard preferencesChanged || featuresChanged || sizeThatFitsChanged else { + return + } + Update.syncMain { + if preferencesChanged { + delegate?.preferencesDidChange() + preferenceBridge?.updateHostValues(data.$hostPreferenceKeys) + } + if featuresChanged { + for feature in features { + guard !async || !feature.skipsAsyncUpdate else { + continue + } + if feature.needsUpdate { + feature.update(graph: self) + feature.needsUpdate = false + } + } + } + if sizeThatFitsChanged { + sizeThatFitsObservers.notify() + } + } + mainUpdates &-= 1 } } diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewGraphFeature.swift b/Sources/OpenSwiftUICore/View/Graph/ViewGraphFeature.swift index 4dd09f1d3..ee2805280 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewGraphFeature.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewGraphFeature.swift @@ -2,7 +2,7 @@ // ViewGraphFeature.swift // OpenSwiftUICore // -// Audited for 6.0.87 +// Audited for 6.5.4 // Status: Complete // ID: 8A0FC0E1EA10CEEE185C2315B618A95C (SwiftUICore) @@ -28,15 +28,15 @@ extension ViewGraphFeature { struct ViewGraphFeatureBuffer: Collection { var contents: UnsafeHeterogeneousBuffer - + @discardableResult mutating func append(_ feature: Feature) -> UnsafeHeterogeneousBuffer.Index where Feature: ViewGraphFeature { contents.append(feature, vtable: _VTable.self) } - + subscript(_ type: Feature.Type) -> UnsafeMutablePointer? where Feature: ViewGraphFeature { guard !contents.isEmpty else { return nil } - for element in contents { + for element in contents { guard element.hasType(type) else { continue } @@ -44,110 +44,144 @@ struct ViewGraphFeatureBuffer: Collection { } return nil } - + typealias Index = UnsafeHeterogeneousBuffer.Index - + struct Element: ViewGraphFeature { var base: UnsafeHeterogeneousBuffer.Element - + private var vtable: VTable.Type { base.vtable(as: VTable.self) } - + func modifyViewInputs(inputs: inout _ViewInputs, graph: ViewGraph) { vtable.modifyViewInputs(elt: base, inputs: &inputs, graph: graph) } - + func modifyViewOutputs(outputs: inout _ViewOutputs, inputs: _ViewInputs, graph: ViewGraph) { vtable.modifyViewOutputs(elt: base, outputs: &outputs, inputs: inputs, graph: graph) } - + func uninstantiate(graph: ViewGraph) { vtable.uninstantiate(elt: base, graph: graph) } - + func isHiddenForReuseDidChange(graph: ViewGraph) { vtable.isHiddenForReuseDidChange(elt: base, graph: graph) } - + func allowsAsyncUpdate(graph: ViewGraph) -> Bool? { vtable.allowsAsyncUpdate(elt: base, graph: graph) } - + func needsUpdate(graph: ViewGraph) -> Bool { vtable.needsUpdate(elt: base, graph: graph) } - + func update(graph: ViewGraph) { vtable.update(elt: base, graph: graph) } + + var needsUpdate: Bool { + get { base.flags.needsUpdate } + nonmutating set { base.flags.needsUpdate = newValue } + } + + var skipsAsyncUpdate: Bool { + get { base.flags.skipsAsyncUpdate } + nonmutating set { base.flags.skipsAsyncUpdate = newValue } + } } var startIndex: UnsafeHeterogeneousBuffer.Index { contents.startIndex } - + var endIndex: UnsafeHeterogeneousBuffer.Index { contents.endIndex } - + var isEmpty: Bool { contents.isEmpty } - + subscript(position: UnsafeHeterogeneousBuffer.Index) -> Element { _read { yield Element(base: contents[position]) } } - + func index(after i: UnsafeHeterogeneousBuffer.Index) -> UnsafeHeterogeneousBuffer.Index { contents.index(after: i) } - + private class VTable: _UnsafeHeterogeneousBuffer_VTable { class func modifyViewInputs(elt: UnsafeHeterogeneousBuffer.Element, inputs: inout _ViewInputs, graph: ViewGraph) {} class func modifyViewOutputs(elt: UnsafeHeterogeneousBuffer.Element, outputs: inout _ViewOutputs, inputs: _ViewInputs, graph: ViewGraph) {} class func uninstantiate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) {} class func isHiddenForReuseDidChange(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) {} - class func needsUpdate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) -> Bool { false } class func allowsAsyncUpdate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) -> Bool? { nil } + class func needsUpdate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) -> Bool { false } class func update(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) {} } - + private final class _VTable: VTable where Feature: ViewGraphFeature { override class func hasType(_ type: T.Type) -> Bool { Feature.self == T.self } - + override class func moveInitialize(elt: UnsafeHeterogeneousBuffer.Element, from: _UnsafeHeterogeneousBuffer_Element) { let dest = elt.body(as: Feature.self) let source = from.body(as: Feature.self) dest.initialize(to: source.move()) } - + override class func deinitialize(elt: UnsafeHeterogeneousBuffer.Element) { elt.body(as: Feature.self).deinitialize(count: 1) } - + override class func modifyViewInputs(elt: UnsafeHeterogeneousBuffer.Element, inputs: inout _ViewInputs, graph: ViewGraph) { elt.body(as: Feature.self).pointee.modifyViewInputs(inputs: &inputs, graph: graph) } - + override class func modifyViewOutputs(elt: UnsafeHeterogeneousBuffer.Element, outputs: inout _ViewOutputs, inputs: _ViewInputs, graph: ViewGraph) { elt.body(as: Feature.self).pointee.modifyViewOutputs(outputs: &outputs, inputs: inputs, graph: graph) } - + override class func uninstantiate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) { elt.body(as: Feature.self).pointee.uninstantiate(graph: graph) } - + override class func isHiddenForReuseDidChange(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) { elt.body(as: Feature.self).pointee.isHiddenForReuseDidChange(graph: graph) } - - override class func needsUpdate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) -> Bool { - elt.body(as: Feature.self).pointee.needsUpdate(graph: graph) - } - + override class func allowsAsyncUpdate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) -> Bool? { elt.body(as: Feature.self).pointee.allowsAsyncUpdate(graph: graph) } - + + override class func needsUpdate(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) -> Bool { + elt.body(as: Feature.self).pointee.needsUpdate(graph: graph) + } + override class func update(elt: UnsafeHeterogeneousBuffer.Element, graph: ViewGraph) { elt.body(as: Feature.self).pointee.update(graph: graph) } } } + +extension UInt32 { + fileprivate var needsUpdate: Bool { + get { self & 0x1 != 0 } + set { + if newValue { + self = self | 0x1 + } else { + self = self & ~0x1 + } + } + } + + fileprivate var skipsAsyncUpdate: Bool { + get { self & 0x2 != 0 } + set { + if newValue { + self = self | 0x2 + } else { + self = self & ~0x2 + } + } + } +} diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewGraphGeometryObservers.swift b/Sources/OpenSwiftUICore/View/Graph/ViewGraphGeometryObservers.swift index a43b483eb..af9192f4f 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewGraphGeometryObservers.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewGraphGeometryObservers.swift @@ -39,6 +39,11 @@ package struct ViewGraphGeometryObservers where Measurer: ViewGraphGeo store = [:] } + @inline(__always) + var isEmpty: Bool { + store.isEmpty + } + /// Checks if any observer needs an update based on the current view graph state. /// /// This method measures sizes for all registered proposals and transitions diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift b/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift index d4b4fb963..285c525e9 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewRendererHost.swift @@ -337,14 +337,26 @@ extension ViewRendererHost { } if asynchronously { // TODO: CustomEventTrace - if let renderedTime = renderer.renderAsync( + #if canImport(SwiftUI, _underlyingVersion: 6.0.87) && _OPENSWIFTUI_SWIFTUI_RENDER + let renderedTime = renderer.swiftUI_renderAsync( to: list, time: time, nextTime: nextTime, targetTimestamp: targetTimestamp, version: version, maxVersion: maxVersion - ) { + ) + #else + let renderedTime = renderer.renderAsync( + to: list, + time: time, + nextTime: nextTime, + targetTimestamp: targetTimestamp, + version: version, + maxVersion: maxVersion + ) + #endif + if let renderedTime { return renderedTime } else { var renderedTime = nextTime diff --git a/Sources/OpenSwiftUISymbolDualTestsSupport/Render/DisplayList/DisplayListViewRenderer+TestStub.c b/Sources/OpenSwiftUISymbolDualTestsSupport/Render/DisplayList/DisplayListViewRenderer+TestStub.c index 75fb7b174..fff430155 100644 --- a/Sources/OpenSwiftUISymbolDualTestsSupport/Render/DisplayList/DisplayListViewRenderer+TestStub.c +++ b/Sources/OpenSwiftUISymbolDualTestsSupport/Render/DisplayList/DisplayListViewRenderer+TestStub.c @@ -10,4 +10,6 @@ DEFINE_SL_STUB_SLF(OpenSwiftUITestStub_DisplayListViewRendererRenderRootView, SwiftUI, $s7SwiftUI11DisplayListVAAE12ViewRendererC6render04rootE04from4time8nextTime7version10maxVersion11environmentAA0L0VyXl_Ac2oC0O0VAqE11EnvironmentVtF); +DEFINE_SL_STUB_SLF(OpenSwiftUITestStub_DisplayListViewRendererRenderAsync, SwiftUI, $s7SwiftUI11DisplayListVAAE12ViewRendererC11renderAsync2to4time8nextTime15targetTimestamp7version10maxVersionAA0L0VSgAC_A2noC0Q0VAQtF); + #endif diff --git a/Tests/OpenSwiftUICoreTests/Data/DynamicProperty/UnsafeHeterogeneousBufferTests.swift b/Tests/OpenSwiftUICoreTests/Data/DynamicProperty/UnsafeHeterogeneousBufferTests.swift index 0eed7df9e..5c8cf0a6b 100644 --- a/Tests/OpenSwiftUICoreTests/Data/DynamicProperty/UnsafeHeterogeneousBufferTests.swift +++ b/Tests/OpenSwiftUICoreTests/Data/DynamicProperty/UnsafeHeterogeneousBufferTests.swift @@ -2,8 +2,11 @@ // UnsafeHeterogeneousBufferTests.swift // OpenSwiftUICoreTests -@_spi(ForOpenSwiftUIOnly) import OpenSwiftUICore -@testable import OpenSwiftUICore +#if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS +@_private(sourceFile: "UnsafeHeterogeneousBuffer.swift") +#endif +@_spi(ForOpenSwiftUIOnly) +import OpenSwiftUICore import Testing struct UnsafeHeterogeneousBufferTests { @@ -33,9 +36,11 @@ struct UnsafeHeterogeneousBufferTests { let index = buffer.append(UInt32(1), vtable: VTable.self) #expect(buffer.isEmpty == false) #expect(index == buffer.index(atOffset: 0)) + #if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS #expect(index.index == 0) #expect(index.offset == 0) #expect(buffer.available == 32) + #endif #expect(buffer.count == 1) let element = buffer[index] #expect(element.body(as: UInt32.self).pointee == 1) @@ -45,9 +50,11 @@ struct UnsafeHeterogeneousBufferTests { let index = buffer.append(Int(-1), vtable: VTable.self) #expect(buffer.isEmpty == false) #expect(index == buffer.index(atOffset: 1)) + #if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS #expect(index.index == 1) #expect(index.offset == 32) #expect(buffer.available == 0) + #endif #expect(buffer.count == 2) let element = buffer[index] #expect(element.body(as: Int.self).pointee == -1) @@ -57,9 +64,11 @@ struct UnsafeHeterogeneousBufferTests { let index = buffer.append(Double.infinity, vtable: VTable.self) #expect(buffer.isEmpty == false) #expect(index == buffer.index(atOffset: 2)) + #if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS #expect(index.index == 2) #expect(index.offset == 64) #expect(buffer.available == 32) + #endif #expect(buffer.count == 3) let element = buffer[index] #expect(element.body(as: Double.self).pointee == Double.infinity) diff --git a/Tests/OpenSwiftUISymbolDualTests/Data/DynamicProperty/UnsafeHeterogeneousBufferDualTests.swift b/Tests/OpenSwiftUISymbolDualTests/Data/DynamicProperty/UnsafeHeterogeneousBufferDualTests.swift index faa8a96a4..eee007575 100644 --- a/Tests/OpenSwiftUISymbolDualTests/Data/DynamicProperty/UnsafeHeterogeneousBufferDualTests.swift +++ b/Tests/OpenSwiftUISymbolDualTests/Data/DynamicProperty/UnsafeHeterogeneousBufferDualTests.swift @@ -3,8 +3,10 @@ // OpenSwiftUISymbolDualTests #if canImport(SwiftUI, _underlyingVersion: 6.5.4) +#if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS +@_private(sourceFile: "UnsafeHeterogeneousBuffer.swift") +#endif @_spi(ForOpenSwiftUIOnly) -@testable import OpenSwiftUICore import OpenSwiftUITestsSupport import Testing @@ -60,9 +62,11 @@ struct UnsafeHeterogeneousBufferDualTests { let index = buffer.swiftUI_append(UInt32(1), vtable: VTable.self) #expect(buffer.swiftUI_isEmpty == false) #expect(index == buffer.index(atOffset: 0)) + #if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS #expect(index.index == 0) #expect(index.offset == 0) #expect(buffer.available == 32) + #endif #expect(buffer.count == 1) let element = buffer[swiftUI: index] #expect(element.body(as: UInt32.self).pointee == 1) @@ -72,9 +76,11 @@ struct UnsafeHeterogeneousBufferDualTests { let index = buffer.swiftUI_append(Int(-1), vtable: VTable.self) #expect(buffer.swiftUI_isEmpty == false) #expect(index == buffer.index(atOffset: 1)) + #if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS #expect(index.index == 1) #expect(index.offset == 32) #expect(buffer.available == 0) + #endif #expect(buffer.count == 2) let element = buffer[swiftUI: index] #expect(element.body(as: Int.self).pointee == -1) @@ -84,9 +90,11 @@ struct UnsafeHeterogeneousBufferDualTests { let index = buffer.swiftUI_append(Double.infinity, vtable: VTable.self) #expect(buffer.swiftUI_isEmpty == false) #expect(index == buffer.index(atOffset: 2)) + #if OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS #expect(index.index == 2) #expect(index.offset == 64) #expect(buffer.available == 32) + #endif #expect(buffer.count == 3) let element = buffer[swiftUI: index] #expect(element.body(as: Double.self).pointee == Double.infinity)