Asynchronous event dispatching, dual WeakMap observation indexing, and decoupled change propagation in SvNotificationCenter.
In a framework where model, view, and storage layers must stay independent, objects announce state changes without holding direct references to observers. Direct method calls create tight coupling—the sender must hold a reference to every observer, and adding a new listener requires modifying sender code.
SvNotificationCenter solves this: senders post named notifications into a shared center, observers register interest by name and sender, and the two sides never reference each other directly.
Senders post notifications when their state mutates:
// Convenience method on SvNode:
this.postNoteNamed("didUpdateNode");
// Advanced notification with info dictionary:
SvNotificationCenter.shared().newNote()
.setSender(this)
.setName("didUpdateNode")
.setInfo({ fieldName: "title", oldValue: "Draft", newValue: "Final" })
.post();Objects register observations using newObservation():
// Register observation
SvNotificationCenter.shared().newObservation()
.setSender(targetNode)
.setName("didUpdateNode")
.setObserver(this)
.startWatching();targetNode posts "didUpdateNode", the notification center automatically calls this.didUpdateNode(note) on the observer if defined.setSendName():obs.setSendName("handleNodeUpdate");To minimize dispatch overhead as domain graphs grow, SvNotificationCenter maintains two internal index maps:
_senderToObservations: A WeakMap mapping senders to their registered observations._nameToObservations: A WeakMap mapping notification names to observations.During a post operation, the notification center intersects the two maps to retrieve target observations in $O(\text{observations on sender})$ time, avoiding full-table scans.
Observers are held in WeakRef wrappers. When an observing view is removed from the DOM and has no remaining strong references, JavaScript's garbage collector automatically reclaims it. Dead observations are cleaned up during dispatch passes without throwing errors.