@@ -13,8 +13,6 @@ class AknTextEditor {
13
13
this . xmlElement = null ;
14
14
// copy of the original element being edited, for when changes are discarded
15
15
this . xmlElementOriginal = null ;
16
- // nonce to prevent concurrent saves
17
- this . nonce = null ;
18
16
this . dirty = false ;
19
17
// flag to prevent circular updates to the text
20
18
this . updating = false ;
@@ -110,28 +108,18 @@ class AknTextEditor {
110
108
const text = this . monacoEditor . getValue ( ) ;
111
109
this . dirty = this . dirty || text !== this . previousText ;
112
110
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 ;
116
116
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 ) ;
135
123
}
136
124
}
137
125
}
@@ -202,42 +190,51 @@ class AknTextEditor {
202
190
return newElement . documentElement . children ;
203
191
}
204
192
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
+
205
213
/**
206
214
* 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
209
215
*/
210
216
async acceptChanges ( ) {
211
- if ( ! this . editing ) return false ;
217
+ if ( ! this . editing ) return ;
212
218
213
219
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 ( ) ;
217
220
const btn = this . root . querySelector ( '.btn.save' ) ;
221
+ btn . setAttribute ( 'disabled' , 'true' ) ;
218
222
219
223
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 ) ;
225
229
} finally {
226
230
btn . removeAttribute ( 'disabled' ) ;
227
231
}
228
-
229
- // check if we're still the current save
230
- if ( nonce !== this . nonce ) return false ;
231
- this . replaceElement ( elements ) ;
232
232
}
233
233
234
234
this . editing = false ;
235
235
this . dirty = false ;
236
236
this . xmlElement = this . xmlElementOriginal = null ;
237
-
238
237
this . onSave ( ) ;
239
-
240
- return true ;
241
238
}
242
239
243
240
/**
0 commit comments