From 3bbdbb51cac68e3e8b9fa7d5473e123297721acc Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Sun, 29 May 2022 14:16:33 +0200 Subject: [PATCH 1/3] fix: Cannot read property of null for bgTokenizer after session is destroyed --- lib/ace/edit_session.js | 34 ++++++++++++++++++---------------- lib/ace/edit_session_test.js | 12 +++++++++++- lib/ace/editor.js | 8 ++++---- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 72f10444af2..8f6463b17c1 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -153,6 +153,15 @@ var EditSession = function(text, mode) { this.$foldData.toString = function() { return this.join("\n"); }; + + // Set default background tokenizer with Text mode until editor session mode is set + this.bgTokenizer = new BackgroundTokenizer((new TextMode()).getTokenizer(), this); + + var _self = this; + this.bgTokenizer.on("update", function(e) { + _self._signal("tokenizerUpdate", e); + }); + this.on("changeFold", this.onChangeFold.bind(this)); this.$onChange = this.onChange.bind(this); @@ -166,6 +175,8 @@ var EditSession = function(text, mode) { config.resetOptions(this); this.setMode(mode); config._signal("session", this); + + this.destroyed = false; }; @@ -188,8 +199,7 @@ EditSession.$uid = 0; this.doc = doc; doc.on("change", this.$onChange); - if (this.bgTokenizer) - this.bgTokenizer.setDocument(this.getDocument()); + this.bgTokenizer.setDocument(this.getDocument()); this.resetCaches(); }; @@ -244,7 +254,7 @@ EditSession.$uid = 0; this.$wrapData = []; this.$rowLengthCache = []; this.$resetRowCache(0); - if (this.bgTokenizer) + if (!this.destroyed) this.bgTokenizer.start(0); }; @@ -273,7 +283,7 @@ EditSession.$uid = 0; this.$informUndoManager.schedule(); } - this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); + this.bgTokenizer.$updateOnChange(delta); this._signal("change", delta); }; @@ -914,16 +924,7 @@ EditSession.$uid = 0; tokenizer.on("update", onReloadTokenizer); } - if (!this.bgTokenizer) { - this.bgTokenizer = new BackgroundTokenizer(tokenizer); - var _self = this; - this.bgTokenizer.on("update", function(e) { - _self._signal("tokenizerUpdate", e); - }); - } else { - this.bgTokenizer.setTokenizer(tokenizer); - } - + this.bgTokenizer.setTokenizer(tokenizer); this.bgTokenizer.setDocument(this.getDocument()); this.tokenRe = mode.tokenRe; @@ -2398,9 +2399,10 @@ EditSession.$uid = 0; }; this.destroy = function() { - if (this.bgTokenizer) { + if (!this.destroyed) { this.bgTokenizer.setDocument(null); - this.bgTokenizer = null; + this.bgTokenizer.removeAllListeners(); + this.destroyed = true; } this.$stopWorker(); this.removeAllListeners(); diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index e185f585eb7..f577de201e7 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -1143,7 +1143,17 @@ module.exports = { next(); }); }, 0); - } + }, + + "test: sets destroyed flag when destroy called and tokenizer is never null": function() { + var session = new EditSession(["foo bar foo bar"]); + assert.notEqual(session.bgTokenizer, null); + assert.equal(session.destroyed, false); + + session.destroy(); + assert.equal(session.destroyed, true); + assert.notEqual(session.bgTokenizer, null); + }, }; }); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 740b0477784..cac7397b87b 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -99,7 +99,7 @@ var Editor = function(renderer, session, options) { this._$emitInputEvent = lang.delayedCall(function() { this._signal("input", {}); - if (this.session && this.session.bgTokenizer) + if (this.session && !this.session.destroyed) this.session.bgTokenizer.scheduleStart(); }.bind(this)); @@ -402,7 +402,7 @@ Editor.$uid = 0; oldSession && oldSession._signal("changeEditor", {oldEditor: this}); session && session._signal("changeEditor", {editor: this}); - if (session && session.bgTokenizer) + if (session && !session.destroyed) session.bgTokenizer.scheduleStart(); }; @@ -532,7 +532,7 @@ Editor.$uid = 0; setTimeout(function () { self.$highlightPending = false; var session = self.session; - if (!session || !session.bgTokenizer) return; + if (!session || session.destroyed) return; if (session.$bracketHighlight) { session.$bracketHighlight.markerIds.forEach(function(id) { session.removeMarker(id); @@ -581,7 +581,7 @@ Editor.$uid = 0; self.$highlightTagPending = false; var session = self.session; - if (!session || !session.bgTokenizer) return; + if (!session || session.destroyed) return; var pos = self.getCursorPosition(); var iterator = new TokenIterator(self.session, pos.row, pos.column); From 4fbbddf5a52a5e7725fcb1d9079a02047d265098 Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Sun, 29 May 2022 14:24:06 +0200 Subject: [PATCH 2/3] fixed lint issues --- lib/ace/edit_session_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index f577de201e7..0045504dd15 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -1153,7 +1153,7 @@ module.exports = { session.destroy(); assert.equal(session.destroyed, true); assert.notEqual(session.bgTokenizer, null); - }, + } }; }); From 57e05cded274d5a8d77a0d1d58804ce38d624b88 Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Mon, 30 May 2022 17:37:05 +0200 Subject: [PATCH 3/3] added bgTokenizer.cleanup method --- lib/ace/background_tokenizer.js | 8 ++++++++ lib/ace/edit_session.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index c500120acce..a6b87ccc19c 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -245,6 +245,14 @@ var BackgroundTokenizer = function(tokenizer, editor) { return this.lines[row] = data.tokens; }; + this.cleanup = function() { + this.running = false; + this.lines = []; + this.states = []; + this.currentLine = 0; + this.removeAllListeners(); + }; + }).call(BackgroundTokenizer.prototype); exports.BackgroundTokenizer = BackgroundTokenizer; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 8f6463b17c1..eabc89ac667 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -2401,7 +2401,7 @@ EditSession.$uid = 0; this.destroy = function() { if (!this.destroyed) { this.bgTokenizer.setDocument(null); - this.bgTokenizer.removeAllListeners(); + this.bgTokenizer.cleanup(); this.destroyed = true; } this.$stopWorker();