`ZoneAwareEffectScheduler.flushQueue` ran each scheduled effect with an
unguarded call, so an effect that threw aborted the flush and left every
effect queued after it dirty but unreached. Because `synchronizeOnce`
clears the `RootEffects` dirty flag before flushing, nothing re-raised a
flush for the stranded effects, and they stopped reacting to their
dependencies until an unrelated effect happened to trigger another flush.
Report the error to the application error handler and continue the loop,
resolving the long-standing TODO in this file.
If one root effect throws, the flush loop stops and every effect after it silently stops working, it never runs again until some other effect happens to trigger a new flush. There's even a // TODO: what happens if this throws an error? sitting on that exact line. This catches the error, reports it to the app error handler, and keeps going, so one broken effect no longer takes its siblings down with it. Scoped to the root effect scheduler.