Re-factor the MessageHandler-class event handler function

- Change the "message" event handler function to a private method.

 - Remove the "message" event listener with an `AbortSignal`.

 - Extend the `LoopbackPort`-class with `AbortSignal` support.
This commit is contained in:
Jonas Jenwald 2024-10-12 17:15:10 +02:00
parent 689ffda9df
commit 788eabc76a
2 changed files with 90 additions and 66 deletions

View File

@ -1982,7 +1982,7 @@ class PDFPageProxy {
} }
class LoopbackPort { class LoopbackPort {
#listeners = new Set(); #listeners = new Map();
#deferred = Promise.resolve(); #deferred = Promise.resolve();
@ -1992,21 +1992,39 @@ class LoopbackPort {
}; };
this.#deferred.then(() => { this.#deferred.then(() => {
for (const listener of this.#listeners) { for (const [listener] of this.#listeners) {
listener.call(this, event); listener.call(this, event);
} }
}); });
} }
addEventListener(name, listener) { addEventListener(name, listener, options = null) {
this.#listeners.add(listener); let rmAbort = null;
if (options?.signal instanceof AbortSignal) {
const { signal } = options;
if (signal.aborted) {
warn("LoopbackPort - cannot use an `aborted` signal.");
return;
}
const onAbort = () => this.removeEventListener(name, listener);
rmAbort = () => signal.removeEventListener("abort", onAbort);
signal.addEventListener("abort", onAbort);
}
this.#listeners.set(listener, rmAbort);
} }
removeEventListener(name, listener) { removeEventListener(name, listener) {
const rmAbort = this.#listeners.get(listener);
rmAbort?.();
this.#listeners.delete(listener); this.#listeners.delete(listener);
} }
terminate() { terminate() {
for (const [, rmAbort] of this.#listeners) {
rmAbort?.();
}
this.#listeners.clear(); this.#listeners.clear();
} }
} }

View File

@ -69,6 +69,8 @@ function wrapReason(reason) {
} }
class MessageHandler { class MessageHandler {
#messageAC = new AbortController();
constructor(sourceName, targetName, comObj) { constructor(sourceName, targetName, comObj) {
this.sourceName = sourceName; this.sourceName = sourceName;
this.targetName = targetName; this.targetName = targetName;
@ -80,8 +82,12 @@ class MessageHandler {
this.callbackCapabilities = Object.create(null); this.callbackCapabilities = Object.create(null);
this.actionHandler = Object.create(null); this.actionHandler = Object.create(null);
this._onComObjOnMessage = event => { comObj.addEventListener("message", this.#onMessage.bind(this), {
const data = event.data; signal: this.#messageAC.signal,
});
}
#onMessage({ data }) {
if (data.targetName !== this.sourceName) { if (data.targetName !== this.sourceName) {
return; return;
} }
@ -111,16 +117,17 @@ class MessageHandler {
throw new Error(`Unknown action from worker: ${data.action}`); throw new Error(`Unknown action from worker: ${data.action}`);
} }
if (data.callbackId) { if (data.callbackId) {
const cbSourceName = this.sourceName; const sourceName = this.sourceName,
const cbTargetName = data.sourceName; targetName = data.sourceName,
comObj = this.comObj;
new Promise(function (resolve) { new Promise(function (resolve) {
resolve(action(data.data)); resolve(action(data.data));
}).then( }).then(
function (result) { function (result) {
comObj.postMessage({ comObj.postMessage({
sourceName: cbSourceName, sourceName,
targetName: cbTargetName, targetName,
callback: CallbackKind.DATA, callback: CallbackKind.DATA,
callbackId: data.callbackId, callbackId: data.callbackId,
data: result, data: result,
@ -128,8 +135,8 @@ class MessageHandler {
}, },
function (reason) { function (reason) {
comObj.postMessage({ comObj.postMessage({
sourceName: cbSourceName, sourceName,
targetName: cbTargetName, targetName,
callback: CallbackKind.ERROR, callback: CallbackKind.ERROR,
callbackId: data.callbackId, callbackId: data.callbackId,
reason: wrapReason(reason), reason: wrapReason(reason),
@ -143,8 +150,6 @@ class MessageHandler {
return; return;
} }
action(data.data); action(data.data);
};
comObj.addEventListener("message", this._onComObjOnMessage);
} }
on(actionName, handler) { on(actionName, handler) {
@ -527,7 +532,8 @@ class MessageHandler {
} }
destroy() { destroy() {
this.comObj.removeEventListener("message", this._onComObjOnMessage); this.#messageAC?.abort();
this.#messageAC = null;
} }
} }