Skip to content

web: derive DOM insertion index from actual mount parent - #76

Merged
tiensonqin merged 3 commits into
mainfrom
pin/dom-visible-index
Sep 29, 2026
Merged

tiensonqin merged 3 commits into
mainfrom
pin/dom-visible-index

Conversation

@tiensonqin

Copy link
Copy Markdown
Collaborator

Summary

Fixes DOM child index is out of bounds thrown by apply_batch when inserting into a container whose retained children include nodes with no DOM presence (portal children, never-mounted dynamic segments, nodes created and dropped inside the same batch).

visible_child_index mapped a schema child index to a DOM index by skipping only kind-pinned children (child_hidden_in_parent: ContextMenu/DropdownMenu/Toast/modal/tooltip). Any other retained child that never materialized a DOM node still counted, so the computed index ran past the container's real child count and insert_dom_child raised Invalid_argument, aborting the whole batch.

Repro: an .cp__overlays-style container with ~8 retained children (cmdk, popups, dialogs, toasts, menu dyns) but only 2 real DOM children; mounting a page menu at schema index 7 threw, wedging the app.

The fix derives the visible index from DOM truth instead of kind heuristics: a retained child counts only when its platform_node's parentElement is the insertion container right now. This subsumes child_hidden_in_parent (portal-mounted children have a different parentElement) and also covers never-mounted segments and same-batch dropped nodes — child_hidden_in_parent is removed.

visible_child_index gains a ~container argument resolved via dom_child_container at the insert/move call sites.

Follow-up to #75.

Link to Devin session: https://app.devin.ai/sessions/5d6b198dceb54bb2b8fa02c8a412f45c
Open in Devin Desktop: https://app.devin.ai/desktop/session/5d6b198dceb54bb2b8fa02c8a412f45c?variant=devin
Requested by: @tiensonqin

… for dropped nodes

- drop_node/emit_dropped_subtree: when a node's create op is still in
  pending_ops, prune every queued op mentioning it and skip the drop op
  instead of emitting an unreplayable create+drop pair (the backend
  commits the batch before DOM replay, so post-commit lookups for the
  node always miss and the Invalid_argument wedges the generation).
- dispatch: return early when the event's node is no longer live —
  listeners can fire after their node was dropped.
- web apply: include the failing op JSON and label the roving-focus
  passes in Invalid_argument messages for diagnosability.
visible_child_index counted retained children by kind, but portal
children, never-mounted dynamic segments and same-batch dropped nodes
all retain entries without a DOM presence. Counting them pushed the
insertion index past the container's real child count and apply_batch
raised 'DOM child index is out of bounds'. Count only children whose
platform node is a DOM child of the target container right now.
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@tiensonqin
tiensonqin merged commit a4ae9b6 into main Sep 29, 2026
4 checks passed
@tiensonqin
tiensonqin deleted the pin/dom-visible-index branch September 29, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant