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