diff --git a/CHANGELOG.md b/CHANGELOG.md index d8ff664b..e90dd246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## X.X.X (comming soon) +## 4.3.0 (30 October 2021) + Features: - Added `LeaderElector.hasLeader` - Added `LeaderElector.broadcastChannel` diff --git a/dist/es5node/broadcast-channel.js b/dist/es5node/broadcast-channel.js index 0e7cbfc1..5e2822a4 100644 --- a/dist/es5node/broadcast-channel.js +++ b/dist/es5node/broadcast-channel.js @@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -85,7 +85,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -155,7 +155,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -193,7 +193,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list diff --git a/dist/es5node/index.js b/dist/es5node/index.js index cbfd05e1..8bc266af 100644 --- a/dist/es5node/index.js +++ b/dist/es5node/index.js @@ -9,16 +9,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -27,10 +27,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); diff --git a/dist/es5node/leader-election.js b/dist/es5node/leader-election.js index 3b2a9105..131febfe 100644 --- a/dist/es5node/leader-election.js +++ b/dist/es5node/leader-election.js @@ -12,10 +12,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -38,12 +39,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -65,23 +72,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -91,7 +107,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -120,11 +136,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -138,9 +158,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -151,9 +177,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -177,13 +201,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -199,11 +226,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -235,7 +263,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); diff --git a/dist/es5node/methods/indexed-db.js b/dist/es5node/methods/indexed-db.js index 25ab2fa8..0621cc11 100644 --- a/dist/es5node/methods/indexed-db.js +++ b/dist/es5node/methods/indexed-db.js @@ -3,21 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -215,7 +217,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -269,9 +271,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -299,7 +301,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } diff --git a/dist/es5node/methods/localstorage.js b/dist/es5node/methods/localstorage.js index f9261883..31921f6a 100644 --- a/dist/es5node/methods/localstorage.js +++ b/dist/es5node/methods/localstorage.js @@ -3,17 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); diff --git a/dist/es5node/methods/native.js b/dist/es5node/methods/native.js index 504ac8e8..3b1ec366 100644 --- a/dist/es5node/methods/native.js +++ b/dist/es5node/methods/native.js @@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -43,7 +44,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } diff --git a/dist/es5node/methods/node.js b/dist/es5node/methods/node.js index 2439f173..0dfb23b7 100644 --- a/dist/es5node/methods/node.js +++ b/dist/es5node/methods/node.js @@ -5,35 +5,36 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau Object.defineProperty(exports, "__esModule", { value: true }); +exports.TMP_FOLDER_BASE = void 0; +exports._filterMessage = _filterMessage; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; exports.cleanPipeName = cleanPipeName; -exports.getPaths = getPaths; -exports.ensureFoldersExist = ensureFoldersExist; exports.clearNodeFolder = clearNodeFolder; -exports.socketPath = socketPath; -exports.socketInfoPath = socketInfoPath; -exports.createSocketInfoFile = createSocketInfoFile; +exports.close = close; exports.countChannelFolders = countChannelFolders; +exports.create = create; exports.createSocketEventEmitter = createSocketEventEmitter; -exports.openClientConnection = openClientConnection; -exports.writeMessage = writeMessage; -exports.getReadersUuids = getReadersUuids; -exports.messagePath = messagePath; +exports.createSocketInfoFile = createSocketInfoFile; +exports.emitOverFastPath = emitOverFastPath; +exports.ensureFoldersExist = ensureFoldersExist; exports.getAllMessages = getAllMessages; +exports.getPaths = getPaths; +exports.getReadersUuids = getReadersUuids; exports.getSingleMessage = getSingleMessage; -exports.readMessage = readMessage; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports._filterMessage = _filterMessage; exports.handleMessagePing = handleMessagePing; -exports.refreshReaderClients = refreshReaderClients; -exports.postMessage = postMessage; -exports.emitOverFastPath = emitOverFastPath; -exports.onMessage = onMessage; -exports.close = close; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; +exports.messagePath = messagePath; exports.microSeconds = microSeconds; -exports.type = exports.TMP_FOLDER_BASE = void 0; +exports.onMessage = onMessage; +exports.openClientConnection = openClientConnection; +exports.postMessage = postMessage; +exports.readMessage = readMessage; +exports.refreshReaderClients = refreshReaderClients; +exports.socketInfoPath = socketInfoPath; +exports.socketPath = socketPath; +exports.type = void 0; +exports.writeMessage = writeMessage; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); @@ -736,7 +737,7 @@ function _create() { messagesCallbackTime: null, messagesCallback: null, // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util2.PROMISE_RESOLVED_VOID, otherReaderClients: {}, // ensure if process crashes, everything is cleaned up removeUnload: _unload["default"].add(function () { diff --git a/dist/es5node/methods/simulate.js b/dist/es5node/methods/simulate.js index 09b12b89..cb4ef3b2 100644 --- a/dist/es5node/methods/simulate.js +++ b/dist/es5node/methods/simulate.js @@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); diff --git a/dist/es5node/util.js b/dist/es5node/util.js index 8fba57af..c8e8bd85 100644 --- a/dist/es5node/util.js +++ b/dist/es5node/util.js @@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -21,6 +21,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/dist/esbrowser/broadcast-channel.js b/dist/esbrowser/broadcast-channel.js index d57d6050..bdccd05e 100644 --- a/dist/esbrowser/broadcast-channel.js +++ b/dist/esbrowser/broadcast-channel.js @@ -1,4 +1,4 @@ -import { isPromise } from './util.js'; +import { isPromise, PROMISE_RESOLVED_FALSE, PROMISE_RESOLVED_VOID } from './util.js'; import { chooseMethod } from './method-chooser.js'; import { fillOptionsWithDefaults } from './options.js'; export var BroadcastChannel = function BroadcastChannel(name, options) { @@ -71,7 +71,7 @@ export function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return PROMISE_RESOLVED_FALSE; } } /** @@ -138,7 +138,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -176,7 +176,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list diff --git a/dist/esbrowser/leader-election.js b/dist/esbrowser/leader-election.js index e201934b..3fed5ea1 100644 --- a/dist/esbrowser/leader-election.js +++ b/dist/esbrowser/leader-election.js @@ -1,10 +1,11 @@ -import { sleep, randomToken } from './util.js'; +import { sleep, randomToken, PROMISE_RESOLVED_FALSE, PROMISE_RESOLVED_VOID, PROMISE_REJECTED } from './util.js'; import unload from 'unload'; -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = randomToken(); this._isApl = false; // _isApplying @@ -27,12 +28,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -54,23 +61,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return sleep(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return sleep(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -80,7 +96,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -109,11 +125,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -127,9 +147,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -140,9 +166,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -166,13 +190,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -188,11 +215,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } export function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = unload.add(function () { return leaderElector.die(); }); @@ -223,7 +251,7 @@ export function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); diff --git a/dist/esbrowser/methods/indexed-db.js b/dist/esbrowser/methods/indexed-db.js index e47568ca..957b8e05 100644 --- a/dist/esbrowser/methods/indexed-db.js +++ b/dist/esbrowser/methods/indexed-db.js @@ -3,7 +3,7 @@ * There is currently no observerAPI for idb * @link https://github.com/w3c/IndexedDB/issues/51 */ -import { sleep, randomInt, randomToken, microSeconds as micro, isNode } from '../util.js'; +import { sleep, randomInt, randomToken, microSeconds as micro, isNode, PROMISE_RESOLVED_VOID } from '../util.js'; export var microSeconds = micro; import { ObliviousSet } from 'oblivious-set'; import { fillOptionsWithDefaults } from '../options'; @@ -180,7 +180,7 @@ export function create(channelName, options) { */ eMIs: new ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -234,9 +234,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -264,7 +264,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return PROMISE_RESOLVED_VOID; }); } diff --git a/dist/esbrowser/methods/native.js b/dist/esbrowser/methods/native.js index cd8bf407..cef714d2 100644 --- a/dist/esbrowser/methods/native.js +++ b/dist/esbrowser/methods/native.js @@ -1,4 +1,4 @@ -import { microSeconds as micro, isNode } from '../util'; +import { microSeconds as micro, isNode, PROMISE_RESOLVED_VOID } from '../util'; export var microSeconds = micro; export var type = 'native'; export function create(channelName) { @@ -24,7 +24,7 @@ export function close(channelState) { export function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } diff --git a/dist/esbrowser/methods/node.js b/dist/esbrowser/methods/node.js index 4993741d..c92395cf 100644 --- a/dist/esbrowser/methods/node.js +++ b/dist/esbrowser/methods/node.js @@ -17,7 +17,7 @@ import { sha3_224 } from 'js-sha3'; import isNode from 'detect-node'; import unload from 'unload'; import { fillOptionsWithDefaults } from '../options.js'; -import { randomInt, randomToken } from '../util.js'; +import { randomInt, randomToken, PROMISE_RESOLVED_VOID } from '../util.js'; import { ObliviousSet } from 'oblivious-set'; /** * windows sucks, so we have handle windows-type of socket-paths @@ -651,7 +651,7 @@ function _create() { messagesCallbackTime: null, messagesCallback: null, // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: PROMISE_RESOLVED_VOID, otherReaderClients: {}, // ensure if process crashes, everything is cleaned up removeUnload: unload.add(function () { diff --git a/dist/esbrowser/util.js b/dist/esbrowser/util.js index f8fc8363..b03f8162 100644 --- a/dist/esbrowser/util.js +++ b/dist/esbrowser/util.js @@ -8,6 +8,9 @@ export function isPromise(obj) { return false; } } +export var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +export var PROMISE_RESOLVED_VOID = Promise.resolve(); +export var PROMISE_REJECTED = Promise.reject(new Error()); export function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/dist/esnode/broadcast-channel.js b/dist/esnode/broadcast-channel.js index d57d6050..bdccd05e 100644 --- a/dist/esnode/broadcast-channel.js +++ b/dist/esnode/broadcast-channel.js @@ -1,4 +1,4 @@ -import { isPromise } from './util.js'; +import { isPromise, PROMISE_RESOLVED_FALSE, PROMISE_RESOLVED_VOID } from './util.js'; import { chooseMethod } from './method-chooser.js'; import { fillOptionsWithDefaults } from './options.js'; export var BroadcastChannel = function BroadcastChannel(name, options) { @@ -71,7 +71,7 @@ export function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return PROMISE_RESOLVED_FALSE; } } /** @@ -138,7 +138,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -176,7 +176,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list diff --git a/dist/esnode/leader-election.js b/dist/esnode/leader-election.js index e201934b..3fed5ea1 100644 --- a/dist/esnode/leader-election.js +++ b/dist/esnode/leader-election.js @@ -1,10 +1,11 @@ -import { sleep, randomToken } from './util.js'; +import { sleep, randomToken, PROMISE_RESOLVED_FALSE, PROMISE_RESOLVED_VOID, PROMISE_REJECTED } from './util.js'; import unload from 'unload'; -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = randomToken(); this._isApl = false; // _isApplying @@ -27,12 +28,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -54,23 +61,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return sleep(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return sleep(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -80,7 +96,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -109,11 +125,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -127,9 +147,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -140,9 +166,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -166,13 +190,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -188,11 +215,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } export function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = unload.add(function () { return leaderElector.die(); }); @@ -223,7 +251,7 @@ export function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); diff --git a/dist/esnode/methods/indexed-db.js b/dist/esnode/methods/indexed-db.js index e47568ca..957b8e05 100644 --- a/dist/esnode/methods/indexed-db.js +++ b/dist/esnode/methods/indexed-db.js @@ -3,7 +3,7 @@ * There is currently no observerAPI for idb * @link https://github.com/w3c/IndexedDB/issues/51 */ -import { sleep, randomInt, randomToken, microSeconds as micro, isNode } from '../util.js'; +import { sleep, randomInt, randomToken, microSeconds as micro, isNode, PROMISE_RESOLVED_VOID } from '../util.js'; export var microSeconds = micro; import { ObliviousSet } from 'oblivious-set'; import { fillOptionsWithDefaults } from '../options'; @@ -180,7 +180,7 @@ export function create(channelName, options) { */ eMIs: new ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -234,9 +234,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -264,7 +264,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return PROMISE_RESOLVED_VOID; }); } diff --git a/dist/esnode/methods/native.js b/dist/esnode/methods/native.js index cd8bf407..cef714d2 100644 --- a/dist/esnode/methods/native.js +++ b/dist/esnode/methods/native.js @@ -1,4 +1,4 @@ -import { microSeconds as micro, isNode } from '../util'; +import { microSeconds as micro, isNode, PROMISE_RESOLVED_VOID } from '../util'; export var microSeconds = micro; export var type = 'native'; export function create(channelName) { @@ -24,7 +24,7 @@ export function close(channelState) { export function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } diff --git a/dist/esnode/methods/node.js b/dist/esnode/methods/node.js index 4993741d..c92395cf 100644 --- a/dist/esnode/methods/node.js +++ b/dist/esnode/methods/node.js @@ -17,7 +17,7 @@ import { sha3_224 } from 'js-sha3'; import isNode from 'detect-node'; import unload from 'unload'; import { fillOptionsWithDefaults } from '../options.js'; -import { randomInt, randomToken } from '../util.js'; +import { randomInt, randomToken, PROMISE_RESOLVED_VOID } from '../util.js'; import { ObliviousSet } from 'oblivious-set'; /** * windows sucks, so we have handle windows-type of socket-paths @@ -651,7 +651,7 @@ function _create() { messagesCallbackTime: null, messagesCallback: null, // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: PROMISE_RESOLVED_VOID, otherReaderClients: {}, // ensure if process crashes, everything is cleaned up removeUnload: unload.add(function () { diff --git a/dist/esnode/util.js b/dist/esnode/util.js index f8fc8363..b03f8162 100644 --- a/dist/esnode/util.js +++ b/dist/esnode/util.js @@ -8,6 +8,9 @@ export function isPromise(obj) { return false; } } +export var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +export var PROMISE_RESOLVED_VOID = Promise.resolve(); +export var PROMISE_REJECTED = Promise.reject(new Error()); export function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/dist/lib/broadcast-channel.js b/dist/lib/broadcast-channel.js index 0e7cbfc1..5e2822a4 100644 --- a/dist/lib/broadcast-channel.js +++ b/dist/lib/broadcast-channel.js @@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -85,7 +85,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -155,7 +155,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -193,7 +193,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list diff --git a/dist/lib/browser.js b/dist/lib/browser.js index 46e18b70..28b785b7 100644 --- a/dist/lib/browser.js +++ b/dist/lib/browser.js @@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -86,7 +86,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -156,7 +156,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -194,7 +194,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list @@ -319,16 +319,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -337,10 +337,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); @@ -362,10 +362,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -388,12 +389,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -415,23 +422,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -441,7 +457,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -470,11 +486,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -488,9 +508,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -501,9 +527,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -527,13 +551,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -549,11 +576,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -585,7 +613,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); @@ -696,21 +724,23 @@ function chooseMethod(options) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -908,7 +938,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -962,9 +992,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -992,7 +1022,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } @@ -1047,17 +1077,19 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); @@ -1245,13 +1277,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1285,7 +1318,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } @@ -1332,13 +1365,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1441,12 +1475,12 @@ function fillOptionsWithDefaults() { Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -1459,6 +1493,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/dist/lib/browser.min.js b/dist/lib/browser.min.js index b5068d1b..cccfdb7f 100644 --- a/dist/lib/browser.min.js +++ b/dist/lib/browser.min.js @@ -1 +1 @@ -!function r(o,i,s){function a(t,e){if(!i[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);throw(n=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",n}n=i[t]={exports:{}},o[t][0].call(n.exports,function(e){return a(o[t][1][e]||e)},n,n.exports,r,o,i,s)}return i[t].exports}for(var u="function"==typeof require&&require,e=0;e=e.time&&e.fn(t.data)})},n=e.method.microSeconds(),e._prepP?e._prepP.then(function(){e._iL=!0,e.method.onMessage(e._state,t,n)}):(e._iL=!0,e.method.onMessage(e._state,t,n)))}}(e)}function l(e,t,n){e._addEL[t]=e._addEL[t].filter(function(e){return e!==n}),function(e){{var t;e._iL&&!u(e)&&(e._iL=!1,t=e.method.microSeconds(),e.method.onMessage(e._state,null,t))}}(e)}(n.BroadcastChannel=e)._pubkey=!0,e.prototype={postMessage:function(e){if(this.closed)throw new Error("BroadcastChannel.postMessage(): Cannot post message after channel has closed");return a(this,"message",e)},postInternal:function(e){return a(this,"internal",e)},set onmessage(e){var t={time:this.method.microSeconds(),fn:e};l(this,"message",this._onML),e&&"function"==typeof e?(this._onML=t,c(this,"message",t)):this._onML=null},addEventListener:function(e,t){var n=this.method.microSeconds();c(this,e,{time:n,fn:t})},removeEventListener:function(e,t){var n=this._addEL[e].find(function(e){return e.fn===t});l(this,e,n)},close:function(){var e=this;if(!this.closed){this.closed=!0;var t=this._prepP||Promise.resolve();return this._onML=null,this._addEL.message=[],t.then(function(){return Promise.all(Array.from(e._uMP))}).then(function(){return Promise.all(e._befC.map(function(e){return e()}))}).then(function(){return e.method.close(e._state)})}},get type(){return this.method.type},get isClosed(){return this.closed}}},{"./method-chooser.js":6,"./options.js":11,"./util.js":12}],2:[function(e,t,n){"use strict";var r=e("./index.es5.js"),e=r.BroadcastChannel,r=r.createLeaderElection;window.BroadcastChannel2=e,window.createLeaderElection=r},{"./index.es5.js":3}],3:[function(e,t,n){"use strict";e=e("./index.js");t.exports={BroadcastChannel:e.BroadcastChannel,createLeaderElection:e.createLeaderElection,clearNodeFolder:e.clearNodeFolder,enforceOptions:e.enforceOptions,beLeader:e.beLeader}},{"./index.js":4}],4:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"BroadcastChannel",{enumerable:!0,get:function(){return r.BroadcastChannel}}),Object.defineProperty(n,"clearNodeFolder",{enumerable:!0,get:function(){return r.clearNodeFolder}}),Object.defineProperty(n,"enforceOptions",{enumerable:!0,get:function(){return r.enforceOptions}}),Object.defineProperty(n,"createLeaderElection",{enumerable:!0,get:function(){return o.createLeaderElection}}),Object.defineProperty(n,"beLeader",{enumerable:!0,get:function(){return o.beLeader}});var r=e("./broadcast-channel"),o=e("./leader-election")},{"./broadcast-channel":1,"./leader-election":5}],5:[function(e,t,n){"use strict";var r=e("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(n,"__esModule",{value:!0}),n.beLeader=u,n.createLeaderElection=function(e,t){if(e._leaderElector)throw new Error("BroadcastChannel already has a leader-elector");t=function(e,t){e=e||{};(e=JSON.parse(JSON.stringify(e))).fallbackInterval||(e.fallbackInterval=3e3);e.responseTime||(e.responseTime=t.method.averageResponseTime(t.options));return e}(t,e);var n=new s(e,t);return e._befC.push(function(){return n.die()}),e._leaderElector=n};var i=e("./util.js"),o=r(e("unload")),s=function(e,t){this._channel=e,this._options=t,this.isLeader=!1,this.isDead=!1,this.token=(0,i.randomToken)(),this._isApl=!1,this._reApply=!1,this._unl=[],this._lstns=[],this._invs=[],this._dpL=function(){},this._dpLC=!1};function a(e,t){t={context:"leader",action:t,token:e.token};return e._channel.postInternal(t)}function u(t){t.isLeader=!0;var e=o.default.add(function(){return t.die()});t._unl.push(e);e=function(e){"leader"===e.context&&"apply"===e.action&&a(t,"tell"),"leader"!==e.context||"tell"!==e.action||t._dpLC||(t._dpLC=!0,t._dpL(),a(t,"tell"))};return t._channel.addEventListener("internal",e),t._lstns.push(e),a(t,"tell")}s.prototype={applyOnce:function(){var t=this;if(this.isLeader)return Promise.resolve(!1);if(this.isDead)return Promise.resolve(!1);if(this._isApl)return this._reApply=!0,Promise.resolve(!1);function n(e){"leader"===e.context&&e.token!=t.token&&(o.push(e),"apply"===e.action&&e.token>t.token&&(r=!0),"tell"===e.action&&(r=!0))}var r=!(this._isApl=!0),o=[];return this._channel.addEventListener("internal",n),a(this,"apply").then(function(){return(0,i.sleep)(t._options.responseTime)}).then(function(){return r?Promise.reject(new Error):a(t,"apply")}).then(function(){return(0,i.sleep)(t._options.responseTime)}).then(function(){return r?Promise.reject(new Error):a(t)}).then(function(){return u(t)}).then(function(){return!0}).catch(function(){return!1}).then(function(e){return t._channel.removeEventListener("internal",n),t._isApl=!1,!e&&t._reApply?(t._reApply=!1,t.applyOnce()):e})},awaitLeadership:function(){var i;return this._aLP||(this._aLP=(i=this).isLeader?Promise.resolve():new Promise(function(e){var t=!1;function n(){t||(t=!0,clearInterval(r),i._channel.removeEventListener("internal",o),e(!0))}i.applyOnce().then(function(){i.isLeader&&n()});var r=setInterval(function(){i.applyOnce().then(function(){i.isLeader&&n()})},i._options.fallbackInterval);i._invs.push(r);var o=function(e){"leader"===e.context&&"death"===e.action&&i.applyOnce().then(function(){i.isLeader&&n()})};i._channel.addEventListener("internal",o),i._lstns.push(o)})),this._aLP},set onduplicate(e){this._dpL=e},die:function(){var t=this;if(!this.isDead)return this.isDead=!0,this._lstns.forEach(function(e){return t._channel.removeEventListener("internal",e)}),this._invs.forEach(function(e){return clearInterval(e)}),this._unl.forEach(function(e){e.remove()}),a(this,"death")}}},{"./util.js":12,"@babel/runtime/helpers/interopRequireDefault":13,unload:20}],6:[function(e,t,n){"use strict";var r=e("@babel/runtime/helpers/interopRequireDefault");e("@babel/runtime/helpers/typeof");Object.defineProperty(n,"__esModule",{value:!0}),n.chooseMethod=function(t){var e=[].concat(t.methods,u).filter(Boolean);if(t.type){if("simulate"===t.type)return s.default;var n=e.find(function(e){return e.type===t.type});if(n)return n;throw new Error("method-type "+t.type+" not found")}t.webWorkerSupport||a.isNode||(e=e.filter(function(e){return"idb"!==e.type}));e=e.find(function(e){return e.canBeUsed()});{if(e)return e;throw new Error("No useable method found in "+JSON.stringify(u.map(function(e){return e.type})))}};var o=r(e("./methods/native.js")),i=r(e("./methods/indexed-db.js")),n=r(e("./methods/localstorage.js")),s=r(e("./methods/simulate.js")),a=e("./util");var u=[o.default,i.default,n.default]},{"./methods/indexed-db.js":7,"./methods/localstorage.js":8,"./methods/native.js":9,"./methods/simulate.js":10,"./util":12,"@babel/runtime/helpers/interopRequireDefault":13,"@babel/runtime/helpers/typeof":14}],7:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.getIdb=u,n.createDatabase=c,n.writeMessage=l,n.getAllMessages=function(e){var n=e.transaction(a).objectStore(a),r=[];return new Promise(function(t){n.openCursor().onsuccess=function(e){e=e.target.result;e?(r.push(e.value),e.continue()):t(r)}})},n.getMessagesHigherThan=d,n.removeMessageById=f,n.getOldMessages=p,n.cleanOldMessages=h,n.create=m,n.close=b,n.postMessage=g,n.onMessage=y,n.canBeUsed=_,n.averageResponseTime=w,n.default=n.type=n.microSeconds=void 0;var o=e("../util.js"),i=e("oblivious-set"),s=e("../options"),e=o.microSeconds;n.microSeconds=e;var r="pubkey.broadcast-channel-0-",a="messages";function u(){if("undefined"!=typeof indexedDB)return indexedDB;if("undefined"!=typeof window){if(void 0!==window.mozIndexedDB)return window.mozIndexedDB;if(void 0!==window.webkitIndexedDB)return window.webkitIndexedDB;if(void 0!==window.msIndexedDB)return window.msIndexedDB}return!1}function c(e){var n=u().open(r+e,1);return n.onupgradeneeded=function(e){e.target.result.createObjectStore(a,{keyPath:"id",autoIncrement:!0})},new Promise(function(e,t){n.onerror=function(e){return t(e)},n.onsuccess=function(){e(n.result)}})}function l(e,t,n){var r={uuid:t,time:(new Date).getTime(),data:n},o=e.transaction([a],"readwrite");return new Promise(function(e,t){o.oncomplete=function(){return e()},o.onerror=function(e){return t(e)},o.objectStore(a).add(r)})}function d(e,n){var r=e.transaction(a).objectStore(a),o=[];return new Promise(function(t){(function(){try{var e=IDBKeyRange.bound(n+1,1/0);return r.openCursor(e)}catch(e){return r.openCursor()}})().onsuccess=function(e){e=e.target.result;e?e.value.idn.lastCursorId&&(n.lastCursorId=e.id),e}).filter(function(e){return t=n,(e=e).uuid!==t.uuid&&(!t.eMIs.has(e.id)&&!(e.data.time=e.time&&e.fn(t.data)})},n=e.method.microSeconds(),e._prepP?e._prepP.then(function(){e._iL=!0,e.method.onMessage(e._state,t,n)}):(e._iL=!0,e.method.onMessage(e._state,t,n)))}}(e)}function l(e,t,n){e._addEL[t]=e._addEL[t].filter(function(e){return e!==n}),function(e){{var t;e._iL&&!u(e)&&(e._iL=!1,t=e.method.microSeconds(),e.method.onMessage(e._state,null,t))}}(e)}(n.BroadcastChannel=e)._pubkey=!0,e.prototype={postMessage:function(e){if(this.closed)throw new Error("BroadcastChannel.postMessage(): Cannot post message after channel has closed");return a(this,"message",e)},postInternal:function(e){return a(this,"internal",e)},set onmessage(e){var t={time:this.method.microSeconds(),fn:e};l(this,"message",this._onML),e&&"function"==typeof e?(this._onML=t,c(this,"message",t)):this._onML=null},addEventListener:function(e,t){var n=this.method.microSeconds();c(this,e,{time:n,fn:t})},removeEventListener:function(e,t){var n=this._addEL[e].find(function(e){return e.fn===t});l(this,e,n)},close:function(){var e=this;if(!this.closed){this.closed=!0;var t=this._prepP||o.PROMISE_RESOLVED_VOID;return this._onML=null,this._addEL.message=[],t.then(function(){return Promise.all(Array.from(e._uMP))}).then(function(){return Promise.all(e._befC.map(function(e){return e()}))}).then(function(){return e.method.close(e._state)})}},get type(){return this.method.type},get isClosed(){return this.closed}}},{"./method-chooser.js":6,"./options.js":11,"./util.js":12}],2:[function(e,t,n){"use strict";var r=e("./index.es5.js"),e=r.BroadcastChannel,r=r.createLeaderElection;window.BroadcastChannel2=e,window.createLeaderElection=r},{"./index.es5.js":3}],3:[function(e,t,n){"use strict";e=e("./index.js");t.exports={BroadcastChannel:e.BroadcastChannel,createLeaderElection:e.createLeaderElection,clearNodeFolder:e.clearNodeFolder,enforceOptions:e.enforceOptions,beLeader:e.beLeader}},{"./index.js":4}],4:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"BroadcastChannel",{enumerable:!0,get:function(){return r.BroadcastChannel}}),Object.defineProperty(n,"beLeader",{enumerable:!0,get:function(){return o.beLeader}}),Object.defineProperty(n,"clearNodeFolder",{enumerable:!0,get:function(){return r.clearNodeFolder}}),Object.defineProperty(n,"createLeaderElection",{enumerable:!0,get:function(){return o.createLeaderElection}}),Object.defineProperty(n,"enforceOptions",{enumerable:!0,get:function(){return r.enforceOptions}});var r=e("./broadcast-channel"),o=e("./leader-election")},{"./broadcast-channel":1,"./leader-election":5}],5:[function(e,t,n){"use strict";var r=e("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(n,"__esModule",{value:!0}),n.beLeader=u,n.createLeaderElection=function(e,t){if(e._leaderElector)throw new Error("BroadcastChannel already has a leader-elector");t=function(e,t){e=e||{};(e=JSON.parse(JSON.stringify(e))).fallbackInterval||(e.fallbackInterval=3e3);e.responseTime||(e.responseTime=t.method.averageResponseTime(t.options));return e}(t,e);var n=new i(e,t);return e._befC.push(function(){return n.die()}),e._leaderElector=n};var s=e("./util.js"),o=r(e("unload")),i=function(e,t){this.broadcastChannel=e,this._options=t,this.isLeader=!1,this.hasLeader=!1,this.isDead=!1,this.token=(0,s.randomToken)(),this._isApl=!1,this._reApply=!1,this._unl=[],this._lstns=[],this._invs=[],this._dpL=function(){},this._dpLC=!1};function a(e,t){t={context:"leader",action:t,token:e.token};return e.broadcastChannel.postInternal(t)}function u(t){t.isLeader=!0,t.hasLeader=!0;var e=o.default.add(function(){return t.die()});t._unl.push(e);e=function(e){"leader"===e.context&&"apply"===e.action&&a(t,"tell"),"leader"!==e.context||"tell"!==e.action||t._dpLC||(t._dpLC=!0,t._dpL(),a(t,"tell"))};return t.broadcastChannel.addEventListener("internal",e),t._lstns.push(e),a(t,"tell")}i.prototype={applyOnce:function(){var t=this;if(this.isLeader)return s.PROMISE_RESOLVED_FALSE;if(this.isDead)return s.PROMISE_RESOLVED_FALSE;if(this._isApl)return this._reApply=!0,s.PROMISE_RESOLVED_FALSE;function n(e){"leader"===e.context&&e.token!=t.token&&(o.push(e),"apply"===e.action&&e.token>t.token&&(r=!0),"tell"===e.action&&(r=!0,t.hasLeader=!0))}var r=!(this._isApl=!0),o=[];return this.broadcastChannel.addEventListener("internal",n),a(this,"apply").then(function(){return(0,s.sleep)(t._options.responseTime)}).then(function(){return r?s.PROMISE_REJECTED:a(t,"apply")}).then(function(){return(0,s.sleep)(t._options.responseTime)}).then(function(){return r?s.PROMISE_REJECTED:a(t)}).then(function(){return u(t)}).then(function(){return!0}).catch(function(){return!1}).then(function(e){return t.broadcastChannel.removeEventListener("internal",n),t._isApl=!1,!e&&t._reApply?(t._reApply=!1,t.applyOnce()):e})},awaitLeadership:function(){return this._aLP||(this._aLP=function(i){if(i.isLeader)return s.PROMISE_RESOLVED_VOID;return new Promise(function(e){var t=!1;function n(){t||(t=!0,clearInterval(r),i.broadcastChannel.removeEventListener("internal",o),e(!0))}i.applyOnce().then(function(){i.isLeader&&n()});var r=setInterval(function(){i.applyOnce().then(function(){i.isLeader&&n()})},i._options.fallbackInterval);i._invs.push(r);var o=function(e){"leader"===e.context&&"death"===e.action&&(i.hasLeader=!1,i.applyOnce().then(function(){i.isLeader&&n()}))};i.broadcastChannel.addEventListener("internal",o),i._lstns.push(o)})}(this)),this._aLP},set onduplicate(e){this._dpL=e},die:function(){var t=this;if(!this.isDead&&this.isLeader)return this.hasLeader=!1,this.isDead=!0,this._lstns.forEach(function(e){return t.broadcastChannel.removeEventListener("internal",e)}),this._invs.forEach(function(e){return clearInterval(e)}),this._unl.forEach(function(e){e.remove()}),a(this,"death")}}},{"./util.js":12,"@babel/runtime/helpers/interopRequireDefault":13,unload:20}],6:[function(e,t,n){"use strict";var r=e("@babel/runtime/helpers/interopRequireDefault");e("@babel/runtime/helpers/typeof");Object.defineProperty(n,"__esModule",{value:!0}),n.chooseMethod=function(t){var e=[].concat(t.methods,u).filter(Boolean);if(t.type){if("simulate"===t.type)return s.default;var n=e.find(function(e){return e.type===t.type});if(n)return n;throw new Error("method-type "+t.type+" not found")}t.webWorkerSupport||a.isNode||(e=e.filter(function(e){return"idb"!==e.type}));e=e.find(function(e){return e.canBeUsed()});{if(e)return e;throw new Error("No useable method found in "+JSON.stringify(u.map(function(e){return e.type})))}};var o=r(e("./methods/native.js")),i=r(e("./methods/indexed-db.js")),n=r(e("./methods/localstorage.js")),s=r(e("./methods/simulate.js")),a=e("./util");var u=[o.default,i.default,n.default]},{"./methods/indexed-db.js":7,"./methods/localstorage.js":8,"./methods/native.js":9,"./methods/simulate.js":10,"./util":12,"@babel/runtime/helpers/interopRequireDefault":13,"@babel/runtime/helpers/typeof":14}],7:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.averageResponseTime=E,n.canBeUsed=y,n.cleanOldMessages=h,n.close=b,n.create=m,n.createDatabase=c,n.default=void 0,n.getAllMessages=function(e){var n=e.transaction(a).objectStore(a),r=[];return new Promise(function(t){n.openCursor().onsuccess=function(e){e=e.target.result;e?(r.push(e.value),e.continue()):t(r)}})},n.getIdb=u,n.getMessagesHigherThan=d,n.getOldMessages=p,n.microSeconds=void 0,n.onMessage=g,n.postMessage=_,n.removeMessageById=f,n.type=void 0,n.writeMessage=l;var o=e("../util.js"),i=e("oblivious-set"),s=e("../options"),e=o.microSeconds;n.microSeconds=e;var r="pubkey.broadcast-channel-0-",a="messages";function u(){if("undefined"!=typeof indexedDB)return indexedDB;if("undefined"!=typeof window){if(void 0!==window.mozIndexedDB)return window.mozIndexedDB;if(void 0!==window.webkitIndexedDB)return window.webkitIndexedDB;if(void 0!==window.msIndexedDB)return window.msIndexedDB}return!1}function c(e){var n=u().open(r+e,1);return n.onupgradeneeded=function(e){e.target.result.createObjectStore(a,{keyPath:"id",autoIncrement:!0})},new Promise(function(e,t){n.onerror=function(e){return t(e)},n.onsuccess=function(){e(n.result)}})}function l(e,t,n){var r={uuid:t,time:(new Date).getTime(),data:n},o=e.transaction([a],"readwrite");return new Promise(function(e,t){o.oncomplete=function(){return e()},o.onerror=function(e){return t(e)},o.objectStore(a).add(r)})}function d(e,n){var r=e.transaction(a).objectStore(a),o=[];return new Promise(function(t){(function(){try{var e=IDBKeyRange.bound(n+1,1/0);return r.openCursor(e)}catch(e){return r.openCursor()}})().onsuccess=function(e){e=e.target.result;e?e.value.idn.lastCursorId&&(n.lastCursorId=e.id),e}).filter(function(e){return t=n,(e=e).uuid!==t.uuid&&(!t.eMIs.has(e.id)&&!(e.data.time this one is now leader @@ -91,7 +107,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -120,11 +136,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -138,9 +158,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -151,9 +177,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -177,13 +201,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -199,11 +226,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -235,7 +263,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); diff --git a/dist/lib/methods/indexed-db.js b/dist/lib/methods/indexed-db.js index 25ab2fa8..0621cc11 100644 --- a/dist/lib/methods/indexed-db.js +++ b/dist/lib/methods/indexed-db.js @@ -3,21 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -215,7 +217,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -269,9 +271,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -299,7 +301,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } diff --git a/dist/lib/methods/localstorage.js b/dist/lib/methods/localstorage.js index f9261883..31921f6a 100644 --- a/dist/lib/methods/localstorage.js +++ b/dist/lib/methods/localstorage.js @@ -3,17 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); diff --git a/dist/lib/methods/native.js b/dist/lib/methods/native.js index 504ac8e8..3b1ec366 100644 --- a/dist/lib/methods/native.js +++ b/dist/lib/methods/native.js @@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -43,7 +44,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } diff --git a/dist/lib/methods/node.js b/dist/lib/methods/node.js index 2439f173..0dfb23b7 100644 --- a/dist/lib/methods/node.js +++ b/dist/lib/methods/node.js @@ -5,35 +5,36 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau Object.defineProperty(exports, "__esModule", { value: true }); +exports.TMP_FOLDER_BASE = void 0; +exports._filterMessage = _filterMessage; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; exports.cleanPipeName = cleanPipeName; -exports.getPaths = getPaths; -exports.ensureFoldersExist = ensureFoldersExist; exports.clearNodeFolder = clearNodeFolder; -exports.socketPath = socketPath; -exports.socketInfoPath = socketInfoPath; -exports.createSocketInfoFile = createSocketInfoFile; +exports.close = close; exports.countChannelFolders = countChannelFolders; +exports.create = create; exports.createSocketEventEmitter = createSocketEventEmitter; -exports.openClientConnection = openClientConnection; -exports.writeMessage = writeMessage; -exports.getReadersUuids = getReadersUuids; -exports.messagePath = messagePath; +exports.createSocketInfoFile = createSocketInfoFile; +exports.emitOverFastPath = emitOverFastPath; +exports.ensureFoldersExist = ensureFoldersExist; exports.getAllMessages = getAllMessages; +exports.getPaths = getPaths; +exports.getReadersUuids = getReadersUuids; exports.getSingleMessage = getSingleMessage; -exports.readMessage = readMessage; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports._filterMessage = _filterMessage; exports.handleMessagePing = handleMessagePing; -exports.refreshReaderClients = refreshReaderClients; -exports.postMessage = postMessage; -exports.emitOverFastPath = emitOverFastPath; -exports.onMessage = onMessage; -exports.close = close; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; +exports.messagePath = messagePath; exports.microSeconds = microSeconds; -exports.type = exports.TMP_FOLDER_BASE = void 0; +exports.onMessage = onMessage; +exports.openClientConnection = openClientConnection; +exports.postMessage = postMessage; +exports.readMessage = readMessage; +exports.refreshReaderClients = refreshReaderClients; +exports.socketInfoPath = socketInfoPath; +exports.socketPath = socketPath; +exports.type = void 0; +exports.writeMessage = writeMessage; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); @@ -736,7 +737,7 @@ function _create() { messagesCallbackTime: null, messagesCallback: null, // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util2.PROMISE_RESOLVED_VOID, otherReaderClients: {}, // ensure if process crashes, everything is cleaned up removeUnload: _unload["default"].add(function () { diff --git a/dist/lib/methods/simulate.js b/dist/lib/methods/simulate.js index 09b12b89..cb4ef3b2 100644 --- a/dist/lib/methods/simulate.js +++ b/dist/lib/methods/simulate.js @@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); diff --git a/dist/lib/util.js b/dist/lib/util.js index 8fba57af..c8e8bd85 100644 --- a/dist/lib/util.js +++ b/dist/lib/util.js @@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -21,6 +21,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/docs/e2e.js b/docs/e2e.js index 659bdf6d..b8df9c6d 100644 --- a/docs/e2e.js +++ b/docs/e2e.js @@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -86,7 +86,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -156,7 +156,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -194,7 +194,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list @@ -310,16 +310,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -328,10 +328,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); @@ -353,10 +353,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -379,12 +380,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -406,23 +413,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -432,7 +448,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -461,11 +477,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -479,9 +499,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -492,9 +518,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -518,13 +542,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -540,11 +567,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -576,7 +604,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); @@ -687,21 +715,23 @@ function chooseMethod(options) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -899,7 +929,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -953,9 +983,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -983,7 +1013,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } @@ -1038,17 +1068,19 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); @@ -1236,13 +1268,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1276,7 +1309,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } @@ -1323,13 +1356,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1432,12 +1466,12 @@ function fillOptionsWithDefaults() { Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -1450,6 +1484,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/docs/iframe.js b/docs/iframe.js index 5b28b68c..2882b315 100644 --- a/docs/iframe.js +++ b/docs/iframe.js @@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -86,7 +86,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -156,7 +156,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -194,7 +194,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list @@ -310,16 +310,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -328,10 +328,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); @@ -353,10 +353,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -379,12 +380,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -406,23 +413,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -432,7 +448,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -461,11 +477,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -479,9 +499,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -492,9 +518,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -518,13 +542,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -540,11 +567,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -576,7 +604,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); @@ -687,21 +715,23 @@ function chooseMethod(options) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -899,7 +929,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -953,9 +983,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -983,7 +1013,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } @@ -1038,17 +1068,19 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); @@ -1236,13 +1268,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1276,7 +1309,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } @@ -1323,13 +1356,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1432,12 +1466,12 @@ function fillOptionsWithDefaults() { Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -1450,6 +1484,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/docs/index.js b/docs/index.js index 11a78067..889790ac 100644 --- a/docs/index.js +++ b/docs/index.js @@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -86,7 +86,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -156,7 +156,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -194,7 +194,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list @@ -310,16 +310,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -328,10 +328,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); @@ -353,10 +353,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -379,12 +380,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -406,23 +413,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -432,7 +448,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -461,11 +477,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -479,9 +499,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -492,9 +518,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -518,13 +542,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -540,11 +567,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -576,7 +604,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); @@ -687,21 +715,23 @@ function chooseMethod(options) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -899,7 +929,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -953,9 +983,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -983,7 +1013,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } @@ -1038,17 +1068,19 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); @@ -1236,13 +1268,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1276,7 +1309,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } @@ -1323,13 +1356,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1432,12 +1466,12 @@ function fillOptionsWithDefaults() { Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -1450,6 +1484,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/docs/leader-iframe.js b/docs/leader-iframe.js index 86025d43..c16eb99f 100644 --- a/docs/leader-iframe.js +++ b/docs/leader-iframe.js @@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -86,7 +86,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -156,7 +156,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -194,7 +194,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list @@ -310,16 +310,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -328,10 +328,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); @@ -353,10 +353,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -379,12 +380,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -406,23 +413,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -432,7 +448,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -461,11 +477,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -479,9 +499,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -492,9 +518,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -518,13 +542,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -540,11 +567,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -576,7 +604,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); @@ -687,21 +715,23 @@ function chooseMethod(options) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -899,7 +929,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -953,9 +983,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -983,7 +1013,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } @@ -1038,17 +1068,19 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); @@ -1236,13 +1268,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1276,7 +1309,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } @@ -1323,13 +1356,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1432,12 +1466,12 @@ function fillOptionsWithDefaults() { Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -1450,6 +1484,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/docs/worker.js b/docs/worker.js index 55ce0128..0cdff596 100644 --- a/docs/worker.js +++ b/docs/worker.js @@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.BroadcastChannel = void 0; exports.clearNodeFolder = clearNodeFolder; exports.enforceOptions = enforceOptions; -exports.BroadcastChannel = void 0; var _util = require("./util.js"); @@ -86,7 +86,7 @@ function clearNodeFolder(options) { return true; }); } else { - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } } /** @@ -156,7 +156,7 @@ BroadcastChannel.prototype = { } this.closed = true; - var awaitPrepare = this._prepP ? this._prepP : Promise.resolve(); + var awaitPrepare = this._prepP ? this._prepP : _util.PROMISE_RESOLVED_VOID; this._onML = null; this._addEL.message = []; return awaitPrepare // wait until all current sending are processed @@ -194,7 +194,7 @@ function _post(broadcastChannel, type, msg) { type: type, data: msg }; - var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : Promise.resolve(); + var awaitPrepare = broadcastChannel._prepP ? broadcastChannel._prepP : _util.PROMISE_RESOLVED_VOID; return awaitPrepare.then(function () { var sendPromise = broadcastChannel.method.postMessage(broadcastChannel._state, msgObj); // add/remove to unsend messages list @@ -310,16 +310,16 @@ Object.defineProperty(exports, "BroadcastChannel", { return _broadcastChannel.BroadcastChannel; } }); -Object.defineProperty(exports, "clearNodeFolder", { +Object.defineProperty(exports, "beLeader", { enumerable: true, get: function get() { - return _broadcastChannel.clearNodeFolder; + return _leaderElection.beLeader; } }); -Object.defineProperty(exports, "enforceOptions", { +Object.defineProperty(exports, "clearNodeFolder", { enumerable: true, get: function get() { - return _broadcastChannel.enforceOptions; + return _broadcastChannel.clearNodeFolder; } }); Object.defineProperty(exports, "createLeaderElection", { @@ -328,10 +328,10 @@ Object.defineProperty(exports, "createLeaderElection", { return _leaderElection.createLeaderElection; } }); -Object.defineProperty(exports, "beLeader", { +Object.defineProperty(exports, "enforceOptions", { enumerable: true, get: function get() { - return _leaderElection.beLeader; + return _broadcastChannel.enforceOptions; } }); @@ -353,10 +353,11 @@ var _util = require("./util.js"); var _unload = _interopRequireDefault(require("unload")); -var LeaderElection = function LeaderElection(channel, options) { - this._channel = channel; +var LeaderElection = function LeaderElection(broadcastChannel, options) { + this.broadcastChannel = broadcastChannel; this._options = options; this.isLeader = false; + this.hasLeader = false; this.isDead = false; this.token = (0, _util.randomToken)(); this._isApl = false; // _isApplying @@ -379,12 +380,18 @@ LeaderElection.prototype = { applyOnce: function applyOnce() { var _this = this; - if (this.isLeader) return Promise.resolve(false); - if (this.isDead) return Promise.resolve(false); // do nothing if already running + if (this.isLeader) { + return _util.PROMISE_RESOLVED_FALSE; + } + + if (this.isDead) { + return _util.PROMISE_RESOLVED_FALSE; + } // do nothing if already running + if (this._isApl) { this._reApply = true; - return Promise.resolve(false); + return _util.PROMISE_RESOLVED_FALSE; } this._isApl = true; @@ -406,23 +413,32 @@ LeaderElection.prototype = { if (msg.action === 'tell') { // other is already leader stopCriteria = true; + _this.hasLeader = true; } } }; - this._channel.addEventListener('internal', handleMessage); + this.broadcastChannel.addEventListener('internal', handleMessage); var ret = _sendMessage(this, 'apply') // send out that this one is applying .then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this, 'apply'); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this, 'apply'); + } }).then(function () { return (0, _util.sleep)(_this._options.responseTime); }) // let others time to respond .then(function () { - if (stopCriteria) return Promise.reject(new Error());else return _sendMessage(_this); + if (stopCriteria) { + return _util.PROMISE_REJECTED; + } else { + return _sendMessage(_this); + } }).then(function () { return beLeader(_this); }) // no one disagreed -> this one is now leader @@ -432,7 +448,7 @@ LeaderElection.prototype = { return false; }) // apply not successfull .then(function (success) { - _this._channel.removeEventListener('internal', handleMessage); + _this.broadcastChannel.removeEventListener('internal', handleMessage); _this._isApl = false; @@ -461,11 +477,15 @@ LeaderElection.prototype = { die: function die() { var _this2 = this; - if (this.isDead) return; + if (this.isDead || !this.isLeader) { + return; + } + + this.hasLeader = false; this.isDead = true; this._lstns.forEach(function (listener) { - return _this2._channel.removeEventListener('internal', listener); + return _this2.broadcastChannel.removeEventListener('internal', listener); }); this._invs.forEach(function (interval) { @@ -479,9 +499,15 @@ LeaderElection.prototype = { return _sendMessage(this, 'death'); } }; +/** + * @param leaderElector {LeaderElector} + */ function _awaitLeadershipOnce(leaderElector) { - if (leaderElector.isLeader) return Promise.resolve(); + if (leaderElector.isLeader) { + return _util.PROMISE_RESOLVED_VOID; + } + return new Promise(function (res) { var resolved = false; @@ -492,9 +518,7 @@ function _awaitLeadershipOnce(leaderElector) { resolved = true; clearInterval(interval); - - leaderElector._channel.removeEventListener('internal', whenDeathListener); - + leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -518,13 +542,16 @@ function _awaitLeadershipOnce(leaderElector) { var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { + leaderElector.hasLeader = false; leaderElector.applyOnce().then(function () { - if (leaderElector.isLeader) finish(); + if (leaderElector.isLeader) { + finish(); + } }); } }; - leaderElector._channel.addEventListener('internal', whenDeathListener); + leaderElector.broadcastChannel.addEventListener('internal', whenDeathListener); leaderElector._lstns.push(whenDeathListener); }); @@ -540,11 +567,12 @@ function _sendMessage(leaderElector, action) { action: action, token: leaderElector.token }; - return leaderElector._channel.postInternal(msgJson); + return leaderElector.broadcastChannel.postInternal(msgJson); } function beLeader(leaderElector) { leaderElector.isLeader = true; + leaderElector.hasLeader = true; var unloadFn = _unload["default"].add(function () { return leaderElector.die(); @@ -576,7 +604,7 @@ function beLeader(leaderElector) { } }; - leaderElector._channel.addEventListener('internal', isLeaderListener); + leaderElector.broadcastChannel.addEventListener('internal', isLeaderListener); leaderElector._lstns.push(isLeaderListener); @@ -687,21 +715,23 @@ function chooseMethod(options) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.getIdb = getIdb; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; +exports.cleanOldMessages = cleanOldMessages; +exports.close = close; +exports.create = create; exports.createDatabase = createDatabase; -exports.writeMessage = writeMessage; +exports["default"] = void 0; exports.getAllMessages = getAllMessages; +exports.getIdb = getIdb; exports.getMessagesHigherThan = getMessagesHigherThan; -exports.removeMessageById = removeMessageById; exports.getOldMessages = getOldMessages; -exports.cleanOldMessages = cleanOldMessages; -exports.create = create; -exports.close = close; -exports.postMessage = postMessage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeMessageById = removeMessageById; +exports.type = void 0; +exports.writeMessage = writeMessage; var _util = require("../util.js"); @@ -899,7 +929,7 @@ function create(channelName, options) { */ eMIs: new _obliviousSet.ObliviousSet(options.idb.ttl * 2), // ensures we do not read messages in parrallel - writeBlockPromise: Promise.resolve(), + writeBlockPromise: _util.PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db: db @@ -953,9 +983,9 @@ function _filterMessage(msgObj, state) { function readNewMessages(state) { // channel already closed - if (state.closed) return Promise.resolve(); // if no one is listening, we do not need to scan for new messages + if (state.closed) return _util.PROMISE_RESOLVED_VOID; // if no one is listening, we do not need to scan for new messages - if (!state.messagesCallback) return Promise.resolve(); + if (!state.messagesCallback) return _util.PROMISE_RESOLVED_VOID; return getMessagesHigherThan(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages /** @@ -983,7 +1013,7 @@ function readNewMessages(state) { state.messagesCallback(msgObj.data); } }); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; }); } @@ -1038,17 +1068,19 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getLocalStorage = getLocalStorage; -exports.storageKey = storageKey; -exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; -exports.removeStorageEventListener = removeStorageEventListener; -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; +exports.create = create; +exports["default"] = void 0; +exports.getLocalStorage = getLocalStorage; +exports.microSeconds = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.removeStorageEventListener = removeStorageEventListener; +exports.storageKey = storageKey; +exports.type = void 0; var _obliviousSet = require("oblivious-set"); @@ -1236,13 +1268,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1276,7 +1309,7 @@ function close(channelState) { function postMessage(channelState, messageJson) { try { channelState.bc.postMessage(messageJson, false); - return Promise.resolve(); + return _util.PROMISE_RESOLVED_VOID; } catch (err) { return Promise.reject(err); } @@ -1323,13 +1356,14 @@ exports["default"] = _default; Object.defineProperty(exports, "__esModule", { value: true }); -exports.create = create; +exports.averageResponseTime = averageResponseTime; +exports.canBeUsed = canBeUsed; exports.close = close; -exports.postMessage = postMessage; +exports.create = create; +exports.microSeconds = exports["default"] = void 0; exports.onMessage = onMessage; -exports.canBeUsed = canBeUsed; -exports.averageResponseTime = averageResponseTime; -exports["default"] = exports.type = exports.microSeconds = void 0; +exports.postMessage = postMessage; +exports.type = void 0; var _util = require("../util"); @@ -1432,12 +1466,12 @@ function fillOptionsWithDefaults() { Object.defineProperty(exports, "__esModule", { value: true }); +exports.isNode = exports.PROMISE_RESOLVED_VOID = exports.PROMISE_RESOLVED_FALSE = exports.PROMISE_REJECTED = void 0; exports.isPromise = isPromise; -exports.sleep = sleep; +exports.microSeconds = microSeconds; exports.randomInt = randomInt; exports.randomToken = randomToken; -exports.microSeconds = microSeconds; -exports.isNode = void 0; +exports.sleep = sleep; /** * returns true if the given object is a promise @@ -1450,6 +1484,13 @@ function isPromise(obj) { } } +var PROMISE_RESOLVED_FALSE = Promise.resolve(false); +exports.PROMISE_RESOLVED_FALSE = PROMISE_RESOLVED_FALSE; +var PROMISE_RESOLVED_VOID = Promise.resolve(); +exports.PROMISE_RESOLVED_VOID = PROMISE_RESOLVED_VOID; +var PROMISE_REJECTED = Promise.reject(new Error()); +exports.PROMISE_REJECTED = PROMISE_REJECTED; + function sleep(time) { if (!time) time = 0; return new Promise(function (res) { diff --git a/package.json b/package.json index 3c7d4e33..703cb139 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "broadcast-channel", - "version": "4.2.0", + "version": "4.3.0", "description": "A BroadcastChannel that works in New Browsers, Old Browsers, WebWorkers and NodeJs", "exports": { ".": {