I’ve tracked down what I think is an issue with observeDeep()
and Y.Array
updates.
I’ve put together the following code which shows the issue and the output when run.
I’m using YJS Version: 13.5.41 however I’ve also tested it on 13.5.43 and see the same issue.
The issue is when I add the first child docToAdd2
, I don’t see observeDeep()
yArrayCollection yArray yEvent
.
/** @package
yjs-observe.js
Author: NEVILLE FRANKS
Created: NF 12/12/2022 4:50:10 PM
Last change: NF 12/12/2022 6:11:32 PM
*/
import * as Y from 'yjs'
let ydocRoot, yMapCollection, yArrayCollection;
function createYJSTYpes(){
ydocRoot = new Y.Doc()
/* Simplify and skip yMapCollection
yMapCollection = ydocRoot.getMap( 'yMC' )
yMapCollection.observeDeep( fnObserver.bind( yMapCollection ) )
*/
yArrayCollection = ydocRoot.getArray( 'yAC' )
yArrayCollection.observeDeep( fnObserver.bind( yArrayCollection ) )
}
function addItem( yIndex, docToAdd ){
return new Promise( ( resolve, reject ) => {
ydocRoot.transact( () => {
const id = docToAdd.id
// 1) Create a new yMapCollection entry
// yMapCollection.set( id, docToAdd )
let added = false
// 2) add docToAdd.id to yArrayCollection. if yIndex is undefined create a create a new top level item else create a child item
if ( yIndex != undefined ){
if ( yArrayCollection.get( yIndex ) ){
newChildTreeNode( { ymap: yArrayCollection.get( yIndex ), id } )
added = true
}else
throw Error()
}
if ( !added ){
// Add it to the top level of the tree
const ymap = newTreeNode( { id } )
yArrayCollection.push( [ ymap ] )
}
resolve()
})
})
}
/** Create a ymap item from `id`
* @param {String} id - id of the noteDoc this node referes to.
* @return {YMap} - the new YMap object.
*/
function newTreeNode( { id } ){
let ymap = new Y.Map()
ymap.set( 'id', id )
return ymap
}
function newChildTreeNode( { ymap, id } ){
// create the new child map { id } node
const ymapChild = newTreeNode( { id } )
return pushChild( ymap, ymapChild )
}
function pushChild( ymap, ymapChild ){
// if ymap already has children just push the new node onto it.
if ( ymap.has( 'children' ) ){
ymap.get( 'children' ).push( [ ymapChild ] )
}else{
// create a new child array node, push new { id } ymap onto it and add the new branch to `ymap`. YJS Observe Deep isn't handling this correctly afaic.
const yarrayChildren = new Y.Array()
ymap.set( 'children', yarrayChildren )
yarrayChildren.push( [ ymapChild ] )
}
return ymapChild
}
function fnObserver( yEvents, transaction ){
yEvents.forEach( yEvent => {
const yName = this == yArrayCollection ? 'yArrayCollection' : 'yMapCollection';
if ( yEvent.target instanceof Y.Map ){
console.log( `fnObserver() ${yName} YMap - yEvent.keysChanged:`, yEvent.keysChanged, ', yEvent.changes:', yEvent.changes )
}else
if ( yEvent.target instanceof Y.Array ){
console.log( `fnObserver() ${yName} YArray - yEvent.changes:`, yEvent.changes )
}
})
}
/****************
******/
async function go( ){
createYJSTYpes()
const docToAdd1 = { id: 1 }
await addItem( undefined, docToAdd1 )
// add first child - we don't see Observer yArrayCollection yArray yEvent ???
const docToAdd2 = { id: 2 }
await addItem( 0, docToAdd2 )
// add second child
const docToAdd3 = { id: 3 }
await addItem( 0, docToAdd3 )
}
go()
When run this outputs:
fnObserver() yArrayCollection YArray - yEvent.changes: {
added: Set(1) {
Item {
id: [ID],
length: 1,
origin: null,
left: null,
right: null,
rightOrigin: null,
parent: [YArray],
parentSub: null,
redone: null,
content: [ContentType],
info: 2
}
},
deleted: Set(0) {},
delta: [ { insert: [Array] } ],
keys: Map(0) {}
}
==>> I expect to see yArrayCollection YArray - yEvent.changes here for docToAdd2.
fnObserver() yArrayCollection YMap - yEvent.keysChanged: Set(1) { 'children' } , yEvent.changes: {
added: Set(0) {},
deleted: Set(0) {},
delta: [],
keys: Map(1) { 'children' => { action: 'add', oldValue: undefined } }
}
fnObserver() yArrayCollection YArray - yEvent.changes: {
added: Set(1) {
Item {
id: [ID],
length: 1,
origin: [ID],
left: [Item],
right: null,
rightOrigin: null,
parent: [YArray],
parentSub: null,
redone: null,
content: [ContentType],
info: 2
}
},
deleted: Set(0) {},
delta: [ { retain: 1 }, { insert: [Array] } ],
keys: Map(0) {}
}