Patch Changes
-
#168
dfb88f3Thanks @spaansba! - Fix lazy predictor connects leaking global listeners when a handler disconnects mid-import.DesktopHandler.connectTabPredictor/connectScrollPredictorandTouchDeviceHandler.setTouchPredictornow re-checkisConnectedafter the dynamicimport()resolves, so a predictor whose handler disconnected during loading no longer attacheskeydown/focusin/pointerdownlisteners that never get aborted. -
#158
8250ad8Thanks @spaansba! -CircularBuffernow exposespeekWriteSlot()for zero-allocation slot reuse and drops the unusedgetFirstLast()tuple accessor in favor ofgetFirst()/getLast(). -
#163
53ef414Thanks @spaansba! - Drop 4 redundantif (!this.isSetup)guards aroundinitializeGlobalListeners(). The method already self-guards onisSetup, so the outer checks were dead weight. -
#167
21f066aThanks @spaansba! - Store event listeners in aSetinstead of an array. Iterating aSetduringemitmeans a listener that unsubscribes another mid-dispatch no longer causes the next listener to be skipped, and registration now dedupes like the DOMaddEventListener. -
#171
31d9222Thanks @spaansba! - DeriveForesightEventfromkeyof ForesightEventMapinstead of hand-duplicating the event names, so adding an event to the map no longer requires updating the union in lockstep. -
#159
1de7d1cThanks @spaansba! - Skip building thecallbackInvokedandcallbackCompletedevent payloads when no one is subscribed. Both emits now sit behind ahasListenersguard, avoiding a per-callback object allocation and, forcallbackCompleted, theactiveElementCountscan that fed itswasLastActiveElementfield. -
#174
f1e06e6Thanks @spaansba! - Element state and bounds subscriberSets are now created on first subscribe instead of eagerly at registration. Headless and plain-JS usage that registers elements but never subscribes to reactive state (the common case outside the framework wrappers) no longer allocates two emptySets per element. -
#166
ef09598Thanks @spaansba! - SimplifyloadedPredictors.mouseto a constant sincemousePredictoris never null. -
#157
502cb8dThanks @spaansba! - Register the globalpointermovelistener as passive, letting the browser dispatch high-frequency pointer events without treating them as cancelable. Reduces main-thread scheduling pressure during fast mouse movement and scrolling. -
#162
b6c50f1Thanks @spaansba! - Remove unusedCircularBuffermembers (clear,size,isFull,isEmpty) that were only referenced by tests. -
#170
8dc9f8eThanks @spaansba! - The mouse trajectory scan now iterates a precomputed set of scannable elements (on-screen, active, not yet predicted) instead of walking the full registry and re-checking those flags every pointer move. Membership is kept in sync on registration, state changes, and unregistration. Cost now scales with the number of visible elements rather than the total registered, so pages with many registered but few on-screen elements run the per-frame scan dramatically faster with no change at small element counts. -
#164
4dd5947Thanks @spaansba! - ExtractscheduleReactivateTimeoutto remove three copy-pasted reactivation-timeoutsetTimeoutblocks, mirroring the existingclearReactivateTimeout. -
#169
b46a3fdThanks @spaansba! -ScrollPredictorno longer caches a"none"scroll direction for the wholehandlePositionChangebatch. A non-moving element (e.g.position:fixed) returning"none"used to poison the cached direction and silently disable scroll prefetch for every later element that actually moved. The direction is now only locked in once a real direction is found. -
#161
ab0798fThanks @spaansba! -predictNextScrollPositionnow writes into a caller-ownedoutpoint instead of allocating a new one per call, matchingpredictNextMousePosition.ScrollPredictorreuses a single predicted-point object across the batch, removing the per-scroll-batch allocation. -
#174
5cbefa6Thanks @spaansba! -applySettingsChangesnow returns just the changed-settings array instead of that array plus six hand-wired side-effect booleans.alterGlobalSettingsderives aSetof changed keys and checkschanged.has(...), so adding a setting no longer means keeping a parallel flag struct in sync in three places. -
#173
51cd5fdThanks @spaansba! - Share a base factory betweencreateElementInternalandcreateUnregisteredSnapshotso the fullForesightElementStatefield list is only written once, preventing the snapshot from silently drifting when a field is added. -
#174
f1e06e6Thanks @spaansba! - Share a single frozen emptymetaobject across element states instead of allocating a fresh{}per element. The state snapshot is immutable andmetais never mutated in place, so registered elements without ametaand unregistered snapshots now reuse one object.