fix: address pr-bug-scan validated finding from #4731

C1: restore-side git-status signature now applies the same treeMode short-circuit as save-side, so branch/commit caches restore. C2: editable-diff modified-model key/component key no longer embed dc.m
This commit is contained in:
orca-bug-scan-bot
2026-06-07 13:13:53 -07:00
parent 2b29acb87b
commit 6974c52417
2 changed files with 27 additions and 5 deletions
@@ -441,11 +441,19 @@ export default function CombinedDiffViewer({
// find their place again.
useEffect(() => {
const cached = combinedDiffViewStateCache.get(viewStateKey)
// Why: the save-side signature is '' for branch/commit modes (only the
// uncommitted tree tracks git status), so the restore-side recompute must
// apply the same treeMode short-circuit. Otherwise '' can never equal the
// recomputed '[]'/'[...]', and branch/commit combined diffs would always
// discard their cached sections and re-enter Loading on every remount.
const cachedGitStatusSignature =
cached && treeMode === 'uncommitted'
? buildCombinedGitStatusSignature(cached.sections, gitStatusEntries)
: ''
const canRestoreCachedSections =
cached &&
cached.entrySignature === entrySignature &&
(cached.gitStatusSignature ?? '') ===
buildCombinedGitStatusSignature(cached.sections, gitStatusEntries) &&
(cached.gitStatusSignature ?? '') === cachedGitStatusSignature &&
(cached.sections.length > 0 || entries.length === 0)
if (canRestoreCachedSections && cached) {
const collapsedPreference = combinedDiffCollapsedPreference
@@ -493,7 +501,7 @@ export default function CombinedDiffViewer({
loadSchedulerRef.current.reset()
generationRef.current += 1
setGeneration((prev) => prev + 1)
}, [entries, entrySignature, file.diffSource, gitStatusEntries, viewStateKey])
}, [entries, entrySignature, file.diffSource, gitStatusEntries, treeMode, viewStateKey])
const loadSectionNow = useCallback(
async (index: number) => {
@@ -851,10 +851,24 @@ export function EditorContent({
// edit-buffer text, so editable unstaged diffs keep their undo stack.
const diffReloadNonce = activeFile.diffContentReloadNonce ?? 0
const originalModelKey = `${diffViewStateKey}:original:${getDiffContentSignature(dc.originalContent)}`
const modifiedModelKey = `${diffViewStateKey}:modified:${getDiffContentSignature(dc.modifiedContent)}:${diffReloadNonce}`
// Why: for editable diffs the modified side is the working tree the user is
// editing. Saving rewrites dc.modifiedContent (via the FILE_SAVED handler),
// so embedding its signature in the modified-model identity / component key
// would remount Monaco on every save and wipe the undo stack the user just
// built. Rotate the modified side on the explicit reload nonce instead; a
// kept modified model still repaints refreshed git blobs through the
// `modified` prop's undo-preserving executeEdits. Non-editable diffs have no
// undo to lose, so they keep rotating on the content signature.
const modifiedContentSignature = getDiffContentSignature(dc.modifiedContent)
const modifiedModelKey = isEditable
? `${diffViewStateKey}:modified:${diffReloadNonce}`
: `${diffViewStateKey}:modified:${modifiedContentSignature}:${diffReloadNonce}`
const diffViewerKey = isEditable
? `${viewStateScopeId}:${diffReloadNonce}`
: `${viewStateScopeId}:${diffReloadNonce}:${modifiedContentSignature}`
return (
<DiffViewer
key={`${viewStateScopeId}:${diffReloadNonce}:${getDiffContentSignature(dc.modifiedContent)}`}
key={diffViewerKey}
modelKey={diffViewStateKey}
originalModelKey={originalModelKey}
modifiedModelKey={modifiedModelKey}