DEV: uses forked Mousetrap to avoid leaking listeners (#14198)

DEV: uses forked Mousetrap to avoid leaking listeners (#14198)

diff --git a/app/assets/javascripts/discourse-shims.js b/app/assets/javascripts/discourse-shims.js
index e93da4e..006a98e 100644
--- a/app/assets/javascripts/discourse-shims.js
+++ b/app/assets/javascripts/discourse-shims.js
@@ -2,11 +2,6 @@ define("message-bus-client", ["exports"], function (__exports__) {
   __exports__.default = window.MessageBus;
 });
 
-define("mousetrap-global-bind", ["exports"], function (__exports__) {
-  // In the Rails app it's applied from the vendored file
-  __exports__.default = {};
-});
-
 define("ember-buffered-proxy/proxy", ["exports"], function (__exports__) {
   __exports__.default = window.BufferedProxy;
 });
@@ -19,8 +14,8 @@ define("xss", ["exports"], function (__exports__) {
   __exports__.default = window.filterXSS;
 });
 
-define("mousetrap", ["exports"], function (__exports__) {
-  __exports__.default = window.Mousetrap;
+define("@discourse/itsatrap", ["exports"], function (__exports__) {
+  __exports__.default = window.ItsATrap;
 });
 
 define("@popperjs/core", ["exports"], function (__exports__) {
diff --git a/app/assets/javascripts/discourse/app/app.js b/app/assets/javascripts/discourse/app/app.js
index ddcc134..8d0aa0b 100644
--- a/app/assets/javascripts/discourse/app/app.js
+++ b/app/assets/javascripts/discourse/app/app.js
@@ -1,5 +1,4 @@
 import Application from "@ember/application";
-import Mousetrap from "mousetrap";
 import { buildResolver } from "discourse-common/resolver";
 import { isTesting } from "discourse-common/config/environment";
 
@@ -13,11 +12,6 @@ const Discourse = Application.extend({
     paste: "paste",
   },
 
-  reset() {
-    this._super(...arguments);
-    Mousetrap.reset();
-  },
-
   Resolver: buildResolver("discourse"),
 
   _prepareInitializer(moduleName) {
diff --git a/app/assets/javascripts/discourse/app/components/bookmark.js b/app/assets/javascripts/discourse/app/components/bookmark.js
index d51cb7b..25157f2 100644
--- a/app/assets/javascripts/discourse/app/components/bookmark.js
+++ b/app/assets/javascripts/discourse/app/components/bookmark.js
@@ -11,7 +11,7 @@ import { AUTO_DELETE_PREFERENCES } from "discourse/models/bookmark";
 import Component from "@ember/component";
 import I18n from "I18n";
 import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
-import Mousetrap from "mousetrap";
+import ItsATrap from "@discourse/itsatrap";
 import { Promise } from "rsvp";
 import { TIME_SHORTCUT_TYPES } from "discourse/lib/time-shortcut";
 import { action } from "@ember/object";
@@ -37,6 +37,7 @@ export default Component.extend({
   _savingBookmarkManually: null,
   _saving: null,
   _deleting: null,
+  _itsatrap: null,
   postDetectedLocalDate: null,
   postDetectedLocalTime: null,
   postDetectedLocalTimezone: null,
@@ -44,7 +45,6 @@ export default Component.extend({
   userTimezone: null,
   showOptions: null,
   model: null,
-
   afterSave: null,
 
   @on("init")
@@ -62,6 +62,7 @@ export default Component.extend({
       prefilledDatetime: null,
       userTimezone: this.currentUser.resolvedTimezone(this.currentUser),
       showOptions: false,
+      _itsatrap: new ItsATrap(),
     });
 
     this.registerOnCloseHandler(this._onModalClose.bind(this));
@@ -123,9 +124,8 @@ export default Component.extend({
   _bindKeyboardShortcuts() {
     KeyboardShortcuts.pause();
 
-    this._mousetrap = new Mousetrap();
     Object.keys(BOOKMARK_BINDINGS).forEach((shortcut) => {
-      this._mousetrap.bind(shortcut, () => {
+      this._itsatrap.bind(shortcut, () => {
         let binding = BOOKMARK_BINDINGS[shortcut];
         this.send(binding.handler);
         return false;
@@ -266,7 +266,9 @@ export default Component.extend({
 
   willDestroyElement() {
     this._super(...arguments);
-    this._mousetrap.reset();
+
+    this._itsatrap?.destroy();
+    this.set("_itsatrap", null);
     KeyboardShortcuts.unpause();
   },
 
diff --git a/app/assets/javascripts/discourse/app/components/d-editor.js b/app/assets/javascripts/discourse/app/components/d-editor.js
index 1d337cb..09b90e5 100644
--- a/app/assets/javascripts/discourse/app/components/d-editor.js
+++ b/app/assets/javascripts/discourse/app/components/d-editor.js
@@ -9,7 +9,7 @@ import { emojiUrlFor, generateCookFunction } from "discourse/lib/text";
 import { later, schedule, scheduleOnce } from "@ember/runloop";
 import Component from "@ember/component";
 import I18n from "I18n";
-import Mousetrap from "mousetrap";
+import ItsATrap from "@discourse/itsatrap";
 import { Promise } from "rsvp";
 import { SKIP } from "discourse/lib/autocomplete";
 import { categoryHashtagTriggerRule } from "discourse/lib/category-hashtags";
@@ -238,7 +238,7 @@ export default Component.extend(TextareaTextManipulation, {
   classNames: ["d-editor"],
   ready: false,
   lastSel: null,
-  _mouseTrap: null,
+  _itsatrap: null,
   showLink: true,
   emojiPickerIsActive: false,
   emojiStore: service("emoji-store"),
@@ -278,12 +278,12 @@ export default Component.extend(TextareaTextManipulation, {
 
     scheduleOnce("afterRender", this, this._readyNow);
 
-    this._mouseTrap = new Mousetrap(this._textarea);
+    this._itsatrap = new ItsATrap(this._textarea);
     const shortcuts = this.get("toolbar.shortcuts");
 
     Object.keys(shortcuts).forEach((sc) => {
       const button = shortcuts[sc];
-      this._mouseTrap.bind(sc, () => {
+      this._itsatrap.bind(sc, () => {
         button.action(button);
         return false;
       });
@@ -335,7 +335,9 @@ export default Component.extend(TextareaTextManipulation, {
       this.appEvents.off("composer:replace-text", this, "_replaceText");
     }
 
-    this._mouseTrap.reset();
+    this._itsatrap?.destroy();
+    this._itsatrap = null;
+
     $(this.element.querySelector(".d-editor-preview")).off("click.preview");
 
     if (isTesting()) {
diff --git a/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js b/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js
index 65ab8b6..1c07ace 100644
--- a/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js
+++ b/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js
@@ -21,7 +21,7 @@ import {
   thisWeekend,
 } from "discourse/lib/time-utils";
 import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
-import Mousetrap from "mousetrap";
+import ItsATrap from "@discourse/itsatrap";
 
 export default Component.extend({
   statusType: readOnly("topicTimer.status_type"),
@@ -43,12 +43,13 @@ export default Component.extend({
     "autoCloseAfterLastPost"
   ),
   duration: null,
+  _itsatrap: null,
 
   init() {
     this._super(...arguments);
 
     KeyboardShortcuts.pause();
-    this._mousetrap = new Mousetrap();
+    this.set("_itsatrap", new ItsATrap());
 
     this.set("duration", this.initialDuration);
   },
@@ -65,7 +66,9 @@ export default Component.extend({
 
   willDestroyElement() {
     this._super(...arguments);
-    this._mousetrap.reset();
+
+    this._itsatrap.destroy();
+    this.set("_itsatrap", null);
     KeyboardShortcuts.unpause();
   },
 
diff --git a/app/assets/javascripts/discourse/app/components/site-header.js b/app/assets/javascripts/discourse/app/components/site-header.js
index 9ac49c9..d78e9c7 100644
--- a/app/assets/javascripts/discourse/app/components/site-header.js
+++ b/app/assets/javascripts/discourse/app/components/site-header.js
@@ -5,7 +5,7 @@ import PanEvents, {
 import { cancel, later, schedule } from "@ember/runloop";
 import Docking from "discourse/mixins/docking";
 import MountWidget from "discourse/components/mount-widget";
-import Mousetrap from "mousetrap";
+import ItsATrap from "@discourse/itsatrap";
 import RerenderOnDoNotDisturbChange from "discourse/mixins/rerender-on-do-not-disturb-change";
 import { observes } from "discourse-common/utils/decorators";
 import { topicTitleDecorators } from "discourse/components/topic-title";
@@ -24,7 +24,7 @@ const SiteHeaderComponent = MountWidget.extend(
     _panMenuOffset: 0,

[... diff too long, it was truncated ...]

GitHub sha: 95b15acb1ef6608ecb1c2c954791769d111c4f59

This commit appears in #14198 which was approved by CvX and eviltrout. It was merged by jjaffeux.