Divec has uploaded a new change for review.

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

Change subject: WIP allegro giocoso doloroso: block bogus 'emit'
......................................................................

WIP allegro giocoso doloroso: block bogus 'emit'

On delete, the DM surface sometimes emits a bogus select event before any
content change has actually taken place. This breaks with native deletion,
because the CE content is already inconsistent with the DM content.

Change-Id: If3270175ce66148ac5dbecb4c5ba11ed634ad855
---
M src/ce/ve.ce.Surface.js
M src/dm/ve.dm.SurfaceFragment.js
2 files changed, 33 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor 
refs/changes/07/196207/1

diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index cac7061..8585bd4 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -3275,7 +3275,15 @@
                }
        }
 
-       this.getModel().getLinearFragment( rangeToRemove ).delete( direction );
+       // 'delete' may end up emitting an early bogus no-op selection change, 
which then kills
+       // onModelSelect because the DM does not yet match the CE. Pass 
callbacks to apply the
+       // render lock in this case
+       this.getModel().getLinearFragment( rangeToRemove ).delete(
+               direction,
+               this.incRenderLock.bind( this ),
+               this.decRenderLock.bind( this )
+       );
+
        // Rerender selection even if it didn't change
        // TODO: is any of this necessary?
        this.focus();
diff --git a/src/dm/ve.dm.SurfaceFragment.js b/src/dm/ve.dm.SurfaceFragment.js
index 22d282a..225c493 100644
--- a/src/dm/ve.dm.SurfaceFragment.js
+++ b/src/dm/ve.dm.SurfaceFragment.js
@@ -825,15 +825,18 @@
  *
  * @method
  * @param {number} [directionAfterDelete=-1] Direction to move after delete: 1 
or -1 or 0
+ * @param {Function} onPreBogusSelectEmit Callback before emitting a premature 
select event
+ * @param {Function} onPostBogusSelectEmit Callback after emitting a premature 
select event
  * @chainable
  */
-ve.dm.SurfaceFragment.prototype.delete = function ( directionAfterDelete ) {
+ve.dm.SurfaceFragment.prototype.delete = function ( directionAfterDelete, 
onPreBogusSelectEmit, onPostBogusSelectEmit ) {
        if ( !( this.selection instanceof ve.dm.LinearSelection ) ) {
                return this;
        }
 
        var rangeAfterRemove, internalListRange,
                tx, startNode, endNode, endNodeData, nodeToDelete,
+               
dmSurfaceEmitsABogusSelectEventThatCanBeIgnoredBecauseItWillEmitAProperOneAMomentLater,
                rangeToRemove = this.getSelection( true ).getRange();
 
        if ( rangeToRemove.isCollapsed() ) {
@@ -852,8 +855,27 @@
                rangeAfterRemove = new ve.Range( 1 );
        } else {
                tx = ve.dm.Transaction.newFromRemoval( this.document, 
rangeToRemove );
-               this.change( tx );
                rangeAfterRemove = tx.translateRange( rangeToRemove );
+               // Detect whether the select event that will be emitted is 
bogus -- if so, it will
+               // be followed by a sensible select event below. We're slightly 
lucky, because we
+               // can predict this before making a call.
+               
dmSurfaceEmitsABogusSelectEventThatCanBeIgnoredBecauseItWillEmitAProperOneAMomentLater
 = !rangeAfterRemove.isCollapsed();
+               if ( 
dmSurfaceEmitsABogusSelectEventThatCanBeIgnoredBecauseItWillEmitAProperOneAMomentLater
 ) {
+                       // Notify the caller that we're about to spout nonsense
+                       if ( onPreBogusSelectEmit ) {
+                               onPreBogusSelectEmit();
+                       }
+                       try {
+                               this.change( tx );
+                       } finally {
+                               if ( onPostBogusSelectEmit ) {
+                                       onPostBogusSelectEmit();
+                               }
+                       }
+               } else {
+                       // Will emit sensible select event; do not notify the 
caller
+                       this.change( tx );
+               }
        }
        if ( !rangeAfterRemove.isCollapsed() ) {
                // If after processing removal transaction range is not 
collapsed it means that not

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: If3270175ce66148ac5dbecb4c5ba11ed634ad855
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Divec <[email protected]>

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

Reply via email to