From 3eae8f636a3bd1379fd77b3df1e47cd12b9d52fe Mon Sep 17 00:00:00 2001 From: Nathan Tannar Date: Fri, 27 Sep 2024 11:19:53 -0700 Subject: [PATCH] 1.8.5 --- Sources/Engine/Sources/GraphInputs.swift | 21 +++++--- Sources/Engine/Sources/PropertyList.swift | 50 +++++++++++++++++++ Sources/Engine/Sources/ViewInputs.swift | 32 ++++++------ Sources/EngineCore/Runtime.swift | 10 ++++ .../EngineCoreMultiViewVisitorTests.swift | 12 ++++- .../EngineCoreViewVisitorTests.swift | 9 +--- 6 files changed, 100 insertions(+), 34 deletions(-) diff --git a/Sources/Engine/Sources/GraphInputs.swift b/Sources/Engine/Sources/GraphInputs.swift index a926f87..a93007d 100644 --- a/Sources/Engine/Sources/GraphInputs.swift +++ b/Sources/Engine/Sources/GraphInputs.swift @@ -108,13 +108,15 @@ public struct _ViewInputsBridgeModifier: ViewModifier { extension PropertyList { fileprivate mutating func detach() { + var ptr = elements - var hasMatchedGeometryScope = false + var hasRoot = false + let rootInputSuffix = ".BodyInput>" while let p = ptr { let key = _typeName(p.keyType, qualified: true) - var isMatch = key.hasSuffix(".MatchedGeometryScope") + var isMatch = key.hasSuffix(rootInputSuffix) if isMatch { - hasMatchedGeometryScope = true + hasRoot = true } #if !os(macOS) let branchKey: String @@ -147,10 +149,13 @@ extension PropertyList { let tail = ptr! var last = tail.after tail.after = nil + tail.skip = nil + tail.skipCount = 1 while let p = last?.after { - if !hasMatchedGeometryScope { - let key = _typeName(p.keyType, qualified: true) - if key.hasSuffix(".MatchedGeometryScope") { + if !hasRoot, let after = p.after { + let key = _typeName(after.keyType, qualified: true) + let isMatch = key.hasSuffix(rootInputSuffix) || key.hasSuffix(".ViewListOptionsInput") + if isMatch { break } } @@ -161,6 +166,10 @@ extension PropertyList { let offset = tail.length - ((last?.length ?? 0) + 1) while offset > 0, let p = ptr { p.length -= offset + if let skip = p.skip, skip.length >= p.length { + p.skip = nil + p.skipCount = 1 + } ptr = p.after } if let last { diff --git a/Sources/Engine/Sources/PropertyList.swift b/Sources/Engine/Sources/PropertyList.swift index 7c4a72a..d42ffc2 100644 --- a/Sources/Engine/Sources/PropertyList.swift +++ b/Sources/Engine/Sources/PropertyList.swift @@ -73,6 +73,13 @@ struct PropertyList { } } + var id: Int { + switch self { + case .v1(let ptr): ptr.pointee.fields.id + case .v6(let ptr): ptr.pointee.fields.id + } + } + var keyType: Any.Type { switch self { case .v1(let ptr): ptr.pointee.fields.keyType @@ -109,6 +116,49 @@ struct PropertyList { } } + var skip: ElementPointer? { + get { + switch self { + case .v1: + return nil + case .v6(let ptr): + guard let skip = ptr.pointee.fields.skip else { return nil } + return .v6(skip) + } + } + nonmutating set { + switch self { + case .v1: + break + case .v6(let ptr): + if case .v6(let ptr) = newValue { + ptr.pointee.fields.skip = ptr + } else { + ptr.pointee.fields.skip = nil + } + } + } + } + + var skipCount: UInt32 { + get { + switch self { + case .v1: + return 0 + case .v6(let ptr): + return ptr.pointee.fields.skipCount + } + } + nonmutating set { + switch self { + case .v1: + break + case .v6(let ptr): + ptr.pointee.fields.skipCount = newValue + } + } + } + var length: UInt32 { get { switch self { diff --git a/Sources/Engine/Sources/ViewInputs.swift b/Sources/Engine/Sources/ViewInputs.swift index 56fbcf8..9b9f73a 100644 --- a/Sources/Engine/Sources/ViewInputs.swift +++ b/Sources/Engine/Sources/ViewInputs.swift @@ -90,25 +90,21 @@ public struct _ViewInputsLogModifier: ViewInputsModifier { public static func makeInputs(inputs: inout ViewInputs) { #if DEBUG - let log: String = { - var message = "\n=== ViewInputs ===\n" - dump(inputs.options, to: &message) - var ptr = inputs._graphInputs.customInputs.elements - while let p = ptr { - dump(p, to: &message) - dump(p.fields, to: &message) - if let valueType = swift_getClassGenerics(for: p.metadata.0)?.first { - func project(_: Value.Type) { - let value = p.getValue(Value.self) - dump(value, to: &message) - } - _openExistential(valueType, do: project) - } - ptr = p.after + var message = "" + dump(inputs.options, to: &message) + os_log(.debug, "%@", message) + var ptr = inputs._graphInputs.customInputs.elements + while let p = ptr { + message = "" + dump(p, to: &message) + dump(p.fields, to: &message) + if let valueType = swift_getClassGenerics(for: p.metadata.0)?.first { + dump(valueType, to: &message) } - return message - }() - os_log(.debug, "%@", log) + ptr = p.after + + os_log(.debug, "%@", message) + } #endif } } diff --git a/Sources/EngineCore/Runtime.swift b/Sources/EngineCore/Runtime.swift index 82c3eb1..8a02227 100644 --- a/Sources/EngineCore/Runtime.swift +++ b/Sources/EngineCore/Runtime.swift @@ -4,6 +4,16 @@ import Foundation +@inline(__always) +public func isOpaqueViewAnyView() -> Bool { + // SwiftUI v6 wraps in AnyView + #if DEBUG && canImport(SwiftUICore) + return true + #else + return false + #endif +} + public struct MetadataField { public let key: String public let type: Any.Type diff --git a/Sources/EngineTests/EngineCoreMultiViewVisitorTests.swift b/Sources/EngineTests/EngineCoreMultiViewVisitorTests.swift index fc485e2..646084b 100644 --- a/Sources/EngineTests/EngineCoreMultiViewVisitorTests.swift +++ b/Sources/EngineTests/EngineCoreMultiViewVisitorTests.swift @@ -427,14 +427,22 @@ final class MultiViewVisitorTests: XCTestCase { expectation(Text.self, count: 2) { CustomMultiView() } validation: { ctx, index in - XCTAssertEqual(ctx.id, .init(CustomMultiView.self).appending(TupleView<(Text, Text)>.self).appending(offset: index).appending(Text.self)) + if isOpaqueViewAnyView() { + XCTAssertEqual(ctx.id, .init(CustomMultiView.self).appending(AnyView.self).appending(TupleView<(Text, Text)>.self).appending(offset: index).appending(Text.self)) + } else { + XCTAssertEqual(ctx.id, .init(CustomMultiView.self).appending(TupleView<(Text, Text)>.self).appending(offset: index).appending(Text.self)) + } } expectation(Text.self, count: 2) { Group { CustomMultiView() } } validation: { ctx, index in - XCTAssertEqual(ctx.id, .init(Group.self).appending(CustomMultiView.self).appending(TupleView<(Text, Text)>.self).appending(offset: index).appending(Text.self)) + if isOpaqueViewAnyView() { + XCTAssertEqual(ctx.id, .init(Group.self).appending(CustomMultiView.self).appending(AnyView.self).appending(TupleView<(Text, Text)>.self).appending(offset: index).appending(Text.self)) + } else { + XCTAssertEqual(ctx.id, .init(Group.self).appending(CustomMultiView.self).appending(TupleView<(Text, Text)>.self).appending(offset: index).appending(Text.self)) + } } } diff --git a/Sources/EngineTests/EngineCoreViewVisitorTests.swift b/Sources/EngineTests/EngineCoreViewVisitorTests.swift index f2bc4fb..c89e191 100644 --- a/Sources/EngineTests/EngineCoreViewVisitorTests.swift +++ b/Sources/EngineTests/EngineCoreViewVisitorTests.swift @@ -16,18 +16,11 @@ final class ViewVisitorTests: XCTestCase { } func testOpaqueVisit() throws { - // SwiftUI v6 wraps in AnyView - var isAnyView = false - #if DEBUG - if #available(iOS 18.0, macOS 15.0, tvOS 18.0, watchOS 11.0, visionOS 2.0, *) { - isAnyView = true - } - #endif func makeContent() -> some View { Text("Hello, World") } let content = makeContent() - if isAnyView { + if isOpaqueViewAnyView() { var visitor = TestVisitor() content.visit(visitor: &visitor) XCTAssert(visitor.output)