Frontmatter
| id | 9403 |
| title | Performance: Eliminate Path scrollTop Layout Thrashing in getTargetData |
| state | Closed |
| labels | enhancementaiperformance |
| assignees | tobiu |
| createdAt | Mar 8, 2026, 11:44 PM |
| updatedAt | Mar 8, 2026, 11:59 PM |
| githubUrl | https://github.com/neomjs/neo/issues/9403 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Mar 8, 2026, 11:59 PM |
Performance: Eliminate Path scrollTop Layout Thrashing in getTargetData
tobiu assigned to @tobiu on Mar 8, 2026, 11:58 PM

tobiu
Mar 8, 2026, 11:58 PM
Input from Gemini 3.1 Pro:
✦ Task Completed:
- Updated
getTargetDatato accept anisTargetboolean flag.- For high-frequency layout-thrashing events (
scrollandwheel), the framework now skips readingscrollTopandscrollLeftfor all nodes in the event's bubble path (isTarget === false).- Instead of returning
0(which implies a valid coordinate that could reset scroll state in the VDOM engine), skipped geometric properties now returnundefinedto cleanly drop them from the serialized JSON payload.- The
event.targetcontinues to return its actualscrollTop, preserving critical scroll behavior for the components generating the event.This targeted excision addresses the secondary layout thrashing bottleneck identified in the benchmarking, eliminating forced synchronous layouts on ancestor wrappers during grid scroll cycles.
tobiu closed this issue on Mar 8, 2026, 11:59 PM
Problem: Profiling the Main Thread during rapid Grid scrolling reveals a secondary massive layout thrashing penalty:
Recalculate style: 50.6% total timeget scrollTop: 13.1% total timeThis occurs because
getTargetDataunconditionally readsnode.scrollTopandnode.scrollLeftfor every node in the event bubble path. When a grid row scrolls, the style tree is invalidated by VDOM delta mutations (set innerHTML,style.transform). ReadingscrollTopon 15 ancestor elements immediately after these mutations forces the browser to synchronously recalculate layout 15 times per frame.Proposed Solution: Pass an
isTargetboolean intogetTargetData(). For high-frequency continuous events likescrollandwheel, we only need the layout state of the actual node that generated the event (isTarget === true).For all other elements in the event
path(isTarget === false), we will skip readingscrollTopandscrollLeftand returnundefined. By returningundefinedrather than0, we prevent the VDOM engine from misinterpreting the omission as a command to reset scroll positions to zero.Additionally, we will convert the previous dimension skips (
clientHeight, etc.) to returnundefinedrather than0for structural safety.