beaverjs
Version:
An abstraction around WebExtension messaging
97 lines • 3.92 kB
JavaScript
import { getWorkerId, isBackground, isContent, isContext, isPassthrough, isWorker } from './destination';
const HAS_BROWSER = !!globalThis.browser;
export function listen(config) {
const isDestination = (dst) => {
switch (config.thisActor) {
case 'worker':
return isWorker(dst);
case 'content':
return isContent(dst);
case 'context':
return isContext(dst);
case 'background':
return isBackground(dst);
}
throw new Error('Never');
};
const handleMessage = (message, sender) => {
if (!isDestination(message.destination))
return false;
if (config.thisActor === 'worker') {
config.onMessage(message, getWorkerId(message.destination));
return true;
}
else {
config.onMessage(message, sender);
return !isPassthrough(message.destination);
}
};
const baseHandler = (src, onFail) => (data, sender) => {
if (typeof data !== 'object' || !data.destination)
return;
if (!handleMessage(data, sender)) {
if (config.worker && isWorker(data.destination))
config.worker.postMessage(data);
if (config.thisActor === 'content') {
if (isContext(data.destination) && src !== 'context') {
postMessage(data, '*');
}
if (isBackground(data.destination) && src !== 'background') {
browser.runtime.sendMessage(data);
}
}
else {
onFail === null || onFail === void 0 ? void 0 : onFail(data);
}
}
};
if (config.thisActor === 'worker') {
const handler = baseHandler('context');
addEventListener('message', ({ data, source }) => handler(data, source));
return;
}
// only do stuff the worker can't do
for (const source of config.listenFrom) {
switch (source) {
case 'content': {
if (config.thisActor === 'context') {
const handler = baseHandler('content');
addEventListener('message', ({ data, source }) => handler(data, source));
}
else if (config.thisActor === 'background' && HAS_BROWSER) {
const handler = baseHandler('content');
browser.runtime.onMessage.addListener((msg, sender) => handler(msg, sender));
}
else
throw new Error('invalid actor');
break;
}
case 'context': {
const handler = baseHandler('context');
addEventListener('message', ({ data, source }) => handler(data, source));
break;
}
case 'background': {
const handler = baseHandler('background');
browser.runtime.onMessage.addListener((msg, source) => handler(msg, source));
break;
}
case 'worker': {
if (config.worker) {
const handler = baseHandler('worker', e => {
// this is either context or background
if (config.thisActor === 'context') {
postMessage(e, '*'); // re-emit
}
else {
browser.runtime.sendMessage(e);
}
});
config.worker.addEventListener('message', ({ data, source }) => handler(data, source));
}
break;
}
}
}
}
//# sourceMappingURL=listeners.js.map