fix(datagrid): show data after Data/Structure/JSON view-mode toggle#981
Merged
fix(datagrid): show data after Data/Structure/JSON view-mode toggle#981
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a regression where toggling between Data, Structure, and JSON view modes left the data grid empty until the user manually refreshed. The data was always intact in the registry — the NSTableView simply never received
reloadData()after recreation.Root cause
DataGridView.makeNSViewwas callingcoordinator.updateCache()at the end of setup. That call primedcachedRowCountandcachedColumnCountto the registry's current row/column counts before NSTableView had rendered anything. The firstupdateNSViewthen computed:structureChanged = false→reloadData()skipped → NSTableView's internal row count stuck at 0 forever.Why first open worked: registry was empty during the first
makeNSView(rows=0 cols=0), so the cache stayed at(0, 0). When the query result later filled in 14 columns,oldColumnCount=0 != newColumnCount=14triggered the reload.Why structure→data broke: the recreated grid found the registry already populated, so the cache primed at
(1, 17), and the comparison saw "no structural change."Why manual refresh fixed it: refresh calls
setActiveTableRows→notifyFullReplaceIfActive→applyFullReplace(), which directly callstableView.reloadData(), bypassing the diff entirely.The cached counts represent what NSTableView has rendered, not what the provider returns. They must not be primed in
makeNSViewbecause the table has not yet rendered anything at that point.Fix
Removed the priming
updateCache()call fromDataGridView.makeNSView(one-line removal, comment added explaining the invariant). Cached counts now stay at0until the firstupdateNSView, which correctly detects "fresh view, needs initial reload" and callsreloadData().Related fix
While auditing the area, found a contract bug in
TabSessionRegistry.evict(). Its doc comment said it bumpsloadEpoch"so SwiftUI's.task(id:)lazy-load re-fires," but onlyTabSession.loadEpoch(the reference-type mirror) was bumped. The.task(id:)inMainEditorContentViewkeys ontabManager.selectedTab?.loadEpoch(the value-typeQueryTabin the array), which was untouched.In practice the bug was dormant — eviction only targets non-selected tabs, so when the user navigates back,
selectedTabIdchanges and the task re-fires for that reason. But the documented mechanism didn't actually work.Both eviction call sites (
MainContentCoordinator.evictInactiveRowDataandMainContentCoordinator+TabSwitch.evictInactiveTabs) now also bumptabManager.tabs[i].loadEpoch. Doc updated to describe the actual contract: callers must mirror the epoch to theQueryTabthemselves.Audit
Checked all other
NSViewRepresentableviews in the project (HighlightedSQLTextView,JSONSyntaxTextView,HexDumpDisplayView,HexInputTextView,FilterValueTextField,StartupCommandsEditor,QuerySplitView) for the same priming-vs-render anti-pattern. None affected — they either keep cache and rendered state in lockstep, or rely onupdateNSViewfor initial sync, or use async dispatch.Test plan
xcodebuild buildclean.xcodebuild test -only-testing:TableProTests/TabSessionRegistryTests -only-testing:TableProTests/QueryTabManagerTestspasses.Diagnostic methodology
Diagnosed empirically. After exhaustive code reading couldn't pin down the cause, instrumented the four registry mutation points (
setTableRows,removeTableRows,evict,unregister/removeAll), the view-mode flip site, and the NSViewRepresentable lifecycle. The captured trace showedtvRows=0immediately aftermakeNSViewdespiterows=1 cols=17from the provider — pinpointing the structure-change-detector miss. All diagnostic logs reverted before commit.Files
4 files: 23 insertions, 4 deletions.