Skip to content

Commit 43d988d

Browse files
committed
use one mechanism to safely parse bluebell text
1 parent f93e8b3 commit 43d988d

File tree

1 file changed

+38
-41
lines changed

1 file changed

+38
-41
lines changed

indigo_app/static/javascript/indigo/views/document_xml_editor.js

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ class AknTextEditor {
1313
this.xmlElement = null;
1414
// copy of the original element being edited, for when changes are discarded
1515
this.xmlElementOriginal = null;
16-
// nonce to prevent concurrent saves
17-
this.nonce = null;
1816
this.dirty = false;
1917
// flag to prevent circular updates to the text
2018
this.updating = false;
@@ -110,28 +108,18 @@ class AknTextEditor {
110108
const text = this.monacoEditor.getValue();
111109
this.dirty = this.dirty || text !== this.previousText;
112110

113-
if (this.liveUpdates) {
114-
if (this.previousText !== text) {
115-
let elements;
111+
if (this.liveUpdates && this.previousText !== text) {
112+
const elements = await this.parseSafely();
113+
if (elements !== false) {
114+
this.previousText = text;
115+
this.updating = true;
116116
try {
117-
elements = await this.parse();
118-
} catch (err) {
119-
Indigo.errorView.show(err);
120-
return;
121-
}
122-
123-
// check that the response is still valid
124-
if (text === this.monacoEditor.getValue()) {
125-
this.previousText = text;
126-
try {
127-
this.updating = true;
128-
this.replaceElement(elements);
129-
} finally {
130-
// clear the flag after the next event loop, which gives mutation events a chance to be dispatched
131-
setTimeout(() => {
132-
this.updating = false;
133-
}, 0);
134-
}
117+
this.replaceElement(elements);
118+
} finally {
119+
// clear the flag after the next event loop, which gives mutation events a chance to be dispatched
120+
setTimeout(() => {
121+
this.updating = false;
122+
}, 0);
135123
}
136124
}
137125
}
@@ -202,42 +190,51 @@ class AknTextEditor {
202190
return newElement.documentElement.children;
203191
}
204192

193+
/**
194+
* Parse the text in the editor and ensure that it hasn't changed underneath us.
195+
* @returns {Promise<Element[]|boolean>}
196+
*/
197+
async parseSafely () {
198+
const text = this.monacoEditor.getValue();
199+
200+
try {
201+
const elements = await this.parse();
202+
// check that the response is still valid
203+
if (text === this.monacoEditor.getValue()) {
204+
return elements;
205+
}
206+
} catch (err) {
207+
Indigo.errorView.show(err);
208+
}
209+
210+
return false;
211+
}
212+
205213
/**
206214
* Accept the changes in the editor. This re-parses the text one last time and updates the DOM.
207-
*
208-
* @returns {Promise<boolean>} true if the changes were accepted, false if they were not
209215
*/
210216
async acceptChanges () {
211-
if (!this.editing) return false;
217+
if (!this.editing) return;
212218

213219
if (!this.liveUpdates) {
214-
let elements;
215-
// use a nonce to check if we're still the current save when the parse completes
216-
const nonce = this.nonce = Math.random();
217220
const btn = this.root.querySelector('.btn.save');
221+
btn.setAttribute('disabled', 'true');
218222

219223
try {
220-
btn.setAttribute('disabled', 'true');
221-
elements = await this.parse();
222-
} catch(err) {
223-
Indigo.errorView.show(err);
224-
return false;
224+
const elements = await this.parseSafely();
225+
if (elements === false) {
226+
return;
227+
}
228+
this.replaceElement(elements);
225229
} finally {
226230
btn.removeAttribute('disabled');
227231
}
228-
229-
// check if we're still the current save
230-
if (nonce !== this.nonce) return false;
231-
this.replaceElement(elements);
232232
}
233233

234234
this.editing = false;
235235
this.dirty = false;
236236
this.xmlElement = this.xmlElementOriginal = null;
237-
238237
this.onSave();
239-
240-
return true;
241238
}
242239

243240
/**

0 commit comments

Comments
 (0)