Bug 1477252 - Check whether editor is destroyed before using it; review=nchevobbe r=nchevobbe
authorJan Odvarko <odvarko@gmail.com>
Fri, 19 Oct 2018 14:21:23 +0000
changeset 491120 99df2932f5d5d0030c9132337ab117bcc4a0fc99
parent 491119 fc43dc9c58ef134764b0f21fea149438d14895ea
child 491121 4ff8166e26697789c95de2b03d45893e4ba90f87
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersnchevobbe
bugs1477252
milestone65.0a1
Bug 1477252 - Check whether editor is destroyed before using it; review=nchevobbe r=nchevobbe Differential Revision: https://phabricator.services.mozilla.com/D9251
devtools/client/netmonitor/src/components/SourceEditor.js
devtools/client/sourceeditor/editor.js
--- a/devtools/client/netmonitor/src/components/SourceEditor.js
+++ b/devtools/client/netmonitor/src/components/SourceEditor.js
@@ -33,43 +33,56 @@ class SourceEditor extends Component {
       mode: null, // Disable auto syntax detection, but then we set mode asynchronously
       readOnly: true,
       theme: "mozilla",
       value: text,
     });
 
     // Delay to CodeMirror initialization content to prevent UI freezing
     this.editorTimeout = setTimeout(() => {
+      this.editorTimeout = null;
       this.editor.appendToLocalElement(this.refs.editorElement);
+
       // CodeMirror's setMode() (syntax highlight) is the performance bottleneck when
       // processing large content, so we enable it asynchronously within the setTimeout
       // to avoid UI blocking. (rendering source code -> drawing syntax highlight)
       this.editorSetModeTimeout = setTimeout(() => {
+        this.editorSetModeTimeout = null;
         this.editor.setMode(mode);
       });
     });
   }
 
   shouldComponentUpdate(nextProps) {
     return nextProps.mode !== this.props.mode || nextProps.text !== this.props.text;
   }
 
   componentDidUpdate(prevProps) {
     const { mode, text } = this.props;
 
+    // Bail out if the editor has been destroyed in the meantime.
+    if (this.editor.isDestroyed()) {
+      return;
+    }
+
     if (prevProps.text !== text) {
       // Reset the existed 'mode' attribute in order to make setText() process faster
       // to prevent drawing unnecessary syntax highlight.
       this.editor.setMode(null);
       this.editor.setText(text);
 
+      if (this.editorSetModeTimeout) {
+        clearTimeout(this.editorSetModeTimeout);
+      }
+
       // CodeMirror's setMode() (syntax highlight) is the performance bottleneck when
       // processing large content, so we enable it asynchronously within the setTimeout
       // to avoid UI blocking. (rendering source code -> drawing syntax highlight)
       this.editorSetModeTimeout = setTimeout(() => {
+        this.editorSetModeTimeout = null;
         this.editor.setMode(mode);
       });
     }
   }
 
   componentWillUnmount() {
     clearTimeout(this.editorTimeout);
     clearTimeout(this.editorSetModeTimeout);
--- a/devtools/client/sourceeditor/editor.js
+++ b/devtools/client/sourceeditor/editor.js
@@ -1326,16 +1326,20 @@ Editor.prototype = {
         funcs[name](ctx);
         return;
       }
 
       this[name] = funcs[name].bind(null, ctx);
     });
   },
 
+  isDestroyed: function() {
+    return !editors.get(this);
+  },
+
   destroy: function() {
     this.container = null;
     this.config = null;
     this.version = null;
 
     if (this._prefObserver) {
       this._prefObserver.off(TAB_SIZE, this.reloadPreferences);
       this._prefObserver.off(EXPAND_TAB, this.reloadPreferences);