* perf: save browser extension storage off the main thread
chrome.storage.sync and declarativeNetRequest state saved each dirty
extension with two synchronous fsyncs on Electron's main thread after a
250 ms debounce, freezing the UI ~10-25 ms per extension per burst.
Writes and forget deletes now share one ordered background queue (the
common pattern): memory stays the source of truth, deletes complete
before later writes of the same key, failed deletes keep blocking them,
and callers await deletes before recording cleanup. Quit closes the
stores last and waits for their final save, as the old synchronous
will-quit save did.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix: settle every extension storage delete before the next save
A multi-file forget now waits for all its deletes before reporting, so a
still-running delete can't erase a later save; file deletes get Node's
busy-file retries; finished deletes retire in one pass.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix: skip stray files when deleting an extension's storage
A .DS_Store beside the profile folders made every removal fail with
ENOTDIR, which now also held that extension's saves back.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test: check extension storage saves leave the caller's turn
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>