Catrope has uploaded a new change for review.

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


Change subject: Guard against detached nodes in 
ve.ce.GeneratedContentNode#doneGenerating
......................................................................

Guard against detached nodes in ve.ce.GeneratedContentNode#doneGenerating

The generation promise can get resolved (e.g. AJAX request can complete)
after the node has been detached. In that case accessing this.model.doc
will fail, so check for this in doneGenerating().

Also attempt to abort the pending promise on teardown.

Bug: 56649
Change-Id: Ia55f1c2c8dc3a3619c0b50795e50fcae4bc6471f
---
M modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
1 file changed, 33 insertions(+), 16 deletions(-)


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

diff --git a/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js 
b/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
index c2b7223..8d2a8a1 100644
--- a/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
+++ b/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
@@ -22,6 +22,7 @@
 
        // Events
        this.model.connect( this, { 'update': 'onGeneratedContentNodeUpdate' } 
);
+       this.connect( this, { 'teardown': 'abortGenerating' } );
 
        // Initialization
        this.update();
@@ -181,19 +182,10 @@
  */
 ve.ce.GeneratedContentNode.prototype.forceUpdate = function ( config ) {
        var promise, node = this;
-       if ( this.generatingPromise ) {
-               // Abort the currently pending generation process if possible
-               // Unset this.generatingPromise first so that if the promise is 
resolved or rejected
-               // when we abort, this is ignored as it should be
-               promise = this.generatingPromise;
-               this.generatingPromise = null;
-               if ( $.isFunction( promise.abort ) ) {
-                       promise.abort();
-               }
-       } else {
-               // Only call startGenerating() if we weren't generating before
-               this.startGenerating();
-       }
+
+       // Abort the currently pending generation process if possible
+       this.abortGenerating();
+       this.startGenerating();
 
        // Create a new promise
        promise = this.generatingPromise = this.generateContents( config );
@@ -225,6 +217,25 @@
 };
 
 /**
+ * Abort the currently pending generation, if any, and remove the generating 
CSS class.
+ *
+ * This invokes .abort() on the pending promise if the promise has that 
method. It also ensures
+ * that if the promise does get resolved or rejected later, this is ignored.
+ */
+ve.ce.GeneratedContentNode.prototype.abortGenerating = function () {
+       var promise = this.generatingPromise;
+       if ( promise ) {
+               // Unset this.generatingPromise first so that if the promise is 
resolved or rejected
+               // from within .abort(), this is ignored as it should be
+               this.generatingPromise = null;
+               if ( $.isFunction( promise.abort ) ) {
+                       promise.abort();
+               }
+       }
+       this.$element.removeClass( 've-ce-generatedContentNode-generating' );
+};
+
+/**
  * Called when the node successfully finishes generating new content.
  *
  * @method
@@ -232,10 +243,16 @@
  * @param {Object} [config] Config object passed to forceUpdate()
  */
 ve.ce.GeneratedContentNode.prototype.doneGenerating = function ( 
generatedContents, config ) {
-       var store = this.model.doc.getStore(),
-               hash = OO.getHash( [ this.model, config ] );
+       var store, hash;
 
-       store.index( generatedContents, hash );
+       // Because doneGenerating is invoked asynchronously, the model node may 
have become detached
+       // in the meantime. Handle this gracefully.
+       if ( this.model.doc ) {
+               store = this.model.doc.getStore();
+               hash = OO.getHash( [ this.model, config ] );
+               store.index( generatedContents, hash );
+       }
+
        this.$element.removeClass( 've-ce-generatedContentNode-generating' );
        this.generatingPromise = null;
        this.render( generatedContents );

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

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

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

Reply via email to