Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit a5cf8b1

Browse files
author
Piotr Jasiun
authored
Merge pull request #1459 from ckeditor/t/new-ot-w-tests
Other: Removed concept of deltas. Added new operations. Rewritten OT algorithms. Closes #1162. BREAKING CHANGE: Everything connected with deltas was removed from the editor. BREAKING CHANGE: `model.Writer#setAttribute` (and `AttributeOperation`) now applies attribute only to the top-level nodes in the `range` (instead of all the nodes in the range).
2 parents 25e3aaf + 82d7715 commit a5cf8b1

File tree

123 files changed

+9955
-12581
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+9955
-12581
lines changed

src/dev-utils/deltareplayer.js

Lines changed: 0 additions & 143 deletions
This file was deleted.

src/dev-utils/enableenginedebug.js

Lines changed: 18 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
/* global console */
1111

12-
import DeltaReplayer from './deltareplayer';
12+
import OperationReplayer from './operationreplayer';
1313

1414
import ModelPosition from '../model/position';
1515
import ModelRange from '../model/range';
@@ -25,18 +25,7 @@ import MoveOperation from '../model/operation/moveoperation';
2525
import NoOperation from '../model/operation/nooperation';
2626
import RenameOperation from '../model/operation/renameoperation';
2727
import RootAttributeOperation from '../model/operation/rootattributeoperation';
28-
import Delta from '../model/delta/delta';
29-
import AttributeDelta from '../model/delta/attributedelta';
30-
import InsertDelta from '../model/delta/insertdelta';
31-
import MarkerDelta from '../model/delta/markerdelta';
32-
import MergeDelta from '../model/delta/mergedelta';
33-
import MoveDelta from '../model/delta/movedelta';
34-
import RenameDelta from '../model/delta/renamedelta';
35-
import RootAttributeDelta from '../model/delta/rootattributedelta';
36-
import SplitDelta from '../model/delta/splitdelta';
37-
import UnwrapDelta from '../model/delta/unwrapdelta';
38-
import WrapDelta from '../model/delta/wrapdelta';
39-
import deltaTransform from '../model/delta/transform';
28+
import transform from '../model/operation/transform';
4029
import Model from '../model/model';
4130
import ModelDocument from '../model/document';
4231
import ModelDocumentFragment from '../model/documentfragment';
@@ -51,8 +40,6 @@ import ViewDocumentFragment from '../view/documentfragment';
5140
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
5241
import Editor from '@ckeditor/ckeditor5-core/src/editor/editor';
5342

54-
import clone from '@ckeditor/ckeditor5-utils/src/lib/lodash/clone';
55-
5643
// Sandbox class allows creating mocks of the functions and restoring these mocks to the original values.
5744
class Sandbox {
5845
constructor() {
@@ -98,7 +85,7 @@ const treeDump = Symbol( '_treeDump' );
9885
// Maximum number of stored states of model and view document.
9986
const maxTreeDumpLength = 20;
10087

101-
// Separator used to separate stringified deltas
88+
// Separator used to separate stringified operations
10289
const LOG_SEPARATOR = '-------';
10390

10491
// Specified whether debug tools were already enabled.
@@ -122,16 +109,14 @@ let logger = console;
122109
* * {@link module:engine/model/documentfragment~DocumentFragment model.DocumentFragment},
123110
* * {@link module:engine/model/document~Document model.Document},
124111
* * all {@link module:engine/model/operation/operation~Operation operations}
125-
* * all {@link module:engine/model/delta/delta~Delta deltas},
126112
* * {@link module:engine/view/element~Element view.Element},
127113
* * {@link module:engine/view/documentfragment~DocumentFragment view.DocumentFragment},
128114
* * {@link module:engine/view/document~Document view.Document}.
129115
*
130116
* Additionally, the following logging utility methods are added:
131117
* * {@link module:engine/model/text~Text model.Text} `logExtended`,
132118
* * {@link module:engine/model/element~Element model.Element} `logExtended`,
133-
* * {@link module:engine/model/element~Element model.Element} `logAll`,
134-
* * {@link module:engine/model/delta/delta~Delta model.Delta} `logAll`.
119+
* * {@link module:engine/model/element~Element model.Element} `logAll`.
135120
*
136121
* Additionally, the following classes are expanded with `logTree` and `printTree` methods:
137122
* * {@link module:engine/model/element~Element model.Element},
@@ -364,136 +349,24 @@ function enableLoggingTools() {
364349
`"${ this.key }": ${ JSON.stringify( this.oldValue ) } -> ${ JSON.stringify( this.newValue ) }, ${ this.root.rootName }`;
365350
} );
366351

367-
sandbox.mock( Delta.prototype, 'log', function() {
368-
logger.log( this.toString() );
369-
} );
370-
371-
sandbox.mock( Delta.prototype, 'logAll', function() {
372-
logger.log( '--------------------' );
373-
374-
this.log();
375-
376-
for ( const op of this.operations ) {
377-
op.log();
378-
}
379-
} );
380-
381-
sandbox.mock( Delta.prototype, '_saveHistory', function( itemToSave ) {
382-
const history = itemToSave.before.history ? itemToSave.before.history : [];
383-
384-
itemToSave.before = clone( itemToSave.before );
385-
delete itemToSave.before.history;
386-
itemToSave.before = JSON.stringify( itemToSave.before );
387-
388-
itemToSave.transformedBy = clone( itemToSave.transformedBy );
389-
delete itemToSave.transformedBy.history;
390-
itemToSave.transformedBy = JSON.stringify( itemToSave.transformedBy );
391-
392-
this.history = history.concat( itemToSave );
393-
} );
394-
395-
const _deltaTransformTransform = deltaTransform.transform;
352+
const _transformTransform = transform.transform;
396353

397-
sandbox.mock( deltaTransform, 'transform', function( a, b, context ) {
354+
sandbox.mock( transform, 'transform', function( a, b, context ) {
398355
let results;
399356

400357
try {
401-
results = _deltaTransformTransform( a, b, context );
358+
results = _transformTransform( a, b, context );
402359
} catch ( e ) {
403-
logger.error( 'Error during delta transformation!' );
360+
logger.error( 'Error during operation transformation!' );
404361
logger.error( a.toString() + ( context.isStrong ? ' (important)' : '' ) );
405362
logger.error( b.toString() + ( context.isStrong ? '' : ' (important)' ) );
406363

407364
throw e;
408365
}
409366

410-
for ( let i = 0; i < results.length; i++ ) {
411-
results[ i ]._saveHistory( {
412-
before: a,
413-
transformedBy: b,
414-
wasImportant: !!context.isStrong,
415-
resultIndex: i,
416-
resultsTotal: results.length
417-
} );
418-
}
419-
420367
return results;
421368
} );
422369

423-
sandbox.mock( AttributeDelta.prototype, 'toString', function() {
424-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
425-
`"${ this.key }": -> ${ JSON.stringify( this.value ) }, ${ this.range }, ${ this.operations.length } ops`;
426-
} );
427-
428-
sandbox.mock( InsertDelta.prototype, 'toString', function() {
429-
const op = this._insertOperation;
430-
const nodeString = op.nodes.length > 1 ? `[ ${ op.nodes.length } ]` : op.nodes.getNode( 0 );
431-
432-
return getClassName( this ) + `( ${ this.baseVersion } ): ${ nodeString } -> ${ op.position }`;
433-
} );
434-
435-
sandbox.mock( MarkerDelta.prototype, 'toString', function() {
436-
const op = this.operations[ 0 ];
437-
438-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
439-
`"${ op.name }": ${ op.oldRange } -> ${ op.newRange }`;
440-
} );
441-
442-
sandbox.mock( MergeDelta.prototype, 'toString', function() {
443-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
444-
( this.position ?
445-
this.position.toString() :
446-
`(move from ${ this.operations[ 0 ].sourcePosition })`
447-
);
448-
} );
449-
450-
sandbox.mock( MoveDelta.prototype, 'toString', function() {
451-
const opStrings = [];
452-
453-
for ( const op of this.operations ) {
454-
const range = ModelRange.createFromPositionAndShift( op.sourcePosition, op.howMany );
455-
456-
opStrings.push( `${ range } -> ${ op.targetPosition }` );
457-
}
458-
459-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
460-
opStrings.join( '; ' );
461-
} );
462-
463-
sandbox.mock( RenameDelta.prototype, 'toString', function() {
464-
const op = this.operations[ 0 ];
465-
466-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
467-
`${ op.position }: "${ op.oldName }" -> "${ op.newName }"`;
468-
} );
469-
470-
sandbox.mock( RootAttributeDelta.prototype, 'toString', function() {
471-
const op = this.operations[ 0 ];
472-
473-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
474-
`"${ op.key }": ${ JSON.stringify( op.oldValue ) } -> ${ JSON.stringify( op.newValue ) }, ${ op.root.rootName }`;
475-
} );
476-
477-
sandbox.mock( SplitDelta.prototype, 'toString', function() {
478-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
479-
( this.position ?
480-
this.position.toString() :
481-
`(clone to ${ this._cloneOperation.position || this._cloneOperation.targetPosition })`
482-
);
483-
} );
484-
485-
sandbox.mock( UnwrapDelta.prototype, 'toString', function() {
486-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
487-
this.position.toString();
488-
} );
489-
490-
sandbox.mock( WrapDelta.prototype, 'toString', function() {
491-
const wrapElement = this._insertOperation.nodes.getNode( 0 );
492-
493-
return getClassName( this ) + `( ${ this.baseVersion } ): ` +
494-
`${ this.range } -> ${ wrapElement }`;
495-
} );
496-
497370
sandbox.mock( ViewText.prototype, 'toString', function() {
498371
return `#${ this.data }`;
499372
} );
@@ -569,30 +442,25 @@ function enableReplayerTools() {
569442
const _modelApplyOperation = Model.prototype.applyOperation;
570443

571444
sandbox.mock( Model.prototype, 'applyOperation', function( operation ) {
572-
if ( !this._lastDelta ) {
573-
this._appliedDeltas = [];
574-
} else if ( this._lastDelta !== operation.delta ) {
575-
this._appliedDeltas.push( this._lastDelta.toJSON() );
445+
if ( !this._appliedOperations ) {
446+
this._appliedOperations = [];
576447
}
577448

578-
this._lastDelta = operation.delta;
449+
this._appliedOperations.push( operation.toJSON() );
579450

580451
return _modelApplyOperation.call( this, operation );
581452
} );
582453

583-
sandbox.mock( Model.prototype, 'getAppliedDeltas', function() {
584-
// No deltas has been applied yet, return empty string.
585-
if ( !this._lastDelta ) {
454+
sandbox.mock( Model.prototype, 'getAppliedOperations', function() {
455+
if ( !this._appliedOperations ) {
586456
return '';
587457
}
588458

589-
const appliedDeltas = this._appliedDeltas.concat( this._lastDelta );
590-
591-
return appliedDeltas.map( JSON.stringify ).join( LOG_SEPARATOR );
459+
return this._appliedOperations.map( JSON.stringify ).join( LOG_SEPARATOR );
592460
} );
593461

594-
sandbox.mock( Model.prototype, 'createReplayer', function( stringifiedDeltas ) {
595-
return new DeltaReplayer( this, LOG_SEPARATOR, stringifiedDeltas );
462+
sandbox.mock( Model.prototype, 'createReplayer', function( stringifiedOperations ) {
463+
return new OperationReplayer( this, LOG_SEPARATOR, stringifiedOperations );
596464
} );
597465
}
598466

@@ -694,8 +562,8 @@ function dumpTrees( document, version ) {
694562
}
695563
}
696564

697-
// Helper function, returns the class name of a given `Delta` or `Operation`.
698-
// @param {module:engine/model/delta/delta~Delta|module:engine/model/operation/operation~Operation}
565+
// Helper function, returns the class name of a given `Operation`.
566+
// @param {module:engine/model/operation/operation~Operation}
699567
// @returns {String} Class name.
700568
function getClassName( obj ) {
701569
const path = obj.constructor.className.split( '.' );

0 commit comments

Comments
 (0)