cosmetics

This commit is contained in:
tophf 2020-10-26 10:18:55 +03:00
parent a4cd6d16e2
commit b2faf438b0

103
js/msg.js
View File

@ -2,8 +2,8 @@
/* global deepCopy getOwnTab URLS */ // not used in content scripts /* global deepCopy getOwnTab URLS */ // not used in content scripts
'use strict'; 'use strict';
// eslint-disable-next-line no-unused-expressions, no-var // eslint-disable-next-line no-unused-expressions
var msg = window.INJECTED === 1 && window.msg || (() => { window.INJECTED !== 1 && (() => {
promisifyChrome({ promisifyChrome({
runtime: ['sendMessage', 'getBackgroundPage'], runtime: ['sendMessage', 'getBackgroundPage'],
tabs: ['sendMessage', 'query'], tabs: ['sendMessage', 'query'],
@ -32,33 +32,31 @@ var msg = window.INJECTED === 1 && window.msg || (() => {
bg = null; bg = null;
} }
chrome.runtime.onMessage.addListener(handleMessage); // TODO: maybe move into polyfill.js and hook addListener + sendMessage so they wrap/unwrap automatically
const wrapData = data => ({
window.API = new Proxy({}, { data,
get(target, name) { });
// using a named function for convenience when debugging const wrapError = error => ({
return async function invokeAPI(...args) { error: Object.assign({
if (!bg && chrome.tabs) { message: error.message || `${error}`,
bg = await browser.runtime.getBackgroundPage().catch(() => {}); stack: error.stack,
} }, error), // passing custom properties e.g. `error.index`
const message = {method: 'invokeAPI', name, args}; });
// content scripts, frames and probably private tabs const unwrapResponse = ({data, error} = {error: {message: ERR_NO_RECEIVER}}) =>
if (!bg || window !== parent) { error
return msg.send(message); ? Promise.reject(Object.assign(new Error(error.message), error))
} : data;
// in FF, the object would become a dead object when the window chrome.runtime.onMessage.addListener(({data, target}, sender, sendResponse) => {
// is closed, so we have to clone the object into background. const res = window.msg._execute(TARGETS[target] || TARGETS.all, data, sender);
const res = bg.msg._execute(TARGETS.extension, bg.deepCopy(message), { if (res instanceof Promise) {
frameId: 0, res.then(wrapData, wrapError).then(sendResponse);
tab: NEEDS_TAB_IN_SENDER.includes(name) && await getOwnTab(), return true;
url: location.href, }
}); if (res !== undefined) sendResponse(wrapData(res));
return deepCopy(await res);
};
},
}); });
return { // This direct assignment allows IDEs to provide autocomplete for msg methods automatically
const msg = window.msg = {
isBg, isBg,
async broadcast(data) { async broadcast(data) {
@ -137,32 +135,27 @@ var msg = window.INJECTED === 1 && window.msg || (() => {
}, },
}; };
// TODO: maybe move into polyfill.js and hook addListener + sendMessage so they wrap/unwrap automatically window.API = new Proxy({}, {
function handleMessage({data, target}, sender, sendResponse) { get(target, name) {
const res = msg._execute(TARGETS[target] || TARGETS.all, data, sender); // using a named function for convenience when debugging
if (res instanceof Promise) { return async function invokeAPI(...args) {
res.then(wrapData, wrapError).then(sendResponse); if (!bg && chrome.tabs) {
return true; bg = await browser.runtime.getBackgroundPage().catch(() => {});
} }
if (res !== undefined) sendResponse(wrapData(res)); const message = {method: 'invokeAPI', name, args};
} // content scripts, frames and probably private tabs
if (!bg || window !== parent) {
function wrapData(data) { return msg.send(message);
return {data}; }
} // in FF, the object would become a dead object when the window
// is closed, so we have to clone the object into background.
function wrapError(error) { const res = bg.msg._execute(TARGETS.extension, bg.deepCopy(message), {
return { frameId: 0,
error: Object.assign({ tab: NEEDS_TAB_IN_SENDER.includes(name) && await getOwnTab(),
message: error.message || `${error}`, url: location.href,
stack: error.stack, });
}, error), // passing custom properties e.g. `error.index` return deepCopy(await res);
}; };
} },
});
function unwrapResponse({data, error} = {error: {message: ERR_NO_RECEIVER}}) {
return error
? Promise.reject(Object.assign(new Error(error.message), error))
: data;
}
})(); })();