docs/solutions/logic-errors/2026-05-09-parent-nested-dom-selections-must-not-import-as-parent-ranges.md
Lexical regression 7635 pushed Slate's editable-void coverage from plain nested editing into rich paste inside a nested editor. The new browser row exposed an adjacent parent/nested selection bug: a DOM range starting in the parent editor and ending in the nested editor could overwrite parent content on the next typed character.
Outer u, proving typed text replaced a parent
range derived from an invalid cross-editor DOM selection.selectionchange import path. Browser beforeinput
supplies target ranges, and those can still overwrite model selection if they
are accepted while the live DOM selection crosses editor ownership.Require both DOM selection endpoints to belong to the current editor's
selectable surface before importing either the live DOM selection or a
beforeinput target range.
The runtime changes:
selection-controller.ts uses ReactEditor.hasSelectableTarget for both
anchor and focus endpoints.selection-reconciler.ts skips beforeinput target-range import when the live
DOM selection crosses out of the current editor.hasSelectableTarget.Verification:
PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration/examples/editable-voids.test.ts --project=chromium -g "parent selection that crosses|rich HTML inside nested editor"
PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration/examples/editable-voids.test.ts --project=chromium
bun run lint:fix && bun check
Nested editors live under the parent editor's DOM, but they have their own
data-slate-editor root and selection ownership. hasSelectableTarget preserves
valid parent selections, including non-readonly void targets, while rejecting
endpoints owned by a nested editor.
Checking the live DOM selection before trusting beforeinput target ranges is
the key part. Otherwise the browser can provide a target range that looks
locally resolvable after an invalid cross-editor selection has already been
created.
selectionchange proof alone when beforeinput can import
target ranges.hasSelectableTarget for both endpoints when deciding whether a DOM
range belongs to the current editor.