Skip to content

feat(storage): 拦截并持久化 localStorage 到磁盘,解决随机端口导致的数据丢失 - #301

Merged
yaojin3616 merged 1 commit into
mainfrom
migrate_persistence_disk_storage
Sep 4, 2026
Merged

feat(storage): 拦截并持久化 localStorage 到磁盘,解决随机端口导致的数据丢失#301
yaojin3616 merged 1 commit into
mainfrom
migrate_persistence_disk_storage

Conversation

@yaojin3616

Copy link
Copy Markdown
Contributor

背景与问题

在 macOS / Windows 桌面端(dsh-desktop),每次启动由 reservePort() 动态分配随机可用端口(例如本次启动是 http://127.0.0.1:54321,下次重启变成 http://127.0.0.1:58962)。
按照 W3C 浏览器的同源策略(Same-Origin Policy),Origin 由 协议 + 主机 + 端口 三者决定,端口改变等于进入全新的独立域。因此,依赖浏览器原生 window.localStorage 的纯前端插件(例如各类设置滑块、UI 主题、自定义面板等)在应用重启后读到的均为空存储,导致用户配置与状态丢失。

如果强制要求所有纯客户端插件重构成「Host + Client 双端架构」,开发门槛高且会使现有社区纯前端小插件失去持久化能力。

改动方案与实现细节

本 PR 采用 Preload 拦截代理 + 主进程磁盘持久化 方案,对插件生态 100% 透明无侵入:

  1. 主进程存储管理 (DesktopStorageManager)

    • 数据保存在当前激活的 Profile 目录下:profiles/<profile>/desktop-storage.json,生命周期与 Profile 深度绑定,天然支持备份与迁移。
    • 采用 200ms 防抖异步落盘及临时文件 .tmp -> rename 原子写入,杜绝断电或崩溃导致 JSON 损坏。
    • 监听窗口关闭事件及应用 before-quit,提供 flushSync() 同步原子落盘保证,确保退出前 0 数据丢失。
    • 支持多 Profile 切换(正常模式与安全模式相互隔离)。
  2. Preload 透明代理 (setupDesktopStoragePersistence)

    • 页面 DOM 与页面脚本执行前(document-start 阶段)通过同步 IPC (dsh:storage-load-sync) 拉取磁盘数据到内存中。
    • 向主上下文注入代理脚本,覆盖 Storage.prototypegetItemsetItemremoveItemclearkeylength)。
    • 前端读操作 0ms 纯同步从内存返回,完全契合 Web Storage 同步规范。
    • 封装 Proxy 代理 window.localStorage,同时兼容 localStorage['key'] = 'val' 属性直接赋值与读取。
    • 前端写操作通过自定义事件由 Preload 发送 IPC 异步通知主进程排队落盘。
  3. 测试覆盖

    • 增加 test/desktop-storage.test.ts,覆盖空文件初始化、CRUD 一致性、防抖批量写入、同步 Flush 退出、JSON 损坏容错自愈及跨 Profile 隔离。
    • 多端口(真实随机端口漂移)E2E 测试验证通过:窗口 1 存入数据后关闭,窗口 2 在全新随机端口下能 100% 同步恢复读取。

- 新增 DesktopStorageManager,将 Web Storage 数据落盘至当前 Profile 目录下的 desktop-storage.json
- 支持 200ms 防抖异步落盘及窗口关闭 / before-quit 时的 flushSync() 原子写入保证
- Preload 注入主上下文透明代理 Storage.prototype 与 window.localStorage(支持方法调用与属性读写)
- 页面加载前同步拉取磁盘数据,解决 DSH 启动随机端口引起的同源隔离(Origin 变更)导致纯前端插件数据丢失的问题
- 增加 DesktopStorageManager 单元测试与测试覆盖
@yaojin3616
yaojin3616 merged commit df9cfcc into main Sep 4, 2026
10 of 12 checks passed
@yaojin3616
yaojin3616 deleted the migrate_persistence_disk_storage branch September 4, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant