Skip to content

[lexical] perf: defer DOM Selection property reads in $updateDOMSelection#8422

Merged
etrepum merged 1 commit into
facebook:mainfrom
rhagigi:perf/defer-dom-selection-reads
Apr 30, 2026
Merged

[lexical] perf: defer DOM Selection property reads in $updateDOMSelection#8422
etrepum merged 1 commit into
facebook:mainfrom
rhagigi:perf/defer-dom-selection-reads

Conversation

@rhagigi

@rhagigi rhagigi commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Accessing domSelection.anchorNode, .focusNode, .anchorOffset, and .focusOffset forces the browser to resolve the selection against the current layout, triggering synchronous style/layout recalculation.

Previously these four properties were read eagerly at the top of $updateDOMSelection, even when the function would immediately return via one of two early-exit paths:

  1. Collaboration tag / decorator input check
  2. !isRangeSelection(nextSelection) (the common case on mount)

During initial mount, both prevSelection and nextSelection are null, so the function hits the !isRangeSelection branch and returns — but only after the browser has already paid the layout recalc cost for property reads that are never consumed.

Performance trace

image

Changes

  • Keep document.activeElement at the top (needed for the first early return)
  • Inline domSelection.anchorNode/.focusNode directly in the isSelectionWithinEditor call (only reached when prevSelection !== null)
  • Defer the four property reads (anchorNode, focusNode, anchorOffset, focusOffset) to just after the early returns, right before the diff-check block that actually uses them

Impact

Zero layout-triggering Selection reads on mount and on any code path that exits early. This eliminates unnecessary forced style/layout recalculations during Lexical node mounting.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 29, 2026
@vercel

vercel Bot commented Apr 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lexical Ready Ready Preview, Comment Apr 29, 2026 7:48pm
lexical-playground Ready Ready Preview, Comment Apr 29, 2026 7:48pm

Request Review

Accessing `domSelection.anchorNode`, `.focusNode`, `.anchorOffset`, and
`.focusOffset` forces the browser to resolve the selection against the
current layout, triggering synchronous style/layout recalculation.

Previously these four properties were read eagerly at the top of
$updateDOMSelection, even when the function would immediately return
via one of two early-exit paths (collaboration tag check, or
`!isRangeSelection(nextSelection)`).

During initial mount, both `prevSelection` and `nextSelection` are null,
so the function hits the `!isRangeSelection` branch and returns — but
only after the browser has already paid the layout recalc cost for
property reads that are never consumed.

This commit:
- Keeps `document.activeElement` at the top (needed for the first
  early return)
- Inlines `domSelection.anchorNode`/`.focusNode` in the
  `isSelectionWithinEditor` call (only reached when
  `prevSelection !== null`)
- Defers the four property reads to just before the diff-check block
  that actually uses them

<!-- TODO: Replace with performance trace screenshot showing the
     style/layout recalc cost before this fix -->

The net effect is zero layout-triggering Selection reads on mount and
on any code path that exits early.
@rhagigi rhagigi force-pushed the perf/defer-dom-selection-reads branch from 902d3a6 to 91c39ac Compare April 29, 2026 19:47
@etrepum etrepum added the extended-tests Run extended e2e tests on a PR label Apr 30, 2026
@etrepum etrepum changed the title perf: defer DOM Selection property reads in $updateDOMSelection Apr 30, 2026
@etrepum etrepum added this pull request to the merge queue Apr 30, 2026
Merged via the queue into facebook:main with commit 6a05922 Apr 30, 2026
44 checks passed
@levensta

Copy link
Copy Markdown
Contributor

It will be interesting to look at the performance trace after these changes

@etrepum etrepum mentioned this pull request May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. extended-tests Run extended e2e tests on a PR

3 participants