Add a real test!
This commit is contained in:
parent
2034139846
commit
342c46df6f
@ -15,7 +15,8 @@
|
|||||||
"build:umd:gzip":
|
"build:umd:gzip":
|
||||||
"npm run build:umd:min && gzip -c9 dist/worker-portal.min.js > dist/worker-portal.min.js.gz",
|
"npm run build:umd:min && gzip -c9 dist/worker-portal.min.js > dist/worker-portal.min.js.gz",
|
||||||
"build": "npm run build:umd:gzip && ls -l dist/",
|
"build": "npm run build:umd:gzip && ls -l dist/",
|
||||||
"prepublish": "npm run clean && npm run build"
|
"prepublish": "npm run clean && npm run build",
|
||||||
|
"test": "npm run build:lib && ava --verbose"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -29,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/explorigin/worker-portal",
|
"homepage": "https://gitlab.com/explorigin/worker-portal",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"ava": "^0.17.0",
|
||||||
"babel-cli": "6.18.0",
|
"babel-cli": "6.18.0",
|
||||||
"babel-core": "6.21.0",
|
"babel-core": "6.21.0",
|
||||||
"babel-eslint": "7.1.1",
|
"babel-eslint": "7.1.1",
|
||||||
|
|||||||
@ -12,14 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
export function isWorker() {
|
|
||||||
try {
|
|
||||||
return self !== window;
|
|
||||||
} catch (e) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function tryJSON(type, destination, id, data) {
|
function tryJSON(type, destination, id, data) {
|
||||||
const packet = [type, destination, id, data];
|
const packet = [type, destination, id, data];
|
||||||
try {
|
try {
|
||||||
@ -29,7 +21,7 @@ function tryJSON(type, destination, id, data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WorkerPortal(context, worker, 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 = Object.keys(context);
|
||||||
@ -84,29 +76,25 @@ export function WorkerPortal(context, worker, serialize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function injectionPointFactory(fnId, callbackFactory) {
|
function injectionPointFactory(fnId, callbackFactory) {
|
||||||
return () =>
|
return function(...args) {
|
||||||
new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!enabled) {
|
if (!enabled && fnId !== 0) {
|
||||||
reject(new Error('Portal disabled'));
|
reject(new Error('Portal disabled'));
|
||||||
}
|
}
|
||||||
const id = callCount;
|
const id = callCount;
|
||||||
callCount += 1;
|
callCount += 1;
|
||||||
responseMap.set(id, [callbackFactory ? callbackFactory(resolve) : resolve, reject]);
|
responseMap.set(id, [callbackFactory ? callbackFactory(resolve) : resolve, reject]);
|
||||||
post(0, id, fnId, Array.from(arguments));
|
post(0, id, fnId, args);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveExternalInterfaceFactory(resolve) {
|
function resolveExternalInterfaceFactory(resolve) {
|
||||||
return linkedFunctionNames => {
|
return (linkedFunctionNames, ...rest) => {
|
||||||
const externalInterface = {};
|
const externalInterface = {};
|
||||||
linkedFunctionNames.forEach((fnName, index) => {
|
linkedFunctionNames.forEach((fnName, index) => {
|
||||||
externalInterface[fnName] = injectionPointFactory(index);
|
externalInterface[fnName] = injectionPointFactory(index);
|
||||||
});
|
});
|
||||||
if (!isWorker()) {
|
|
||||||
externalInterface._cleanup = injectionPointFactory(linkedFunctionNames.length, resolve =>
|
|
||||||
resolve(cleanup())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
enabled = true;
|
enabled = true;
|
||||||
resolve(externalInterface);
|
resolve(externalInterface);
|
||||||
return contextIndex;
|
return contextIndex;
|
||||||
@ -125,13 +113,16 @@ export function WorkerPortal(context, worker, serialize) {
|
|||||||
|
|
||||||
_worker.addEventListener('message', dispatcher);
|
_worker.addEventListener('message', dispatcher);
|
||||||
|
|
||||||
if (isWorker()) {
|
if (isSlave) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
contextIndex.splice(0, 0, '__init', '__cleanup');
|
contextIndex.splice(0, 0, '__init', '__cleanupSlave');
|
||||||
context.__init = resolveExternalInterfaceFactory(resolve);
|
context.__init = resolveExternalInterfaceFactory(resolve);
|
||||||
context.__cleanup = cleanup;
|
context.__cleanupSlave = cleanup;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return injectionPointFactory(0, resolveExternalInterfaceFactory)(contextIndex);
|
return injectionPointFactory(0, resolveExternalInterfaceFactory)(contextIndex).then(api => ({
|
||||||
|
...api,
|
||||||
|
_cleanup: injectionPointFactory(1, resolve => resolve(cleanup()))
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
80
packages/portal/test.js
Normal file
80
packages/portal/test.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
|
||||||
|
import { WorkerPortal } from './lib';
|
||||||
|
|
||||||
|
function FakeWorkerPair() {
|
||||||
|
let cbA = null;
|
||||||
|
let cbB = null;
|
||||||
|
|
||||||
|
const objA = {
|
||||||
|
postMessage: data => {
|
||||||
|
cbB({ data: data });
|
||||||
|
},
|
||||||
|
addEventListener: (eventName, fn) => {
|
||||||
|
cbA = (...r) => {
|
||||||
|
fn(...r);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
removeEventListener: (eventName, fn) => {
|
||||||
|
cbA = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const objB = {
|
||||||
|
postMessage: data => {
|
||||||
|
cbA({ data: data });
|
||||||
|
},
|
||||||
|
addEventListener: (eventName, fn) => {
|
||||||
|
cbB = (...r) => {
|
||||||
|
fn(...r);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
removeEventListener: (eventName, fn) => {
|
||||||
|
cbB = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return [objA, objB];
|
||||||
|
}
|
||||||
|
|
||||||
|
test('Workers can call and respond equally', async t => {
|
||||||
|
const [a, b] = FakeWorkerPair();
|
||||||
|
|
||||||
|
const slave = WorkerPortal(
|
||||||
|
{
|
||||||
|
slaveAdd: (a, b) => a + b
|
||||||
|
},
|
||||||
|
a,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
const master = WorkerPortal(
|
||||||
|
{
|
||||||
|
masterSubtract: (a, b) => a - b
|
||||||
|
},
|
||||||
|
b,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
const masterApi = await master;
|
||||||
|
const slaveApi = await slave;
|
||||||
|
|
||||||
|
t.deepEqual(Object.keys(masterApi), ['__init', '__cleanupSlave', 'slaveAdd', '_cleanup']);
|
||||||
|
t.deepEqual(Object.keys(slaveApi), ['masterSubtract']);
|
||||||
|
|
||||||
|
t.is(await slaveApi.masterSubtract(9, 2), 7);
|
||||||
|
t.is(await masterApi.slaveAdd(9, 2), 11);
|
||||||
|
|
||||||
|
t.is(await masterApi.slaveAdd(5, 2), 7);
|
||||||
|
t.is(await slaveApi.masterSubtract(2, 2), 0);
|
||||||
|
|
||||||
|
await masterApi._cleanup();
|
||||||
|
|
||||||
|
return masterApi
|
||||||
|
.slaveAdd(9, 2)
|
||||||
|
.then(e => {
|
||||||
|
t.fail('Expected rejection');
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
t.is(e.message, 'Portal disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user