Must `get` Shared Types from ydoc for updates to work

Hi, I’ve just found some behavior that I’m a bit confused by, and I didn’t think this was how YJs worked, but after some experimenting… it does.

My basic issue is that when I recreate a Y.Doc() using updates (received from listeners), the new ydoc does not have all the Shared Types I expect it to unless I’ve asked for those types explicitly using ydoc.get(). Here is a repro of what I’m talking about.

import * as Y from 'yjs';

const ydoc = new Y.Doc();
const ytext = ydoc.getText("text")
const ymap = ydoc.getMap("map")

let mergedUpdates = null
const updateListener = (update) => {
  mergedUpdates = mergedUpdates ? Y.mergeUpdates([mergedUpdates, update]) : update;
  console.log("merged:", mergedUpdates.toString())
}

ydoc.on("update", updateListener);
ydoc.transact(() => {
  ytext.insert(0, "ok")
  ymap.set("key", "val")
})


// create new ydoc from updates, asking for the text and map fields up front
const y2 = new Y.Doc();
const y2t = y2.getText("text")
const y2m = y2.getMap("map")
Y.applyUpdate(y2, mergedUpdates)

// create new ydoc from updates without asking for the text and map fields
const y3 = new Y.Doc();
Y.applyUpdate(y3, mergedUpdates)

console.log("ydoc", ydoc.toJSON()) // { text: 'ok', map: { key: 'val' } }
console.log("y2", y2.toJSON()) // { text: 'ok', map: { key: 'val' } }
console.log("y3", y3.toJSON()) //  { text: undefined, map: undefined }

I was expecting the three console.logs at the end to be the same, but as you can see the third ydoc (y3) shows the text and map types, but their values are undefined. Is this expected behavior? Am I weird for wanting to be able to not know explicitly what types have been on a ydoc and still expect Y.applyUpdate to work?

Thanks!

2 Likes

Any thoughts on this @dmonad?

Doc.toJSON is deprecated, probably for this reason. Instead it is recommended to call toJSON directly on the shared types.

Your top-level types are effectively part of your “schema”, so it is assumed that they will be known at compile-time. You could wrap everything in a top-level doc.getMap('root'), and then you would be able to able to iterate over the entries.

1 Like