diff --git a/built/worka_require.js b/built/worka_require.js index 82c2347..71dda2b 100644 --- a/built/worka_require.js +++ b/built/worka_require.js @@ -26,23 +26,18 @@ workerSupport.transferrables = (smallArrayBuffer.byteLength === 0) const workers = {}; -let symbol = 0; -const symbolGenerator = function () { - symbol += 1; - return symbol; -}; const WORKA_SYMBOLS = { // loadMode - STRING: symbolGenerator(), - DECORATED: symbolGenerator(), - FUNCTION: symbolGenerator(), - MULTI_FUNCTION: symbolGenerator(), - FILE: symbolGenerator(), - DECORATED_FILE: symbolGenerator(), + STRING: Symbol(), + DECORATED: Symbol(), + FUNCTION: Symbol(), + MULTI_FUNCTION: Symbol(), + FILE: Symbol(), + DECORATED_FILE: Symbol(), // errors - NO_SUPPORT_ERROR: symbolGenerator(), - TIME_OUT_ERROR: symbolGenerator(), + NO_SUPPORT_ERROR: Symbol(), + TIME_OUT_ERROR: Symbol(), SPLIT: `/`, JS_MIME: {type: `text/javascript`} }; @@ -74,7 +69,9 @@ const WORKER_INITIAL_SETTINGS = { instance: undefined, awakened: false, hasEventListener: false, - resolveRejectQueue: undefined // [] + resolveRejectQueue: undefined, + inputQueue: undefined, + workerStore: workers }; const loadWorker = function (worker) { @@ -159,11 +156,11 @@ self.addEventListener(\`message\`, function(event) { }; const instanciateWorker = function (worker) { - const decoratedAsString = worker.decoratedAsString; let workerObjectURL; if (worker.workerObjectURL) { workerObjectURL = worker.workerObjectURL; } else { + const decoratedAsString = worker.decoratedAsString; const workerBlob = new Blob([decoratedAsString], WORKA_SYMBOLS.JS_MIME); workerObjectURL = URL.createObjectURL(workerBlob); } @@ -219,8 +216,19 @@ const afterWorkerFinished = function (worker) { if (hope > 0) { return; } - const workerStore = worker.workerStore || workers; - delete workerStore[worker.name]; + delete worker.workerStore[worker.name]; +}; + + +const afterWorkerErrored = function (worker) { + /* stop everything */ + const error = `request to worker canceled because an error occured before`; + worker.resolveRejectQueue.forEach(function ([resolve, reject]) { + reject(error); + }); + + forceTerminateWorker(worker); + delete worker.workerStore[worker.name]; }; const addEventListenerToWorker = function (worker) { @@ -235,7 +243,7 @@ const addEventListenerToWorker = function (worker) { } else if (Object.prototype.hasOwnProperty.call(message, `error`)) { const error = message.error; reject(error); - afterWorkerFinished(worker); + afterWorkerErrored(worker); } }); worker.hasEventListener = true; @@ -251,9 +259,9 @@ const prepareWorkerTimeOut = function (worker, resolve, reject, preparedInput) { setTimeout(function () { // if the resolveRejectQueue still includes the resolve, it means it has not yet // resolved - if (worker.resolveRejectQueue.findIndex(function ([resolveX]) { - return resolve === resolveX; - }) !== -1) { + if (worker.resolveRejectQueue.some(function ([resolveI]) { + return resolve === resolveI; + })) { /*const discardedResolve = */ worker.resolveRejectQueue.shift(); // forceTerminateWorker, because we don't care anymore about the result @@ -309,7 +317,8 @@ const registerWorker = function (options, workerStore = workers) { const worker = { ...WORKER_DEFAULT_OPTIONS, ...options, - ...WORKER_INITIAL_SETTINGS + ...WORKER_INITIAL_SETTINGS, + workerStore }; worker.resolveRejectQueue = []; if (worker.timeOut && worker.hope > 5) { @@ -338,7 +347,6 @@ const findWorkerWithEmptyQueue = function (workerStore = workers) { }); }; -const mock = {resolveRejectQueue: {length: Number.MAX_SAFE_INTEGER}}; const workerWithLowestresolveRejectQueue = function (workers) { return workers.reduce(function (workerWithLowestresolveRejectQueueSoFar, worker) { if ( @@ -348,7 +356,7 @@ const workerWithLowestresolveRejectQueue = function (workers) { return worker; } return workerWithLowestresolveRejectQueueSoFar; - }, mock); + }); }; const work = function (name, input, workerStore = workers, forceWork = false) { @@ -395,6 +403,12 @@ const work = function (name, input, workerStore = workers, forceWork = false) { // the worker has not yet utilized this feature and needs to be initialized worker.coWorkers = {}; worker.nextCoWorkerOptions = Object.assign({}, worker, { + instanciated: false, + hasEventListener: false, + lazy: 10, + hope: 1, + coWorkers: undefined, + max: 1, name: `0`, workerStore: worker.coWorkers }); diff --git a/built/worka_script.js b/built/worka_script.js index 84ef6e7..7624f5c 100644 --- a/built/worka_script.js +++ b/built/worka_script.js @@ -1,92 +1,93 @@ var worka = (function (exports) { -'use strict'; - -/*worka.js*/ - -const workerSupport = { - - basic: Boolean(window.Worker), - transferrables: undefined - // encapsulation: undefined // Worker inside Worker -}; - -// transferrables feature detection -// a priori not supported in IE 10, 11 -/* -const smallArrayBuffer = new ArrayBuffer(1); -const emptyWorker = new Worker(`../empty-worker.js`); - -emptyWorker.postMessage(smallArrayBuffer, [smallArrayBuffer]); - -// length must be set to 0 in this context -workerSupport.transferrables = (smallArrayBuffer.byteLength === 0) - -*/ - -const workers = {}; - -let symbol = 0; -const symbolGenerator = function () { - symbol += 1; - return symbol; -}; - -const WORKA_SYMBOLS = { - // loadMode - STRING: symbolGenerator(), - DECORATED: symbolGenerator(), - FUNCTION: symbolGenerator(), - MULTI_FUNCTION: symbolGenerator(), - FILE: symbolGenerator(), - DECORATED_FILE: symbolGenerator(), - // errors - NO_SUPPORT_ERROR: symbolGenerator(), - TIME_OUT_ERROR: symbolGenerator(), - SPLIT: `/`, - JS_MIME: {type: `text/javascript`} -}; - -const WORKER_DEFAULT_OPTIONS = { - name: ``, - resource: ``, - loadMode: WORKA_SYMBOLS.STRING, - lazy: 5, - hope: 6, - max: navigator.hardwareConcurrency || 1, - stateless: true, - initialize: false, - timeOut: false -}; - -// separate from WORKER_DEFAULT_OPTIONS, impossible to overwrite with options in registerWorker -const WORKER_INITIAL_SETTINGS = { - loaded: false, - originalAsString: ``, - decorated: false, - decoratedAsString: ``, - instanciated: false, - workerObjectURL: undefined, - instance: undefined, - awakened: false, - hasEventListener: false, - resolveRejectQueue: undefined // [] -}; - -const loadWorker = function (worker) { - const resource = worker.resource; - const loadMode = worker.loadMode; - if ( - loadMode === WORKA_SYMBOLS.FUNCTION || - loadMode === WORKA_SYMBOLS.MULTI_FUNCTION - ) { - worker.originalAsString = resource.toString(); + 'use strict'; + + /*worka.js*/ + + const workerSupport = { + + basic: (typeof Worker === `function`), + transferrables: undefined + // encapsulation: undefined // Worker inside Worker + }; + + // transferrables feature detection + // a priori not supported in IE 10, 11 + /* + const smallArrayBuffer = new ArrayBuffer(1); + const emptyWorker = new Worker(`../empty-worker.js`); + + emptyWorker.postMessage(smallArrayBuffer, [smallArrayBuffer]); + + // length must be set to 0 in this context + workerSupport.transferrables = (smallArrayBuffer.byteLength === 0) + + */ + + const workers = {}; + + + const WORKA_SYMBOLS = { + // loadMode + STRING: Symbol(), + DECORATED: Symbol(), + FUNCTION: Symbol(), + MULTI_FUNCTION: Symbol(), + FILE: Symbol(), + DECORATED_FILE: Symbol(), + // errors + NO_SUPPORT_ERROR: Symbol(), + TIME_OUT_ERROR: Symbol(), + SPLIT: `/`, + JS_MIME: {type: `text/javascript`} + }; + + let max = 1; + if (typeof navigator === `object`) { + max = navigator.hardwareConcurrency || max; } - worker.loaded = true; -}; + const WORKER_DEFAULT_OPTIONS = { + name: ``, + resource: ``, + loadMode: WORKA_SYMBOLS.STRING, + lazy: 5, + hope: 6, + max, + stateless: true, + initialize: false, + timeOut: false + }; -const useStrict = `"use strict";`; -/* conver to String because errorEvent can not be cloned*/ -const errorHandler = `self.addEventListener(\`error\`, function (errorEvent) { + // separate from WORKER_DEFAULT_OPTIONS, impossible to overwrite with options in registerWorker + const WORKER_INITIAL_SETTINGS = { + loaded: false, + originalAsString: ``, + decorated: false, + decoratedAsString: ``, + instanciated: false, + workerObjectURL: undefined, + instance: undefined, + awakened: false, + hasEventListener: false, + resolveRejectQueue: undefined, + inputQueue: undefined, + workerStore: workers + }; + + const loadWorker = function (worker) { + const resource = worker.resource; + const loadMode = worker.loadMode; + if ( + loadMode === WORKA_SYMBOLS.FUNCTION || + loadMode === WORKA_SYMBOLS.MULTI_FUNCTION + ) { + worker.originalAsString = resource.toString(); + } + worker.loaded = true; + }; + + const useStrict = `"use strict";`; + /* conver to String because errorEvent can not be cloned*/ + const errorHandler = `self.addEventListener(\`error\`, function (errorEvent) { errorEvent.preventDefault(); let asString; if (errorEvent.message) { @@ -98,12 +99,12 @@ const errorHandler = `self.addEventListener(\`error\`, function (errorEvent) { error: asString }); });`; -const decorateWorker = function (worker) { - const originalAsString = worker.originalAsString; - const loadMode = worker.loadMode; - let decoratedAsString; - if (loadMode === WORKA_SYMBOLS.MULTI_FUNCTION) { - decoratedAsString = ` + const decorateWorker = function (worker) { + const originalAsString = worker.originalAsString; + const loadMode = worker.loadMode; + let decoratedAsString; + if (loadMode === WORKA_SYMBOLS.MULTI_FUNCTION) { + decoratedAsString = ` ${useStrict} ${errorHandler} const functions = ${originalAsString}(); @@ -126,14 +127,14 @@ self.addEventListener(\`message\`, function(event) { }); `; - } else { - let initializeSuffix; - if (worker.stateless && !worker.initialize) { - initializeSuffix = ``; } else { - initializeSuffix = `()`; - } - decoratedAsString = ` + let initializeSuffix; + if (worker.stateless && !worker.initialize) { + initializeSuffix = ``; + } else { + initializeSuffix = `()`; + } + decoratedAsString = ` ${useStrict} ${errorHandler} const doWork = ${originalAsString}${initializeSuffix}; @@ -148,303 +149,320 @@ self.addEventListener(\`message\`, function(event) { }); }); `; - } - worker.decoratedAsString = decoratedAsString; - worker.decorated = true; -}; - -const instanciateWorker = function (worker) { - const decoratedAsString = worker.decoratedAsString; - let workerObjectURL; - if (worker.workerObjectURL) { - workerObjectURL = worker.workerObjectURL; - } else { - const workerBlob = new Blob([decoratedAsString], WORKA_SYMBOLS.JS_MIME); - workerObjectURL = URL.createObjectURL(workerBlob); - } - const instance = new Worker(workerObjectURL); - if (worker.hope > 5 || worker.hope < 1) { - // remove for debugging - URL.revokeObjectURL(workerObjectURL); - } else { - // keep for reuse - worker.workerObjectURL = workerObjectURL; - } - worker.instance = instance; - worker.instanciated = true; -}; - -const forceAwakenWorker = function (worker) { - // a worker is awaken as soon as it receives it first message - // this function can be used to awake the worker before it is used - // can be a good idea when the worker needs time to set up - const instance = worker.instance; - instance.postMessage(``); - worker.awakened = true; // or will be in a few -}; - -const forceTerminateWorker = function (worker) { - if (worker.instance) { - worker.instance.terminate(); - } - worker.instance = undefined; - worker.instanciated = false; - worker.awakened = false; - worker.hasEventListener = false; -}; - -const afterWorkerFinished = function (worker) { - /* a worker with 0 hope was made to be used 1 time - a worker with 100 hope was made to be used multiple times*/ - const length = worker.resolveRejectQueue.length; - if (length !== 0) { - if (worker.timeOut && worker.inputQueue.length !== 0) { - worker.instance.postMessage(worker.inputQueue.shift()); } - // still has things to do - return; - } - - const hope = worker.hope; - if (hope > 5) { - return; - } - forceTerminateWorker(worker); + worker.decoratedAsString = decoratedAsString; + worker.decorated = true; + }; - if (hope > 0) { - return; - } - const workerStore = worker.workerStore || workers; - delete workerStore[worker.name]; -}; - -const addEventListenerToWorker = function (worker) { - const instance = worker.instance; - instance.addEventListener(`message`, function (event) { - const message = event.data; - const [resolve, reject] = worker.resolveRejectQueue.shift(); - if (Object.prototype.hasOwnProperty.call(message, `result`)) { - const result = message.result; - resolve(result); - afterWorkerFinished(worker); - } else if (Object.prototype.hasOwnProperty.call(message, `error`)) { - const error = message.error; - reject(error); - afterWorkerFinished(worker); + const instanciateWorker = function (worker) { + let workerObjectURL; + if (worker.workerObjectURL) { + workerObjectURL = worker.workerObjectURL; + } else { + const decoratedAsString = worker.decoratedAsString; + const workerBlob = new Blob([decoratedAsString], WORKA_SYMBOLS.JS_MIME); + workerObjectURL = URL.createObjectURL(workerBlob); } - }); - worker.hasEventListener = true; -}; + const instance = new Worker(workerObjectURL); + if (worker.hope > 5 || worker.hope < 1) { + // remove for debugging + URL.revokeObjectURL(workerObjectURL); + } else { + // keep for reuse + worker.workerObjectURL = workerObjectURL; + } + worker.instance = instance; + worker.instanciated = true; + }; -const prepareWorkerTimeOut = function (worker, resolve, reject, preparedInput) { - if (worker.resolveRejectQueue.length === 1) { - worker.instance.postMessage(preparedInput); - } else { - worker.inputQueue.push(preparedInput); - } + const forceAwakenWorker = function (worker) { + // a worker is awaken as soon as it receives it first message + // this function can be used to awake the worker before it is used + // can be a good idea when the worker needs time to set up + const instance = worker.instance; + instance.postMessage(``); + worker.awakened = true; // or will be in a few + }; + + const forceTerminateWorker = function (worker) { + if (worker.instance) { + worker.instance.terminate(); + } + worker.instance = undefined; + worker.instanciated = false; + worker.awakened = false; + worker.hasEventListener = false; + }; - setTimeout(function () { - // if the resolveRejectQueue still includes the resolve, it means it has not yet - // resolved - if (worker.resolveRejectQueue.findIndex(function ([resolveX]) { - return resolve === resolveX; - }) !== -1) { - /*const discardedResolve = */ - worker.resolveRejectQueue.shift(); - // forceTerminateWorker, because we don't care anymore about the result - forceTerminateWorker(worker); - if (worker.inputQueue.length !== 0) { - instanciateWorker(worker); - addEventListenerToWorker(worker); + const afterWorkerFinished = function (worker) { + /* a worker with 0 hope was made to be used 1 time + a worker with 100 hope was made to be used multiple times*/ + const length = worker.resolveRejectQueue.length; + if (length !== 0) { + if (worker.timeOut && worker.inputQueue.length !== 0) { + worker.instance.postMessage(worker.inputQueue.shift()); } - afterWorkerFinished(worker); - reject(WORKA_SYMBOLS.TIME_OUT_ERROR); + // still has things to do + return; } - }, worker.timeOut); -}; -const prepareWorker = function (worker, lazy, makesSenseToAwake = false) { - // lazy is used for cascade pattern - if (lazy > 4) { - return; - } - if (!worker.loaded) { - loadWorker(worker); - } - if (lazy > 3) { - return; - } - if (!worker.decorated) { - decorateWorker(worker); - } - if (lazy > 2) { - return; - } - if (!worker.instanciated) { - instanciateWorker(worker); - } - if (lazy > 1) { - return; - } - if (!worker.hasEventListener) { - addEventListenerToWorker(worker); - } - if (lazy > 0) { - return; - } - if (!worker.awakened && makesSenseToAwake) { - forceAwakenWorker(worker); - } -}; + const hope = worker.hope; + if (hope > 5) { + return; + } + forceTerminateWorker(worker); -const registerWorker = function (options, workerStore = workers) { - if (!workerSupport.basic) { - return; - } - const worker = { - ...WORKER_DEFAULT_OPTIONS, - ...options, - ...WORKER_INITIAL_SETTINGS + if (hope > 0) { + return; + } + delete worker.workerStore[worker.name]; }; - worker.resolveRejectQueue = []; - if (worker.timeOut && worker.hope > 5) { - worker.inputQueue = []; - // need to manage input queue manually for timeouts - } - const loadMode = worker.loadMode; - const resource = worker.resource; - if (loadMode === WORKA_SYMBOLS.STRING) { - worker.originalAsString = resource; - worker.loaded = true; - } else if (loadMode === WORKA_SYMBOLS.DECORATED) { - worker.decoratedAsString = resource; - worker.decorated = true; - worker.loaded = true; - } - prepareWorker(worker, worker.lazy, true); - workerStore[worker.name] = worker; -}; - -const findWorkerWithEmptyQueue = function (workerStore = workers) { - // returns the worker found or undefined - return Object.values(workerStore).find(function (worker) { - return worker.resolveRejectQueue.length === 0; - }); -}; -const mock = {resolveRejectQueue: {length: Number.MAX_SAFE_INTEGER}}; -const workerWithLowestresolveRejectQueue = function (workers) { - return workers.reduce(function (workerWithLowestresolveRejectQueueSoFar, worker) { - if ( - worker.resolveRejectQueue.length < - workerWithLowestresolveRejectQueueSoFar.resolveRejectQueue.length - ) { - return worker; - } - return workerWithLowestresolveRejectQueueSoFar; - }, mock); -}; - -const work = function (name, input, workerStore = workers, forceWork = false) { - // is overloaded on many levels, could benefit from refactoring - // functionName not needed ? - if (!workerSupport.basic) { - return Promise.reject(WORKA_SYMBOLS.NO_SUPPORT_ERROR); - } - let preparedInput; - let workerName; - let functionName; - if (Array.isArray(name)) { - [workerName, functionName] = name; - } else { - const nameSplit = name.split(WORKA_SYMBOLS.SPLIT); - if (nameSplit.length === 2) { - // worker.loadMode === WORKA_SYMBOLS.MULTI_FUNCTION - [workerName, functionName] = nameSplit; + const afterWorkerErrored = function (worker) { + /* stop everything */ + const error = `request to worker canceled because an error occured before`; + worker.resolveRejectQueue.forEach(function ([resolve, reject]) { + reject(error); + }); + + forceTerminateWorker(worker); + delete worker.workerStore[worker.name]; + }; + const addEventListenerToWorker = function (worker) { + const instance = worker.instance; + instance.addEventListener(`message`, function (event) { + const message = event.data; + const [resolve, reject] = worker.resolveRejectQueue.shift(); + if (Object.prototype.hasOwnProperty.call(message, `result`)) { + const result = message.result; + resolve(result); + afterWorkerFinished(worker); + } else if (Object.prototype.hasOwnProperty.call(message, `error`)) { + const error = message.error; + reject(error); + afterWorkerErrored(worker); + } + }); + worker.hasEventListener = true; + }; + + const prepareWorkerTimeOut = function (worker, resolve, reject, preparedInput) { + if (worker.resolveRejectQueue.length === 1) { + worker.instance.postMessage(preparedInput); } else { - workerName = name; + worker.inputQueue.push(preparedInput); } - } - if (!Object.prototype.hasOwnProperty.call(workerStore, workerName)) { - return Promise.reject(`"${workerName}" not registered`); - } - if (Object.prototype.hasOwnProperty.call(input, `input`)) { - // already prepared - preparedInput = input; - } else { - preparedInput = { - input + + setTimeout(function () { + // if the resolveRejectQueue still includes the resolve, it means it has not yet + // resolved + if (worker.resolveRejectQueue.some(function ([resolveI]) { + return resolve === resolveI; + })) { + /*const discardedResolve = */ + worker.resolveRejectQueue.shift(); + // forceTerminateWorker, because we don't care anymore about the result + forceTerminateWorker(worker); + if (worker.inputQueue.length !== 0) { + instanciateWorker(worker); + addEventListenerToWorker(worker); + } + afterWorkerFinished(worker); + reject(WORKA_SYMBOLS.TIME_OUT_ERROR); + } + }, worker.timeOut); + }; + + const prepareWorker = function (worker, lazy, makesSenseToAwake = false) { + // lazy is used for cascade pattern + if (lazy > 4) { + return; + } + if (!worker.loaded) { + loadWorker(worker); + } + if (lazy > 3) { + return; + } + if (!worker.decorated) { + decorateWorker(worker); + } + if (lazy > 2) { + return; + } + if (!worker.instanciated) { + instanciateWorker(worker); + } + if (lazy > 1) { + return; + } + if (!worker.hasEventListener) { + addEventListenerToWorker(worker); + } + if (lazy > 0) { + return; + } + if (!worker.awakened && makesSenseToAwake) { + forceAwakenWorker(worker); + } + }; + + const registerWorker = function (options, workerStore = workers) { + if (!workerSupport.basic) { + return; + } + const worker = { + ...WORKER_DEFAULT_OPTIONS, + ...options, + ...WORKER_INITIAL_SETTINGS, + workerStore }; - if (functionName !== undefined) { - preparedInput.functionName = functionName; + worker.resolveRejectQueue = []; + if (worker.timeOut && worker.hope > 5) { + worker.inputQueue = []; + // need to manage input queue manually for timeouts } - } - const worker = workerStore[workerName]; - - if (worker.stateless && worker.resolveRejectQueue.length !== 0 && !forceWork) { - // the worker is already doing something and it is stateless - // only stateless worker can duplicate themselves - if (!worker.coWorkers) { - // the worker has not yet utilized this feature and needs to be initialized - worker.coWorkers = {}; - worker.nextCoWorkerOptions = Object.assign({}, worker, { - name: `0`, - workerStore: worker.coWorkers - }); + + const loadMode = worker.loadMode; + const resource = worker.resource; + if (loadMode === WORKA_SYMBOLS.STRING) { + worker.originalAsString = resource; + worker.loaded = true; + } else if (loadMode === WORKA_SYMBOLS.DECORATED) { + worker.decoratedAsString = resource; + worker.decorated = true; + worker.loaded = true; } - const coWorkerCount = Object.keys(worker.coWorkers).length; - - if (coWorkerCount !== 0) { - // there are already coWorkers - const workerWithEmptyQueue = findWorkerWithEmptyQueue(worker.coWorkers); - if (workerWithEmptyQueue) { - // at least 1 is idle, give it something to do - return work( - [workerWithEmptyQueue.name, functionName], - preparedInput, - worker.coWorkers - ); + prepareWorker(worker, worker.lazy, true); + workerStore[worker.name] = worker; + }; + + const findWorkerWithEmptyQueue = function (workerStore = workers) { + // returns the worker found or undefined + return Object.values(workerStore).find(function (worker) { + return worker.resolveRejectQueue.length === 0; + }); + }; + + const workerWithLowestresolveRejectQueue = function (workers) { + return workers.reduce(function (workerWithLowestresolveRejectQueueSoFar, worker) { + if ( + worker.resolveRejectQueue.length < + workerWithLowestresolveRejectQueueSoFar.resolveRejectQueue.length + ) { + return worker; } + return workerWithLowestresolveRejectQueueSoFar; + }); + }; + + const work = function (name, input, workerStore = workers, forceWork = false) { + // is overloaded on many levels, could benefit from refactoring + // functionName not needed ? + if (!workerSupport.basic) { + return Promise.reject(WORKA_SYMBOLS.NO_SUPPORT_ERROR); } + let preparedInput; + let workerName; + let functionName; + if (Array.isArray(name)) { + [workerName, functionName] = name; + } else { + const nameSplit = name.split(WORKA_SYMBOLS.SPLIT); + if (nameSplit.length === 2) { + // worker.loadMode === WORKA_SYMBOLS.MULTI_FUNCTION + [workerName, functionName] = nameSplit; - // there are no idle coworkers - if ((coWorkerCount + 1) < worker.max) { - // the worker count is below maximum, we can create more - // + 1 is for the parent worker itself - const nameNow = worker.nextCoWorkerOptions.name; - registerWorker(worker.nextCoWorkerOptions, worker.coWorkers); - worker.nextCoWorkerOptions.name = String(Number(nameNow) + 1); - return work([nameNow, functionName], preparedInput, worker.coWorkers); + } else { + workerName = name; + } + } + if (!Object.prototype.hasOwnProperty.call(workerStore, workerName)) { + return Promise.reject(`"${workerName}" not registered`); } + if (Object.prototype.hasOwnProperty.call(input, `input`)) { + // already prepared + preparedInput = input; + } else { + preparedInput = { + input + }; + if (functionName !== undefined) { + preparedInput.functionName = functionName; + } + } + const worker = workerStore[workerName]; + + if (worker.stateless && worker.resolveRejectQueue.length !== 0 && !forceWork) { + // the worker is already doing something and it is stateless + // only stateless worker can duplicate themselves + if (!worker.coWorkers) { + // the worker has not yet utilized this feature and needs to be initialized + worker.coWorkers = {}; + worker.nextCoWorkerOptions = Object.assign({}, worker, { + instanciated: false, + hasEventListener: false, + lazy: 10, + hope: 1, + coWorkers: undefined, + max: 1, + name: `0`, + workerStore: worker.coWorkers + }); + } + const coWorkerCount = Object.keys(worker.coWorkers).length; + + if (coWorkerCount !== 0) { + // there are already coWorkers + const workerWithEmptyQueue = findWorkerWithEmptyQueue(worker.coWorkers); + if (workerWithEmptyQueue) { + // at least 1 is idle, give it something to do + return work( + [workerWithEmptyQueue.name, functionName], + preparedInput, + worker.coWorkers + ); + } + } - // search for the worker with the lowest resolution queue and delegate to it - // use a boolean to avoid infinite recursion loop - const bestWorker = workerWithLowestresolveRejectQueue( - Object.values(worker.coWorkers).concat(worker) - ); - return work([bestWorker.name, functionName], preparedInput, bestWorker.workerStore, true); - } + // there are no idle coworkers + if ((coWorkerCount + 1) < worker.max) { + // the worker count is below maximum, we can create more + // + 1 is for the parent worker itself + const nameNow = worker.nextCoWorkerOptions.name; + registerWorker(worker.nextCoWorkerOptions, worker.coWorkers); + worker.nextCoWorkerOptions.name = String(Number(nameNow) + 1); + return work([nameNow, functionName], preparedInput, worker.coWorkers); + } - // normal case - return new Promise(function (resolve, reject) { - worker.resolveRejectQueue.push([resolve, reject]); - prepareWorker(worker, 0); - worker.awakened = true; - if (worker.timeOut) { - prepareWorkerTimeOut(worker, resolve, reject, preparedInput); - } else { - worker.instance.postMessage(preparedInput); + // search for the worker with the lowest resolution queue and delegate to it + // use a boolean to avoid infinite recursion loop + const bestWorker = workerWithLowestresolveRejectQueue( + Object.values(worker.coWorkers).concat(worker) + ); + return work([bestWorker.name, functionName], preparedInput, bestWorker.workerStore, true); } - }); -}; -exports.registerWorker = registerWorker; -exports.work = work; -exports.workerSupport = workerSupport; -exports.WORKA_SYMBOLS = WORKA_SYMBOLS; + // normal case + return new Promise(function (resolve, reject) { + worker.resolveRejectQueue.push([resolve, reject]); + prepareWorker(worker, 0); + worker.awakened = true; + if (worker.timeOut) { + prepareWorkerTimeOut(worker, resolve, reject, preparedInput); + } else { + worker.instance.postMessage(preparedInput); + } + }); + }; + + exports.registerWorker = registerWorker; + exports.work = work; + exports.workerSupport = workerSupport; + exports.WORKA_SYMBOLS = WORKA_SYMBOLS; -return exports; + return exports; }({})); diff --git a/example/example.js b/example/example.js index f99ff57..b873973 100644 --- a/example/example.js +++ b/example/example.js @@ -5,14 +5,14 @@ import {registerWorker, WORKA_SYMBOLS, work} from "../source/worka.js"; -import d from "./node_modules/dom99/built/dom99Module.js"; +import * as d from "./node_modules/dom99/built/dom99ES.js"; import { doNTimes, chainPromises, chainPromiseNTimes, - timeCallback, + timeFunction, timePromise, - fillArrayWithFunctionResult + arrayWithResults } from "./node_modules/utilsac/utility.js"; import estimatePi from "./estimatePi.js"; import { estimatePiWorkerURL } from "./estimatePiPrepared.js"; @@ -155,7 +155,7 @@ d.functions.remoteServer = function () { d.functions.withOutWebWorker = function () { let result; - const duration = timeCallback(function () { + const duration = timeFunction(function () { result = estimatePi(precision); }); d.feed({ @@ -165,7 +165,6 @@ d.functions.withOutWebWorker = function () { }; d.functions.runFullTestSuite = function () { - chainPromises([ testWithoutWorker, testWithRemoteServer, @@ -198,10 +197,10 @@ const testWithoutWorker = function () { results: [] }; - aggregates.totalTime = timeCallback(function () { + aggregates.totalTime = timeFunction(function () { doNTimes(function () { let piEstimation; - const duration = timeCallback(function () { + const duration = timeFunction(function () { piEstimation = estimatePi(precision); }); aggregates.results.push({ @@ -212,7 +211,7 @@ const testWithoutWorker = function () { aggregates.totalComputationTime += duration; }, SAMPLE_SIZE); }); - addAggregatesStats(aggregates) + addAggregatesStats(aggregates); return Promise.resolve(aggregates); }; @@ -252,7 +251,7 @@ const testWithRemoteServer = function () { }).then(function ({timeElapsed, value}) { aggregates.results = value; aggregates.totalTime = timeElapsed; - addAggregatesStats(aggregates) + addAggregatesStats(aggregates); return aggregates; }); }; @@ -319,7 +318,7 @@ const testWithWorkerCreatedEveryTime = function () { const workerWork = function() { return timePromise(function() { - return work("getPiEstimationForceRestart", precision); + return work("getPiEstimationForceRestart", precision).catch(console.error); }).then(function ({timeElapsed, value}) { aggregates.totalComputationTime += timeElapsed; return { @@ -353,7 +352,7 @@ const testWithWorker = function () { const workerWork = function() { return timePromise(function() { - return work("getPiEstimation", precision); + return work("getPiEstimation", precision).catch(console.error); }).then(function ({timeElapsed, value}) { aggregates.totalComputationTime += timeElapsed; return { @@ -387,7 +386,7 @@ const testWithWorkerAutoSplit = function () { const workerWork = function() { return timePromise(function() { - return work("getPiEstimation", precision); + return work("getPiEstimation", precision).catch(console.error); }).then(function ({timeElapsed, value}) { aggregates.totalComputationTime += timeElapsed; return { @@ -399,7 +398,7 @@ const testWithWorkerAutoSplit = function () { }; return timePromise(function () { - const allPromises = fillArrayWithFunctionResult(workerWork, SAMPLE_SIZE); + const allPromises = arrayWithResults(workerWork, SAMPLE_SIZE); return Promise.all(allPromises); }).then(function ({timeElapsed, value}) { aggregates.results = value; diff --git a/example/package-lock.json b/example/package-lock.json index 8d23df9..aa7ee0f 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -1,15 +1,15 @@ { "name": "example", - "version": "2.0.2", + "version": "4.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { - "mime-types": "2.1.17", + "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, @@ -19,20 +19,20 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.1", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "1.6.15" + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" } }, "bytes": { @@ -69,9 +69,9 @@ } }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "destroy": { "version": "1.0.4", @@ -79,9 +79,9 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "dom99": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/dom99/-/dom99-11.1.0.tgz", - "integrity": "sha512-utOZDkr2kMjsj90qxfCugC3XMXRmfucANrp2RTuOcGxha/rAPC1VqUS5bvLmBfffU6lHNtuEoPcMGpB2YP3W+g==" + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/dom99/-/dom99-17.0.1.tgz", + "integrity": "sha512-Yh6J2NXe0I5H8AsdBdF30xp0De2ivxkoXL5XamZ3tBlaF/7lNN27vKB4T4vBJPT2yQh1ndnqhwgfwFp2/SZakw==" }, "ee-first": { "version": "1.1.1", @@ -89,9 +89,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "escape-html": { "version": "1.0.3", @@ -104,54 +104,54 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", "requires": { - "accepts": "1.3.4", + "accepts": "~1.3.5", "array-flatten": "1.1.1", - "body-parser": "1.18.2", + "body-parser": "1.18.3", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "finalhandler": "1.1.0", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", - "qs": "6.5.1", - "range-parser": "1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "~1.4.0", + "type-is": "~1.6.16", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" } }, "forwarded": { @@ -165,27 +165,23 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { - "depd": "1.1.1", + "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.3.1" - }, - "dependencies": { - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" } }, "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "inherits": { "version": "2.0.3", @@ -193,13 +189,13 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "merge-descriptors": { @@ -218,16 +214,16 @@ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "requires": { - "mime-db": "1.30.0" + "mime-db": "~1.37.0" } }, "ms": { @@ -264,18 +260,18 @@ "integrity": "sha1-cflVSpic9r+Jh7Q6UhMtXHkxJlc=" }, "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" } }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "range-parser": { "version": "1.2.0", @@ -283,50 +279,55 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "requires": { "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", "unpipe": "1.0.0" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "requires": { "debug": "2.6.9", - "depd": "1.1.1", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.2", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" } }, "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "requires": { - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "parseurl": "1.3.2", - "send": "0.16.1" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" } }, "setprototypeof": { @@ -335,17 +336,17 @@ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.17" + "mime-types": "~2.1.18" } }, "unpipe": { @@ -359,9 +360,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "utilsac": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/utilsac/-/utilsac-3.0.2.tgz", - "integrity": "sha512-VmuYmhU1voE5B6e6VadKJMBCOL94CSk/jAMkeaA3uXShBNBDMz/D95mHd+oeU7ptNwmVzDvqqbzHlZEp58RmUw==" + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/utilsac/-/utilsac-9.5.0.tgz", + "integrity": "sha512-HMeyRS2xMi3ax/y+qiN6YBtTIbGlw1ZL2KQUEIGIsHcUs1iZ8pCeNItDlZzJPstCuFW0pFQulyfcn/51wDlckw==" }, "vary": { "version": "1.1.2", diff --git a/example/package.json b/example/package.json index 55d51be..721cd41 100644 --- a/example/package.json +++ b/example/package.json @@ -1,6 +1,6 @@ { "name": "example", - "version": "4.0.0", + "version": "5.0.0", "description": "example", "main": "example.js", "scripts": { @@ -9,9 +9,9 @@ "author": "author", "license": "ISC", "dependencies": { - "dom99": "^11.1.0", - "express": "^4.16.2", + "dom99": "^17.0.1", + "express": "^4.16.4", "promise-memoize": "^1.2.1", - "utilsac": "^3.0.2" + "utilsac": "^9.5.0" } } diff --git a/package-lock.json b/package-lock.json index dbd3fea..23ff7aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,30 @@ { "name": "worka", - "version": "4.0.6", + "version": "5.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { - "rollup": { - "version": "0.56.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.56.5.tgz", - "integrity": "sha512-IGPk5vdWrsc4vkiW9XMeXr5QMtxmvATTttTi59w2jBQWe9G/MMQtn8teIBAj+DdK51TrpVT6P0aQUaQUlUYCJA==", + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "10.12.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.9.tgz", + "integrity": "sha512-eajkMXG812/w3w4a1OcBlaTwsFPO5F7fJ/amy+tieQxEMWBlbV1JGSjkFM+zkHNf81Cad+dfIRA+IBkvmvdAeA==", "dev": true + }, + "rollup": { + "version": "0.67.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.67.3.tgz", + "integrity": "sha512-TyNQCz97rKuVVbsKUTXfwIjV7UljWyTVd7cTMuE+aqlQ7WJslkYF5QaYGjMLR2BlQtUOO5CAxSVnpQ55iYp5jg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "@types/node": "*" + } } } } diff --git a/package.json b/package.json index ff373a8..b0f1389 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "worka", - "version": "4.0.6", + "version": "5.0.0", "description": "Easy web workers modelled as HTTP API endpoints", "main": "built/worka_require.js", "module": "source/worka.js", @@ -21,7 +21,7 @@ "author": "GrosSacASacs", "license": "BSL-1.0", "devDependencies": { - "rollup": "^0.56.3" + "rollup": "^0.67.3" }, "keywords": [ "web-worker", diff --git a/source/worka.js b/source/worka.js index d2239c0..e745bb3 100644 --- a/source/worka.js +++ b/source/worka.js @@ -179,11 +179,11 @@ self.addEventListener(\`message\`, function(event) { }; const instanciateWorker = function (worker) { - const decoratedAsString = worker.decoratedAsString; let workerObjectURL; if (worker.workerObjectURL) { workerObjectURL = worker.workerObjectURL; } else { + const decoratedAsString = worker.decoratedAsString; const workerBlob = new Blob([decoratedAsString], WORKA_SYMBOLS.JS_MIME); workerObjectURL = URL.createObjectURL(workerBlob); } @@ -340,7 +340,8 @@ const registerWorker = function (options, workerStore = workers) { const worker = { ...WORKER_DEFAULT_OPTIONS, ...options, - ...WORKER_INITIAL_SETTINGS + ...WORKER_INITIAL_SETTINGS, + workerStore }; worker.resolveRejectQueue = []; if (worker.timeOut && worker.hope > 5) { @@ -369,7 +370,6 @@ const findWorkerWithEmptyQueue = function (workerStore = workers) { }); }; -const mock = {resolveRejectQueue: {length: Number.MAX_SAFE_INTEGER}}; const workerWithLowestresolveRejectQueue = function (workers) { return workers.reduce(function (workerWithLowestresolveRejectQueueSoFar, worker) { if ( @@ -379,7 +379,7 @@ const workerWithLowestresolveRejectQueue = function (workers) { return worker; } return workerWithLowestresolveRejectQueueSoFar; - }, mock); + }); }; const work = function (name, input, workerStore = workers, forceWork = false) { @@ -426,6 +426,12 @@ const work = function (name, input, workerStore = workers, forceWork = false) { // the worker has not yet utilized this feature and needs to be initialized worker.coWorkers = {}; worker.nextCoWorkerOptions = Object.assign({}, worker, { + instanciated: false, + hasEventListener: false, + lazy: 10, + hope: 1, + coWorkers: undefined, + max: 1, name: `0`, workerStore: worker.coWorkers });