Skip to content

web: tolerate nodes created and dropped inside one patch batch - #75

Merged
tiensonqin merged 2 commits into
mainfrom
devin/web-same-batch-drop
Sep 29, 2026
Merged

tiensonqin merged 2 commits into
mainfrom
devin/web-same-batch-drop

Conversation

@tiensonqin

Copy link
Copy Markdown
Collaborator

Summary

The web DOM applier crashed with unknown DOM node when a patch batch created a node and dropped it again inside the same batch (a keyed remount that replaces a subtree mid-flush). Ops are replayed against the retained store's final state, so a node absent at batch end had no platform_node to resolve:

  • CreateNode/CreateExtension → Nodes.dom_node threw on the missing store record.
  • InsertChild/RemoveChild/MoveChild → dom_node/dom_node_before threw for the transient node.
  • SetProp → invalid_arg "unknown DOM node" (inconsistent with RemoveProp, which already tolerated misses).

Changes

  • Add known_node (current store ∪ previous_nodes) and skip InsertChild/RemoveChild/MoveChild whose parent or child is unresolvable — the element was either never created or is being discarded with its batch.
  • CreateNode/CreateExtension set-id now resolve the record via Store.node and skip when absent.
  • insert_child_dom resolves parent/child via dom_node_before and takes previous_nodes; a child missing from the store still gets inserted (a later RemoveChild in the same stream detaches it).
  • SetProp on a missing node is now a no-op, matching RemoveProp.

Reproduced in Logseq's e2e (Meta+k opening cmdk while the editor mounted → batch contained create-extension → … → drop for the same ids → Invalid_argument aborted the flush and the palette never opened). After this change the batch applies cleanly.

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

@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

… 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.
@tiensonqin
tiensonqin merged commit 58a9563 into main Sep 29, 2026
4 checks passed
@tiensonqin
tiensonqin deleted the devin/web-same-batch-drop branch September 29, 2026 01:53
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