automerge / automerge-classic

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.
http://automerge.org/
MIT License
14.75k stars 466 forks source link

Cannot read property 'backendState' of undefined #329

Closed michaelvogt closed 3 years ago

michaelvogt commented 3 years ago

Hello.

I'm using automerge through perge. When running the demo exactly as shown with the gif in the readme, I get the following exception:

Uncaught TypeError: Cannot read property 'backendState' of undefined at Object.getBackendState (index.js:488) at Connection.docChanged (connection.js:77) at doc_set.js:26 at immutable.js:3905 at immutable.js:1377 at ArrayMapNode.iterate.HashCollisionNode.iterate (immutable.js:1726) at Map.iterate (immutable.js:1375) at Set.iterate (immutable.js:3905) at Set.forEach (immutable.js:4381) at DocSet.setDoc (doc_set.js:26)

I'm using Chrome 91 on Windows 10 with automerge 0.14.2

To takle the symptom, I changed

doc[STATE].backendState

to

const docsymbols = Object.getOwnPropertySymbols(doc) return doc[docsymbols[5]].backendState

which obviously doesn't solve the actual problem, but fixes the exception.

ept commented 3 years ago

Hi @michaelvogt, it looks like the symbol STATE does not exist on the document. I'm not sure how that would happen; one theory is that maybe the Automerge library is somehow getting loaded twice, and that you're taking an Automerge document created by one instance of the library and then handing it to the other instance of the library. This would presumably be due to the way you are loading or bundling library dependencies. I don't know enough about the JS ecosystem to know how this might happen, but perhaps someone else in the community can help.

To help debug this, could you make a self-contained project that reproduces the issue? Ideal would be a minimal repo that imports perge and that triggers this exception.

michaelvogt commented 3 years ago

Hello @ept.

Thank you for your response.

I have just used the default example from perge. Unfortunately I can't reproduce the exception right now. So I will close this issue and my reopen when I encounter it again.

michaelvogt commented 3 years ago

Hello @ept

I can reproduce the problem again.

Please find the sample here. It is pretty much the example from perge.

When opening 2 browser windows with this url, copy the actor id from one window and connect with it from another window, this exception is thrown

` Uncaught TypeError: Cannot read property 'backendState' of undefined

at Object.getBackendState (example.77de5100.js:14994)
at getChanges (example.77de5100.js:30096)
at Object.getAllChanges (example.77de5100.js:30101)
at Perge.connect (example.77de5100.js:31037)
at HTMLFormElement.peerForm.onsubmit (example.77de5100.js:31253)

` What I want to accomplish is to send the current automerge doc state to newly connecting peers. For this, I added

peer.send(_this._encode(automerge_1.getAllChanges(this.docSet)));

to line 31032 (thanks ts)

I found issue #96 and tried to adapt it to my code, but either there is no update or I get this exception.

Any tips on how to get the current state transmitted to a newly connecting peer would be highly appreciated.

lukesmurray commented 3 years ago

FWIW I can reproduce this in the CRDT-benchmarks repo. rm package-lock.json upgrade the automerge dependency in package.json to "automerge": "^1.0.1-preview.0", and try npm i && npm start. I'm very new to automerge so I haven't tried to fix or diagnose the problem but if the issue is common then some upgrade docs could be useful! Cheers!

ept commented 3 years ago

Okay, I believe what's happening here is that the object getting passed into the Automerge function (such as getChanges) is not actually an Automerge document. In the case of the CRDT-benchmarks repo this is because the API has changed between 0.14 and 1.0-preview, so the benchmarks will need to be updated. In the benchmarks in particular, applyChanges used to return a document but now returns an array whose first element is the document. The benchmark is taking the return value of applyChanges and passing it directly to applyChanges again, so the first argument is an array rather than an Automerge document.

For TypeScript users, the type definitions ought to catch this. I have also improved the error messages in f0bf79b73f1a91be854faf2e80bdd3b5d62d7a3d to make them more helpful.