Skip to content

Commit 662c2c8

Browse files
committed
Only process signals created by an operation after execution is complete
This ensures the operation cannot be accidentally interrupted by an external consumer of an event.
1 parent db2096f commit 662c2c8

File tree

7 files changed

+45
-7
lines changed

7 files changed

+45
-7
lines changed

webodf/lib/ops/OdtDocument.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
7979
/**@const*/ SHOW_ALL = NodeFilter.SHOW_ALL,
8080
blacklistedNodes = new gui.BlacklistNamespaceNodeFilter(["urn:webodf:names:cursor", "urn:webodf:names:editinfo"]),
8181
odfTextBodyFilter = new gui.OdfTextBodyNodeFilter(),
82-
defaultNodeFilter = new core.NodeFilterChain([blacklistedNodes, odfTextBodyFilter]);
82+
defaultNodeFilter = new core.NodeFilterChain([blacklistedNodes, odfTextBodyFilter]),
83+
/**@type{!Array.<!function():undefined>}*/
84+
pendingSignals = [];
8385

8486
/**
8587
*
@@ -890,12 +892,18 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
890892
};
891893

892894
/**
895+
* Emit a signal to interested subscribers. Note, signals are not emitted
896+
* until *after* the current operation has completed execution in order to
897+
* ensure operation atomicity.
898+
*
893899
* @param {!string} eventid
894900
* @param {*} args
895901
* @return {undefined}
896902
*/
897903
this.emit = function (eventid, args) {
898-
eventNotifier.emit(eventid, args);
904+
pendingSignals.push(function() {
905+
eventNotifier.emit(eventid, args);
906+
});
899907
};
900908

901909
/**
@@ -963,6 +971,18 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
963971
self.emit(ops.OdtDocument.signalStepsRemoved, args);
964972
};
965973

974+
/**
975+
* Process all signals queued up during operation execution
976+
* @return {undefined}
977+
*/
978+
this.processPendingSignals = function() {
979+
var signal = pendingSignals.shift();
980+
while (signal) {
981+
signal();
982+
signal = pendingSignals.shift();
983+
}
984+
};
985+
966986
/**
967987
* @return {undefined}
968988
*/

webodf/lib/ops/Session.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ ops.Session = function Session(odfCanvas) {
4747
*/
4848
function forwardBatchStart(args) {
4949
odtDocument.emit(ops.OdtDocument.signalProcessingBatchStart, args);
50+
odtDocument.processPendingSignals();
5051
}
5152

5253
/**
@@ -56,6 +57,7 @@ ops.Session = function Session(odfCanvas) {
5657
*/
5758
function forwardBatchEnd(args) {
5859
odtDocument.emit(ops.OdtDocument.signalProcessingBatchEnd, args);
60+
odtDocument.processPendingSignals();
5961
}
6062

6163
/**
@@ -81,12 +83,14 @@ ops.Session = function Session(odfCanvas) {
8183
operationRouter.subscribe(ops.OperationRouter.signalProcessingBatchStart, forwardBatchStart);
8284
operationRouter.subscribe(ops.OperationRouter.signalProcessingBatchEnd, forwardBatchEnd);
8385
opRouter.setPlaybackFunction(function (op) {
86+
var result = false;
8487
odtDocument.emit(ops.OdtDocument.signalOperationStart, op);
8588
if (op.execute(odtDocument)) {
8689
odtDocument.emit(ops.OdtDocument.signalOperationEnd, op);
87-
return true;
90+
result = true;
8891
}
89-
return false;
92+
odtDocument.processPendingSignals();
93+
return result;
9094
});
9195
opRouter.setOperationFactory(operationFactory);
9296
};

webodf/tests/gui/DirectFormattingControllerTests.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ gui.DirectFormattingControllerTests = function DirectFormattingControllerTests(r
8989

9090
this.enqueue = function(ops) {
9191
self.operations.push.apply(self.operations, ops);
92-
ops.forEach(function(op) { op.execute(odtDocument); });
92+
ops.forEach(function(op) {
93+
op.execute(odtDocument);
94+
odtDocument.processPendingSignals();
95+
});
9396
};
9497

9598
this.reset = function() {
@@ -142,6 +145,7 @@ gui.DirectFormattingControllerTests = function DirectFormattingControllerTests(r
142145
});
143146
t.odtDocument.emit(ops.Document.signalCursorMoved, t.cursor);
144147
}
148+
t.odtDocument.processPendingSignals();
145149
return node;
146150
}
147151

webodf/tests/gui/MetadataControllerTests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ gui.MetadataControllerTests = function MetadataControllerTests(runner) {
8888
if (timedOp.execute(odtDocument)) {
8989
odtDocument.emit(ops.OdtDocument.signalOperationEnd, timedOp);
9090
}
91+
odtDocument.processPendingSignals();
9192
});
9293
};
9394

webodf/tests/gui/SelectionControllerTests.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ gui.SelectionControllerTests = function SelectionControllerTests(runner) {
6969

7070
this.enqueue = function(ops) {
7171
self.operations.push.apply(self.operations, ops);
72-
ops.forEach(function(op) { op.execute(odtDocument); });
72+
ops.forEach(function(op) {
73+
op.execute(odtDocument);
74+
odtDocument.processPendingSignals();
75+
});
7376
};
7477

7578
this.reset = function() {
@@ -97,6 +100,7 @@ gui.SelectionControllerTests = function SelectionControllerTests(runner) {
97100
t.rangeToSelection = t.selectionController.rangeToSelection;
98101
t.cursor = new ops.OdtCursor(inputMemberId, t.odtDocument);
99102
t.odtDocument.addCursor(t.cursor);
103+
t.odtDocument.processPendingSignals();
100104
return node;
101105
}
102106

webodf/tests/gui/TextControllerTests.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ gui.TextControllerTests = function TextControllerTests(runner) {
7272

7373
this.enqueue = function(ops) {
7474
self.operations.push.apply(self.operations, ops);
75-
ops.forEach(function(op) { op.execute(odtDocument); });
75+
ops.forEach(function(op) {
76+
op.execute(odtDocument);
77+
odtDocument.processPendingSignals();
78+
});
7679
};
7780

7881
this.reset = function() {
@@ -132,6 +135,7 @@ gui.TextControllerTests = function TextControllerTests(runner) {
132135
range.setEndAfter(node.getElementsByTagNameNS(testns, "end")[0]);
133136
t.cursor.setSelectedRange(range, true);
134137
}
138+
t.odtDocument.processPendingSignals();
135139
return node;
136140
}
137141

webodf/tests/ops/OperationTests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ ops.OperationTests = function OperationTests(runner) {
293293
if (metabefore) {
294294
t.odtDocument.emit(ops.OdtDocument.signalOperationEnd, op);
295295
}
296+
t.odtDocument.processPendingSignals();
296297
checkForEmptyTextNodes(t.odtDocument.getCanvas().getElement());
297298
}
298299

0 commit comments

Comments
 (0)