Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@eroc/core

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eroc/core - npm Package Compare versions

Comparing version 4.1.0 to 4.3.0

src/prepareWorkerCode.js

88

dist/core.es.js

@@ -1,2 +0,2 @@

/* @eroc/core v4.1.0 2021-09-01T21:05:19.889Z licensed MIT */
/* @eroc/core v4.3.0 2021-09-15T19:01:12.070Z licensed MIT */
const startEventRecorder = (core) => {

@@ -310,5 +310,7 @@ const events = [];

const CORE_STOPPED = `CORE_STOPPED`;
const CORE_GET_STATE = `CORE_GET_STATE`;
const CORE_SET_STATE = `CORE_SET_STATE`;
const CORE_ERROR = `CORE_ERROR`;
const workerGlueCode = "/**\n * Use it as a constructor\n * or as a decorator for an existing object\n * or as a base class for extend\n * cannot be used as a mixin for a constructor's prototype\n * without calling the constructor\n */\nfunction EventEmitter3(obj) {\n (obj || this)._callbacks = Object.create(null);\n if (obj) {return Object.assign(obj, EventEmitter3.prototype);}\n}\n\n/**\n * Listen on the given `eventName` with `fn`\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.on = function (eventName, fn) {\n (this._callbacks[eventName] = this._callbacks[eventName] || [])\n .push(fn);\n};\n\n/**\n * Adds an `eventName` listener that will be invoked once then removed\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.once = function (eventName, fn) {\n const once = (data) => {\n this.off(eventName, once);\n fn(data);\n };\n\n once.fn = fn; // makes it possible to remove with off\n this.on(eventName, once);\n};\n\n/**\n * Remove a callback for `eventName` or\n * all callbacks for `eventName` or\n * all callbacks for all events\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.off = function (eventName, fn) {\n // all\n if (!eventName) {\n this._callbacks = Object.create(null);\n return;\n }\n\n // specific event\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n\n // remove all handlers\n if (!fn) {\n delete this._callbacks[eventName];\n return;\n }\n\n // remove specific handler\n const index = callbacks.findIndex(function (cb) {\n return (cb === fn || cb.fn === fn);\n });\n if (index > -1) {\n // Remove event specific arrays for the eventName type that no\n // one is subscribed for, to avoid memory leak.\n if (callbacks.length === 1) {\n delete this._callbacks[eventName];\n } else {\n callbacks.splice(index, 1);\n }\n }\n};\n\n/**\n * Emit `eventName` with data\n *\n * @param {String | Symbol} eventName\n * @param {any} data\n */\n\nEventEmitter3.prototype.emit = function (eventName, data) {\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n const frozenCallbacks = Array.from(callbacks);\n frozenCallbacks.forEach(callback => {\n callback(data);\n });\n};\n\n/**\n * Return array of callbacks for `eventName`\n *\n * @param {String | Symbol} eventName\n * @return {Array} listeners\n * @api public\n */\n\nEventEmitter3.prototype.listeners = function (eventName) {\n return this._callbacks[eventName] || [];\n};\n\n/**\n * True if this emitter has `eventName` handlers\n *\n * @param {String | Symbol} eventName\n * @return {Boolean}\n * @api public\n */\n\nEventEmitter3.prototype.hasListeners = function (eventName) {\n return Boolean(this.listeners(eventName).length);\n};\n\n/**\n * Returns an array of event names for which the emitter has registered listeners\n *\n * @return {Array <String || Symbol>}\n * @api public\n */\nEventEmitter3.prototype.eventNames = function () {\n return Reflect.ownKeys(this._callbacks);\n};\n\n/**\n * Returns an array of event anmes of type string\n * for which the emitter has registered listeners\n *\n * @return {Array <String>}\n * @api public\n */\nEventEmitter3.prototype.eventNamesStrings = function () {\n return Object.keys(this._callbacks);\n};\n\n// prefix to avoid variable name collision\r\nconst CORE_ACTION_KEY = `action`;\r\n\r\n// actions\r\nconst CORE_EVENT = `CORE_EVENT`;\r\nconst CORE_START = `CORE_START`;\r\nconst CORE_STARTED = `CORE_STARTED`;\r\nconst CORE_STOP = `CORE_STOP`;\r\nconst CORE_STOPPED = `CORE_STOPPED`;\r\nconst CORE_ERROR = `CORE_ERROR`;\n\nlet localEmitter;\r\nlet localInstance;\r\n\r\nself.addEventListener(`error`, function (errorEvent) {\r\n errorEvent.preventDefault();\r\n let asString;\r\n if (errorEvent.message) {\r\n asString = errorEvent.message;\r\n } else {\r\n asString = String(errorEvent);\r\n }\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: asString,\r\n });\r\n});\r\n\r\nself.addEventListener(`message`, async function(messageEvent) {\r\n const message = messageEvent.data;\r\n if (!Object.prototype.hasOwnProperty.call(message, CORE_ACTION_KEY)) {\r\n return;\r\n }\r\n const action = message[CORE_ACTION_KEY];\r\n if (action === CORE_EVENT) {\r\n if (!localInstance) {\r\n return;\r\n }\r\n // avoid infinite loop\r\n localEmitter.originalEmit(message.name, message.data);\r\n return;\r\n }\r\n if (action === CORE_START) {\r\n localEmitter = new EventEmitter3();\r\n localEmitter.originalEmit = localEmitter.emit;\r\n localEmitter.emit = function (eventName, data) {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_EVENT,\r\n name: eventName,\r\n data,\r\n });\r\n localEmitter.originalEmit(eventName, data);\r\n };\r\n \r\n Promise.resolve().then(() => {\r\n return start(localEmitter, message.data);\r\n }).then(instance => {\r\n localInstance = instance;\r\n }).catch(errorModuleStart => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.start`,\r\n error: errorModuleStart,\r\n });\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STARTED,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_STOP) {\r\n if (!localInstance) {\r\n // should never happen\r\n return;\r\n }\r\n Promise.resolve().then(() => {\r\n if (typeof stop === `function`) {\r\n return stop(wrapper.instance);\r\n }\r\n }).catch(errorModuleStop => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.stop`,\r\n error: errorModuleStop,\r\n });\r\n }).then(() => {\r\n localInstance = undefined;\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STOPPED,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n // todo CORE_GET_STATE, CORE_SET_STATE\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: `action ${action} not implemented`,\r\n });\r\n});\r\n\r\n// module code below (defintion of start and stop)\n";
const workerGlueCode = "/**\n * Use it as a constructor\n * or as a decorator for an existing object\n * or as a base class for extend\n * cannot be used as a mixin for a constructor's prototype\n * without calling the constructor\n */\nfunction EventEmitter3(obj) {\n (obj || this)._callbacks = Object.create(null);\n if (obj) {return Object.assign(obj, EventEmitter3.prototype);}\n}\n\n/**\n * Listen on the given `eventName` with `fn`\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.on = function (eventName, fn) {\n (this._callbacks[eventName] = this._callbacks[eventName] || [])\n .push(fn);\n};\n\n/**\n * Adds an `eventName` listener that will be invoked once then removed\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.once = function (eventName, fn) {\n const once = (data) => {\n this.off(eventName, once);\n fn(data);\n };\n\n once.fn = fn; // makes it possible to remove with off\n this.on(eventName, once);\n};\n\n/**\n * Remove a callback for `eventName` or\n * all callbacks for `eventName` or\n * all callbacks for all events\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.off = function (eventName, fn) {\n // all\n if (!eventName) {\n this._callbacks = Object.create(null);\n return;\n }\n\n // specific event\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n\n // remove all handlers\n if (!fn) {\n delete this._callbacks[eventName];\n return;\n }\n\n // remove specific handler\n const index = callbacks.findIndex(function (cb) {\n return (cb === fn || cb.fn === fn);\n });\n if (index > -1) {\n // Remove event specific arrays for the eventName type that no\n // one is subscribed for, to avoid memory leak.\n if (callbacks.length === 1) {\n delete this._callbacks[eventName];\n } else {\n callbacks.splice(index, 1);\n }\n }\n};\n\n/**\n * Emit `eventName` with data\n *\n * @param {String | Symbol} eventName\n * @param {any} data\n */\n\nEventEmitter3.prototype.emit = function (eventName, data) {\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n const frozenCallbacks = Array.from(callbacks);\n frozenCallbacks.forEach(callback => {\n callback(data);\n });\n};\n\n/**\n * Return array of callbacks for `eventName`\n *\n * @param {String | Symbol} eventName\n * @return {Array} listeners\n * @api public\n */\n\nEventEmitter3.prototype.listeners = function (eventName) {\n return this._callbacks[eventName] || [];\n};\n\n/**\n * True if this emitter has `eventName` handlers\n *\n * @param {String | Symbol} eventName\n * @return {Boolean}\n * @api public\n */\n\nEventEmitter3.prototype.hasListeners = function (eventName) {\n return Boolean(this.listeners(eventName).length);\n};\n\n/**\n * Returns an array of event names for which the emitter has registered listeners\n *\n * @return {Array <String || Symbol>}\n * @api public\n */\nEventEmitter3.prototype.eventNames = function () {\n return Reflect.ownKeys(this._callbacks);\n};\n\n/**\n * Returns an array of event anmes of type string\n * for which the emitter has registered listeners\n *\n * @return {Array <String>}\n * @api public\n */\nEventEmitter3.prototype.eventNamesStrings = function () {\n return Object.keys(this._callbacks);\n};\n\n// prefix to avoid variable name collision\r\nconst CORE_ACTION_KEY = `action`;\r\n\r\n// actions\r\nconst CORE_EVENT = `CORE_EVENT`;\r\nconst CORE_START = `CORE_START`;\r\nconst CORE_STARTED = `CORE_STARTED`;\r\nconst CORE_STOP = `CORE_STOP`;\r\nconst CORE_STOPPED = `CORE_STOPPED`;\r\nconst CORE_GET_STATE = `CORE_GET_STATE`;\r\nconst CORE_SET_STATE = `CORE_SET_STATE`;\r\nconst CORE_ERROR = `CORE_ERROR`;\n\nlet localEmitter;\r\nlet localInstance;\r\n\r\nself.addEventListener(`error`, function (errorEvent) {\r\n errorEvent.preventDefault();\r\n let asString;\r\n if (errorEvent.message) {\r\n asString = errorEvent.message;\r\n } else {\r\n asString = String(errorEvent);\r\n }\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: asString,\r\n });\r\n});\r\n\r\nself.addEventListener(`message`, async function(messageEvent) {\r\n const message = messageEvent.data;\r\n if (!Object.prototype.hasOwnProperty.call(message, CORE_ACTION_KEY)) {\r\n return;\r\n }\r\n const action = message[CORE_ACTION_KEY];\r\n if (action === CORE_EVENT) {\r\n if (!localInstance) {\r\n return;\r\n }\r\n // avoid infinite loop\r\n localEmitter.originalEmit(message.name, message.data);\r\n return;\r\n }\r\n if (action === CORE_START) {\r\n localEmitter = new EventEmitter3();\r\n localEmitter.originalEmit = localEmitter.emit;\r\n localEmitter.emit = function (eventName, data) {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_EVENT,\r\n name: eventName,\r\n data,\r\n });\r\n localEmitter.originalEmit(eventName, data);\r\n };\r\n \r\n Promise.resolve().then(() => {\r\n return start(localEmitter, message.data);\r\n }).then(instance => {\r\n localInstance = instance;\r\n }).catch(errorModuleStart => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.start`,\r\n error: errorModuleStart,\r\n });\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STARTED,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_STOP) {\r\n if (!localInstance) {\r\n // should never happen\r\n return;\r\n }\r\n Promise.resolve().then(() => {\r\n if (typeof stop === `function`) {\r\n return stop(wrapper.instance);\r\n }\r\n }).catch(errorModuleStop => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.stop`,\r\n error: errorModuleStop,\r\n });\r\n }).then(() => {\r\n localInstance = undefined;\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STOPPED,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n if (action === CORE_SET_STATE) {\r\n Promise.resolve().then(() => {\r\n if (typeof restoreState === `function`) {\r\n return restoreState(localInstance, message.data);\r\n }\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_GET_STATE,\r\n });\r\n }).catch(errorModuleRestoreState => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.restoreState`,\r\n error: errorModuleRestoreState,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_GET_STATE) {\r\n Promise.resolve().then(() => {\r\n if (typeof getState === `function`) {\r\n return getState(localInstance);\r\n }\r\n }).then((result) => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_SET_STATE,\r\n data: result, // core will handle undefined\r\n });\r\n }).catch(errorModuleRestoreState => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.restoreState`,\r\n error: errorModuleRestoreState,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: `action ${action} not implemented`,\r\n });\r\n});\r\n\r\n// module code below (defintion of start and stop)\n";

@@ -321,2 +323,6 @@ // @ts-check

const prepareWorkerCode = function (moduleCodeAsIIFE) {
return `${workerGlueCode};${moduleCodeAsIIFE}`;
};
const createCore = function () {

@@ -335,2 +341,5 @@ const core = {};

const wrapper = core.moduleInstances.get(name);
if (wrapper.worker) {
return core.requestStateFromWorker(wrapper)
}
if (!wrapper.module.getState) {

@@ -344,2 +353,11 @@ return Promise.resolve({});

requestStateFromWorker(wrapper) {
return new Promise(function (resolve, reject) {
wrapper.getStateResolve = resolve;
wrapper.worker.postMessage({
[CORE_ACTION_KEY]: CORE_GET_STATE,
});
});
},
/* returns a promise with an object

@@ -372,2 +390,5 @@ as keys the names of the module instances

const wrapper = core.moduleInstances.get(name);
if (wrapper.worker) {
return core.restoreStateInWorker(wrapper);
}
if (!wrapper.module.restoreState) {

@@ -382,2 +403,11 @@ return Promise.resolve();

},
restoreStateInWorker(wrapper) {
return new Promise(function (resolve, reject) {
wrapper.setStateResolve = resolve;
wrapper.worker.postMessage({
[CORE_ACTION_KEY]: CORE_SET_STATE,
});
});
},

@@ -393,3 +423,4 @@ restoreAllStates(states) {

data = undefined,
worker = false
worker = false,
workerReady = false,
} = {}) {

@@ -402,3 +433,3 @@

if (worker) {
return core.startWorker(module, name, data);
return core.startWorker(module, name, data, workerReady);
}

@@ -434,11 +465,20 @@

startWorker(moduleUrl, name, data) {
startWorker(moduleUrl, name, data, workerReady) {
return new Promise(function (resolve, reject) {
fetch(moduleUrl).then(response => {
return response.text();
}).then(moduleCode => {
const workerCode = `${workerGlueCode};${moduleCode}`;
const workerBlob = new Blob([workerCode], JS_MIME);
const workerObjectURL = URL.createObjectURL(workerBlob);
const moduleInsideWorker = new Worker(workerObjectURL, {
let workerRessourcePromise;
if (workerReady) {
workerRessourcePromise = Promise.resolve(moduleUrl);
} else {
workerRessourcePromise = fetch(moduleUrl).then(response => {
return response.text();
}).then(moduleCode => {
const workerCode = prepareWorkerCode(moduleCode);
const workerBlob = new Blob([workerCode], JS_MIME);
const workerObjectURL = URL.createObjectURL(workerBlob);
return workerObjectURL
});
}
workerRessourcePromise.then(workerRessource => {
const moduleInsideWorker = new Worker(workerRessource, {
type: "module",

@@ -485,4 +525,8 @@ name: String(name), // help debugging

}
if (action === CORE_ERROR) {
core.emit(ERROR, message);
return;
}
const wrapper = core.moduleInstances.get(name);
if (action === CORE_STOPPED) {
const wrapper = core.moduleInstances.get(name);
if (wrapper?.stopResolve) {

@@ -495,7 +539,17 @@ wrapper.stopResolve();

}
if (action === CORE_ERROR) {
core.emit(ERROR, message);
if (action === CORE_SET_STATE) {
if (wrapper?.getStateResolve) {
wrapper.getStateResolve(message.data || {});
wrapper.getStateResolve = undefined;
}
return;
}
// todo CORE_GET_STATE set State
if (action === CORE_GET_STATE) {
if (wrapper?.setStateResolve) {
wrapper.setStateResolve();
wrapper.setStateResolve = undefined;
}
return;
}
});

@@ -576,2 +630,2 @@ },

export { ALL, ERROR, createCore, replayEvents, startEventRecorder, stopEventRecorder, useDefaultLogging };
export { ALL, ERROR, createCore, prepareWorkerCode, replayEvents, startEventRecorder, stopEventRecorder, useDefaultLogging };

@@ -1,2 +0,2 @@

/* @eroc/core v4.1.0 2021-09-01T21:05:19.889Z licensed MIT */
/* @eroc/core v4.3.0 2021-09-15T19:01:12.070Z licensed MIT */
var Core = (function (exports) {

@@ -313,5 +313,7 @@ 'use strict';

const CORE_STOPPED = `CORE_STOPPED`;
const CORE_GET_STATE = `CORE_GET_STATE`;
const CORE_SET_STATE = `CORE_SET_STATE`;
const CORE_ERROR = `CORE_ERROR`;
const workerGlueCode = "/**\n * Use it as a constructor\n * or as a decorator for an existing object\n * or as a base class for extend\n * cannot be used as a mixin for a constructor's prototype\n * without calling the constructor\n */\nfunction EventEmitter3(obj) {\n (obj || this)._callbacks = Object.create(null);\n if (obj) {return Object.assign(obj, EventEmitter3.prototype);}\n}\n\n/**\n * Listen on the given `eventName` with `fn`\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.on = function (eventName, fn) {\n (this._callbacks[eventName] = this._callbacks[eventName] || [])\n .push(fn);\n};\n\n/**\n * Adds an `eventName` listener that will be invoked once then removed\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.once = function (eventName, fn) {\n const once = (data) => {\n this.off(eventName, once);\n fn(data);\n };\n\n once.fn = fn; // makes it possible to remove with off\n this.on(eventName, once);\n};\n\n/**\n * Remove a callback for `eventName` or\n * all callbacks for `eventName` or\n * all callbacks for all events\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.off = function (eventName, fn) {\n // all\n if (!eventName) {\n this._callbacks = Object.create(null);\n return;\n }\n\n // specific event\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n\n // remove all handlers\n if (!fn) {\n delete this._callbacks[eventName];\n return;\n }\n\n // remove specific handler\n const index = callbacks.findIndex(function (cb) {\n return (cb === fn || cb.fn === fn);\n });\n if (index > -1) {\n // Remove event specific arrays for the eventName type that no\n // one is subscribed for, to avoid memory leak.\n if (callbacks.length === 1) {\n delete this._callbacks[eventName];\n } else {\n callbacks.splice(index, 1);\n }\n }\n};\n\n/**\n * Emit `eventName` with data\n *\n * @param {String | Symbol} eventName\n * @param {any} data\n */\n\nEventEmitter3.prototype.emit = function (eventName, data) {\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n const frozenCallbacks = Array.from(callbacks);\n frozenCallbacks.forEach(callback => {\n callback(data);\n });\n};\n\n/**\n * Return array of callbacks for `eventName`\n *\n * @param {String | Symbol} eventName\n * @return {Array} listeners\n * @api public\n */\n\nEventEmitter3.prototype.listeners = function (eventName) {\n return this._callbacks[eventName] || [];\n};\n\n/**\n * True if this emitter has `eventName` handlers\n *\n * @param {String | Symbol} eventName\n * @return {Boolean}\n * @api public\n */\n\nEventEmitter3.prototype.hasListeners = function (eventName) {\n return Boolean(this.listeners(eventName).length);\n};\n\n/**\n * Returns an array of event names for which the emitter has registered listeners\n *\n * @return {Array <String || Symbol>}\n * @api public\n */\nEventEmitter3.prototype.eventNames = function () {\n return Reflect.ownKeys(this._callbacks);\n};\n\n/**\n * Returns an array of event anmes of type string\n * for which the emitter has registered listeners\n *\n * @return {Array <String>}\n * @api public\n */\nEventEmitter3.prototype.eventNamesStrings = function () {\n return Object.keys(this._callbacks);\n};\n\n// prefix to avoid variable name collision\r\nconst CORE_ACTION_KEY = `action`;\r\n\r\n// actions\r\nconst CORE_EVENT = `CORE_EVENT`;\r\nconst CORE_START = `CORE_START`;\r\nconst CORE_STARTED = `CORE_STARTED`;\r\nconst CORE_STOP = `CORE_STOP`;\r\nconst CORE_STOPPED = `CORE_STOPPED`;\r\nconst CORE_ERROR = `CORE_ERROR`;\n\nlet localEmitter;\r\nlet localInstance;\r\n\r\nself.addEventListener(`error`, function (errorEvent) {\r\n errorEvent.preventDefault();\r\n let asString;\r\n if (errorEvent.message) {\r\n asString = errorEvent.message;\r\n } else {\r\n asString = String(errorEvent);\r\n }\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: asString,\r\n });\r\n});\r\n\r\nself.addEventListener(`message`, async function(messageEvent) {\r\n const message = messageEvent.data;\r\n if (!Object.prototype.hasOwnProperty.call(message, CORE_ACTION_KEY)) {\r\n return;\r\n }\r\n const action = message[CORE_ACTION_KEY];\r\n if (action === CORE_EVENT) {\r\n if (!localInstance) {\r\n return;\r\n }\r\n // avoid infinite loop\r\n localEmitter.originalEmit(message.name, message.data);\r\n return;\r\n }\r\n if (action === CORE_START) {\r\n localEmitter = new EventEmitter3();\r\n localEmitter.originalEmit = localEmitter.emit;\r\n localEmitter.emit = function (eventName, data) {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_EVENT,\r\n name: eventName,\r\n data,\r\n });\r\n localEmitter.originalEmit(eventName, data);\r\n };\r\n \r\n Promise.resolve().then(() => {\r\n return start(localEmitter, message.data);\r\n }).then(instance => {\r\n localInstance = instance;\r\n }).catch(errorModuleStart => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.start`,\r\n error: errorModuleStart,\r\n });\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STARTED,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_STOP) {\r\n if (!localInstance) {\r\n // should never happen\r\n return;\r\n }\r\n Promise.resolve().then(() => {\r\n if (typeof stop === `function`) {\r\n return stop(wrapper.instance);\r\n }\r\n }).catch(errorModuleStop => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.stop`,\r\n error: errorModuleStop,\r\n });\r\n }).then(() => {\r\n localInstance = undefined;\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STOPPED,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n // todo CORE_GET_STATE, CORE_SET_STATE\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: `action ${action} not implemented`,\r\n });\r\n});\r\n\r\n// module code below (defintion of start and stop)\n";
const workerGlueCode = "/**\n * Use it as a constructor\n * or as a decorator for an existing object\n * or as a base class for extend\n * cannot be used as a mixin for a constructor's prototype\n * without calling the constructor\n */\nfunction EventEmitter3(obj) {\n (obj || this)._callbacks = Object.create(null);\n if (obj) {return Object.assign(obj, EventEmitter3.prototype);}\n}\n\n/**\n * Listen on the given `eventName` with `fn`\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.on = function (eventName, fn) {\n (this._callbacks[eventName] = this._callbacks[eventName] || [])\n .push(fn);\n};\n\n/**\n * Adds an `eventName` listener that will be invoked once then removed\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.once = function (eventName, fn) {\n const once = (data) => {\n this.off(eventName, once);\n fn(data);\n };\n\n once.fn = fn; // makes it possible to remove with off\n this.on(eventName, once);\n};\n\n/**\n * Remove a callback for `eventName` or\n * all callbacks for `eventName` or\n * all callbacks for all events\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.off = function (eventName, fn) {\n // all\n if (!eventName) {\n this._callbacks = Object.create(null);\n return;\n }\n\n // specific event\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n\n // remove all handlers\n if (!fn) {\n delete this._callbacks[eventName];\n return;\n }\n\n // remove specific handler\n const index = callbacks.findIndex(function (cb) {\n return (cb === fn || cb.fn === fn);\n });\n if (index > -1) {\n // Remove event specific arrays for the eventName type that no\n // one is subscribed for, to avoid memory leak.\n if (callbacks.length === 1) {\n delete this._callbacks[eventName];\n } else {\n callbacks.splice(index, 1);\n }\n }\n};\n\n/**\n * Emit `eventName` with data\n *\n * @param {String | Symbol} eventName\n * @param {any} data\n */\n\nEventEmitter3.prototype.emit = function (eventName, data) {\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n const frozenCallbacks = Array.from(callbacks);\n frozenCallbacks.forEach(callback => {\n callback(data);\n });\n};\n\n/**\n * Return array of callbacks for `eventName`\n *\n * @param {String | Symbol} eventName\n * @return {Array} listeners\n * @api public\n */\n\nEventEmitter3.prototype.listeners = function (eventName) {\n return this._callbacks[eventName] || [];\n};\n\n/**\n * True if this emitter has `eventName` handlers\n *\n * @param {String | Symbol} eventName\n * @return {Boolean}\n * @api public\n */\n\nEventEmitter3.prototype.hasListeners = function (eventName) {\n return Boolean(this.listeners(eventName).length);\n};\n\n/**\n * Returns an array of event names for which the emitter has registered listeners\n *\n * @return {Array <String || Symbol>}\n * @api public\n */\nEventEmitter3.prototype.eventNames = function () {\n return Reflect.ownKeys(this._callbacks);\n};\n\n/**\n * Returns an array of event anmes of type string\n * for which the emitter has registered listeners\n *\n * @return {Array <String>}\n * @api public\n */\nEventEmitter3.prototype.eventNamesStrings = function () {\n return Object.keys(this._callbacks);\n};\n\n// prefix to avoid variable name collision\r\nconst CORE_ACTION_KEY = `action`;\r\n\r\n// actions\r\nconst CORE_EVENT = `CORE_EVENT`;\r\nconst CORE_START = `CORE_START`;\r\nconst CORE_STARTED = `CORE_STARTED`;\r\nconst CORE_STOP = `CORE_STOP`;\r\nconst CORE_STOPPED = `CORE_STOPPED`;\r\nconst CORE_GET_STATE = `CORE_GET_STATE`;\r\nconst CORE_SET_STATE = `CORE_SET_STATE`;\r\nconst CORE_ERROR = `CORE_ERROR`;\n\nlet localEmitter;\r\nlet localInstance;\r\n\r\nself.addEventListener(`error`, function (errorEvent) {\r\n errorEvent.preventDefault();\r\n let asString;\r\n if (errorEvent.message) {\r\n asString = errorEvent.message;\r\n } else {\r\n asString = String(errorEvent);\r\n }\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: asString,\r\n });\r\n});\r\n\r\nself.addEventListener(`message`, async function(messageEvent) {\r\n const message = messageEvent.data;\r\n if (!Object.prototype.hasOwnProperty.call(message, CORE_ACTION_KEY)) {\r\n return;\r\n }\r\n const action = message[CORE_ACTION_KEY];\r\n if (action === CORE_EVENT) {\r\n if (!localInstance) {\r\n return;\r\n }\r\n // avoid infinite loop\r\n localEmitter.originalEmit(message.name, message.data);\r\n return;\r\n }\r\n if (action === CORE_START) {\r\n localEmitter = new EventEmitter3();\r\n localEmitter.originalEmit = localEmitter.emit;\r\n localEmitter.emit = function (eventName, data) {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_EVENT,\r\n name: eventName,\r\n data,\r\n });\r\n localEmitter.originalEmit(eventName, data);\r\n };\r\n \r\n Promise.resolve().then(() => {\r\n return start(localEmitter, message.data);\r\n }).then(instance => {\r\n localInstance = instance;\r\n }).catch(errorModuleStart => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.start`,\r\n error: errorModuleStart,\r\n });\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STARTED,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_STOP) {\r\n if (!localInstance) {\r\n // should never happen\r\n return;\r\n }\r\n Promise.resolve().then(() => {\r\n if (typeof stop === `function`) {\r\n return stop(wrapper.instance);\r\n }\r\n }).catch(errorModuleStop => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.stop`,\r\n error: errorModuleStop,\r\n });\r\n }).then(() => {\r\n localInstance = undefined;\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STOPPED,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n if (action === CORE_SET_STATE) {\r\n Promise.resolve().then(() => {\r\n if (typeof restoreState === `function`) {\r\n return restoreState(localInstance, message.data);\r\n }\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_GET_STATE,\r\n });\r\n }).catch(errorModuleRestoreState => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.restoreState`,\r\n error: errorModuleRestoreState,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_GET_STATE) {\r\n Promise.resolve().then(() => {\r\n if (typeof getState === `function`) {\r\n return getState(localInstance);\r\n }\r\n }).then((result) => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_SET_STATE,\r\n data: result, // core will handle undefined\r\n });\r\n }).catch(errorModuleRestoreState => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.restoreState`,\r\n error: errorModuleRestoreState,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: `action ${action} not implemented`,\r\n });\r\n});\r\n\r\n// module code below (defintion of start and stop)\n";

@@ -324,2 +326,6 @@ // @ts-check

const prepareWorkerCode = function (moduleCodeAsIIFE) {
return `${workerGlueCode};${moduleCodeAsIIFE}`;
};
const createCore = function () {

@@ -338,2 +344,5 @@ const core = {};

const wrapper = core.moduleInstances.get(name);
if (wrapper.worker) {
return core.requestStateFromWorker(wrapper)
}
if (!wrapper.module.getState) {

@@ -347,2 +356,11 @@ return Promise.resolve({});

requestStateFromWorker(wrapper) {
return new Promise(function (resolve, reject) {
wrapper.getStateResolve = resolve;
wrapper.worker.postMessage({
[CORE_ACTION_KEY]: CORE_GET_STATE,
});
});
},
/* returns a promise with an object

@@ -375,2 +393,5 @@ as keys the names of the module instances

const wrapper = core.moduleInstances.get(name);
if (wrapper.worker) {
return core.restoreStateInWorker(wrapper);
}
if (!wrapper.module.restoreState) {

@@ -385,2 +406,11 @@ return Promise.resolve();

},
restoreStateInWorker(wrapper) {
return new Promise(function (resolve, reject) {
wrapper.setStateResolve = resolve;
wrapper.worker.postMessage({
[CORE_ACTION_KEY]: CORE_SET_STATE,
});
});
},

@@ -396,3 +426,4 @@ restoreAllStates(states) {

data = undefined,
worker = false
worker = false,
workerReady = false,
} = {}) {

@@ -405,3 +436,3 @@

if (worker) {
return core.startWorker(module, name, data);
return core.startWorker(module, name, data, workerReady);
}

@@ -437,11 +468,20 @@

startWorker(moduleUrl, name, data) {
startWorker(moduleUrl, name, data, workerReady) {
return new Promise(function (resolve, reject) {
fetch(moduleUrl).then(response => {
return response.text();
}).then(moduleCode => {
const workerCode = `${workerGlueCode};${moduleCode}`;
const workerBlob = new Blob([workerCode], JS_MIME);
const workerObjectURL = URL.createObjectURL(workerBlob);
const moduleInsideWorker = new Worker(workerObjectURL, {
let workerRessourcePromise;
if (workerReady) {
workerRessourcePromise = Promise.resolve(moduleUrl);
} else {
workerRessourcePromise = fetch(moduleUrl).then(response => {
return response.text();
}).then(moduleCode => {
const workerCode = prepareWorkerCode(moduleCode);
const workerBlob = new Blob([workerCode], JS_MIME);
const workerObjectURL = URL.createObjectURL(workerBlob);
return workerObjectURL
});
}
workerRessourcePromise.then(workerRessource => {
const moduleInsideWorker = new Worker(workerRessource, {
type: "module",

@@ -488,4 +528,8 @@ name: String(name), // help debugging

}
if (action === CORE_ERROR) {
core.emit(ERROR, message);
return;
}
const wrapper = core.moduleInstances.get(name);
if (action === CORE_STOPPED) {
const wrapper = core.moduleInstances.get(name);
if (wrapper?.stopResolve) {

@@ -498,7 +542,17 @@ wrapper.stopResolve();

}
if (action === CORE_ERROR) {
core.emit(ERROR, message);
if (action === CORE_SET_STATE) {
if (wrapper?.getStateResolve) {
wrapper.getStateResolve(message.data || {});
wrapper.getStateResolve = undefined;
}
return;
}
// todo CORE_GET_STATE set State
if (action === CORE_GET_STATE) {
if (wrapper?.setStateResolve) {
wrapper.setStateResolve();
wrapper.setStateResolve = undefined;
}
return;
}
});

@@ -582,2 +636,3 @@ },

exports.createCore = createCore;
exports.prepareWorkerCode = prepareWorkerCode;
exports.replayEvents = replayEvents;

@@ -584,0 +639,0 @@ exports.startEventRecorder = startEventRecorder;

@@ -160,2 +160,4 @@ /**

const CORE_STOPPED = `CORE_STOPPED`;
const CORE_GET_STATE = `CORE_GET_STATE`;
const CORE_SET_STATE = `CORE_SET_STATE`;
const CORE_ERROR = `CORE_ERROR`;

@@ -249,3 +251,42 @@

// todo CORE_GET_STATE, CORE_SET_STATE
if (action === CORE_SET_STATE) {
Promise.resolve().then(() => {
if (typeof restoreState === `function`) {
return restoreState(localInstance, message.data);
}
}).then(() => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_GET_STATE,
});
}).catch(errorModuleRestoreState => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_ERROR,
time: Date.now(),
phase: `module.restoreState`,
error: errorModuleRestoreState,
});
});
return;
}
if (action === CORE_GET_STATE) {
Promise.resolve().then(() => {
if (typeof getState === `function`) {
return getState(localInstance);
}
}).then((result) => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_SET_STATE,
data: result, // core will handle undefined
});
}).catch(errorModuleRestoreState => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_ERROR,
time: Date.now(),
phase: `module.restoreState`,
error: errorModuleRestoreState,
});
});
return;
}
self.postMessage({

@@ -252,0 +293,0 @@ [CORE_ACTION_KEY]: CORE_ERROR,

2

dist/tempWorkerGlueCode.js
export {workerGlueCode};
const workerGlueCode = "/**\n * Use it as a constructor\n * or as a decorator for an existing object\n * or as a base class for extend\n * cannot be used as a mixin for a constructor's prototype\n * without calling the constructor\n */\nfunction EventEmitter3(obj) {\n (obj || this)._callbacks = Object.create(null);\n if (obj) {return Object.assign(obj, EventEmitter3.prototype);}\n}\n\n/**\n * Listen on the given `eventName` with `fn`\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.on = function (eventName, fn) {\n (this._callbacks[eventName] = this._callbacks[eventName] || [])\n .push(fn);\n};\n\n/**\n * Adds an `eventName` listener that will be invoked once then removed\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.once = function (eventName, fn) {\n const once = (data) => {\n this.off(eventName, once);\n fn(data);\n };\n\n once.fn = fn; // makes it possible to remove with off\n this.on(eventName, once);\n};\n\n/**\n * Remove a callback for `eventName` or\n * all callbacks for `eventName` or\n * all callbacks for all events\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.off = function (eventName, fn) {\n // all\n if (!eventName) {\n this._callbacks = Object.create(null);\n return;\n }\n\n // specific event\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n\n // remove all handlers\n if (!fn) {\n delete this._callbacks[eventName];\n return;\n }\n\n // remove specific handler\n const index = callbacks.findIndex(function (cb) {\n return (cb === fn || cb.fn === fn);\n });\n if (index > -1) {\n // Remove event specific arrays for the eventName type that no\n // one is subscribed for, to avoid memory leak.\n if (callbacks.length === 1) {\n delete this._callbacks[eventName];\n } else {\n callbacks.splice(index, 1);\n }\n }\n};\n\n/**\n * Emit `eventName` with data\n *\n * @param {String | Symbol} eventName\n * @param {any} data\n */\n\nEventEmitter3.prototype.emit = function (eventName, data) {\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n const frozenCallbacks = Array.from(callbacks);\n frozenCallbacks.forEach(callback => {\n callback(data);\n });\n};\n\n/**\n * Return array of callbacks for `eventName`\n *\n * @param {String | Symbol} eventName\n * @return {Array} listeners\n * @api public\n */\n\nEventEmitter3.prototype.listeners = function (eventName) {\n return this._callbacks[eventName] || [];\n};\n\n/**\n * True if this emitter has `eventName` handlers\n *\n * @param {String | Symbol} eventName\n * @return {Boolean}\n * @api public\n */\n\nEventEmitter3.prototype.hasListeners = function (eventName) {\n return Boolean(this.listeners(eventName).length);\n};\n\n/**\n * Returns an array of event names for which the emitter has registered listeners\n *\n * @return {Array <String || Symbol>}\n * @api public\n */\nEventEmitter3.prototype.eventNames = function () {\n return Reflect.ownKeys(this._callbacks);\n};\n\n/**\n * Returns an array of event anmes of type string\n * for which the emitter has registered listeners\n *\n * @return {Array <String>}\n * @api public\n */\nEventEmitter3.prototype.eventNamesStrings = function () {\n return Object.keys(this._callbacks);\n};\n\n// prefix to avoid variable name collision\r\nconst CORE_ACTION_KEY = `action`;\r\n\r\n// actions\r\nconst CORE_EVENT = `CORE_EVENT`;\r\nconst CORE_START = `CORE_START`;\r\nconst CORE_STARTED = `CORE_STARTED`;\r\nconst CORE_STOP = `CORE_STOP`;\r\nconst CORE_STOPPED = `CORE_STOPPED`;\r\nconst CORE_ERROR = `CORE_ERROR`;\n\nlet localEmitter;\r\nlet localInstance;\r\n\r\nself.addEventListener(`error`, function (errorEvent) {\r\n errorEvent.preventDefault();\r\n let asString;\r\n if (errorEvent.message) {\r\n asString = errorEvent.message;\r\n } else {\r\n asString = String(errorEvent);\r\n }\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: asString,\r\n });\r\n});\r\n\r\nself.addEventListener(`message`, async function(messageEvent) {\r\n const message = messageEvent.data;\r\n if (!Object.prototype.hasOwnProperty.call(message, CORE_ACTION_KEY)) {\r\n return;\r\n }\r\n const action = message[CORE_ACTION_KEY];\r\n if (action === CORE_EVENT) {\r\n if (!localInstance) {\r\n return;\r\n }\r\n // avoid infinite loop\r\n localEmitter.originalEmit(message.name, message.data);\r\n return;\r\n }\r\n if (action === CORE_START) {\r\n localEmitter = new EventEmitter3();\r\n localEmitter.originalEmit = localEmitter.emit;\r\n localEmitter.emit = function (eventName, data) {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_EVENT,\r\n name: eventName,\r\n data,\r\n });\r\n localEmitter.originalEmit(eventName, data);\r\n };\r\n \r\n Promise.resolve().then(() => {\r\n return start(localEmitter, message.data);\r\n }).then(instance => {\r\n localInstance = instance;\r\n }).catch(errorModuleStart => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.start`,\r\n error: errorModuleStart,\r\n });\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STARTED,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_STOP) {\r\n if (!localInstance) {\r\n // should never happen\r\n return;\r\n }\r\n Promise.resolve().then(() => {\r\n if (typeof stop === `function`) {\r\n return stop(wrapper.instance);\r\n }\r\n }).catch(errorModuleStop => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.stop`,\r\n error: errorModuleStop,\r\n });\r\n }).then(() => {\r\n localInstance = undefined;\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STOPPED,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n // todo CORE_GET_STATE, CORE_SET_STATE\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: `action ${action} not implemented`,\r\n });\r\n});\r\n\r\n// module code below (defintion of start and stop)\n"
const workerGlueCode = "/**\n * Use it as a constructor\n * or as a decorator for an existing object\n * or as a base class for extend\n * cannot be used as a mixin for a constructor's prototype\n * without calling the constructor\n */\nfunction EventEmitter3(obj) {\n (obj || this)._callbacks = Object.create(null);\n if (obj) {return Object.assign(obj, EventEmitter3.prototype);}\n}\n\n/**\n * Listen on the given `eventName` with `fn`\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.on = function (eventName, fn) {\n (this._callbacks[eventName] = this._callbacks[eventName] || [])\n .push(fn);\n};\n\n/**\n * Adds an `eventName` listener that will be invoked once then removed\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.once = function (eventName, fn) {\n const once = (data) => {\n this.off(eventName, once);\n fn(data);\n };\n\n once.fn = fn; // makes it possible to remove with off\n this.on(eventName, once);\n};\n\n/**\n * Remove a callback for `eventName` or\n * all callbacks for `eventName` or\n * all callbacks for all events\n *\n * @param {String | Symbol} eventName\n * @param {Function} fn\n * @api public\n */\n\nEventEmitter3.prototype.off = function (eventName, fn) {\n // all\n if (!eventName) {\n this._callbacks = Object.create(null);\n return;\n }\n\n // specific event\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n\n // remove all handlers\n if (!fn) {\n delete this._callbacks[eventName];\n return;\n }\n\n // remove specific handler\n const index = callbacks.findIndex(function (cb) {\n return (cb === fn || cb.fn === fn);\n });\n if (index > -1) {\n // Remove event specific arrays for the eventName type that no\n // one is subscribed for, to avoid memory leak.\n if (callbacks.length === 1) {\n delete this._callbacks[eventName];\n } else {\n callbacks.splice(index, 1);\n }\n }\n};\n\n/**\n * Emit `eventName` with data\n *\n * @param {String | Symbol} eventName\n * @param {any} data\n */\n\nEventEmitter3.prototype.emit = function (eventName, data) {\n const callbacks = this._callbacks[eventName];\n if (!callbacks) {\n return;\n }\n const frozenCallbacks = Array.from(callbacks);\n frozenCallbacks.forEach(callback => {\n callback(data);\n });\n};\n\n/**\n * Return array of callbacks for `eventName`\n *\n * @param {String | Symbol} eventName\n * @return {Array} listeners\n * @api public\n */\n\nEventEmitter3.prototype.listeners = function (eventName) {\n return this._callbacks[eventName] || [];\n};\n\n/**\n * True if this emitter has `eventName` handlers\n *\n * @param {String | Symbol} eventName\n * @return {Boolean}\n * @api public\n */\n\nEventEmitter3.prototype.hasListeners = function (eventName) {\n return Boolean(this.listeners(eventName).length);\n};\n\n/**\n * Returns an array of event names for which the emitter has registered listeners\n *\n * @return {Array <String || Symbol>}\n * @api public\n */\nEventEmitter3.prototype.eventNames = function () {\n return Reflect.ownKeys(this._callbacks);\n};\n\n/**\n * Returns an array of event anmes of type string\n * for which the emitter has registered listeners\n *\n * @return {Array <String>}\n * @api public\n */\nEventEmitter3.prototype.eventNamesStrings = function () {\n return Object.keys(this._callbacks);\n};\n\n// prefix to avoid variable name collision\r\nconst CORE_ACTION_KEY = `action`;\r\n\r\n// actions\r\nconst CORE_EVENT = `CORE_EVENT`;\r\nconst CORE_START = `CORE_START`;\r\nconst CORE_STARTED = `CORE_STARTED`;\r\nconst CORE_STOP = `CORE_STOP`;\r\nconst CORE_STOPPED = `CORE_STOPPED`;\r\nconst CORE_GET_STATE = `CORE_GET_STATE`;\r\nconst CORE_SET_STATE = `CORE_SET_STATE`;\r\nconst CORE_ERROR = `CORE_ERROR`;\n\nlet localEmitter;\r\nlet localInstance;\r\n\r\nself.addEventListener(`error`, function (errorEvent) {\r\n errorEvent.preventDefault();\r\n let asString;\r\n if (errorEvent.message) {\r\n asString = errorEvent.message;\r\n } else {\r\n asString = String(errorEvent);\r\n }\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: asString,\r\n });\r\n});\r\n\r\nself.addEventListener(`message`, async function(messageEvent) {\r\n const message = messageEvent.data;\r\n if (!Object.prototype.hasOwnProperty.call(message, CORE_ACTION_KEY)) {\r\n return;\r\n }\r\n const action = message[CORE_ACTION_KEY];\r\n if (action === CORE_EVENT) {\r\n if (!localInstance) {\r\n return;\r\n }\r\n // avoid infinite loop\r\n localEmitter.originalEmit(message.name, message.data);\r\n return;\r\n }\r\n if (action === CORE_START) {\r\n localEmitter = new EventEmitter3();\r\n localEmitter.originalEmit = localEmitter.emit;\r\n localEmitter.emit = function (eventName, data) {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_EVENT,\r\n name: eventName,\r\n data,\r\n });\r\n localEmitter.originalEmit(eventName, data);\r\n };\r\n \r\n Promise.resolve().then(() => {\r\n return start(localEmitter, message.data);\r\n }).then(instance => {\r\n localInstance = instance;\r\n }).catch(errorModuleStart => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.start`,\r\n error: errorModuleStart,\r\n });\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STARTED,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_STOP) {\r\n if (!localInstance) {\r\n // should never happen\r\n return;\r\n }\r\n Promise.resolve().then(() => {\r\n if (typeof stop === `function`) {\r\n return stop(wrapper.instance);\r\n }\r\n }).catch(errorModuleStop => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.stop`,\r\n error: errorModuleStop,\r\n });\r\n }).then(() => {\r\n localInstance = undefined;\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_STOPPED,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n if (action === CORE_SET_STATE) {\r\n Promise.resolve().then(() => {\r\n if (typeof restoreState === `function`) {\r\n return restoreState(localInstance, message.data);\r\n }\r\n }).then(() => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_GET_STATE,\r\n });\r\n }).catch(errorModuleRestoreState => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.restoreState`,\r\n error: errorModuleRestoreState,\r\n });\r\n });\r\n return;\r\n }\r\n if (action === CORE_GET_STATE) {\r\n Promise.resolve().then(() => {\r\n if (typeof getState === `function`) {\r\n return getState(localInstance);\r\n }\r\n }).then((result) => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_SET_STATE,\r\n data: result, // core will handle undefined\r\n });\r\n }).catch(errorModuleRestoreState => {\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n time: Date.now(),\r\n phase: `module.restoreState`,\r\n error: errorModuleRestoreState,\r\n });\r\n });\r\n return;\r\n }\r\n\r\n self.postMessage({\r\n [CORE_ACTION_KEY]: CORE_ERROR,\r\n error: `action ${action} not implemented`,\r\n });\r\n});\r\n\r\n// module code below (defintion of start and stop)\n"
{
"name": "@eroc/core",
"version": "4.1.0",
"version": "4.3.0",
"description": "Lightweight framework for scalable applications",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -184,2 +184,3 @@ # core [![Build Status](https://travis-ci.org/mauriciosoares/core.js.svg?branch=master)](https://travis-ci.org/mauriciosoares/core.js) [![Coverage Status](https://img.shields.io/coveralls/mauriciosoares/core.js.svg)](https://coveralls.io/r/mauriciosoares/core.js) [![Code Climate](https://codeclimate.com/github/mauriciosoares/core.js/badges/gpa.svg)](https://codeclimate.com/github/mauriciosoares/core.js)

* worker optional, if true the module will be inside a worker see 4.1.0 limitations
* workerReady, mark as true if the url has code prepared with storeWorkerCodeFromIIFEFile or prepareWorkerCode

@@ -294,2 +295,15 @@ returns a promise that resolves with *moduleInstanceId* that can later be used to stop the module

## Preparing worker code with prepareWorkerCode.js
```js
import {prepareWorkerCode, storeWorkerCodeFromIIFEFile} from "@eroc/core";
// source has to be an IIFE that exposes start and stop
const source = "./examples/gameOfLife/gameOfLife.js";
const destination = "./examples/gameOfLife/gameOfLifeWorkerReady.js";
storeWorkerCodeFromIIFEFile(source, destination);
```
This code can then be used with the workerReady option
## Maintainers

@@ -319,6 +333,14 @@

### 4.3.0
* core.js and prepareWorkerCode.js export a function prepareWorkerCode
* prepareWorkerCode.js exports a function storeWorkerCodeFromIIFEFile
### 4.2.0
* Modules inside worker can use restoreState and getState
### 4.1.0
* Modules without imports and export, and without setState and getState can run inside worker
* Modules without imports and export, without restoreState and getState can run inside worker

@@ -325,0 +347,0 @@ ### 4.0.0

// @ts-check
export { createCore, ALL, ERROR };
export { createCore, ALL, ERROR, prepareWorkerCode };
export { startEventRecorder, stopEventRecorder } from "./eventRecorder.js";

@@ -27,2 +27,6 @@ export { replayEvents } from "./eventPlayer.js";

const prepareWorkerCode = function (moduleCodeAsIIFE) {
return `${workerGlueCode};${moduleCodeAsIIFE}`;
};
const createCore = function () {

@@ -41,2 +45,5 @@ const core = {};

const wrapper = core.moduleInstances.get(name);
if (wrapper.worker) {
return core.requestStateFromWorker(wrapper)
}
if (!wrapper.module.getState) {

@@ -50,2 +57,11 @@ return Promise.resolve({});

requestStateFromWorker(wrapper) {
return new Promise(function (resolve, reject) {
wrapper.getStateResolve = resolve;
wrapper.worker.postMessage({
[CORE_ACTION_KEY]: CORE_GET_STATE,
});
});
},
/* returns a promise with an object

@@ -78,2 +94,5 @@ as keys the names of the module instances

const wrapper = core.moduleInstances.get(name);
if (wrapper.worker) {
return core.restoreStateInWorker(wrapper);
}
if (!wrapper.module.restoreState) {

@@ -88,2 +107,11 @@ return Promise.resolve();

},
restoreStateInWorker(wrapper) {
return new Promise(function (resolve, reject) {
wrapper.setStateResolve = resolve;
wrapper.worker.postMessage({
[CORE_ACTION_KEY]: CORE_SET_STATE,
});
});
},

@@ -99,3 +127,4 @@ restoreAllStates(states) {

data = undefined,
worker = false
worker = false,
workerReady = false,
} = {}) {

@@ -108,3 +137,3 @@

if (worker) {
return core.startWorker(module, name, data);
return core.startWorker(module, name, data, workerReady);
}

@@ -140,11 +169,20 @@

startWorker(moduleUrl, name, data) {
startWorker(moduleUrl, name, data, workerReady) {
return new Promise(function (resolve, reject) {
fetch(moduleUrl).then(response => {
return response.text();
}).then(moduleCode => {
const workerCode = `${workerGlueCode};${moduleCode}`;
const workerBlob = new Blob([workerCode], JS_MIME);
const workerObjectURL = URL.createObjectURL(workerBlob);
const moduleInsideWorker = new Worker(workerObjectURL, {
let workerRessourcePromise;
if (workerReady) {
workerRessourcePromise = Promise.resolve(moduleUrl);
} else {
workerRessourcePromise = fetch(moduleUrl).then(response => {
return response.text();
}).then(moduleCode => {
const workerCode = prepareWorkerCode(moduleCode);
const workerBlob = new Blob([workerCode], JS_MIME);
const workerObjectURL = URL.createObjectURL(workerBlob);
return workerObjectURL
})
}
workerRessourcePromise.then(workerRessource => {
const moduleInsideWorker = new Worker(workerRessource, {
type: "module",

@@ -191,4 +229,8 @@ name: String(name), // help debugging

}
if (action === CORE_ERROR) {
core.emit(ERROR, message)
return;
}
const wrapper = core.moduleInstances.get(name);
if (action === CORE_STOPPED) {
const wrapper = core.moduleInstances.get(name);
if (wrapper?.stopResolve) {

@@ -201,7 +243,17 @@ wrapper.stopResolve();

}
if (action === CORE_ERROR) {
core.emit(ERROR, message)
if (action === CORE_SET_STATE) {
if (wrapper?.getStateResolve) {
wrapper.getStateResolve(message.data || {});
wrapper.getStateResolve = undefined;
}
return;
}
// todo CORE_GET_STATE set State
if (action === CORE_GET_STATE) {
if (wrapper?.setStateResolve) {
wrapper.setStateResolve();
wrapper.setStateResolve = undefined;
}
return;
}
});

@@ -208,0 +260,0 @@ },

@@ -103,3 +103,42 @@ "use strict";

// todo CORE_GET_STATE, CORE_SET_STATE
if (action === CORE_SET_STATE) {
Promise.resolve().then(() => {
if (typeof restoreState === `function`) {
return restoreState(localInstance, message.data);
}
}).then(() => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_GET_STATE,
});
}).catch(errorModuleRestoreState => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_ERROR,
time: Date.now(),
phase: `module.restoreState`,
error: errorModuleRestoreState,
});
});
return;
}
if (action === CORE_GET_STATE) {
Promise.resolve().then(() => {
if (typeof getState === `function`) {
return getState(localInstance);
}
}).then((result) => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_SET_STATE,
data: result, // core will handle undefined
});
}).catch(errorModuleRestoreState => {
self.postMessage({
[CORE_ACTION_KEY]: CORE_ERROR,
time: Date.now(),
phase: `module.restoreState`,
error: errorModuleRestoreState,
});
});
return;
}
self.postMessage({

@@ -106,0 +145,0 @@ [CORE_ACTION_KEY]: CORE_ERROR,

@@ -8,2 +8,3 @@ export {

CORE_STOPPED,
// symmetry
CORE_GET_STATE,

@@ -10,0 +11,0 @@ CORE_SET_STATE,

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc