diff --git a/src/utils/runtime.ts b/src/utils/runtime.ts index 35b486b..61eff34 100644 --- a/src/utils/runtime.ts +++ b/src/utils/runtime.ts @@ -19,9 +19,9 @@ export function takeRenderingControl() { hasExternalUpdate = true; return () => { hasExternalUpdate = false; - } + }; } - + export function scheduleRevalidate() { if (hasExternalUpdate) { return; @@ -33,39 +33,41 @@ export function scheduleRevalidate() { } } revalidateScheduled = true; - Promise.resolve().then(async () => { - await syncDom(); - if (resolveRender !== undefined) { - resolveRender(); - resolveRender = undefined; + queueMicrotask(async () => { + try { + await syncDom(); + if (resolveRender !== undefined) { + resolveRender(); + resolveRender = undefined; + } + } finally { + revalidateScheduled = false; } - revalidateScheduled = false; }); } } export async function syncDom() { - const sharedTags = new Set(); + const sharedTags: MergedCell[] = []; + const executedTags: WeakSet = new WeakSet(); setIsRendering(true); for (const cell of tagsToRevalidate) { await executeTag(cell); - // we always have related tags - if (relatedTags.has(cell)) { - const subTags = relatedTags.get(cell)!; + + const subTags = relatedTags.get(cell)!; + if (subTags !== undefined) { relatedTags.delete(cell); - subTags.forEach((tag) => { - sharedTags.add(tag); - }); + sharedTags.push(...subTags.values()); subTags.clear(); } } - tagsToRevalidate.clear(); - // sort shared tags by id - const sharedTagsArray = Array.from(sharedTags); - sharedTags.clear(); // sort tags in order of creation to avoid stale logic - sharedTagsArray.sort((a, b) => a.id - b.id); - for (const tag of sharedTagsArray) { - await executeTag(tag); + sharedTags.sort((a, b) => a.id - b.id); + for (const tag of sharedTags) { + if (!executedTags.has(tag)) { + executedTags.add(tag); + await executeTag(tag); + } } + tagsToRevalidate.clear(); setIsRendering(false); }