From 009ae48671b7e88eca97188ae7b9a128096352db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20R=C3=A4dle?= Date: Thu, 7 Jan 2021 10:50:01 -0800 Subject: [PATCH 1/2] [ISSUE #7] ITextModel.pushEditOperations will eventually create delete ops when local ops are applied, which can lead to inconsistent ITextModels on the different clients. Using the ITextModel.applyEdits prevents these ops --- src/y-monaco.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/y-monaco.js b/src/y-monaco.js index 4ed388f..f2a9b1f 100644 --- a/src/y-monaco.js +++ b/src/y-monaco.js @@ -10,7 +10,7 @@ class RelativeSelection { * @param {Y.RelativePosition} end * @param {monaco.SelectionDirection} direction */ - constructor (start, end, direction) { + constructor(start, end, direction) { this.start = start this.end = end this.direction = direction @@ -60,7 +60,7 @@ export class MonacoBinding { * @param {Set} [editors] * @param {Awareness?} [awareness] */ - constructor (ytext, monacoModel, editors = new Set(), awareness = null) { + constructor(ytext, monacoModel, editors = new Set(), awareness = null) { this.doc = /** @type {Y.Doc} */ (ytext.doc) this.ytext = ytext this.monacoModel = monacoModel @@ -135,18 +135,17 @@ export class MonacoBinding { } else if (op.insert !== undefined) { const pos = monacoModel.getPositionAt(index) const range = new monaco.Selection(pos.lineNumber, pos.column, pos.lineNumber, pos.column) - monacoModel.pushEditOperations([], [{ range, text: op.insert }], () => null) + monacoModel.applyEdits([{ range, text: op.insert }]) index += op.insert.length } else if (op.delete !== undefined) { const pos = monacoModel.getPositionAt(index) const endPos = monacoModel.getPositionAt(index + op.delete) const range = new monaco.Selection(pos.lineNumber, pos.column, endPos.lineNumber, endPos.column) - monacoModel.pushEditOperations([], [{ range, text: '' }], () => null) + monacoModel.applyEdits([{ range, text: '' }]) } else { throw error.unexpectedCase() } }) - monacoModel.pushStackElement() this._savedSelections.forEach((rsel, editor) => { const sel = createMonacoSelectionFromRelativeSelection(editor, ytext, rsel, this.doc) if (sel !== null) { @@ -199,7 +198,7 @@ export class MonacoBinding { } } - destroy () { + destroy() { this._monacoChangeHandler.dispose() this.ytext.unobserve(this._ytextObserver) this.doc.off('beforeAllTransactions', this._beforeTransaction) From 8ed54ef669130ff703dc440fc10523c64c635b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20R=C3=A4dle?= Date: Thu, 7 Jan 2021 10:50:01 -0800 Subject: [PATCH 2/2] [ISSUE #7] ITextModel.pushEditOperations will eventually create delete ops when local ops are applied, which can lead to inconsistent ITextModels on the different clients. Using the ITextModel.applyEdits prevents these ops --- src/y-monaco.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/y-monaco.js b/src/y-monaco.js index 4ed388f..182786f 100644 --- a/src/y-monaco.js +++ b/src/y-monaco.js @@ -135,18 +135,17 @@ export class MonacoBinding { } else if (op.insert !== undefined) { const pos = monacoModel.getPositionAt(index) const range = new monaco.Selection(pos.lineNumber, pos.column, pos.lineNumber, pos.column) - monacoModel.pushEditOperations([], [{ range, text: op.insert }], () => null) + monacoModel.applyEdits([{ range, text: op.insert }]) index += op.insert.length } else if (op.delete !== undefined) { const pos = monacoModel.getPositionAt(index) const endPos = monacoModel.getPositionAt(index + op.delete) const range = new monaco.Selection(pos.lineNumber, pos.column, endPos.lineNumber, endPos.column) - monacoModel.pushEditOperations([], [{ range, text: '' }], () => null) + monacoModel.applyEdits([{ range, text: '' }]) } else { throw error.unexpectedCase() } }) - monacoModel.pushStackElement() this._savedSelections.forEach((rsel, editor) => { const sel = createMonacoSelectionFromRelativeSelection(editor, ytext, rsel, this.doc) if (sel !== null) {