tildefriends/core/tfrpc.js

79 lines
1.9 KiB
JavaScript

const k_is_browser = get_is_browser();
let g_api = {};
let g_next_id = 1;
let g_calls = {};
function get_is_browser() {
try { return window !== undefined && console !== undefined; } catch { return false; }
}
if (k_is_browser) {
print = console.log;
}
function make_rpc(target, prop, receiver) {
return function() {
let id = g_next_id++;
let promise = new Promise(function(resolve, reject) {
g_calls[id] = {resolve: resolve, reject: reject};
});
if (k_is_browser) {
window.parent.postMessage({message: 'tfrpc', method: prop, params: [...arguments], id: id}, '*');
return promise;
} else {
return app.postMessage({message: 'tfrpc', method: prop, params: [...arguments], id: id}).then(x => promise);
}
}
}
function call_rpc(message) {
if (message && message.message === 'tfrpc') {
if (message.method) {
let method = g_api[message.method];
if (method) {
let response = {message: 'tfrpc', id: message.id};
try {
response.result = method(...message.params);
} catch (error) {
response.error = error;
}
if (k_is_browser) {
window.parent.postMessage(response, '*');
} else {
app.postMessage(response);
}
} else {
throw new Error(message.method + ' not found.');
}
} else if (message.result !== undefined) {
if (g_calls[message.id]) {
g_calls[message.id].resolve(message.result);
} else {
throw new Error(message.id + ' not found to reply.');
}
} else if (message.error !== undefined) {
if (g_calls[message.id]) {
g_calls[message.id].reject(message.error);
} else {
throw new Error(message.id + ' not found to reply.');
}
}
}
}
if (k_is_browser) {
window.addEventListener('message', function(event) {
call_rpc(event.data);
});
} else {
core.register('message', function(message) {
call_rpc(message?.message);
});
}
export let rpc = new Proxy({}, {get: make_rpc});
export function register(method) {
g_api[method.name] = method;
}