WIP: drop api.js

This commit is contained in:
eight 2018-10-06 04:39:48 +08:00
parent 3a618aca2a
commit 171339f710
6 changed files with 73 additions and 99 deletions

View File

@ -1,46 +0,0 @@
/* global promisify */
'use strict';
const API = (() => {
const preparing = chrome.runtime.getBackgroundPage ?
promisify(chrome.runtime.getBackgroundPage.bind(chrome.runtime))()
.catch(() => null) :
Promise.resolve(null);
const runtimeSendMessage = promisify(chrome.runtime.sendMessage.bind(chrome.runtime));
return new Proxy(() => {}, {
get: (target, name) =>
(...args) => invokeBG(name, args),
});
function sendMessage(msg) {
return runtimeSendMessage(msg)
.then(result => {
if (result && result.__ERROR__) {
throw new Error(result.__ERROR__);
}
return result;
});
}
function invokeBG(name, args) {
return preparing.then(BG => {
if (!BG) {
return sendMessage({
method: 'invokeAPI',
name,
args
});
}
// FIXME: why deep-copying input/output?
if (BG !== window) {
args = BG.deepCopy(args);
}
const fn = BG.API_METHODS[name];
if (!fn) {
throw new Error(`unknown API method: ${name}`);
}
return Promise.resolve(fn(...args))
.then(BG.deepCopy);
});
}
})();

View File

@ -26,7 +26,7 @@
<script src="js/script-loader.js"></script> <script src="js/script-loader.js"></script>
<script src="js/storage-util.js"></script> <script src="js/storage-util.js"></script>
<script src="js/exclusions.js"></script> <script src="js/exclusions.js"></script>
<script src="content/api.js"></script> <script src="js/msg.js"></script>
<script src="content/apply.js"></script> <script src="content/apply.js"></script>
<script src="edit/util.js"></script> <script src="edit/util.js"></script>
<script src="edit/regexp-tester.js"></script> <script src="edit/regexp-tester.js"></script>

112
js/msg.js
View File

@ -1,4 +1,5 @@
/* global promisify deepCopy */ /* global promisify deepCopy */
// deepCopy is only used if the script is executed in extension pages.
'use strict'; 'use strict';
const msg = (() => { const msg = (() => {
@ -119,54 +120,56 @@ const msg = (() => {
tab: [], tab: [],
extension: [] extension: []
}; };
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { chrome.runtime.onMessage.addListener(handleMessage);
const handlers = message.target === 'tab' ? }
handler.tab.concat(handler.both) : message.target === 'extension' ?
handler.extension.concat(handler.both) :
handler.both.concat(handler.extension, handler.tab);
if (!handlers.length) {
return;
}
if (message.type === 'exchange') {
const pending = exchangeGet(message, true);
if (pending) {
pending.then(response);
return true;
}
}
return response();
function response() { function handleMessage(message, sender, sendResponse) {
let result; const handlers = message.target === 'tab' ?
for (const handle of handlers) { handler.tab.concat(handler.both) : message.target === 'extension' ?
const data = handle(message.data, sender); handler.extension.concat(handler.both) :
if (data !== undefined && result === undefined) { handler.both.concat(handler.extension, handler.tab);
result = data; if (!handlers.length) {
} return;
} }
if (result === undefined) { if (message.type === 'exchange') {
return; const pending = exchangeGet(message, true);
} if (pending) {
Promise.resolve(result) pending.then(response);
.then(
data => ({error: false, data}),
err => ({error: true, data: err.message || String(err)})
)
.then(function doResponse(responseMessage) {
if (message.from === 'extension' && bg === undefined) {
return preparing.then(() => doResponse(responseMessage));
}
if (message.from === 'extension' && bg) {
exchangeSet(responseMessage);
} else {
responseMessage.type = 'direct';
}
return responseMessage;
})
.then(sendResponse);
return true; return true;
} }
}); }
return response();
function response() {
let result;
for (const handle of handlers) {
const data = withPromiseError(handle, message.data, sender);
if (data !== undefined && result === undefined) {
result = data;
}
}
if (result === undefined) {
return;
}
Promise.resolve(result)
.then(
data => ({error: false, data}),
err => ({error: true, data: err.message || String(err)})
)
.then(function doResponse(responseMessage) {
if (message.from === 'extension' && bg === undefined) {
return preparing.then(() => doResponse(responseMessage));
}
if (message.from === 'extension' && bg) {
exchangeSet(responseMessage);
} else {
responseMessage.type = 'direct';
}
return responseMessage;
})
.then(sendResponse);
return true;
}
} }
function exchangeGet(message, keepStorage = false) { function exchangeGet(message, keepStorage = false) {
@ -175,7 +178,7 @@ const msg = (() => {
} }
message.data = bg._msg.storage.get(message.id); message.data = bg._msg.storage.get(message.id);
if (keepStorage) { if (keepStorage) {
message.data = deepCopy(data); message.data = deepCopy(message.data);
} else { } else {
bg._msg.storage.delete(message.id); bg._msg.storage.delete(message.id);
} }
@ -190,6 +193,14 @@ const msg = (() => {
delete message.data; delete message.data;
} }
function withPromiseError(fn, ...args) {
try {
return fn(...args);
} catch (err) {
return Promise.reject(err);
}
}
function withCleanup(p, fn) { function withCleanup(p, fn) {
return p.then( return p.then(
result => { result => {
@ -229,3 +240,12 @@ const msg = (() => {
} }
} }
})(); })();
const API = new Proxy({}, {
get: (target, name) =>
(...args) => msg.send({
method: 'invokeAPI',
name,
args
})
});

View File

@ -157,7 +157,7 @@
<script src="js/dom.js"></script> <script src="js/dom.js"></script>
<script src="js/messaging.js"></script> <script src="js/messaging.js"></script>
<script src="js/prefs.js"></script> <script src="js/prefs.js"></script>
<script src="content/api.js"></script> <script src="js/msg.js"></script>
<script src="content/apply.js"></script> <script src="content/apply.js"></script>
<script src="js/localization.js"></script> <script src="js/localization.js"></script>
<script src="manage/filters.js"></script> <script src="manage/filters.js"></script>

View File

@ -61,19 +61,19 @@
"run_at": "document_start", "run_at": "document_start",
"all_frames": true, "all_frames": true,
"match_about_blank": true, "match_about_blank": true,
"js": ["js/promisify.js", "content/api.js", "content/apply.js"] "js": ["js/promisify.js", "js/msg.js", "content/apply.js"]
}, },
{ {
"matches": ["http://userstyles.org/*", "https://userstyles.org/*"], "matches": ["http://userstyles.org/*", "https://userstyles.org/*"],
"run_at": "document_start", "run_at": "document_start",
"all_frames": true, "all_frames": true,
"js": ["js/promisify.js", "content/api.js", "content/install-hook-userstyles.js"] "js": ["js/promisify.js", "js/msg.js", "content/install-hook-userstyles.js"]
}, },
{ {
"matches": ["https://openusercss.org/*", "https://openusercss.com/*"], "matches": ["https://openusercss.org/*", "https://openusercss.com/*"],
"run_at": "document_start", "run_at": "document_start",
"all_frames": false, "all_frames": false,
"js": ["js/promisify.js", "content/api.js", "content/install-hook-openusercss.js"] "js": ["js/promisify.js", "js/msg.js", "content/install-hook-openusercss.js"]
}, },
{ {
"matches": [ "matches": [
@ -97,7 +97,7 @@
], ],
"run_at": "document_idle", "run_at": "document_idle",
"all_frames": false, "all_frames": false,
"js": ["js/promisify.js", "content/api.js", "content/install-hook-usercss.js"] "js": ["js/promisify.js", "js/msg.js", "content/install-hook-usercss.js"]
} }
], ],
"browser_action": { "browser_action": {

View File

@ -156,7 +156,7 @@
<script src="js/localization.js"></script> <script src="js/localization.js"></script>
<script src="js/prefs.js"></script> <script src="js/prefs.js"></script>
<script src="js/promisify.js"></script> <script src="js/promisify.js"></script>
<script src="content/api.js"></script> <script src="js/msg.js"></script>
<script src="content/apply.js"></script> <script src="content/apply.js"></script>
<link rel="stylesheet" href="popup/popup.css"> <link rel="stylesheet" href="popup/popup.css">