From 08f91acd171320aa0e4ab0160d9add9f297d9497 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 8 Feb 2026 18:19:02 +0800 Subject: [PATCH] Update interpose to fix ShapeLayerHelper update issue --- Example/Example.xcodeproj/project.pbxproj | 16 ++--- .../Shape/ShapeUITests.swift | 6 +- Example/SharedExample/interpose.c | 58 +++++++++++++++++++ Example/SharedExample/kdebug_interpose.c | 31 ---------- .../OpenSwiftUICore/Graphic/Color/Paint.swift | 2 +- 5 files changed, 69 insertions(+), 44 deletions(-) create mode 100644 Example/SharedExample/interpose.c delete mode 100644 Example/SharedExample/kdebug_interpose.c diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 5f32cf2db..870786d34 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -66,13 +66,6 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - 27240CFE2E8FFBC900E9DABD /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - kdebug_interpose.c, - ); - target = 27CD0B482AFC8D37003665EB /* Example */; - }; 275751CC2DEE136C003E467C /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( @@ -93,6 +86,13 @@ }; target = 27D49DF72BA604FB00F6E2E2 /* HostingExample */; }; + 275C29E52F389AE8008676C3 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + interpose.c, + ); + target = 275751E22DEE1441003E467C /* TestingHost */; + }; /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ @@ -102,7 +102,7 @@ 275751F62DEE1456003E467C /* OpenSwiftUIUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = OpenSwiftUIUITests; sourceTree = ""; }; 279FEC572DF450D200320390 /* ReferenceImages */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ReferenceImages; sourceTree = ""; }; 27E6C4F62D2842D80010502F /* Configurations */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); name = Configurations; path = ../Configurations; sourceTree = ""; }; - 27FFF0422E08850C0060A4DA /* SharedExample */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (27240CFE2E8FFBC900E9DABD /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SharedExample; sourceTree = ""; }; + 27FFF0422E08850C0060A4DA /* SharedExample */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (275C29E52F389AE8008676C3 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SharedExample; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ diff --git a/Example/OpenSwiftUIUITests/Shape/ShapeUITests.swift b/Example/OpenSwiftUIUITests/Shape/ShapeUITests.swift index d128d45cf..c46597003 100644 --- a/Example/OpenSwiftUIUITests/Shape/ShapeUITests.swift +++ b/Example/OpenSwiftUIUITests/Shape/ShapeUITests.swift @@ -29,8 +29,7 @@ struct ShapeUITests { .frame(width: 100, height: 100, alignment: .center) } } - // FIXME - openSwiftUIAssertSnapshot(of: ContentView(), perceptualPrecision: 0.8) + openSwiftUIAssertSnapshot(of: ContentView()) } @Test @@ -42,7 +41,6 @@ struct ShapeUITests { .frame(width: 100, height: 100, alignment: .center) } } - // FIXME - openSwiftUIAssertSnapshot(of: ContentView(), perceptualPrecision: 0.8) + openSwiftUIAssertSnapshot(of: ContentView()) } } diff --git a/Example/SharedExample/interpose.c b/Example/SharedExample/interpose.c new file mode 100644 index 000000000..112c9791f --- /dev/null +++ b/Example/SharedExample/interpose.c @@ -0,0 +1,58 @@ +// +// interpose.c +// SharedExample +// +// Created by Kyle on 2025/10/3. +// + +#include +#include +#include +#include + +// Forward declare the original +extern bool kdebug_is_enabled(uint32_t debugid); + +// Our replacement +static bool my_kdebug_is_enabled(uint32_t debugid) { + return true; +} + +extern const void *$s15OpenSwiftUICore5ColorV8ResolvedVN; + +const void *_OpenSwiftUI_ColorResolvedNTD(void) { + return &$s15OpenSwiftUICore5ColorV8ResolvedVN; +} + +extern bool swift_dynamicCast(void *dest, void *src, + const void *srcType, + const void *targetType, + uint64_t flags); + +static bool my_swift_dynamicCast(void *dest, void *src, const void *srcType, const void *targetType, uint64_t flags) { + CFStringRef target_description = AGTypeDescription((AGTypeID)targetType); + // Check if target_description contains "Color.Resolved" + if (target_description != NULL) { + CFRange range = CFStringFind(target_description, CFSTR("Color.Resolved"), 0); + if (range.location != kCFNotFound) { + // First try the original cast, if it fails try with OpenSwiftUI's Color.Resolved + return swift_dynamicCast(dest, src, srcType, targetType, flags) || + swift_dynamicCast(dest, src, srcType, _OpenSwiftUI_ColorResolvedNTD(), flags); + } + } + return swift_dynamicCast(dest, src, srcType, targetType, flags); +} + +// Interpose using Mach-O section +typedef struct interpose_s { + const void *replacement; + const void *original; +} interpose_t; + +__attribute__((used)) static const interpose_t interposers[] + __attribute__((section("__DATA, __interpose"))) = { + // Interpose kdebug_is_enabled to always return true to perform Signpost testing with Instruments + { (const void *)my_kdebug_is_enabled, (const void *)kdebug_is_enabled }, + // Interpose swift_dynamicCast to handle casts to SwiftUI's internal Color.Resolved type to fix SwiftUI.ShapeLayerHelper visit check for Shape.fill API + { (const void *)my_swift_dynamicCast, (const void *)swift_dynamicCast }, +}; diff --git a/Example/SharedExample/kdebug_interpose.c b/Example/SharedExample/kdebug_interpose.c deleted file mode 100644 index 01f514e0e..000000000 --- a/Example/SharedExample/kdebug_interpose.c +++ /dev/null @@ -1,31 +0,0 @@ -// -// kdebug_interpose.c -// SharedExample -// -// Created by Kyle on 2025/10/3. -// - -// Interpose kdebug_is_enabled to always return true to perform Signpost testing with Instruments - -#include -#include -#include - -// Forward declare the original -extern bool kdebug_is_enabled(uint32_t debugid); - -// Our replacement -static bool my_kdebug_is_enabled(uint32_t debugid) { - return true; -} - -// Interpose using Mach-O section -typedef struct interpose_s { - const void *replacement; - const void *original; -} interpose_t; - -__attribute__((used)) static const interpose_t interposers[] - __attribute__((section("__DATA, __interpose"))) = { - { (const void *)my_kdebug_is_enabled, (const void *)kdebug_is_enabled }, -}; diff --git a/Sources/OpenSwiftUICore/Graphic/Color/Paint.swift b/Sources/OpenSwiftUICore/Graphic/Color/Paint.swift index aba367107..41f18500a 100644 --- a/Sources/OpenSwiftUICore/Graphic/Color/Paint.swift +++ b/Sources/OpenSwiftUICore/Graphic/Color/Paint.swift @@ -90,7 +90,7 @@ final package class _AnyResolvedPaint

: AnyResolvedPaint where P: ResolvedPain return paint == other.paint } - override package func visit(_ visitor: inout V) where V : ResolvedPaintVisitor { + override package func visit(_ visitor: inout V) where V: ResolvedPaintVisitor { visitor.visitPaint(paint) }