Support nested methods.
This commit is contained in:
parent
e46c929761
commit
e7622c8558
@ -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;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user