v0.3.7: 全面代码审计修复 - 20项Bug/安全/稳定性改进

This commit is contained in:
thzxx
2026-06-15 15:02:38 +08:00
parent c0e16f2885
commit dd78ff15a9
20 changed files with 158 additions and 67 deletions
+19 -9
View File
@@ -12,6 +12,9 @@ const AUTO_SAVE_DELAY = 2000
* Uses `useTabStore.getState()` and `.subscribe()` so it doesn't need to
* re-render on every keystroke — the effect is triggered once and runs
* reactively via the store subscription.
*
* Captures the tabId at debounce start so the timeout always saves the
* correct tab even if the user switches tabs during the debounce window.
*/
export function useAutoSave(): { isAutoSaving: boolean; autoSaveEnabled: boolean; toggleAutoSave: () => void } {
const [isAutoSaving, setIsAutoSaving] = useState(false)
@@ -19,6 +22,7 @@ export function useAutoSave(): { isAutoSaving: boolean; autoSaveEnabled: boolean
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const isSavingRef = useRef(false)
const enabledRef = useRef(true)
const mountedRef = useRef(true)
const toggleAutoSave = useCallback(() => {
setAutoSaveEnabled(prev => {
@@ -33,6 +37,8 @@ export function useAutoSave(): { isAutoSaving: boolean; autoSaveEnabled: boolean
}, [])
useEffect(() => {
mountedRef.current = true
// Subscribe to Zustand store — fires on every state change
const unsub = useTabStore.subscribe((state) => {
if (!enabledRef.current) return
@@ -40,6 +46,9 @@ export function useAutoSave(): { isAutoSaving: boolean; autoSaveEnabled: boolean
const tab = state.getActiveTab()
if (!tab || !tab.filePath || !tab.isModified) return
// Capture the tabId so the timeout saves the correct tab
const tabIdToSave = tab.id
// Debounce: clear previous timer, start new one
if (timerRef.current) {
clearTimeout(timerRef.current)
@@ -48,33 +57,34 @@ export function useAutoSave(): { isAutoSaving: boolean; autoSaveEnabled: boolean
timerRef.current = setTimeout(async () => {
if (isSavingRef.current) return
// Re-read latest state inside the timeout callback
// Re-read latest state; verify the captured tab still exists and is modified
const currentState = useTabStore.getState()
const currentTab = currentState.getActiveTab()
if (!currentTab || !currentTab.filePath || !currentTab.isModified) return
const tabToSave = currentState.tabs.find(t => t.id === tabIdToSave)
if (!tabToSave || !tabToSave.filePath || !tabToSave.isModified) return
isSavingRef.current = true
setIsAutoSaving(true)
if (mountedRef.current) setIsAutoSaving(true)
try {
if (!window.electronAPI) return
const result = await window.electronAPI.saveFile({
filePath: currentTab.filePath,
content: currentTab.content
filePath: tabToSave.filePath,
content: tabToSave.content
})
if (result.success) {
currentState.setModified(currentTab.id, false)
if (result.success && mountedRef.current) {
currentState.setModified(tabToSave.id, false)
}
} catch (error) {
logError('自动保存失败', error)
} finally {
setIsAutoSaving(false)
if (mountedRef.current) setIsAutoSaving(false)
isSavingRef.current = false
}
}, AUTO_SAVE_DELAY)
})
return () => {
mountedRef.current = false
unsub()
if (timerRef.current) {
clearTimeout(timerRef.current)