Darling Viewer: Query Store grid DarkButton crash — Lite's #2114 on the other SKU (#2181, #2331) - #2332
Conversation
… on the other SKU The inline View Plan button in Queries -> Query Store by Duration referenced DarkButton, a key that IS defined in the Viewer - in MainWindow.xaml's window resources, a scope a UserControl's templates cannot see, because StaticResource resolves lexically at load rather than through the runtime tree. A missing key inside a cell template stack-overflows the process the moment the grid renders a row: uncatchable, no error dialog. It survived dogfooding because an EMPTY grid never applies its cell template, and the dogfood fleet's Query Store data is empty. #2181 reported it against the Darling Viewer and was closed as a duplicate of the Lite-only fix (#2118) on a wrong premise; #2331 re-proved it on 3.4.0 stable, which the Lite fix missed by twelve hours anyway. The button uses default chrome now - Lite's exact fix. And the hygiene test that let this through gets the model it should have had: per-FILE resolution (own keys + transitively merged dictionaries + App.xaml scope), matching WPF's actual StaticResource lookup instead of the per-app existence check that declared MainWindow's key 'defined somewhere, good enough'. The widened scan was proven exact before adoption: over both apps it flagged exactly this one real crash and zero false positives. Closes #2181 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| src = src[(componentIndex + ";component/".Length)..]; | ||
| } | ||
|
|
||
| var candidate = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(file)!, src.Replace('/', Path.DirectorySeparatorChar))); |
There was a problem hiding this comment.
Nit: the doc comment on TransitiveDefinitions (line 111-112) says pack paths are "resolved against the file, falling back to the repo layout," but there's no repo-layout fallback here — a ;component/ path is always resolved relative to the referencing file's directory after the prefix is stripped. For a same-assembly relative Source (the only kind actually used in this repo today, confirmed via grep -rn "ResourceDictionary Source" across both apps) that's correct. But a genuine pack URI like /OtherAssembly;component/Themes/Foo.xaml — which points at a different project's root, not a path relative to the current file — would resolve to a nonexistent path here. TransitiveDefinitions degrades safely in that case (unresolvable file → empty key set → scan gets stricter, per the comment on line 113), so today this is inert, not a live bug. Just flagging so the comment doesn't overstate what the code does, in case a future merge actually uses cross-assembly ;component/ syntax.
There was a problem hiding this comment.
Fixed in 9be67af — the doc now says what the code does: prefix stripped, remainder resolved against the referencing file, correct for same-assembly sources (the only kind in the repo), and a cross-assembly pack URI degrades toward stricter. (Note for the record: the first version of this reply cited a hash before the fix had actually been committed — a scripted edit's anchor missed and the chain kept going; caught and corrected within minutes.)
|
Reviewed. This is a well-scoped, well-verified fix — no blocking issues found. Correctness check performed: I reimplemented the hygiene test's regex/traversal logic and ran it by hand against the actual XAML tree in both apps to confirm the "zero false positives" claim in the PR description. Two things stood out that I specifically checked and can confirm are not bugs:
The new Left one non-blocking nit inline on the test file: a doc-comment/implementation mismatch around |
… does not have Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Reviewed. This is a clean, well-scoped fix — verified the following and found no correctness, parity, security, or perf issues:
No SQL changes in this PR, so the T-SQL style guide doesn't apply here. |
Closes #2181. #2331 is the fresh duplicate that exposed the gap (being closed as a dupe of #2181, which is reopened as the canonical Darling-side report).
What actually happened
DarkButtonkey into Lite. Fixed in Lite Query Store grid: drop the Viewer-only DarkButton style that stack-overflowed the app #2118 for Lite only, plus a hygiene test scanning for cross-app keys.ViewerServerTab.xaml:1409referencesDarkButton, which IS a Viewer key — defined inMainWindow.xaml's window resources, a scope a UserControl's templates cannot see (StaticResource resolves lexically at load, never through the runtime tree).The fix
IsEnabled=HasQueryPlangate doesn't transplant: Darling's button fetches the stored plan on demand and shows "Plan Not Found" on a miss, by design.)Source=, including;component/paths) + App.xaml scope — matching WPF's actual StaticResource lookup. The widened scan was proven exact before adoption: run over both apps it flagged exactly this one real crash and zero false positives.🤖 Generated with Claude Code