I am writing a music live coding editor where decoration changes can be dispatched every frame.
When the document gets shorter, it can happen that changes are fired that still receive the old document state, leading to errors like:
Position 281 is out of range for changeset of length 180
When that error happens, the application crashes and gets into an unusable state. It would be really helpful to be able to catch that error and just ignore it, because it is not critical if a highlight is missed.
I assume the problem is that the document changes between the call to view.dispatch and the actual execution, possibly because requestAnimationFrame is not fired synchronously.
Questions:
Is there a way to hook into codemirrors requestAnimationFrame loop or a way to always get the latest state of the document?
If this is a just a problem with the react component, wouldn’t it still make sense to be able to catch critical errors?
dispatch happens entirely synchronously. If you can reproduce an issue like this without react and react-codemirror, I’d be interested in debugging that. As it is, I don’t know what magic might be going on inside that React component.
Your field definition isn’t mapping the decoration set through the transaction’s changes, which will cause it to still have decorations pointing at parts of the document that no longer exist, leading to this error. Add a line like highlights = highlights.map(tr.changes) at the top of the update function to avoid that.
thank you both for the help! We have now managed to use the codemirror API to make the highlights work much better FYI this is the result: Strudel REPL
extra thanks to @marijn for the incredible work in the JS space! we use both acorn and codemirror in strudel and it’s amazing what you can do with it