Skip to content

[lexical-code-prism][lexical-code-shiki] Bug Fix: don't restore a negative selection offset when a code line starts with a line break - #8947

Closed
LeSingh1 wants to merge 1 commit into
facebook:mainfrom
LeSingh1:fix/8943-code-retain-selection-negative-offset
Closed

[lexical-code-prism][lexical-code-shiki] Bug Fix: don't restore a negative selection offset when a code line starts with a line break#8947
LeSingh1 wants to merge 1 commit into
facebook:mainfrom
LeSingh1:fix/8943-code-retain-selection-negative-offset

Conversation

@LeSingh1

@LeSingh1 LeSingh1 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

$updateAndRetainSelection measures the caret's text offset against the code node's children before the highlight transform replaces them, then walks the new children to find that offset again. A LineBreakNode had its size subtracted even when the remaining offset was already 0, so the offset went negative; the following text node then matched size >= offset and was selected at an out-of-range position. A code block starting with a line break always produces that layout, since $plainifyCodeContent('\nfoo') yields [LineBreakNode, CodeHighlightNode('foo')].

The result is a RangeSelection pointing outside its node — typed characters land on the wrong line, and the invalid point can throw during reconciliation.

This walks the children explicitly instead: stop on a line break when the remaining offset is 0 and use an element point on the code node (an empty line has no text node to anchor to), and clamp to the end of the code node if the offset outruns the content. The same function is duplicated in @lexical/code-shiki, so both copies are fixed, each with a regression test.

Fixes #8943

…ative selection offset when a code line starts with a line break

$updateAndRetainSelection walks the children produced by the highlight
transform looking for the pre-update text offset. It subtracted a
LineBreakNode's size even when the remaining offset was already 0, driving
the offset negative; the next text node then matched `size >= offset` and
was selected at that out-of-range position.

Walk the children explicitly instead: stop on a line break when the
remaining offset is 0 and use an element point on the code node, since an
empty line has no text node to anchor to, and clamp to the end of the code
node if the offset outruns the content.

Fixes facebook#8943
@vercel

vercel Bot commented Aug 7, 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 Aug 7, 2026 9:25am
lexical-playground Ready Ready Preview Aug 7, 2026 9:25am

Request Review

@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 Aug 7, 2026
@etrepum

etrepum commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

If these functions are the same we should move it to the code-core parent package rather than maintain two identical copies.

@LeSingh1

Copy link
Copy Markdown
Contributor Author

Consolidated into #9056 with the other PRs that share this defect, per @etrepum's note on #9027 and @mayrang's on #9035. Same fix and same tests, one review.

@LeSingh1 LeSingh1 closed this Aug 10, 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: $updateAndRetainSelection restores a negative offset when a code block starts with a line break

2 participants