fractal-core
Version:
A minimalist and well crafted app, content or component is our conviction
238 lines • 9.83 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("../core");
function makeSyncQueue() {
let queue = [];
return {
queue,
addWaiter(waiter) {
queue.push(waiter);
},
next(data) {
if (queue[0] && queue[0](data)) {
queue.shift();
}
},
};
}
exports.makeSyncQueue = makeSyncQueue;
exports.workerHandler = (type, name, syncQueue, workerAPI) => (mod) => {
let _self = workerAPI ? workerAPI : self;
let waiter;
return {
state: undefined,
handle: (id, value) => __awaiter(this, void 0, void 0, function* () {
if (type === 'group') {
waiter = new Promise((resolve) => {
syncQueue.addWaiter(data => {
if (data[0] === 'setGroup') {
resolve();
return true;
}
});
});
}
_self.postMessage([type, name, 'handle', id, value]);
return waiter;
}),
destroy: () => {
_self.postMessage([type, name, 'destroy']);
},
};
};
exports.workerLog = (type, workerAPI) => {
let _self = workerAPI ? workerAPI : self;
return (source, description) => {
_self.postMessage(['log', type, source, description]);
};
};
// receives messages from runWorker in the WorkerSide
exports.createWorkerListener = (syncQueue, workerAPI) => (mod) => {
let _self = workerAPI ? workerAPI : self;
// allows to dispatch inputs from the main thread
_self.onmessage = ev => {
let data = ev.data;
switch (data[0]) {
case 'dispatchEv':
mod.dispatchEv(data[1], data[2]);
break;
case 'dispatch':
mod.dispatch(data[1]);
break;
case 'toComp':
mod.toComp(data[1], data[2], data[3]);
break;
case 'setGroup':
mod.setGroup(data[1], data[2], data[3]);
break;
case 'task':
mod.task(data[1], data[2]);
break;
case 'destroy':
mod.destroy();
_self.postMessage(['destroy']);
break;
case 'nest':
// not implemented yet, should deserialize a component with a safe eval
mod.error('workerListener', `unimplemented method`);
break;
case 'nestAll':
// not implemented yet, should deserialize a list of components with a safe eval
mod.error('workerListener', `unimplemented method`);
break;
case 'unnest':
// not implemented yet, should deserialize a component with a safe eval
mod.error('workerListener', `unimplemented method`);
break;
case 'unnestAll':
// not implemented yet, should deserialize a list of components with a safe eval
mod.error('workerListener', `unimplemented method`);
break;
default:
mod.error('workerListener', `unknown message type recived from worker: ${data.join(', ')}`);
}
syncQueue.next(data);
};
};
function runWorker(def) {
return __awaiter(this, void 0, void 0, function* () {
let worker = def.worker;
let groupObjects = {};
let taskObjects = {};
let interfaceObjects = {};
let attach = (comp) => __awaiter(this, void 0, void 0, function* () {
def.error('reattach', 'unimplemented method');
});
// const eventHandlerRegister = {}
// API for modules (Main Thread)
let moduleAPI = {
on: (eventName, eventData, pullable) => ['ev', 12],
off: descriptor => worker.postMessage(['off', descriptor]),
emit: (eventName, data) => new Promise(() => { }),
// dispatch function type used for handlers
dispatchEv: (event, iData) => __awaiter(this, void 0, void 0, function* () { return worker.postMessage(['dispatchEv', event, iData]); }),
dispatch: (eventData) => __awaiter(this, void 0, void 0, function* () { return worker.postMessage(['dispatch', eventData]); }),
toComp: (id, inputName, data) => __awaiter(this, void 0, void 0, function* () { return worker.postMessage(['toComp', id, inputName, data]); }),
destroy,
attach,
// delegated methods
setGroup: (id, name, group) => worker.postMessage(['setGroup', id, name, group]),
task: (name, data) => __awaiter(this, void 0, void 0, function* () { return worker.postMessage(['task', name, data]); }),
warn: def.warn,
error: def.error,
};
if (def.groups) {
for (let i = 0, names = Object.keys(def.groups), len = names.length; i < len; i++) {
groupObjects[names[i]] = yield (yield def.groups[names[i]])(moduleAPI);
}
}
if (def.tasks) {
for (let i = 0, names = Object.keys(def.tasks), len = names.length; i < len; i++) {
taskObjects[names[i]] = yield (yield def.tasks[names[i]])(moduleAPI);
}
}
if (def.interfaces) {
for (let i = 0, names = Object.keys(def.interfaces), len = names.length; i < len; i++) {
interfaceObjects[names[i]] = yield (yield def.interfaces[names[i]])(moduleAPI);
}
}
let initTrap;
worker.onmessage = (ev) => __awaiter(this, void 0, void 0, function* () {
let data = ev.data;
switch (data[0]) {
case 'initialized':
initTrap();
break;
case 'interface':
if (data[2] === 'handle') {
yield interfaceObjects[data[1]].handle('Root', data[4]);
break;
}
else if (data[2] === 'destroy') {
interfaceObjects[data[1]].destroy();
break;
}
case 'task':
if (data[2] === 'handle') {
yield taskObjects[data[1]].handle(data[3], data[4]);
break;
}
else if (data[2] === 'destroy') {
yield taskObjects[data[1]].destroy();
break;
}
case 'group':
if (data[2] === 'handle') {
yield groupObjects[data[1]].handle(data[3], data[4]);
break;
}
else if (data[2] === 'destroy') {
groupObjects[data[1]].destroy();
break;
}
case 'log':
if (moduleAPI[data[1]]) {
moduleAPI[data[1]](data[2], data[3]);
break;
}
case 'destroy':
if (def.onDestroy) {
def.onDestroy(moduleAPI);
}
break;
default:
moduleAPI.error('runWorker', `unknown message type recived from worker: ${data.join(', ')}`);
}
});
yield new Promise(resolve => {
initTrap = resolve;
});
function destroy() {
worker.postMessage(['destroy']);
}
return {
worker,
moduleAPI,
groupObjects,
taskObjects,
interfaceObjects,
};
});
}
exports.runWorker = runWorker;
exports.runInWorker = (moduleDef, exceptions, workerAPI) => __awaiter(this, void 0, void 0, function* () {
let _self = workerAPI ? workerAPI : self;
const syncQueue = makeSyncQueue();
const workerModule = core_1.clone(moduleDef);
const workerListener = exports.createWorkerListener(syncQueue, workerAPI);
// Inject into onBeforeInit hook
workerModule.onBeforeInit
= moduleDef.onBeforeInit
? mod => {
workerListener(mod);
workerModule.onBeforeInit(mod);
}
: workerListener;
// Make a proxy for handler inside the worker for comunicating to the main thread
let handlerType, handlerName, handlerTypePlural;
for (handlerType of core_1.handlerTypes) {
handlerTypePlural = handlerType + 's';
for (handlerName in moduleDef[handlerTypePlural]) {
if (exceptions && exceptions[handlerTypePlural].indexOf(handlerName) === -1 || !exceptions) {
workerModule[handlerTypePlural][handlerName] = exports.workerHandler(handlerType, handlerName, syncQueue, workerAPI);
}
}
}
const mod = yield core_1.run(workerModule);
_self.postMessage(['initialized']);
return mod;
});
//# sourceMappingURL=worker.js.map