fix(editor): guard stale suggestion query cleanup

This commit is contained in:
lucaronin
2026-05-05 02:19:49 +02:00
parent 92c0b895dc
commit 982d6476d7
3 changed files with 104 additions and 12 deletions

View File

@@ -1,8 +1,9 @@
diff --git a/dist/blocknote-react.js b/dist/blocknote-react.js
index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3f9f0ea59 100644
index d4d36cd4dbb5370c3b7431ffeb577e4870b39825..5a6c325bf0ff9a23f2023169d7fcf6319df91544 100644
--- a/dist/blocknote-react.js
+++ b/dist/blocknote-react.js
@@ -155,8 +155,26 @@ var Rt = (e) => {
@@ -154,8 +154,26 @@ const co = (e) => {
};
function so(e) {
let t = new DOMRect();
- const n = "getBoundingClientRect" in e ? () => e.getBoundingClientRect() : () => e.element.getBoundingClientRect();
@@ -17,7 +18,7 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3
+ t = n();
+ return t;
+ };
}
+}
+function __bnSafeDomAtPos(e, t) {
+ const n = e.prosemirrorView;
+ if (!n || n.isDestroyed)
@@ -27,11 +28,10 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3
+ } catch {
+ return null;
+ }
+}
}
const z = (e) => {
var h, b, p;
const { refs: t, floatingStyles: n, context: o } = Ze({
@@ -216,9 +234,7 @@ const Lt = (e) => {
@@ -216,9 +234,7 @@ const z = (e) => {
const s = Ue(t, c.doc);
if (!s)
return;
@@ -42,7 +42,39 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3
if (a instanceof Element)
return {
element: a
@@ -3306,14 +3322,15 @@ const pi = (e) => {
@@ -2499,7 +2515,14 @@ function Kr(e) {
columns: d
} = e, m = H(
(C) => {
- a(), s(), u == null || u(C);
+ a();
+ try {
+ s();
+ } catch (x) {
+ console.warn("Ignored stale suggestion menu query cleanup:", x);
+ return;
+ }
+ u == null || u(C);
},
[u, a, s]
), { items: g, usedQuery: f, loadingState: h } = Yt(
@@ -2734,7 +2757,14 @@ function ti(e) {
onItemClick: u
} = e, d = H(
(p) => {
- a(), s(), u == null || u(p);
+ a();
+ try {
+ s();
+ } catch (C) {
+ console.warn("Ignored stale suggestion menu query cleanup:", C);
+ return;
+ }
+ u == null || u(p);
},
[u, a, s]
), { items: m, usedQuery: g, loadingState: f } = Yt(
@@ -3306,14 +3336,15 @@ const ii = (e, t = 0.3) => {
);
if (!m)
return {};
@@ -61,7 +93,7 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3
return p instanceof Element ? (d.cellReference = { element: p }, d.rowReference = {
element: f,
getBoundingClientRect: () => {
@@ -4371,7 +4388,7 @@ const El = (e) => {
@@ -4371,7 +4402,7 @@ const zi = (e) => {
const a = Ue(t, c.prosemirrorState.doc);
if (!a)
return;

8
pnpm-lock.yaml generated
View File

@@ -19,7 +19,7 @@ patchedDependencies:
hash: c93b0eab9c8a1800cc1489627146cbe9037999f409efcc8234b33f670d2ccf8d
path: patches/@blocknote__core@0.46.2.patch
'@blocknote/react@0.46.2':
hash: e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76
hash: 9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08
path: patches/@blocknote__react@0.46.2.patch
'@tiptap/extension-link@3.19.0':
hash: fbe59b1b8b798ba3fefa371c0729b5aa3458e1ea70a4b86cd5267f9f62529284
@@ -46,7 +46,7 @@ importers:
version: 0.46.2(@floating-ui/dom@1.7.5)(@mantine/core@8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@mantine/hooks@8.3.14(react@19.2.4))(@mantine/utils@6.0.22(react@19.2.4))(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@blocknote/react':
specifier: ^0.46.2
version: 0.46.2(patch_hash=e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
version: 0.46.2(patch_hash=9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@codemirror/commands':
specifier: ^6.10.2
version: 6.10.2
@@ -5677,7 +5677,7 @@ snapshots:
'@blocknote/mantine@0.46.2(@floating-ui/dom@1.7.5)(@mantine/core@8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@mantine/hooks@8.3.14(react@19.2.4))(@mantine/utils@6.0.22(react@19.2.4))(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@blocknote/core': 0.46.2(patch_hash=c93b0eab9c8a1800cc1489627146cbe9037999f409efcc8234b33f670d2ccf8d)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
'@blocknote/react': 0.46.2(patch_hash=e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@blocknote/react': 0.46.2(patch_hash=9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@mantine/core': 8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@mantine/hooks': 8.3.14(react@19.2.4)
'@mantine/utils': 6.0.22(react@19.2.4)
@@ -5696,7 +5696,7 @@ snapshots:
- sugar-high
- supports-color
'@blocknote/react@0.46.2(patch_hash=e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
'@blocknote/react@0.46.2(patch_hash=9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@blocknote/core': 0.46.2(patch_hash=c93b0eab9c8a1800cc1489627146cbe9037999f409efcc8234b33f670d2ccf8d)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
'@emoji-mart/data': 1.2.1

View File

@@ -0,0 +1,60 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { BlockNoteContext, SuggestionMenuWrapper } from '@blocknote/react'
import { describe, expect, it, vi } from 'vitest'
import type { SuggestionMenuProps } from '@blocknote/react'
function createEditor() {
return {
domElement: document.createElement('div'),
}
}
function Menu({ items, onItemClick }: SuggestionMenuProps<string>) {
return (
<button type="button" onClick={() => onItemClick?.(items[0])}>
Pick suggestion
</button>
)
}
describe('patched BlockNote suggestion wrapper', () => {
it('ignores stale query cleanup before running a suggestion item action', async () => {
const closeMenu = vi.fn()
const clearQuery = vi.fn(() => {
throw new RangeError('Position -1322 outside of fragment')
})
const onItemClick = vi.fn()
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
render(
<BlockNoteContext.Provider
value={{
editor: createEditor() as never,
setContentEditableProps: vi.fn(),
}}
>
<SuggestionMenuWrapper
query=""
closeMenu={closeMenu}
clearQuery={clearQuery}
getItems={async () => ['paragraph']}
suggestionMenuComponent={Menu}
onItemClick={onItemClick}
/>
</BlockNoteContext.Provider>,
)
fireEvent.click(await screen.findByRole('button', { name: 'Pick suggestion' }))
expect(closeMenu).toHaveBeenCalledOnce()
expect(clearQuery).toHaveBeenCalledOnce()
expect(onItemClick).not.toHaveBeenCalled()
await waitFor(() => {
expect(warn).toHaveBeenCalledWith(
'Ignored stale suggestion menu query cleanup:',
expect.any(RangeError),
)
})
warn.mockRestore()
})
})