LearnNewsExamplesServices
Frontmatter
id9370
titleUpgrade ScrollSync Locking Mechanism
stateClosed
labels
enhancementaiarchitecture
assigneestobiu
createdAtMar 7, 2026, 5:38 PM
updatedAtMar 7, 2026, 5:54 PM
githubUrlhttps://github.com/neomjs/neo/issues/9370
authortobiu
commentsCount1
parentIssue9369
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMar 7, 2026, 5:53 PM

Upgrade ScrollSync Locking Mechanism

Closed v12.1.0 enhancementaiarchitecture
tobiu
tobiu commented on Mar 7, 2026, 5:38 PM

Part of Epic #9369

Refactor src/main/addon/ScrollSync.mjs to introduce an internal isCoordinating lock. When a scroll event is received from a source node, the addon must acquire the lock, mutate the target node, and release the lock only after the resulting native events have cleared. This stateful coordination prevents infinite "ping-pong" feedback loops during two-way synchronization.

tobiu added the enhancement label on Mar 7, 2026, 5:38 PM
tobiu added the ai label on Mar 7, 2026, 5:38 PM
tobiu added the architecture label on Mar 7, 2026, 5:38 PM
tobiu added parent issue #9369 on Mar 7, 2026, 5:38 PM
tobiu referenced in commit 3fd7bd0 - "feat(Grid): replace global scroll sync touch flag with granular DOM node locks (#9370, #9371)" on Mar 7, 2026, 5:52 PM
tobiu
tobiu Mar 7, 2026, 5:53 PM

Input from Gemini 3.1 Pro:

✦ During implementation of the lock mechanism, we pivoted the architectural design to avoid a critical race condition.

Instead of a single global isCoordinating = true flag (which would have locked the entire application and prevented multiple grids from being scrolled simultaneously), we implemented a granular Set-based lock (this.coordinatingNodes = new Set()).

When syncTo or onScroll mutates a DOM node, it adds that specific node's id to the Set. The interceptor then only ignores incoming native scroll events if their event.target.id is currently in the Set. This allows parallel scrolling of unrelated components while still perfectly preventing ping-pong loops within synchronized pairs.

The syncTo API is now in place and uses this granular locking. I will close this ticket and #9371. We will create a separate sub-task to handle the complexities of releasing the lock during continuous momentum scrolling (rAF vs setTimeout).

tobiu closed this issue on Mar 7, 2026, 5:53 PM
tobiu assigned to @tobiu on Mar 7, 2026, 5:54 PM