[Bug?] empty top-level doc items do not seem to be persisted

The following code

  const sharedDoc = new Y.Doc()
    sharedDoc.getMap('sharedMap')
    sharedDoc.getArray('sharedArray')
    sharedDoc.get('sharedText',Y.Text)
    sharedDoc.get('sharedXmlElement',Y.XmlElement)
    sharedDoc.get('sharedXmlFragment',Y.XmlFragment)
    sharedDoc.get('sharedXmlText',Y.XmlText)
//  sharedDoc.get('sharedDoc',Y.Doc) // is not allowed
//console.log('sharedDoc',sharedDoc)

  const Persistence = new IndexeddbPersistence('Yjs-Test-TopLevel-Content',sharedDoc)
  Persistence.on('synced', async () => {
    console.log('persisted')

    const sharedDoc   = new Y.Doc()
    const Persistence = new IndexeddbPersistence('Yjs-Test-TopLevel-Content',sharedDoc)
    Persistence.on('synced', async () => {
      console.log('loaded')
      console.log('sharedDoc.share',sharedDoc.share)
    })
  })

(run in a browser) shows that all the top-level “shared types” will not be persisted.

However, if these top-level entries contain some (dummy) data, persistence works as intended:

  const sharedDoc = new Y.Doc()
    sharedDoc.getMap('sharedMap').set('Dummy',true)
    sharedDoc.getArray('sharedArray').insert(0,['Dummy'])
    sharedDoc.get('sharedText',Y.Text).insert(0,'Dummy')
    sharedDoc.get('sharedXmlElement',Y.XmlElement).setAttribute('Dummy','Dummy')
    sharedDoc.get('sharedXmlFragment',Y.XmlFragment).insert(0,[new Y.XmlText()])
    sharedDoc.get('sharedXmlText',Y.XmlText).insert(0,'Dummy')
//  sharedDoc.get('sharedDoc',Y.Doc) // is not allowed
//console.log('sharedDoc',sharedDoc)

  const Persistence = new IndexeddbPersistence('Yjs-Test-TopLevel-Content',sharedDoc)
  Persistence.on('synced', async () => {
    console.log('persisted')

    const sharedDoc   = new Y.Doc()
    const Persistence = new IndexeddbPersistence('Yjs-Test-TopLevel-Content',sharedDoc)
    Persistence.on('synced', async () => {
      console.log('loaded')
      console.log('sharedDoc.share',sharedDoc.share)
    })
  })

Is this really the intended behaviour?

Yes. When do you need empty top-level shared types?

Well, for the same reason that there are empty maps and empty arrays.

I would have expected a note in the docs, at least.

@raine do you know if it’s possibly to have empty YText? Been searching Discord and the Community here for an answer. I’m trying to YText.insert(0, '', { bold: true }) as an example, but it seems empty strings may not be permitted? How can you have an “empty paragraph” then (a paragraph with empty text)?

Thanks if you know!

@BrentFarese I’m not sure, I haven’t worked with YText.

Empty maps and empty arrays are instances, whereas top-level types are singletons. So, there is no need to persist an empty top-level shared type because they are effectively already instantiated.

Another way to put it is that top-level shared types are non-nullable.

However, the implication is that if you need to differentiate a defined state from an undefined state, you would need to store a separate initialized flag.