fix(autocompile): prevent compile chaining — wait for previous compile before starting next
Build and Deploy Verso / deploy (push) Successful in 11m38s

The auto-compile effect was calling debouncedAutoCompile() on every changedAt
update (every keystroke), including while a compile was already running.  With
a 1000ms maxWait the debounce fired every second even mid-compile, chaining
compiles back-to-back and making the user wait for all of them to drain.

Fix: add `compiling` to the effect's dependency array.
- While compiling: the effect cancels the debounce immediately, preventing
  any new compile from being queued.
- When compile finishes (compiling → false): the effect re-runs; if changedAt
  is still > 0 (changes were made during the compile), it re-arms the debounce
  exactly once.  One follow-up compile, then idle.

Also remove the debouncedAutoCompile() re-queue from compiler.ts's
wasCompiling guard — the effect now owns that responsibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
claude
2026-06-07 13:38:43 +00:00
parent 71755e5cee
commit 165219dcb1
2 changed files with 9 additions and 6 deletions
@@ -119,9 +119,8 @@ export default class DocumentCompiler {
this.setCompiling(true)
if (wasCompiling) {
if (options.isAutoCompileOnChange) {
this.debouncedAutoCompile()
}
// The auto-compile effect in local-compile-context re-arms the debounce
// once compiling flips back to false, so we don't re-queue here.
return
}
@@ -696,16 +696,20 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
// show that the project has pending changes
const hasChanges = Boolean(canAutoCompile && uncompiled && compiledOnce)
// call the debounced autocompile function if the project is available for auto-compiling and it has changed
// Trigger a debounced auto-compile when the project has changed.
// Crucially: cancel the debounce while a compile is already in flight so
// compiles don't chain back-to-back. When the compile finishes (compiling
// flips to false) and there are still uncompiled changes, the effect re-runs
// and re-arms the debounce exactly once.
useEffect(() => {
if (canAutoCompile) {
if (canAutoCompile && !compiling) {
if (changedAt > 0) {
compiler.debouncedAutoCompile()
}
} else {
compiler.debouncedAutoCompile.cancel()
}
}, [compiler, canAutoCompile, changedAt])
}, [compiler, canAutoCompile, changedAt, compiling])
// cancel debounced recompile on unmount
useEffect(() => {