Open hesselbom opened 4 years ago
I've tried to understand why, when y-indexeddb loads stored data, and updates CodeMirror, we don't get the same problem with a CodeMirror update resulting in two inserts. It appears that inside y-codemirror we have a typeObserver (with updates from our YText) and targetObserver (with updates from our CodeMirror) and because they're using the same mutex (from lib0/mutex) and get the updates at the same time only the typeObserver update is called. Type updates first, then target.
So the question is now why, when undoing a change, we don't get the same effect, that both type and target are updated simultaneously and thus targetObserver being ignored thanks to mutex.
It looks like when undoing we get first a typeObserver update and then a targetObserver update but both are running so maybe there is something happening async here, making the first typeObserver update not mutex block the targetObserver update.
Will continue investigating.
I believe I've found a solution, even if I'm a little bit unsure exactly why it works. Looking at CodeMirror source, if there is a curOp object (which there isn't is when y-indexeddb does its load), the operation() method appears to buffer operations and waits to call endOperation(), probably until no more operations are added. endOperation() flushes changes to the DOM.
So tried adding cm.endOperation() inside y-codemirror on line 69 like this:
// if possible, bundle the changes using cm.operation
if (cm) {
cm.operation(performChange)
cm.endOperation() // <-- new line
} else {
performChange()
}
And doing that for the reproducable demo I shared in my original post seems to solve the problem. I think this is a good solution but because I'm note 100% sure of all the side-effects of doing this I'll probably wait a bit for a PR until I've tested it more.
Describe the bug When deleting a character in CodeMirror editor, then undo-ing with Y.UndoManager, yjs reports that undo as two inputs. So even though the CodeMirror editor just shows one update, yjs "update" event gets called twice with two inputs making the resulting document value be incorrect.
My theory is something with Y.UndoManager reporting the undo, updating the Y.Text document and then updating CodeMirror, which recognizes an insert and reports that as a new insert operation. Or something similar, still investigating.
To Reproduce Steps to reproduce the behavior:
Expected behavior When undoing a delete, yjs should only insert the deleted character once, not twice. So the result in the above example should just read:
Screenshots
Environment Information
Additional context Files used to replicate problem:
package.json
index.html
index.js