@@ -215,6 +215,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
215215 const { isLive, sendTransforms } = this . props ;
216216
217217 if ( isLive && sendTransforms && ! this . receivingCode ) {
218+ console . log ( changes ) ;
218219 this . addChangesOperation ( changes ) ;
219220 }
220221
@@ -435,7 +436,10 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
435436 */
436437 addChangesOperation = ( changes : Array < any > ) => {
437438 // Module changed in the meantime
438- if ( this . changes . moduleShortid !== this . currentModule . shortid ) {
439+ if (
440+ this . changes . moduleShortid &&
441+ this . changes . moduleShortid !== this . currentModule . shortid
442+ ) {
439443 this . sendChangeOperations ( ) ;
440444 }
441445
@@ -453,62 +457,77 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
453457 if ( this . changeTimeout ) {
454458 clearTimeout ( this . changeTimeout ) ;
455459 }
456- this . changeTimeout = setTimeout ( ( ) => {
457- this . sendChangeOperations ( ) ;
458- } , 10 ) ;
460+
461+ this . sendChangeOperations ( ) ;
459462 } ;
460463
461- sendChangeOperations = ( ) => {
464+ sendChangeOperations = ( retry : boolean = false ) => {
462465 const { sendTransforms, isLive, onCodeReceived } = this . props ;
463466
464- if (
465- sendTransforms &&
466- this . changes . changes &&
467- this . changes . moduleShortid === this . currentModule . shortid
468- ) {
469- let code = this . changes . code ;
470- const t = this . changes . changes
471- . map ( change => {
472- const startPos = change . range . getStartPosition ( ) ;
473- const lines = code . split ( '\n' ) ;
474- const totalLength = code . length ;
475- let index = lineAndColumnToIndex (
476- lines ,
477- startPos . lineNumber ,
478- startPos . column
479- ) ;
467+ try {
468+ if (
469+ sendTransforms &&
470+ this . changes . changes &&
471+ this . changes . moduleShortid === this . currentModule . shortid
472+ ) {
473+ let code = this . changes . code ;
474+ const t = this . changes . changes
475+ . map ( change => {
476+ const startPos = change . range . getStartPosition ( ) ;
477+ const lines = code . split ( '\n' ) ;
478+ const totalLength = code . length ;
479+ let index = lineAndColumnToIndex (
480+ lines ,
481+ startPos . lineNumber ,
482+ startPos . column
483+ ) ;
484+
485+ const operation = new TextOperation ( ) ;
486+ if ( index ) {
487+ operation . retain ( index ) ;
488+ }
480489
481- const operation = new TextOperation ( ) ;
482- if ( index ) {
483- operation . retain ( index ) ;
484- }
490+ if ( change . rangeLength > 0 ) {
491+ // Deletion
492+ operation . delete ( change . rangeLength ) ;
485493
486- if ( change . rangeLength > 0 ) {
487- // Deletion
488- operation . delete ( change . rangeLength ) ;
494+ index += change . rangeLength ;
495+ }
496+ if ( change . text ) {
497+ // Insertion
498+ operation . insert ( change . text ) ;
499+ }
489500
490- index += change . rangeLength ;
491- }
492- if ( change . text ) {
493- // Insertion
494- operation . insert ( change . text ) ;
495- }
501+ operation . retain ( Math . max ( 0 , totalLength - index ) ) ;
496502
497- operation . retain ( Math . max ( 0 , totalLength - index ) ) ;
503+ if ( this . changes . changes . length > 1 ) {
504+ code = operation . apply ( code ) ;
505+ }
498506
499- if ( this . changes . changes . length > 1 ) {
500- code = operation . apply ( code ) ;
501- }
507+ return operation ;
508+ } )
509+ . reduce ( ( prev , next ) => prev . compose ( next ) ) ;
502510
503- return operation ;
504- } )
505- . reduce ( ( prev , next ) => prev . compose ( next ) ) ;
511+ sendTransforms ( t ) ;
512+ } else if ( ! isLive && onCodeReceived ) {
513+ onCodeReceived ( ) ;
514+ }
515+ this . changes = { moduleShortid : null , code : '' , changes : [ ] } ;
516+ } catch ( e ) {
517+ if ( retry ) {
518+ throw e ;
519+ }
506520
507- sendTransforms ( t ) ;
508- } else if ( ! isLive && onCodeReceived ) {
509- onCodeReceived ( ) ;
521+ console . error ( e ) ;
522+ // This can happen on undo, Monaco sends a huge list of operations
523+ // that all apply to the same code and causes the `compose` function
524+ // to throw. The solution is to wait for the new code and try again. That's why
525+ // we call this function again in a timeout
526+
527+ setTimeout ( ( ) => {
528+ this . sendChangeOperations ( true ) ;
529+ } , 10 ) ;
510530 }
511- this . changes = { moduleShortid : null , code : '' , changes : [ ] } ;
512531 } ;
513532
514533 userClassesGenerated = { } ;
0 commit comments