Files
new-markdown/tests/editor-pane-unload.test.tsx
Muse fb2315a2f3 audit(docs/29): 全项目审计——修分片载入卸载截断高危、Sidebar memo 击穿与 Rust 资源/搜索/恢复上限等 20 余处
三线并行审计(编辑器核心/Rust 后端/服务与组件)+ App 编排层自审。
高危:分片载入未收尾时窗格卸载回写部分序列化,干净标签会被静默
截断——cleanup 补 muted 守卫,create 完成回调补取消守卫。
性能:gitSync/outline/收起回调稳定化保住 Sidebar memo;光标行列
rAF 合并;图片显示解析加缓存;导出图片并发解析;chunkLoader
偏移前缀表;围栏切点只认顶格(列表内嵌围栏等价回归实测)。
Rust:资源命令 async 化 + 32MB 上限;搜索 junction 越界校验;
recovery/workspace 条数与单条上限;启动坏库改名重建 + WAL;
validate 补 ext:: 黑名单与 ref 形态;init 先种 .gitignore
(含 .*.tmp-* 防崩溃残留被提交);游离 HEAD 不再猜分支。
验证:vitest 122+2、tsc、构建通过;Rust 过 rustfmt 解析、
validate 纯函数抽出实跑断言、命令对账 28=28。
2026-11-14 18:00:31 +08:00

44 lines
2.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 回归(docs/29 高危):EditorPane 卸载最终回写的守卫。
// 分片载入未收尾(muted)时 cleanup 跳过回写——否则部分序列化会把干净
// 标签静默截断。该交错(卸载提交时追加仍在途)在 jsdom 里无法自动化
// 复现:React act 会把待办异步工作抽干,分片追加总是先跑完(已实测
// 三种卸载方式均如此),故中途卸载一例靠代码复核保证(muted 仅在追加
// 完成/失败的收尾回调里解除,cleanup 只在 !muted 时回写),这里只锁
// 对照组:正常文档卸载时最终回写照常发生(守卫不能误伤正常路径)。
import { describe, it, expect, vi } from 'vitest'
import { createRoot } from 'react-dom/client'
import { act } from 'react-dom/test-utils'
import EditorPane from '../src/components/EditorPane'
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
describe('EditorPane 卸载回写', () => {
it('普通文档卸载:最终回写照常', async () => {
const container = document.createElement('div')
document.body.appendChild(container)
const root = createRoot(container)
const onFinalMarkdown = vi.fn()
let readyApi: { editor: unknown } | null = null
const onReady = vi.fn((api: { editor: unknown }) => { if (api.editor) readyApi = api })
await act(async () => {
root.render(
<EditorPane
tabId="t1"
initialMarkdown={'# 小文档\n\n你好,世界。\n'}
onMarkdown={() => undefined}
onFinalMarkdown={onFinalMarkdown}
onCursor={() => undefined}
onReady={onReady}
focusMode={false}
typewriter={false}
/>,
)
})
for (let i = 0; i < 200 && !readyApi; i++) await sleep(10)
expect(readyApi).not.toBeNull()
await act(async () => { root.unmount() })
expect(onFinalMarkdown).toHaveBeenCalledTimes(1)
expect(onFinalMarkdown.mock.calls[0][1]).toContain('你好,世界。')
}, 30000)
})