From 00e203b8f6018920da5b5bf052665d7da3201e86 Mon Sep 17 00:00:00 2001 From: PJ Date: Sun, 7 Jun 2026 17:01:48 +0530 Subject: [PATCH] fix(companion): capture snapshots on the main thread inside the catch bridge --- companion/Sources/Snapshot.swift | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/companion/Sources/Snapshot.swift b/companion/Sources/Snapshot.swift index f8fbf9c..d70d06a 100644 --- a/companion/Sources/Snapshot.swift +++ b/companion/Sources/Snapshot.swift @@ -4,14 +4,29 @@ import XCTest enum Snapshot { // Produces the flat element array for the given bundle identifier. Falls back // to springboard if the requested app is not running or its snapshot throws. + // Snapshot resolution can demand the test's execution context, which lives + // on the main thread, and a framework assertion raises an exception that + // would kill the server; so the capture runs on main inside the catch + // bridge, and an assertion yields an empty dump, which upstream treats as + // collapsed and retries. static func elements(bundleIdentifier: String) -> [[String: Any]] { - if let captured = try? capture(bundleIdentifier: bundleIdentifier) { - return captured + var result: [[String: Any]] = [] + var caughtError: NSError? + let work = { + _ = CompanionRunCatching({ + if let captured = try? capture(bundleIdentifier: bundleIdentifier) { + result = captured + } else if let fallback = try? capture(bundleIdentifier: "com.apple.springboard") { + result = fallback + } + }, &caughtError) } - if let fallback = try? capture(bundleIdentifier: "com.apple.springboard") { - return fallback + if Thread.isMainThread { + work() + } else { + DispatchQueue.main.sync(execute: work) } - return [] + return result } private static func capture(bundleIdentifier: String) throws -> [[String: Any]] {