From 6ead2bbcc1c16f5d4d4cf74523d2f583400e0813 Mon Sep 17 00:00:00 2001 From: David Krcek Date: Wed, 10 Jun 2026 00:06:25 +0200 Subject: [PATCH] fix(plugins): yield to a macrotask between vault snapshot chunks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit streamVaultSnapshot yielded with queueMicrotask, which drains before any render — the whole chunk loop ran as one blocking task on the host main thread. Use the existing yieldToMain() helper (scheduler.postTask / 0ms timeout) so the UI can repaint between chunks. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/plugins/vaultSnapshot.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/plugins/vaultSnapshot.ts b/src/plugins/vaultSnapshot.ts index 32431f45..16049cae 100644 --- a/src/plugins/vaultSnapshot.ts +++ b/src/plugins/vaultSnapshot.ts @@ -24,6 +24,7 @@ import { useNoteStore } from '@/stores/noteStore' import { useFolderStore } from '@/stores/folderStore' import { parseFrontmatter } from '@/utils/frontmatter' +import { yieldToMain } from '@/utils/bootTrace' import type { Note, Folder } from '@/types' import type { NoteWithBodyWire } from './protocol' @@ -155,10 +156,12 @@ export async function streamVaultSnapshot( chunkIndex++ const slice = all.slice(i, i + chunkSize) await opts.onChunk(slice, chunkIndex) - // Cooperative yield. queueMicrotask is enough — the worker - // postMessage queued before the next iteration also yields the - // main thread macrotask boundary. - await new Promise((resolve) => queueMicrotask(resolve)) + // Cooperative yield to a MACROTASK boundary so the host main thread + // can repaint between chunks. queueMicrotask is NOT enough — the + // microtask queue drains before any rendering, so the whole loop + // would run as one blocking task. yieldToMain uses scheduler.postTask + // (or a 0ms timeout) — a real macrotask yield. + await yieldToMain() } await opts.onEnd?.() }