Skip to content

Commit 343322e

Browse files
authored
refactor(web): enhance event callback management with fingerprint support (#1745)
1 parent 91bc0fe commit 343322e

File tree

1 file changed

+59
-19
lines changed
  • web/src/app/features/Visualizer/Crust/Plugins/utils

1 file changed

+59
-19
lines changed

web/src/app/features/Visualizer/Crust/Plugins/utils/events.ts

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,54 +29,94 @@ export function events<
2929
E extends { [P in string]: any[] } = { [P in string]: any[] }
3030
>(): [Events<E>, EventEmitter<E>] {
3131
const e = new EventTarget();
32-
const callbacks = new Map<keyof E, Map<string, (e: Event) => void>>();
32+
const callbacks = new Map<
33+
keyof E,
34+
Map<
35+
EventCallback<E[keyof E]>,
36+
{ fn: (e: Event) => void; fingerprint: string }
37+
>
38+
>();
3339

3440
const getEventCallback = <T extends keyof E>(
3541
type: T,
3642
cb: EventCallback<E[T]>,
37-
ignoreExisting = false
43+
fingerprint: string,
44+
checkFingerprint = false
3845
): ((e: Event) => void) => {
39-
const fingerprint = getFunctionFingerprintString(cb);
4046
let ecbs = callbacks.get(type);
4147
if (!ecbs) {
4248
ecbs = new Map();
4349
callbacks.set(type, ecbs);
4450
}
4551

46-
let ecb = ecbs.get(fingerprint);
47-
if (!ecb || ignoreExisting) {
48-
ecb = (e: Event): void => {
49-
cb(...(e as CustomEvent).detail);
52+
let ecb = ecbs.get(cb as EventCallback);
53+
54+
if (checkFingerprint && !ecb) {
55+
// try get by fingerprint
56+
for (const [_key, value] of ecbs.entries()) {
57+
if (value.fingerprint === fingerprint) {
58+
ecb = value;
59+
break;
60+
}
61+
}
62+
}
63+
64+
if (!ecb) {
65+
ecb = {
66+
fn: (e: Event): void => {
67+
cb(...(e as CustomEvent).detail);
68+
},
69+
fingerprint
5070
};
51-
ecbs.set(fingerprint, ecb);
71+
ecbs.set(cb as EventCallback, ecb);
5272
}
5373

54-
return ecb;
74+
return ecb.fn;
5575
};
5676

57-
const deleteEventCallback = (type: keyof E, cb: EventCallback): void => {
77+
const deleteEventCallback = (
78+
type: keyof E,
79+
cb: EventCallback,
80+
fingerprint: string
81+
): void => {
5882
const ecbs = callbacks.get(type);
59-
const fingerprint = getFunctionFingerprintString(cb);
6083
if (ecbs) {
61-
ecbs.delete(fingerprint);
84+
if (ecbs.has(cb)) {
85+
ecbs.delete(cb);
86+
} else {
87+
// try delete by fingerprint
88+
for (const [key, value] of ecbs.entries()) {
89+
if (value.fingerprint === fingerprint) {
90+
ecbs.delete(key);
91+
break;
92+
}
93+
}
94+
}
6295
if (ecbs.size === 0) {
6396
callbacks.delete(type);
6497
}
6598
}
6699
};
67100

68101
const on = <T extends keyof E>(type: T, callback: EventCallback<E[T]>) => {
69-
const ecb = getEventCallback(type, callback, true);
70-
e.addEventListener(String(type), ecb);
102+
const fingerprint = getFunctionFingerprintString(callback);
103+
// Note: when binding callbacks, we don't check fingerprint,
104+
// because the previous one could be out of lifecycle but with the same fingerprint.
105+
const ecbFn = getEventCallback(type, callback, fingerprint);
106+
e.addEventListener(String(type), ecbFn);
71107
};
72108
const off = <T extends keyof E>(type: T, callback: EventCallback<E[T]>) => {
73-
const ecb = getEventCallback(type, callback);
74-
e.removeEventListener(String(type), ecb);
75-
deleteEventCallback(type, ecb);
109+
const fingerprint = getFunctionFingerprintString(callback);
110+
const ecbFn = getEventCallback(type, callback, fingerprint, true);
111+
// Note: we check fingerprint here to ensure we remove the correct callback.
112+
// because the same callback becomes different after synchronization, but the fingerprint remains the same.
113+
e.removeEventListener(String(type), ecbFn);
114+
deleteEventCallback(type, ecbFn, fingerprint);
76115
};
77116
const once = <T extends keyof E>(type: T, callback: EventCallback<E[T]>) => {
78-
const ecb = getEventCallback(type, callback, true);
79-
e.addEventListener(String(type), ecb, { once: true });
117+
const fingerprint = getFunctionFingerprintString(callback);
118+
const ecbFn = getEventCallback(type, callback, fingerprint);
119+
e.addEventListener(String(type), ecbFn, { once: true });
80120
};
81121

82122
const events = {

0 commit comments

Comments
 (0)