Cscott has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/84440


Change subject: Record intention in `ve.dm.Transaction` object.
......................................................................

Record intention in `ve.dm.Transaction` object.

For OT purposes we try to reconcile the high level intention of the
transaction, not the raw low-level operations.  As a first step,
record the intention of the transaction in a field when it is created.

Note that the `intention` field is an array consisting of the name of a
constructor method in `ve.dm.Transaction` (starting with "new"), followed
by the non-document arguments to the constructor.  The first argument is
always a `ve.dm.Range` object giving the affected region; some methods
which take numeric offsets have been tweaked to allow collapsed ranges
instead.  If the second argument is a range, it gives the affected
region within the metadata at a given offset (given by a collapsed
range as the first argument).

Change-Id: I71117699b07f78a605d99a568e861d06e8fd3d0e
---
M modules/ve/dm/ve.dm.Transaction.js
M modules/ve/test/dm/ve.dm.Document.test.js
M modules/ve/test/dm/ve.dm.MetaList.test.js
M modules/ve/test/dm/ve.dm.Surface.test.js
M modules/ve/test/dm/ve.dm.Transaction.test.js
M modules/ve/test/dm/ve.dm.TransactionProcessor.test.js
6 files changed, 88 insertions(+), 34 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/40/84440/1

diff --git a/modules/ve/dm/ve.dm.Transaction.js 
b/modules/ve/dm/ve.dm.Transaction.js
index 5f319b1..bbc0aa9 100644
--- a/modules/ve/dm/ve.dm.Transaction.js
+++ b/modules/ve/dm/ve.dm.Transaction.js
@@ -11,7 +11,8 @@
  * @class
  * @constructor
  */
-ve.dm.Transaction = function VeDmTransaction() {
+ve.dm.Transaction = function VeDmTransaction( intention ) {
+       this.intention = intention;
        this.operations = [];
        this.lengthDifference = 0;
        this.applied = false;
@@ -30,7 +31,16 @@
  * @returns {ve.dm.Transaction} Transaction that inserts data
  */
 ve.dm.Transaction.newFromInsertion = function ( doc, offset, insertion ) {
-       var tx = new ve.dm.Transaction();
+       var tx;
+
+       if ( offset instanceof ve.Range ) {
+               offset = offset.from;
+       }
+
+       tx = new ve.dm.Transaction( [
+               'newFromInsertion', new ve.Range( offset ), insertion
+       ] );
+
        // Fix up the insertion
        insertion = doc.fixupInsertion( insertion, offset );
        // Retain up to insertion point, if needed
@@ -67,11 +77,13 @@
  * @throws {Error} Invalid range
  */
 ve.dm.Transaction.newFromRemoval = function ( doc, range ) {
-       var i, selection, first, last, nodeStart, nodeEnd,
+       var i, selection, first, last, nodeStart, nodeEnd, tx,
                offset = 0,
                removeStart = null,
-               removeEnd = null,
-               tx = new ve.dm.Transaction();
+               removeEnd = null;
+
+       tx = new ve.dm.Transaction( [ 'newFromRemoval', range ] );
+
        // Validate range
        if ( range.isCollapsed() ) {
                // Empty range, nothing to remove, retain up to the end of the 
document (for completeness)
@@ -162,13 +174,14 @@
  * @throws {Error} nodeOrRange must be a ve.dm.Node or a ve.Range
  */
 ve.dm.Transaction.newFromNodeReplacement = function ( doc, nodeOrRange, 
newData ) {
-       var tx = new ve.dm.Transaction(), range = nodeOrRange;
+       var tx, range = nodeOrRange;
        if ( range instanceof ve.dm.Node ) {
                range = range.getRange();
        }
        if ( !( range instanceof ve.Range ) ) {
                throw new Error( 'nodeOrRange must be a ve.dm.Node or a 
ve.Range' );
        }
+       tx = new ve.dm.Transaction( [ 'newFromNodeReplacement', range, newData 
] );
        tx.pushRetain( range.start );
        tx.pushReplace( doc, range.start, range.end - range.start, newData );
        tx.pushFinalRetain( doc, range.end );
@@ -189,9 +202,16 @@
  * @throws {Error} Cannot set attributes on closing element
  */
 ve.dm.Transaction.newFromAttributeChanges = function ( doc, offset, attr ) {
-       var key,
-               tx = new ve.dm.Transaction(),
-               data = doc.getData();
+       var tx, key, data = doc.getData();
+
+       if ( offset instanceof ve.Range ) {
+               offset = offset.from;
+       }
+
+       tx = new ve.dm.Transaction( [
+               'newFromAttributeChanges', new ve.Range( offset ), attr
+       ] );
+
        // Verify element exists at offset
        if ( data[offset].type === undefined ) {
                throw new Error( 'Cannot set attributes to non-element data' );
@@ -227,13 +247,17 @@
  * @returns {ve.dm.Transaction} Transaction that annotates content
  */
 ve.dm.Transaction.newFromAnnotation = function ( doc, range, method, 
annotation ) {
-       var covered, type,
-               tx = new ve.dm.Transaction(),
+       var covered, type, tx,
                data = doc.data,
                i = range.start,
                span = i,
                on = false,
                insideContentNode = false;
+
+       tx = new ve.dm.Transaction( [
+               'newFromAnnotation', range, method, annotation
+       ] );
+
        // Iterate over all data in range, annotating where appropriate
        while ( i < range.end ) {
                type = data.getType( i );
@@ -302,10 +326,18 @@
  * @returns {ve.dm.Transaction} Transaction that inserts the metadata elements
  */
 ve.dm.Transaction.newFromMetadataInsertion = function ( doc, offset, index, 
newElements ) {
-       var tx = new ve.dm.Transaction(),
-               data = doc.metadata,
-               elements = data.getData( offset ) || [];
+       var tx, elements,
+               data = doc.metadata;
 
+       if ( offset instanceof ve.Range ) {
+               offset = offset.from;
+       }
+
+       tx = new ve.dm.Transaction( [
+               'newFromMetadataInsertion', new ve.Range( offset ), index, 
newElements
+       ] );
+
+       elements = data.getData( offset ) || [];
        // Retain up to element
        tx.pushRetain( offset );
        // Retain up to metadata element (second dimension)
@@ -335,11 +367,18 @@
  * @throws {Error} Range out of bounds
  */
 ve.dm.Transaction.newFromMetadataRemoval = function ( doc, offset, range ) {
-       var selection,
-               tx = new ve.dm.Transaction(),
-               data = doc.metadata,
-               elements = data.getData( offset ) || [];
+       var selection, tx, elements,
+               data = doc.metadata;
 
+       if ( offset instanceof ve.Range ) {
+               offset = offset.from;
+       }
+
+       tx = new ve.dm.Transaction( [
+               'newFromMetadataRemoval', new ve.Range( offset ), range
+       ] );
+
+       elements = data.getData( offset ) || [];
        if ( !elements.length ) {
                throw new Error( 'Cannot remove metadata from empty list' );
        }
@@ -378,11 +417,19 @@
  * @throws {Error} Metadata index out of bounds
  */
 ve.dm.Transaction.newFromMetadataElementReplacement = function ( doc, offset, 
index, newElement ) {
-       var oldElement,
-               tx = new ve.dm.Transaction(),
-               data = doc.getMetadata(),
-               elements = data[offset] || [];
+       var oldElement, tx, elements,
+               data = doc.getMetadata();
 
+       if ( offset instanceof ve.Range ) {
+               offset = offset.from;
+       }
+
+       tx = new ve.dm.Transaction( [
+               'newFromMetadataElementReplacement',
+               new ve.Range( offset ), new ve.Range( index ), newElement
+       ] );
+
+       elements = data[offset] || [];
        if ( index >= elements.length ) {
                throw new Error( 'Metadata index out of bounds' );
        }
@@ -416,13 +463,17 @@
  * @returns {ve.dm.Transaction} Transaction that converts content branches
  */
 ve.dm.Transaction.newFromContentBranchConversion = function ( doc, range, 
type, attr ) {
-       var i, selected, branch, branchOuterRange,
-               tx = new ve.dm.Transaction(),
+       var i, selected, branch, branchOuterRange, tx,
                selection = doc.selectNodes( range, 'leaves' ),
                opening = { 'type': type },
                closing = { 'type': '/' + type },
                previousBranch,
                previousBranchOuterRange;
+
+       tx = new ve.dm.Transaction( [
+               'newFromContentBranchConversion', range, type, attr
+       ] );
+
        // Add attributes to opening if needed
        if ( ve.isPlainObject( attr ) ) {
                opening.attributes = attr;
@@ -497,10 +548,13 @@
  * @returns {ve.dm.Transaction}
  */
 ve.dm.Transaction.newFromWrap = function ( doc, range, unwrapOuter, wrapOuter, 
unwrapEach, wrapEach ) {
-       var i, j, unwrapOuterData, startOffset, unwrapEachData, 
closingUnwrapEach, closingWrapEach,
-               tx = new ve.dm.Transaction(),
+       var i, j, unwrapOuterData, startOffset, unwrapEachData, 
closingUnwrapEach, closingWrapEach, tx,
                depth = 0;
 
+       tx = new ve.dm.Transaction( [
+               'newFromWrap', range, unwrapOuter, wrapOuter, unwrapEach, 
wrapEach
+       ] );
+
        // Function to generate arrays of closing elements in reverse order
        function closingArray( openings ) {
                var closings = [], i, len = openings.length;
diff --git a/modules/ve/test/dm/ve.dm.Document.test.js 
b/modules/ve/test/dm/ve.dm.Document.test.js
index 0efe710..0ef03d9 100644
--- a/modules/ve/test/dm/ve.dm.Document.test.js
+++ b/modules/ve/test/dm/ve.dm.Document.test.js
@@ -394,7 +394,7 @@
 } );
 
 QUnit.test( 'protection against double application of transactions', 3, 
function ( assert ) {
-       var tx = new ve.dm.Transaction(),
+       var tx = new ve.dm.Transaction( [ 'bogus' ] ),
                testDocument = new ve.dm.Document( ve.dm.example.data );
        tx.pushRetain( 1 );
        tx.pushReplace( testDocument, 1, 0, ['H', 'e', 'l', 'l', 'o' ] );
diff --git a/modules/ve/test/dm/ve.dm.MetaList.test.js 
b/modules/ve/test/dm/ve.dm.MetaList.test.js
index cc8480d..7e3da27 100644
--- a/modules/ve/test/dm/ve.dm.MetaList.test.js
+++ b/modules/ve/test/dm/ve.dm.MetaList.test.js
@@ -118,7 +118,7 @@
        QUnit.expect( cases.length*( 4*doc.metadata.getTotalDataLength() + 2 ) 
);
 
        for ( i = 0; i < cases.length; i++ ) {
-               tx = new ve.dm.Transaction();
+               tx = new ve.dm.Transaction( [ 'bogus' ] );
                for ( j = 0; j < cases[i].calls.length; j++ ) {
                        tx[cases[i].calls[j][0]].apply( tx, 
cases[i].calls[j].slice( 1 ) );
                }
diff --git a/modules/ve/test/dm/ve.dm.Surface.test.js 
b/modules/ve/test/dm/ve.dm.Surface.test.js
index 232897d..edd62b4 100644
--- a/modules/ve/test/dm/ve.dm.Surface.test.js
+++ b/modules/ve/test/dm/ve.dm.Surface.test.js
@@ -34,7 +34,7 @@
 
 QUnit.test( 'change', 3, function ( assert ) {
        var surface = new ve.dm.SurfaceStub(),
-               tx = new ve.dm.Transaction(),
+               tx = new ve.dm.Transaction( [ 'bogus' ] ),
                events = {
                        'transact': 0,
                        'select': 0,
diff --git a/modules/ve/test/dm/ve.dm.Transaction.test.js 
b/modules/ve/test/dm/ve.dm.Transaction.test.js
index 116c6b9..1202cdf 100644
--- a/modules/ve/test/dm/ve.dm.Transaction.test.js
+++ b/modules/ve/test/dm/ve.dm.Transaction.test.js
@@ -12,7 +12,7 @@
 function runBuilderTests( assert, cases ) {
        var msg, tx, i;
        for ( msg in cases ) {
-               tx = new ve.dm.Transaction();
+               tx = new ve.dm.Transaction( [ 'bogus' ] );
                for ( i = 0; i < cases[msg].calls.length; i++ ) {
                        tx[cases[msg].calls[i][0]].apply( tx, 
cases[msg].calls[i].slice( 1 ) );
                }
@@ -1239,7 +1239,7 @@
 QUnit.test( 'translateOffset', function ( assert ) {
        var mapping, offset, expected,
                doc = new ve.dm.Document( '-----defg---h--'.split( '' ) ),
-               tx = new ve.dm.Transaction();
+               tx = new ve.dm.Transaction( [ 'bogus' ] );
 
        tx.pushReplace( doc, 0, 0, ['a','b','c'] );
        tx.pushRetain( 5 );
@@ -1281,7 +1281,7 @@
 QUnit.test( 'translateOffsetReversed', function ( assert ) {
        var mapping, offset, expected,
                doc = new ve.dm.Document( '-----defg---h--'.split( '' ) ),
-               tx = new ve.dm.Transaction();
+               tx = new ve.dm.Transaction( [ 'bogus' ] );
 
        tx.pushReplace( doc, 0, 0, ['a','b','c'] );
        tx.pushRetain( 5 );
@@ -1329,7 +1329,7 @@
 QUnit.test( 'translateRange', function ( assert ) {
        var i, cases,
                doc = ve.dm.example.createExampleDocument(),
-               tx = new ve.dm.Transaction();
+               tx = new ve.dm.Transaction( [ 'bogus' ] );
        tx.pushRetain( 55 );
        tx.pushReplace( doc, 55, 0, [ { 'type': 'list', 'attributes': { 
'style': 'number' } } ] );
        tx.pushReplace( doc, 55, 0, [ { 'type': 'listItem' } ] );
diff --git a/modules/ve/test/dm/ve.dm.TransactionProcessor.test.js 
b/modules/ve/test/dm/ve.dm.TransactionProcessor.test.js
index 4132067..1610082 100644
--- a/modules/ve/test/dm/ve.dm.TransactionProcessor.test.js
+++ b/modules/ve/test/dm/ve.dm.TransactionProcessor.test.js
@@ -557,7 +557,7 @@
                        ve.dm.example.preprocessAnnotations( ve.copy( 
originalData ), store )
                );
 
-               tx = new ve.dm.Transaction();
+               tx = new ve.dm.Transaction( [ 'bogus' ] );
                for ( i = 0; i < cases[msg].calls.length; i++ ) {
                        // some calls need the document as its first argument
                        if ( /^(pushReplace$|new)/.test( cases[msg].calls[i][0] 
) ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/84440
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I71117699b07f78a605d99a568e861d06e8fd3d0e
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Cscott <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to