on master help sign in
Use the same function for all DOM event handlers
49fdb93Till Schneidereit
js/change-list.js+23−38
@@ -135,10 +135,9 @@ const OP_TABLE = [
135 const a = mem32[i++];
135 const a = mem32[i++];
136 const b = mem32[i++];
136 const b = mem32[i++];
137 const el = top(changeList.stack);
137 const el = top(changeList.stack);
138− const listener = new Listener(a, b, eventType, changeList.eventsTrampoline, el);
139− changeList.listeners.add(listener);
140− el.addEventListener(eventType, listener.callback);
138+ el.addEventListener(eventType, changeList.eventHandler);
139+ el["dodrio-a-" + eventType] = a;
141− el[`dodrio-${eventType}`] = listener;
140+ el["dodrio-b-" + eventType] = b;
142 return i;
141 return i;
143 },
142 },
144
143
@@ -147,9 +146,8 @@ const OP_TABLE = [
147 const eventId = mem32[i++];
146 const eventId = mem32[i++];
148 const eventType = changeList.getString(eventId);
147 const eventType = changeList.getString(eventId);
149 const el = top(changeList.stack);
148 const el = top(changeList.stack);
150− const listener = el[`dodrio-${eventType}`];
149+ el["dodrio-a-" + eventType] = mem32[i++];
151− listener.a = mem32[i++];
150+ el["dodrio-b-" + eventType] = mem32[i++];
152− listener.b = mem32[i++];
153 return i;
151 return i;
154 },
152 },
155
153
@@ -158,9 +156,7 @@ const OP_TABLE = [
158 const eventId = mem32[i++];
156 const eventId = mem32[i++];
159 const eventType = changeList.getString(eventId);
157 const eventType = changeList.getString(eventId);
160 const el = top(changeList.stack);
158 const el = top(changeList.stack);
161− const listener = el[`dodrio-${eventType}`];
162− el.removeEventListener(eventType, listener.callback);
159+ el.removeEventListener(eventType, changeList.eventHandler);
163− changeList.listeners.delete(listener);
164 return i;
160 return i;
165 },
161 },
166
162
@@ -182,25 +178,9 @@ const OP_TABLE = [
182 }
178 }
183];
179];
184
180
185−class Listener {
186− constructor(a, b, eventType, trampoline, el) {
187− this.a = a;
188− this.b = b;
189− this.eventType = eventType;
190− this.trampoline = trampoline;
191− this.el = el;
192− this.callback = this.callback.bind(this);
193− }
194−
195− callback(event) {
196− this.trampoline(event, this.a, this.b);
197− }
198−}
199−
200// export
181// export
201class ChangeList {
182class ChangeList {
202 constructor(container) {
183 constructor(container) {
203− this.listeners = new Set();
204 this.trampoline = null;
184 this.trampoline = null;
205 this.container = container;
185 this.container = container;
206 this.ranges = [];
186 this.ranges = [];
@@ -209,18 +189,10 @@ class ChangeList {
209 }
189 }
210
190
211 unmount() {
191 unmount() {
212− for (const listener of this.listeners) {
213− listener.el.removeEventListener(listener.eventType, listener.callback);
214− listener.trampoline = () => {
192+ this.trampoline.mounted = false;
215− throw new Error("invocation of listener after it has been removed");
216− };
217− listener.a = 0;
218− listener.b = 0;
219− }
220
193
221 // Null out all of our properties just to ensure that if we mistakenly ever
194 // Null out all of our properties just to ensure that if we mistakenly ever
222 // call a method on this instance again, it will throw.
195 // call a method on this instance again, it will throw.
223− this.listeners = null;
224 this.trampoline = null;
196 this.trampoline = null;
225 this.container = null;
197 this.container = null;
226 this.ranges = null;
198 this.ranges = null;
@@ -273,9 +245,22 @@ class ChangeList {
273 }
245 }
274
246
275 initEventsTrampoline(trampoline) {
247 initEventsTrampoline(trampoline) {
276− this.eventsTrampoline = (...args) => {
248+ this.trampoline = trampoline;
249+ trampoline.mounted = true;
250+ this.eventHandler = function(event) {
277− trampoline(...args);
251+ if (!trampoline.mounted) {
252+ throw new Error("invocation of listener after VDOM has been unmounted");
253+ }
254+
255+ // `this` always refers to the element the handler was added to.
256+ // Since we're adding the handler to all elements our content wants
257+ // to listen for events on, this ensures that we always get the right
258+ // values for `a` and `b`.
259+ const type = event.type;
260+ const a = this["dodrio-a-" + type];
261+ const b = this["dodrio-b-" + type];
262+ trampoline(event, a, b);
278− };
263+ }
279 }
264 }
280}
265}
281window.ChangeList = ChangeList;
266window.ChangeList = ChangeList;