Support nested methods.

This commit is contained in:
Timothy Farrell 2016-12-28 08:29:04 -06:00
parent e46c929761
commit e7622c8558
2 changed files with 43 additions and 8 deletions

View File

@ -21,10 +21,37 @@ function tryJSON(type, destination, id, data) {
} }
} }
function getPaths(obj, prefix = '') {
return Object.keys(obj)
.map(key => {
const prop = obj[key];
const path = `${prefix}${key}`;
if (typeof prop === 'function') {
return path;
}
return getPaths(prop, path + '.');
})
.reduce((a, b) => a.concat(b), []);
}
function traverseObj(obj, pathStr, assignValue) {
const path = pathStr.split('.');
const last = path.pop();
const ptr = path.reduce(
(acc, next) => (acc[next] === undefined ? (acc[next] = {}) : acc[next]),
obj
);
if (assignValue) {
return (ptr[last] = assignValue);
}
return ptr[last];
}
export function WorkerPortal(context, worker, isSlave, serialize) { export function WorkerPortal(context, worker, isSlave, serialize) {
const responseMap = new Map(); const responseMap = new Map();
const _worker = worker || self; const _worker = worker || self;
const contextIndex = Object.keys(context); const contextIndex = getPaths(context);
const methods = contextIndex.map(path => traverseObj(context, path));
const _serialize = serialize const _serialize = serialize
? (type, destination, id, params) => serialize(type, destination, id, params, tryJSON) ? (type, destination, id, params) => serialize(type, destination, id, params, tryJSON)
: tryJSON; : tryJSON;
@ -66,7 +93,7 @@ export function WorkerPortal(context, worker, isSlave, serialize) {
// If we have received an RPC call, execute and respond. // If we have received an RPC call, execute and respond.
let thennable; let thennable;
try { try {
thennable = context[contextIndex[destination]].apply(null, params); thennable = methods[destination].apply(null, params);
} catch (e) { } catch (e) {
_reject(e); _reject(e);
} }
@ -94,8 +121,8 @@ export function WorkerPortal(context, worker, isSlave, serialize) {
function resolveExternalInterfaceFactory(resolve) { function resolveExternalInterfaceFactory(resolve) {
return (linkedFunctionNames, ...rest) => { return (linkedFunctionNames, ...rest) => {
const externalInterface = {}; const externalInterface = {};
linkedFunctionNames.forEach((fnName, index) => { linkedFunctionNames.forEach((pathStr, index) => {
externalInterface[fnName] = injectionPointFactory(index); traverseObj(externalInterface, pathStr, injectionPointFactory(index));
}); });
enabled = true; enabled = true;
resolve(externalInterface); resolve(externalInterface);
@ -118,8 +145,7 @@ export function WorkerPortal(context, worker, isSlave, serialize) {
if (isSlave) { if (isSlave) {
return new Promise(resolve => { return new Promise(resolve => {
contextIndex.splice(0, 0, '__init', '__cleanupSlave'); contextIndex.splice(0, 0, '__init', '__cleanupSlave');
context.__init = resolveExternalInterfaceFactory(resolve); methods.splice(0, 0, resolveExternalInterfaceFactory(resolve), cleanup);
context.__cleanupSlave = cleanup;
}); });
} }

View File

@ -42,7 +42,13 @@ test('Workers can call and respond equally', async t => {
const slave = WorkerPortal( const slave = WorkerPortal(
{ {
slaveAdd: (a, b) => a + b slaveAdd: (a, b) => a + b,
math: {
multiply: (a, b) => a * b,
lib: {
pow: (a, b) => Math.pow(a, b)
}
}
}, },
a, a,
true true
@ -58,11 +64,14 @@ test('Workers can call and respond equally', async t => {
const masterApi = await master; const masterApi = await master;
const slaveApi = await slave; const slaveApi = await slave;
t.deepEqual(Object.keys(masterApi), ['__init', '__cleanupSlave', 'slaveAdd', '_cleanup']); t.deepEqual(Object.keys(masterApi), ['__init', '__cleanupSlave', 'slaveAdd', 'math', '_cleanup']);
t.deepEqual(Object.keys(masterApi.math), ['multiply', 'lib']);
t.deepEqual(Object.keys(slaveApi), ['masterSubtract']); t.deepEqual(Object.keys(slaveApi), ['masterSubtract']);
t.is(await slaveApi.masterSubtract(9, 2), 7); t.is(await slaveApi.masterSubtract(9, 2), 7);
t.is(await masterApi.slaveAdd(9, 2), 11); t.is(await masterApi.slaveAdd(9, 2), 11);
t.is(await masterApi.math.multiply(9, 2), 18);
t.is(await masterApi.math.lib.pow(9, 2), 81);
t.is(await masterApi.slaveAdd(5, 2), 7); t.is(await masterApi.slaveAdd(5, 2), 7);
t.is(await slaveApi.masterSubtract(2, 2), 0); t.is(await slaveApi.masterSubtract(2, 2), 0);