Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-collab-caret-null-awareness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tiptap/extension-collaboration-caret': patch
---

Fix crash when awareness state value is null or undefined (e.g. after a client disconnects)
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,66 @@ describe('extension-collaboration-caret', () => {

getEditorEl()?.remove()
})

it('should handle null or undefined awareness state values without crashing', () => {
const ydoc = new Y.Doc()

const states = new Map<number, Record<string, any> | null>()

states.set(1, { user: { name: 'Alice', color: '#ff0000' } })
states.set(2, null as any)
states.set(3, undefined as any)
Comment thread
bdbch marked this conversation as resolved.
states.set(4, { user: { name: 'Bob', color: '#00ff00' } })

const mockProvider = {
awareness: {
states,
setLocalStateField: () => {},
on: () => {},
off: () => {},
getStates: () => states,
},
}

const editorEl = createEditorEl()

const editor = new Editor({
element: editorEl,
extensions: [
Document,
Paragraph,
Text,
Collaboration.configure({
document: ydoc,
}),
CollaborationCaret.configure({
provider: mockProvider,
user: {
name: 'Test User',
color: '#0000ff',
},
}),
],
})

const users = editor.storage.collaborationCaret.users

expect(users).toEqual(
expect.arrayContaining([
expect.objectContaining({ clientId: 1, name: 'Alice', color: '#ff0000' }),
expect.objectContaining({ clientId: 4, name: 'Bob', color: '#00ff00' }),
]),
)

const nullUser = users.find((u: any) => u.clientId === 2)

expect(nullUser).toEqual({ clientId: 2 })

const undefinedUser = users.find((u: any) => u.clientId === 3)

expect(undefinedUser).toEqual({ clientId: 3 })

editor.destroy()
getEditorEl()?.remove()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,16 @@ declare module '@tiptap/core' {
}
}

const awarenessStatesToArray = (states: Map<number, Record<string, any>>) => {
const awarenessStatesToArray = (states: Map<number, Record<string, any> | null | undefined>) => {
return Array.from(states.entries()).map(([key, value]) => {
if (value) {
Comment thread
bdbch marked this conversation as resolved.
Outdated
return {
clientId: key,
...value.user,
}
}
return {
clientId: key,
...value.user,
}
})
}
Expand Down
Loading