fix: restore depth guard in getParentBlockInfo to prevent RangeError (blo-1103)#2585
fix: restore depth guard in getParentBlockInfo to prevent RangeError (blo-1103)#2585hedi-ghodhbane wants to merge 3 commits intoTypeCellOS:mainfrom
Conversation
PR TypeCellOS#2126 removed the depth guard that prevented calling `$pos.before(0)` on the top-level document node. When pressing Delete at the end of the last block, `$pos.depth` is 1, so `depth` becomes 0, and `$pos.before(0)` throws "RangeError: There is no position before the top-level node". This restores the guard by returning undefined when depth < 1, before the `.before()` call. Fixes TypeCellOS#2584
|
@hedi-ghodhbane is attempting to deploy a commit to the TypeCell Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughA depth guard was added to getParentBlockInfo so it returns undefined when the computed depth is less than 1, preventing calls to $pos.before(0) that previously threw a RangeError for top-level positions. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
|
@hedi-ghodhbane thanks for contributing this, ideally we'd have a test case which proves this behavior |
@blocknote/ariakit
@blocknote/code-block
@blocknote/core
@blocknote/mantine
@blocknote/react
@blocknote/server-util
@blocknote/shadcn
@blocknote/xl-ai
@blocknote/xl-docx-exporter
@blocknote/xl-email-exporter
@blocknote/xl-multi-column
@blocknote/xl-odt-exporter
@blocknote/xl-pdf-exporter
commit: |
…0.47.1 https://sonarly.com/issue/17525?type=bug Pressing the Delete (forward-delete) key at the end of the last block in any BlockNote rich text editor throws an unhandled RangeError, crashing the editor. This is caused by a regression in BlockNote 0.47.1's `getParentBlockInfo` function. Fix: Pinned `@blocknote/mantine`, `@blocknote/react`, `@blocknote/xl-docx-exporter`, and `@blocknote/xl-pdf-exporter` back to exact version `0.47.0` in `packages/twenty-front/package.json`. BlockNote 0.47.1 introduced a regression in `@blocknote/core` (upstream PR #2126, "handle more delete key cases") that removed a depth guard in `getParentBlockInfo()`. This causes `$pos.before(0)` to be called when the cursor is at the end of the last top-level block and the user presses Delete, throwing `RangeError: There is no position before the top-level node`. The dependabot commit `6a2e0182ab` bumped these from exact `"0.47.0"` to `"^0.47.1"`, pulling in the buggy release. This pin restores the exact versions from the original deliberate upgrade (commit `4ed09a3feb`). The server-side `@blocknote/server-util` is left unchanged at `^0.47.1` since it's a headless package that doesn't use ProseMirror's view layer or keyboard handlers — the regression only affects browser-side editing. Once BlockNote publishes a fix (tracked in upstream issue [#2584](TypeCellOS/BlockNote#2584), fix PR [#2585](TypeCellOS/BlockNote#2585)), these packages can be upgraded again.
|
@nperez0111 I'm not sure what you mean by a test case. You mean a record / demo of the issue? or a Unit test? |
|
@hedi-ghodhbane I mean more of a unit test which proves that this does what it intended to. There is a test file next to the one you modified: https://github.com/hedi-ghodhbane/BlockNote/blob/4bbfd90ee0749fa038a500e043021d19bbb43916/packages/core/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts |
Verifies that getParentBlockInfo returns undefined when called on a top-level block (depth < 1), preventing the RangeError that was thrown by $pos.before(0). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@nperez0111 Added a unit test in Without the depth guard (reproduces the bug): |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/core/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts (1)
80-88: Tighten this regression test by asserting the depth-guard precondition.Right now the test only checks the return value. Please also assert that the resolved position is in the
depth < 1guard path so the test can’t pass for an unrelatedundefinedcase.Suggested test hardening
const beforePos = getPosBeforeSelectedBlock(); const doc = getEditor()._tiptapEditor.state.doc; + const resolved = doc.resolve(beforePos); + expect(resolved.depth - 1).toBeLessThan(1); const result = getParentBlockInfo(doc, beforePos); expect(result).toBeUndefined();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts` around lines 80 - 88, The test should also assert the resolved position meets the depth guard to ensure we exercise the "top-level" branch: after computing beforePos via getPosBeforeSelectedBlock() and doc from getEditor()._tiptapEditor.state.doc, resolve the position (use doc.resolve(beforePos) or the same helper used in getParentBlockInfo) and assert resolvedPos.depth < 1 before calling getParentBlockInfo; keep the existing expect(result).toBeUndefined() to validate the return value for the top-level case (functions referenced: getParentBlockInfo, getPosBeforeSelectedBlock, getEditor).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@packages/core/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts`:
- Around line 80-88: The test should also assert the resolved position meets the
depth guard to ensure we exercise the "top-level" branch: after computing
beforePos via getPosBeforeSelectedBlock() and doc from
getEditor()._tiptapEditor.state.doc, resolve the position (use
doc.resolve(beforePos) or the same helper used in getParentBlockInfo) and assert
resolvedPos.depth < 1 before calling getParentBlockInfo; keep the existing
expect(result).toBeUndefined() to validate the return value for the top-level
case (functions referenced: getParentBlockInfo, getPosBeforeSelectedBlock,
getEditor).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 82547264-af75-450d-a460-65416afc1ed9
📒 Files selected for processing (1)
packages/core/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts
Verify that the resolved position's depth is < 1 before calling getParentBlockInfo, ensuring we exercise the top-level branch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Coderabbit comment fixed :) |
nperez0111
left a comment
There was a problem hiding this comment.
Thanks @hedi-ghodhbane!
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary
PR #2126 introduced a regression in
getParentBlockInfo(mergeBlocks.ts). The depth guard that prevented calling$pos.before(0)on the top-level document node was removed.When pressing
Deleteat the end of the last block,$pos.depthis1, sodepthbecomes0, and$pos.before(0)throws:This PR restores the guard by returning
undefinedwhendepth < 1, before the.before()call.Test plan
Deleteat the end of the last block in the editor → should be a no-op, no errorDeletein an empty editor → should be a no-op, no errorFixes #2584
Summary by CodeRabbit
Bug Fixes
Tests