@@ -271,7 +271,21 @@ struct TabTableContext: Equatable {
271271}
272272
273273struct TabQueryContent : Equatable {
274- var query : String = " "
274+ /// Holds the query text behind a reference. SwiftUI's attribute-graph diff compares a value by walking its memory
275+ /// layout, so a stored `String` field made it normalize the whole multi-megabyte query (NFC) on every view update.
276+ /// Storing the text in a class makes that walk compare an 8-byte pointer instead. Value semantics are preserved
277+ /// because the setter replaces the box.
278+ private final class QueryStorage : Sendable {
279+ let text : String
280+ init ( _ text: String ) { self . text = text }
281+ }
282+
283+ private var queryStorage : QueryStorage
284+
285+ var query : String {
286+ get { queryStorage. text }
287+ set { queryStorage = QueryStorage ( newValue) }
288+ }
275289 var queryParameters : [ QueryParameter ] = [ ]
276290 var isParameterPanelVisible : Bool = false
277291 var sourceFileURL : URL ?
@@ -281,6 +295,24 @@ struct TabQueryContent: Equatable {
281295
282296 static let maxPersistableQuerySize = 500_000
283297
298+ init (
299+ query: String = " " ,
300+ queryParameters: [ QueryParameter ] = [ ] ,
301+ isParameterPanelVisible: Bool = false ,
302+ sourceFileURL: URL ? = nil ,
303+ savedFileContent: String ? = nil ,
304+ loadMtime: Date ? = nil ,
305+ externalModificationDetected: Bool = false
306+ ) {
307+ self . queryStorage = QueryStorage ( query)
308+ self . queryParameters = queryParameters
309+ self . isParameterPanelVisible = isParameterPanelVisible
310+ self . sourceFileURL = sourceFileURL
311+ self . savedFileContent = savedFileContent
312+ self . loadMtime = loadMtime
313+ self . externalModificationDetected = externalModificationDetected
314+ }
315+
284316 var isFileDirty : Bool {
285317 guard sourceFileURL != nil , let saved = savedFileContent else { return false }
286318 let queryNS = query as NSString
@@ -290,11 +322,10 @@ struct TabQueryContent: Equatable {
290322 }
291323
292324 static func == ( lhs: TabQueryContent , rhs: TabQueryContent ) -> Bool {
293- // `query` can be multiple megabytes and is bridged from the editor's NSTextStorage. The synthesized `==`
294- // compared it with Swift's canonical Unicode equality, which walks the whole string through NFC normalization
295- // on every SwiftUI diff and pins the CPU while editing a large query. NSString equality returns in O(1) when
296- // the lengths differ (every keystroke changes the length) and uses literal comparison otherwise.
297- guard ( lhs. query as NSString ) . isEqual ( to: rhs. query) ,
325+ // The query can be multiple megabytes and is bridged from the editor's NSTextStorage. Same-box comparison is
326+ // O(1); otherwise use NSString literal equality, which returns in O(1) when the lengths differ (every keystroke
327+ // changes the length) and avoids Swift's canonical Unicode normalization.
328+ guard lhs. queryStorage === rhs. queryStorage || ( lhs. query as NSString ) . isEqual ( to: rhs. query) ,
298329 lhs. queryParameters == rhs. queryParameters,
299330 lhs. isParameterPanelVisible == rhs. isParameterPanelVisible,
300331 lhs. sourceFileURL == rhs. sourceFileURL,
0 commit comments