build: first round of blast radius#2833
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| } | ||
|
|
||
| // Save suggestion node content before reconstruction | ||
| // drops prev suggestionBefore and next suggestionAfter on merge |
There was a problem hiding this comment.
part of the previous fixes, mergeBlocks needs to be updated for suggestions anyway, so still 1
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Add root-cause counter at getBlockInfoFromPos (suggestionBefore/After unused by callers), census-pass position annotations, comment cleanup, and a SUGGESTIONS_BLAST_RADIUS.md covering the conceptual fallout.
Summary
Audits the blast radius of the
blockContainercontent-spec change and annotatesevery affected (and notably-safe) site in the codebase, plus a written summary of
the conceptual fallout.
The change
packages/core/src/pm-nodes/BlockContainer.ts:27A
blockContainercan now hold 0-NsuggestionBlockContentshadow nodes bothbefore and after its
blockContent. These hold the old content of ablock with a pending "modify" suggestion.
Rationale
This is not a localised change: it changes what a "block" structurally contains,
which ripples through position arithmetic, conversion/serialization, the public
Block API, collaboration, and every menu that mutates blocks. This PR maps that
surface so the follow-up implementation work is scoped, rather than discovered
piecemeal.
Changes
packages (
firstChild,nodeAt(pos+1),childCount,nodeBefore/After,compound-group equality checks, etc.).
nodeToBlock.ts:485—(Affects ~23 callsites)strips suggestion state.blockToNode.ts:324—(Affects ~7 callsites)emits no suggestion nodes.getBlockInfoFromPos.ts:44—(Affects ~58 callsites)callers never branchon
suggestionBefore/suggestionAfter.packages/core/SUGGESTIONS_BLAST_RADIUS.mddocumenting the considerations below.Considerations (blast radius)
Two distinct suggestion mechanisms
y-attributed-insert/-format/-delete, allowedon
blockContainer,blockGroup,column, table nodes. Mark a real block /structure as inserted, deleted, or modified.
${type}--attributed(e.g.paragraph--attributed), groupis the COMPOUND string
"suggestionBlockContent blockContent". They sit insidea
blockContainernext toblockContentand hold the old content.Footguns
node.type.spec.group === "blockContent"and=== "suggestionBlockContent"are BOTHfalsefor a shadow node. Usenode.type.isInGroup(...). Several existing guards (splitBlock.ts:50,internal.ts:104,nodeToBlock.ts:608) are dead because of strict-equality ora
"suggestion-"name prefix the real*--attributednodes never match.*--attributed, notsuggestion-*.SpecialNode.test.tsasserts the non-existentsuggestion-*names.firstChildis no longerblockContent. ReadingblockContainer.firstChild,nodeAt(pos+1), orchildCount === 1now risks landing on / miscounting aleading shadow node.
selectable: falsebut render withan editable
contentDOMand have NO node view, soapplyNonSelectableBlockFixnever runs. A caret / text-selection can land inside a shadow node, so those
positions are genuinely reachable.
What is inside
editor.document?Produced by
nodeToBlock, which buildsBlock = {id, type, props, content, children}only and strips all suggestion state (shadow nodes dropped,y-attributed-*marks ignored). Soblock.contentis always the new content;the old content is invisible; the public
Blocktype has no suggestion-statefield; and every consumer (
getSelection().blocks,getBlock, allExportManagerAPIs) is suggestion-blind.
What does a "deleted" block mean?
A suggested-deleted block still has its
data-id, is in thebnBlockgroup, andresolves through
getNodeById/getBlock/forEachBlockas a normal liveblock with no deletion flag. Menus and commands will read and mutate content
the user believes is deleted. This is the most acute hazard.
How do menu items interact with this?
Every side-menu / formatting-toolbar / table-handle action resolves a
suggestion-blind
Blockand mutates it viaupdateBlock/removeBlocks/insertBlocks, none suggestion-aware. Type/color/alignment/file ops on asuggested block are untracked edits that corrupt the diff; "+" inserts an
untracked block next to tracked content; drag-and-drop moves a suggested block and
deleteSelections the origin untracked;BlockTypeSelectshows the new content'stype, never reflecting the tracked change. These should be disabled or routed
through accept/reject semantics when suggestions are enabled.
How would the unique-id extension rewrite ids?
Shadow nodes carry no own
data-id(it lives on the outerblockContainer), sothey should not be assigned ids. But dedupe (
UniqueID.ts:208) can regenerate anid when a suggestion transiently produces a duplicate, potentially detaching a
block from its tracked history. Dedupe must ignore shadow-bearing transitions.
Multi-column
columncontent is"blockContainer+"and carriesy-attributed-*marks, so awhole column can be a tracked insert/delete.
multiColumnDropCursor.ts/ColumnResizeExtension.tswork at column/columnListlevel (shadow-safe) but resolve via the suggestion-blind
getNodeById.multiColumnHandleDropPlugin.tsrebuilds an entirecolumnListfromnodeToBlockoutput, dropping any suggestion state in moved columns — thehighest-risk multi-column path.
Round-trips and serialization
blockToNodeemits only[contentNode, groupNode], so any Block-JSON round-tripdrops suggestions.
does emit shadow nodes — so copy/paste can duplicate/inject shadow content, and
the
text/html/ markdown branches (Block-JSON based) disagree with theblocknote/htmlbranch about whether suggestions exist.Schema-validity hazards
updateBlockinserts ablockGroupatblockContent.afterPos, i.e. before atrailing shadow node, violating the
... blockGroup?ordering.mergeBlocksis partly suggestion-aware but dropsprev.suggestionBeforeandnext.suggestionAfter, and reconstructs withtype.create(no validation).BlockInfo.suggestionBefore/suggestionAfterare singular while the schemaallows
*; containers with ≥2 shadows on a side are under-represented.Impact
This PR is annotation + documentation only (the code diff is comment-only; the only
new file is the markdown summary). No runtime behaviour changes.
Testing
N/A — no behavioural changes. Existing tests unaffected. The audit flags
SpecialNode.test.tsas a separate test-correctness issue (asserts non-existentsuggestion-*node names) to be addressed in follow-up work.Checklist
Additional Notes
Search the source for the
(Affects ~N callsites)counters to find the systemicentry points, and for the single-line
// ... suggestion ...annotations for theindividual sites. Full write-up lives in
packages/core/SUGGESTIONS_BLAST_RADIUS.md.