redux-saga
Advanced tools
Comparing version 0.9.5 to 0.10.0
@@ -62,3 +62,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
}); | ||
exports.utils = exports.effects = exports.takeLatest = exports.takeEvery = exports.storeIO = exports.runSaga = exports.isCancelError = exports.SagaCancellationException = undefined; | ||
exports.utils = exports.effects = exports.delay = exports.takeLatest = exports.takeEvery = exports.buffers = exports.channel = exports.eventChannel = exports.END = exports.CANCEL = exports.runSaga = undefined; | ||
@@ -73,9 +73,42 @@ var _runSaga = __webpack_require__(9); | ||
}); | ||
Object.defineProperty(exports, 'storeIO', { | ||
var _proc = __webpack_require__(5); | ||
Object.defineProperty(exports, 'CANCEL', { | ||
enumerable: true, | ||
get: function get() { | ||
return _runSaga.storeIO; | ||
return _proc.CANCEL; | ||
} | ||
}); | ||
var _channel = __webpack_require__(2); | ||
Object.defineProperty(exports, 'END', { | ||
enumerable: true, | ||
get: function get() { | ||
return _channel.END; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'eventChannel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _channel.eventChannel; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'channel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _channel.channel; | ||
} | ||
}); | ||
var _buffers = __webpack_require__(4); | ||
Object.defineProperty(exports, 'buffers', { | ||
enumerable: true, | ||
get: function get() { | ||
return _buffers.buffers; | ||
} | ||
}); | ||
var _sagaHelpers = __webpack_require__(10); | ||
@@ -96,2 +129,11 @@ | ||
var _utils = __webpack_require__(1); | ||
Object.defineProperty(exports, 'delay', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.delay; | ||
} | ||
}); | ||
var _middleware = __webpack_require__(8); | ||
@@ -101,13 +143,9 @@ | ||
var _SagaCancellationException2 = __webpack_require__(2); | ||
var _effects = __webpack_require__(6); | ||
var _SagaCancellationException3 = _interopRequireDefault(_SagaCancellationException2); | ||
var _effects = __webpack_require__(7); | ||
var effects = _interopRequireWildcard(_effects); | ||
var _utils = __webpack_require__(12); | ||
var _utils2 = __webpack_require__(11); | ||
var utils = _interopRequireWildcard(_utils); | ||
var utils = _interopRequireWildcard(_utils2); | ||
@@ -119,7 +157,2 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
exports.default = _middleware2.default; | ||
var SagaCancellationException = exports.SagaCancellationException = _SagaCancellationException3.default; | ||
var isCancelError = exports.isCancelError = function isCancelError(error) { | ||
return error instanceof SagaCancellationException; | ||
}; | ||
exports.effects = effects; | ||
@@ -145,13 +178,22 @@ exports.utils = utils; | ||
exports.arrayOfDeffered = arrayOfDeffered; | ||
exports.delay = delay; | ||
exports.createMockTask = createMockTask; | ||
exports.autoInc = autoInc; | ||
exports.asap = asap; | ||
exports.warnDeprecated = warnDeprecated; | ||
exports.makeIterator = makeIterator; | ||
exports.log = log; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var sym = exports.sym = function sym(id) { | ||
return '@@redux-saga/' + id; | ||
}; | ||
var TASK = exports.TASK = sym('TASK'); | ||
var kTrue = exports.kTrue = function kTrue() { | ||
return true; | ||
var MATCH = exports.MATCH = sym('MATCH'); | ||
var konst = exports.konst = function konst(v) { | ||
return function () { | ||
return v; | ||
}; | ||
}; | ||
var kTrue = exports.kTrue = konst(true); | ||
var kFalse = exports.kFalse = konst(false); | ||
var noop = exports.noop = function noop() {}; | ||
@@ -178,2 +220,5 @@ function ident(v) { | ||
}, | ||
number: function number(n) { | ||
return typeof n === 'number'; | ||
}, | ||
array: Array.isArray, | ||
@@ -186,4 +231,19 @@ promise: function promise(p) { | ||
}, | ||
task: function task(it) { | ||
return it && it[TASK]; | ||
task: function task(t) { | ||
return t && t[TASK]; | ||
}, | ||
take: function take(ch) { | ||
return ch && is.func(ch.take); | ||
}, | ||
put: function put(ch) { | ||
return ch && is.func(ch.put); | ||
}, | ||
observable: function observable(ob) { | ||
return ob && is.func(ob.subscribe); | ||
}, | ||
buffer: function buffer(buf) { | ||
return buf && is.func(buf.isEmpty) && is.func(buf.take) && is.func(buf.put); | ||
}, | ||
pattern: function pattern(pat) { | ||
return pat && (typeof pat === 'string' || is.func(pat) || is.array(pat)); | ||
} | ||
@@ -217,2 +277,34 @@ }; | ||
function delay(ms) { | ||
var val = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; | ||
return new Promise(function (resolve) { | ||
return setTimeout(function () { | ||
return resolve(val); | ||
}, ms); | ||
}); | ||
} | ||
function createMockTask() { | ||
var _ref; | ||
var running = true; | ||
var _result = void 0, | ||
_error = void 0; | ||
return _ref = {}, _defineProperty(_ref, TASK, true), _defineProperty(_ref, 'isRunning', function isRunning() { | ||
return running; | ||
}), _defineProperty(_ref, 'result', function result() { | ||
return _result; | ||
}), _defineProperty(_ref, 'error', function error() { | ||
return _error; | ||
}), _defineProperty(_ref, 'setRunning', function setRunning(b) { | ||
return running = b; | ||
}), _defineProperty(_ref, 'setResult', function setResult(r) { | ||
return _result = r; | ||
}), _defineProperty(_ref, 'setError', function setError(e) { | ||
return _error = e; | ||
}), _ref; | ||
} | ||
function autoInc() { | ||
@@ -226,19 +318,40 @@ var seed = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; | ||
function asap(action) { | ||
return Promise.resolve(1).then(function () { | ||
return action(); | ||
}); | ||
var kThrow = function kThrow(err) { | ||
throw err; | ||
}; | ||
function makeIterator(next) { | ||
var thro = arguments.length <= 1 || arguments[1] === undefined ? kThrow : arguments[1]; | ||
var name = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2]; | ||
var iterator = { name: name, next: next, throw: thro }; | ||
if (typeof Symbol !== 'undefined') { | ||
iterator[Symbol.iterator] = function () { | ||
return iterator; | ||
}; | ||
} | ||
return iterator; | ||
} | ||
/* eslint-disable no-console */ | ||
function warnDeprecated(msg) { | ||
if (isDev) { | ||
console.warn('DEPRECATION WARNING', msg); | ||
/** | ||
Print error in a useful way whether in a browser environment | ||
(with expandable error stack traces), or in a node.js environment | ||
(text-only log output) | ||
**/ | ||
function log(level, message, error) { | ||
/*eslint-disable no-console*/ | ||
if (typeof window === 'undefined') { | ||
console.log('redux-saga ' + level + ': ' + message + '\n' + (error && error.stack || error)); | ||
} else { | ||
console[level].call(console, message, error); | ||
} | ||
} | ||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(13))) | ||
var internalErr = exports.internalErr = function internalErr(err) { | ||
return new Error('\n redux-saga: Error checking hooks detected an inconsisten state. This is likely a bug\n in redux-saga code and not yours. Thanks for reporting this in the project\'s github repo.\n Error: ' + err + '\n'); | ||
}; | ||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12))) | ||
/***/ }, | ||
/* 2 */ | ||
/***/ function(module, exports) { | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -250,26 +363,136 @@ 'use strict'; | ||
}); | ||
exports.default = SagaCancellationException; | ||
exports.UNDEFINED_INPUT_ERROR = exports.INVALID_BUFFER = exports.END = undefined; | ||
exports.emitter = emitter; | ||
exports.channel = channel; | ||
exports.eventChannel = eventChannel; | ||
/** | ||
* Creates an instance of a cancellation error | ||
* used internally by the Library to handle Cancellations effects | ||
* params: | ||
* type: PARALLEL_AUTO_CANCEL | RACE_AUTO_CANCEL | MANUAL_CANCEL | ||
* saga: current saga where the cancellation is to be thrown | ||
* origin: Origin saga from which the cancellation originated | ||
*/ | ||
var _utils = __webpack_require__(1); | ||
function SagaCancellationException(type, saga, origin) { | ||
var message = 'SagaCancellationException; type: ' + type + ', saga: ' + saga + ', origin: ' + origin; | ||
var _buffers = __webpack_require__(4); | ||
this.name = 'SagaCancellationException'; | ||
this.message = message; | ||
this.type = type; | ||
this.saga = saga; | ||
this.origin = origin; | ||
this.stack = new Error().stack; | ||
var END = exports.END = { type: '@@redux-saga/CHANNEL_END' }; | ||
function emitter() { | ||
var subscribers = []; | ||
function subscribe(sub) { | ||
subscribers.push(sub); | ||
return function () { | ||
return (0, _utils.remove)(subscribers, sub); | ||
}; | ||
} | ||
function emit(item) { | ||
var arr = subscribers.slice(); | ||
for (var i = 0, len = arr.length; i < len; i++) { | ||
arr[i](item); | ||
} | ||
} | ||
return { | ||
subscribe: subscribe, | ||
emit: emit | ||
}; | ||
} | ||
SagaCancellationException.prototype = Object.create(Error.prototype); | ||
SagaCancellationException.prototype.constructor = SagaCancellationException; | ||
var INVALID_BUFFER = exports.INVALID_BUFFER = 'invalid buffer passed to channel factory function'; | ||
var UNDEFINED_INPUT_ERROR = exports.UNDEFINED_INPUT_ERROR = '\n Saga was provided with an undefined action\n Hints :\n - check that your Action Creator returns a non undefined value\n - if the Saga was started using runSaga, check that your subscribe source provides the action to its listeners\n'; | ||
function channel(buffer) { | ||
var closed = false; | ||
var takers = []; | ||
if (arguments.length > 0) { | ||
(0, _utils.check)(buffer, _utils.is.buffer, INVALID_BUFFER); | ||
} else { | ||
buffer = _buffers.buffers.fixed(); | ||
} | ||
function checkForbiddenStates() { | ||
if (closed && takers.length) throw (0, _utils.internalErr)('Can not have a closed channel with pending takers'); | ||
if (takers.length && !buffer.isEmpty()) throw (0, _utils.internalErr)('Can not have pedning takers with non empty buffer'); | ||
} | ||
function put(input) { | ||
checkForbiddenStates(); | ||
(0, _utils.check)(input, _utils.is.notUndef, UNDEFINED_INPUT_ERROR); | ||
if (!closed) { | ||
if (takers.length) { | ||
for (var i = 0; i < takers.length; i++) { | ||
var cb = takers[i]; | ||
if (!cb[_utils.MATCH] || cb[_utils.MATCH](input)) { | ||
takers.splice(i, 1); | ||
return cb(input); | ||
} | ||
} | ||
} else { | ||
buffer.put(input); | ||
} | ||
} | ||
} | ||
function take(cb, matcher) { | ||
checkForbiddenStates(); | ||
(0, _utils.check)(cb, _utils.is.func, 'channel.take\'s callback must be a function'); | ||
if (arguments.length > 1) { | ||
(0, _utils.check)(matcher, _utils.is.func, 'channel.take\'s matcher argument must be a function'); | ||
cb[_utils.MATCH] = matcher; | ||
} | ||
if (closed && buffer.isEmpty()) cb(END);else if (!buffer.isEmpty()) cb(buffer.take());else { | ||
takers.push(cb); | ||
cb.cancel = function () { | ||
return (0, _utils.remove)(takers, cb); | ||
}; | ||
} | ||
} | ||
function close() { | ||
checkForbiddenStates(); | ||
if (!closed) { | ||
closed = true; | ||
if (takers.length) { | ||
var arr = takers; | ||
takers = []; | ||
for (var i = 0, len = arr.length; i < len; i++) { | ||
arr[i](END); | ||
} | ||
takers = []; | ||
} | ||
} | ||
} | ||
return { take: take, put: put, close: close, | ||
get __takers__() { | ||
return takers; | ||
}, | ||
get __closed__() { | ||
return closed; | ||
} | ||
}; | ||
} | ||
function eventChannel(subscribe) { | ||
var buffer = arguments.length <= 1 || arguments[1] === undefined ? _buffers.buffers.none() : arguments[1]; | ||
var matcher = arguments[2]; | ||
if (arguments.length > 1) (0, _utils.check)(matcher, _utils.is.func, 'Invalid match function passed to eventChannel'); | ||
var chan = channel(buffer); | ||
var unsubscribe = subscribe(function (input) { | ||
if (input === END) chan.close();else if (!matcher || matcher(input)) chan.put(input); | ||
}); | ||
return { | ||
take: chan.take, | ||
close: function close() { | ||
if (!chan.__closed__) { | ||
chan.close(); | ||
unsubscribe(); | ||
} | ||
} | ||
}; | ||
} | ||
/***/ }, | ||
@@ -279,3 +502,3 @@ /* 3 */ | ||
"use strict"; | ||
'use strict'; | ||
@@ -285,8 +508,8 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.asEffect = exports.SELECT_ARG_ERROR = exports.INVALID_PATTERN = exports.CANCEL_ARG_ERROR = exports.JOIN_ARG_ERROR = exports.FORK_ARG_ERROR = exports.CALL_FUNCTION_ARG_ERROR = undefined; | ||
exports.asEffect = undefined; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
exports.matcher = matcher; | ||
exports.take = take; | ||
exports.takem = takem; | ||
exports.put = put; | ||
@@ -298,5 +521,8 @@ exports.race = race; | ||
exports.fork = fork; | ||
exports.spawn = spawn; | ||
exports.join = join; | ||
exports.cancel = cancel; | ||
exports.select = select; | ||
exports.actionChannel = actionChannel; | ||
exports.cancelled = cancelled; | ||
@@ -307,9 +533,2 @@ var _utils = __webpack_require__(1); | ||
var CALL_FUNCTION_ARG_ERROR = exports.CALL_FUNCTION_ARG_ERROR = "call/cps/fork first argument must be a function, an array [context, function] or an object {context, fn}"; | ||
var FORK_ARG_ERROR = exports.FORK_ARG_ERROR = "fork first argument must be a generator function or an iterator"; | ||
var JOIN_ARG_ERROR = exports.JOIN_ARG_ERROR = "join argument must be a valid task (a result of a fork)"; | ||
var CANCEL_ARG_ERROR = exports.CANCEL_ARG_ERROR = "cancel argument must be a valid task (a result of a fork)"; | ||
var INVALID_PATTERN = exports.INVALID_PATTERN = "Invalid pattern passed to `take` (HINT: check if you didn't mispell a constant)"; | ||
var SELECT_ARG_ERROR = exports.SELECT_ARG_ERROR = "select first argument must be a function"; | ||
var IO = (0, _utils.sym)('IO'); | ||
@@ -325,2 +544,4 @@ var TAKE = 'TAKE'; | ||
var SELECT = 'SELECT'; | ||
var ACTION_CHANNEL = 'ACTION_CHANNEL'; | ||
var CANCELLED = 'CANCELLED'; | ||
@@ -333,39 +554,38 @@ var effect = function effect(type, payload) { | ||
var matchers = { | ||
wildcard: function wildcard() { | ||
return _utils.kTrue; | ||
}, | ||
default: function _default(pattern) { | ||
return function (input) { | ||
return input.type === pattern; | ||
}; | ||
}, | ||
array: function array(patterns) { | ||
return function (input) { | ||
return patterns.some(function (p) { | ||
return p === input.type; | ||
}); | ||
}; | ||
}, | ||
predicate: function predicate(_predicate) { | ||
return function (input) { | ||
return _predicate(input); | ||
}; | ||
} | ||
}; | ||
function take(channel, pattern) { | ||
if (arguments.length >= 2) { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'take(channel, pattern): channel is undefined'); | ||
(0, _utils.check)(channel, _utils.is.take, 'take(channel, pattern): argument ' + channel + ' is not a valid channel (channel argument must have a take method)'); | ||
(0, _utils.check)(pattern, _utils.is.notUndef, 'take(channel, pattern): pattern is undefined'); | ||
(0, _utils.check)(pattern, _utils.is.pattern, 'take(channel, pattern): argument ' + pattern + ' is not a valid pattern (pattern must be String | Function: a => boolean | Array<String>)'); | ||
} else if (arguments.length === 1) { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'take(patternOrChannel): undefined argument'); | ||
if (!_utils.is.take(channel)) { | ||
if (_utils.is.pattern(channel)) { | ||
pattern = channel; | ||
channel = null; | ||
} else throw new Error('take(patternOrChannel): argument ' + channel + ' is not valid channel or a valid pattern'); | ||
} else pattern = '*'; | ||
} else pattern = '*'; | ||
function matcher(pattern) { | ||
return (pattern === '*' ? matchers.wildcard : _utils.is.array(pattern) ? matchers.array : _utils.is.func(pattern) ? matchers.predicate : matchers.default)(pattern); | ||
return effect(TAKE, { channel: channel, pattern: pattern }); | ||
} | ||
function take(pattern) { | ||
if (arguments.length > 0 && _utils.is.undef(pattern)) { | ||
throw new Error(INVALID_PATTERN); | ||
} | ||
return effect(TAKE, _utils.is.undef(pattern) ? '*' : pattern); | ||
function takem() { | ||
var eff = take.apply(undefined, arguments); | ||
eff[TAKE].maybe = true; | ||
return eff; | ||
} | ||
function put(action) { | ||
return effect(PUT, action); | ||
function put(channel, action) { | ||
if (arguments.length > 1) { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'put(channel, action): argument channel is undefined'); | ||
(0, _utils.check)(channel, _utils.is.put, 'put(channel, action): argument ' + channel + ' is not a valid channel (channel argument must have a put method)'); | ||
(0, _utils.check)(action, _utils.is.notUndef, 'put(channel, action): argument action is undefined'); | ||
} else { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'put(action): argument action is undefined'); | ||
action = channel; | ||
channel = null; | ||
} | ||
return effect(PUT, { channel: channel, action: action }); | ||
} | ||
@@ -377,4 +597,4 @@ | ||
function getFnCallDesc(fn, args) { | ||
(0, _utils.check)(fn, _utils.is.notUndef, CALL_FUNCTION_ARG_ERROR); | ||
function getFnCallDesc(meth, fn, args) { | ||
(0, _utils.check)(fn, _utils.is.notUndef, meth + ': argument fn is undefined'); | ||
@@ -394,3 +614,3 @@ var context = null; | ||
} | ||
(0, _utils.check)(fn, _utils.is.func, CALL_FUNCTION_ARG_ERROR); | ||
(0, _utils.check)(fn, _utils.is.func, meth + ': argument ' + fn + ' is not a function'); | ||
@@ -405,3 +625,3 @@ return { context: context, fn: fn, args: args }; | ||
return effect(CALL, getFnCallDesc(fn, args)); | ||
return effect(CALL, getFnCallDesc('call', fn, args)); | ||
} | ||
@@ -412,3 +632,3 @@ | ||
return effect(CALL, getFnCallDesc({ context: context, fn: fn }, args)); | ||
return effect(CALL, getFnCallDesc('apply', { context: context, fn: fn }, args)); | ||
} | ||
@@ -421,3 +641,3 @@ | ||
return effect(CPS, getFnCallDesc(fn, args)); | ||
return effect(CPS, getFnCallDesc('cps', fn, args)); | ||
} | ||
@@ -430,5 +650,15 @@ | ||
return effect(FORK, getFnCallDesc(fn, args)); | ||
return effect(FORK, getFnCallDesc('fork', fn, args)); | ||
} | ||
function spawn(fn) { | ||
for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | ||
args[_key4 - 1] = arguments[_key4]; | ||
} | ||
var eff = fork.apply(undefined, [fn].concat(args)); | ||
eff[FORK].detached = true; | ||
return eff; | ||
} | ||
var isForkedTask = function isForkedTask(task) { | ||
@@ -438,17 +668,19 @@ return task[_utils.TASK]; | ||
function join(taskDesc) { | ||
if (!isForkedTask(taskDesc)) throw new Error(JOIN_ARG_ERROR); | ||
function join(task) { | ||
(0, _utils.check)(task, _utils.is.notUndef, 'join(task): argument task is undefined'); | ||
if (!isForkedTask(task)) throw new Error('join(task): argument ' + task + ' is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)'); | ||
return effect(JOIN, taskDesc); | ||
return effect(JOIN, task); | ||
} | ||
function cancel(taskDesc) { | ||
if (!isForkedTask(taskDesc)) throw new Error(CANCEL_ARG_ERROR); | ||
function cancel(task) { | ||
(0, _utils.check)(task, _utils.is.notUndef, 'cancel(task): argument task is undefined'); | ||
if (!isForkedTask(task)) throw new Error('cancel(task): argument ' + task + ' is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)'); | ||
return effect(CANCEL, taskDesc); | ||
return effect(CANCEL, task); | ||
} | ||
function select(selector) { | ||
for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | ||
args[_key4 - 1] = arguments[_key4]; | ||
for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { | ||
args[_key5 - 1] = arguments[_key5]; | ||
} | ||
@@ -459,3 +691,4 @@ | ||
} else { | ||
(0, _utils.check)(selector, _utils.is.func, SELECT_ARG_ERROR); | ||
(0, _utils.check)(select, _utils.is.notUndef, 'select(selector,[...]): argument selector is undefined'); | ||
(0, _utils.check)(selector, _utils.is.func, 'select(selector,[...]): argument ' + selector + ' is not a function'); | ||
} | ||
@@ -465,2 +698,19 @@ return effect(SELECT, { selector: selector, args: args }); | ||
/** | ||
channel(pattern, [buffer]) => creates an event channel for store actions | ||
**/ | ||
function actionChannel(pattern, buffer) { | ||
(0, _utils.check)(pattern, _utils.is.notUndef, 'actionChannel(pattern,...): argument pattern is undefined'); | ||
if (arguments.length > 1) { | ||
(0, _utils.check)(buffer, _utils.is.notUndef, 'actionChannel(pattern, buffer): argument buffer is undefined'); | ||
(0, _utils.check)(buffer, _utils.is.notUndef, 'actionChannel(pattern, buffer): argument ' + buffer + ' is not a valid buffer'); | ||
} | ||
return effect(ACTION_CHANNEL, { pattern: pattern, buffer: buffer }); | ||
} | ||
function cancelled() { | ||
return effect(CANCELLED, {}); | ||
} | ||
var asEffect = exports.asEffect = { | ||
@@ -493,2 +743,8 @@ take: function take(effect) { | ||
return effect && effect[IO] && effect[SELECT]; | ||
}, | ||
actionChannel: function actionChannel(effect) { | ||
return effect && effect[IO] && effect[ACTION_CHANNEL]; | ||
}, | ||
cancelled: function cancelled(effect) { | ||
return effect && effect[IO] && effect[CANCELLED]; | ||
} | ||
@@ -499,3 +755,3 @@ }; | ||
/* 4 */ | ||
/***/ function(module, exports) { | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -507,31 +763,61 @@ 'use strict'; | ||
}); | ||
exports.effectTriggered = effectTriggered; | ||
exports.effectResolved = effectResolved; | ||
exports.effectRejected = effectRejected; | ||
exports.buffers = exports.BUFFER_OVERFLOW = undefined; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var _utils = __webpack_require__(1); | ||
var MONITOR_ACTION = exports.MONITOR_ACTION = 'MONITOR_ACTION'; | ||
var EFFECT_TRIGGERED = exports.EFFECT_TRIGGERED = 'EFFECT_TRIGGERED'; | ||
var EFFECT_RESOLVED = exports.EFFECT_RESOLVED = 'EFFECT_RESOLVED'; | ||
var EFFECT_REJECTED = exports.EFFECT_REJECTED = 'EFFECT_REJECTED'; | ||
var BUFFER_OVERFLOW = exports.BUFFER_OVERFLOW = 'Channel\'s Buffer overflow!'; | ||
function effectTriggered(effectId, parentEffectId, label, effect) { | ||
var _ref; | ||
var ON_OVERFLOW_THROW = 1; | ||
var ON_OVERFLOW_DROP = 2; | ||
var ON_OVERFLOW_SLIDE = 3; | ||
return _ref = {}, _defineProperty(_ref, MONITOR_ACTION, true), _defineProperty(_ref, 'type', EFFECT_TRIGGERED), _defineProperty(_ref, 'effectId', effectId), _defineProperty(_ref, 'parentEffectId', parentEffectId), _defineProperty(_ref, 'label', label), _defineProperty(_ref, 'effect', effect), _ref; | ||
} | ||
var zeroBuffer = { isEmpty: _utils.kTrue, put: _utils.noop, take: _utils.noop }; | ||
function effectResolved(effectId, result) { | ||
var _ref2; | ||
/** | ||
TODO: Need to make a more optimized implementation: e.g. Ring buffers, linked lists with Node Object pooling... | ||
**/ | ||
function arrBuffer() { | ||
var limit = arguments.length <= 0 || arguments[0] === undefined ? Infinity : arguments[0]; | ||
var overflowAction = arguments[1]; | ||
return _ref2 = {}, _defineProperty(_ref2, MONITOR_ACTION, true), _defineProperty(_ref2, 'type', EFFECT_RESOLVED), _defineProperty(_ref2, 'effectId', effectId), _defineProperty(_ref2, 'result', result), _ref2; | ||
var arr = []; | ||
return { | ||
isEmpty: function isEmpty() { | ||
return !arr.length; | ||
}, | ||
put: function put(it) { | ||
if (arr.length < limit) arr.push(it);else { | ||
switch (overflowAction) { | ||
case ON_OVERFLOW_THROW: | ||
throw new Error(BUFFER_OVERFLOW); | ||
case ON_OVERFLOW_SLIDE: | ||
arr.shift(); | ||
arr.push(it); | ||
break; | ||
default: | ||
// DROP | ||
} | ||
} | ||
}, | ||
take: function take() { | ||
return arr.shift(); | ||
} | ||
}; | ||
} | ||
function effectRejected(effectId, error) { | ||
var _ref3; | ||
var buffers = exports.buffers = { | ||
none: function none() { | ||
return zeroBuffer; | ||
}, | ||
fixed: function fixed(limit) { | ||
return arrBuffer(limit, ON_OVERFLOW_THROW); | ||
}, | ||
drop: function drop(limit) { | ||
return arrBuffer(limit, ON_OVERFLOW_DROP); | ||
}, | ||
slide: function slide(limit) { | ||
return arrBuffer(limit, ON_OVERFLOW_SLIDE); | ||
} | ||
}; | ||
return _ref3 = {}, _defineProperty(_ref3, MONITOR_ACTION, true), _defineProperty(_ref3, 'type', EFFECT_REJECTED), _defineProperty(_ref3, 'effectId', effectId), _defineProperty(_ref3, 'error', error), _ref3; | ||
} | ||
/***/ }, | ||
@@ -546,3 +832,3 @@ /* 5 */ | ||
}); | ||
exports.MANUAL_CANCEL = exports.RACE_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.CANCEL = exports.undefindInputError = exports.NOT_ITERATOR_ERROR = undefined; | ||
exports.Never = exports.CANCEL = exports.NOT_ITERATOR_ERROR = undefined; | ||
exports.default = proc; | ||
@@ -552,15 +838,15 @@ | ||
var _io = __webpack_require__(3); | ||
var _asap = __webpack_require__(7); | ||
var _monitorActions = __webpack_require__(4); | ||
var _asap2 = _interopRequireDefault(_asap); | ||
var monitorActions = _interopRequireWildcard(_monitorActions); | ||
var _io = __webpack_require__(3); | ||
var _SagaCancellationException = __webpack_require__(2); | ||
var _channel = __webpack_require__(2); | ||
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException); | ||
var _buffers = __webpack_require__(4); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
function _defineEnumerableProperties(obj, descs) { for (var key in descs) { var desc = descs[key]; desc.configurable = desc.enumerable = true; if ("value" in desc) desc.writable = true; Object.defineProperty(obj, key, desc); } return obj; } | ||
@@ -572,13 +858,106 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator'; | ||
var undefindInputError = exports.undefindInputError = function undefindInputError(name) { | ||
return '\n ' + name + ' saga was provided with an undefined input action\n Hints :\n - check that your Action Creator returns a non undefined value\n - if the Saga was started using runSaga, check that your subscribe source provides the action to its listeners\n'; | ||
}; | ||
var CANCEL = exports.CANCEL = (0, _utils.sym)('@@redux-saga/cancelPromise'); | ||
var PARALLEL_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = 'PARALLEL_AUTO_CANCEL'; | ||
var RACE_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = 'RACE_AUTO_CANCEL'; | ||
var MANUAL_CANCEL = exports.MANUAL_CANCEL = 'MANUAL_CANCEL'; | ||
var CANCEL = exports.CANCEL = (0, _utils.sym)('cancelPromise'); | ||
var nextEffectId = (0, _utils.autoInc)(); | ||
var Never = exports.Never = { | ||
toString: function toString() { | ||
return '@@redux-saga/Never'; | ||
} | ||
}; | ||
Object.freeze(Never); | ||
var matchers = { | ||
wildcard: function wildcard() { | ||
return _utils.kTrue; | ||
}, | ||
default: function _default(pattern) { | ||
return function (input) { | ||
return input.type === pattern; | ||
}; | ||
}, | ||
array: function array(patterns) { | ||
return function (input) { | ||
return patterns.some(function (p) { | ||
return p === input.type; | ||
}); | ||
}; | ||
}, | ||
predicate: function predicate(_predicate) { | ||
return function (input) { | ||
return _predicate(input); | ||
}; | ||
} | ||
}; | ||
function matcher(pattern) { | ||
return (pattern === '*' ? matchers.wildcard : _utils.is.array(pattern) ? matchers.array : _utils.is.func(pattern) ? matchers.predicate : matchers.default)(pattern); | ||
} | ||
/** | ||
Used to track a parent task and its forks | ||
In the new fork model, forked tasks are attached by default to their parent | ||
We model this using the concept of Parent task && main Task | ||
main task is the main flow of the current Generator, the parent tasks is the | ||
aggregation of the main tasks + all its forked tasks. | ||
Thus the whole model represents an execution tree with multiple branches (vs the | ||
linear execution tree in sequential (non parallel) programming) | ||
A parent tasks has the following semantics | ||
- It completes iff all its forks either complete or all cancelled | ||
- If it's cancelled, all forks are cancelled as well | ||
- It aborts if any uncaught error bubbles up from forks | ||
- If it completes, the return value is the one returned by the main task | ||
**/ | ||
function forkQueue(name, mainTask, cb) { | ||
var tasks = [], | ||
result = void 0, | ||
completed = false; | ||
addTask(mainTask); | ||
function addTask(task) { | ||
tasks.push(task); | ||
task.cont = function (err, res) { | ||
if (completed) return; | ||
(0, _utils.remove)(tasks, task); | ||
task.cont = _utils.noop; | ||
if (err) { | ||
cancelAll(); | ||
cb(err); | ||
} else { | ||
if (task === mainTask) result = res; | ||
if (!tasks.length) { | ||
completed = true; | ||
cb(null, result); | ||
} | ||
} | ||
}; | ||
//task.cont.cancel = task.cancel | ||
} | ||
function cancelAll() { | ||
if (completed) return; | ||
completed = true; | ||
tasks.forEach(function (t) { | ||
t.cont = _utils.noop; | ||
t.cancel(); | ||
}); | ||
tasks = []; | ||
} | ||
return { | ||
addTask: addTask, | ||
cancelAll: cancelAll, | ||
getTasks: function getTasks() { | ||
return tasks; | ||
}, | ||
taskNames: function taskNames() { | ||
return tasks.map(function (t) { | ||
return t.name; | ||
}); | ||
} | ||
}; | ||
} | ||
function proc(iterator) { | ||
@@ -590,6 +969,6 @@ var subscribe = arguments.length <= 1 || arguments[1] === undefined ? function () { | ||
var getState = arguments.length <= 3 || arguments[3] === undefined ? _utils.noop : arguments[3]; | ||
var monitor = arguments.length <= 4 || arguments[4] === undefined ? _utils.noop : arguments[4]; | ||
var monitor = arguments[4]; | ||
var parentEffectId = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5]; | ||
var name = arguments.length <= 6 || arguments[6] === undefined ? 'anonymous' : arguments[6]; | ||
var forked = arguments[7]; | ||
var cont = arguments[7]; | ||
@@ -599,28 +978,5 @@ | ||
var UNDEFINED_INPUT_ERROR = undefindInputError(name); | ||
// tracks the current `take` effects | ||
var deferredInputs = []; | ||
// Promise to be resolved/rejected when this generator terminates (or throws) | ||
var deferredEnd = (0, _utils.deferred)(); | ||
// subscribe to input events, this will resolve the current `take` effects | ||
var unsubscribe = subscribe(function (input) { | ||
if (input === undefined) throw UNDEFINED_INPUT_ERROR; | ||
for (var i = 0; i < deferredInputs.length; i++) { | ||
var def = deferredInputs[i]; | ||
if (def.match(input)) { | ||
// cancel all deferredInputs; parallel takes are disallowed | ||
// and in concurrent takes, first wins | ||
deferredInputs = []; | ||
def.resolve(input); | ||
} | ||
} | ||
}); | ||
var stdChannel = (0, _channel.eventChannel)(subscribe); | ||
/** | ||
cancel : (SagaCancellationException) -> () | ||
Tracks the current effect cancellation | ||
Tracks the current effect cancellation | ||
Each time the generator progresses. calling runEffect will set a new value | ||
@@ -632,19 +988,46 @@ on it. It allows propagating cancellation to child effects | ||
/** | ||
Creates a new task descriptor for this generator | ||
Creates a new task descriptor for this generator, We'll also create a main task | ||
to track the main flow (besides other forked tasks) | ||
**/ | ||
var task = newTask(parentEffectId, name, iterator, deferredEnd.promise, forked); | ||
var task = newTask(parentEffectId, name, iterator, cont); | ||
var mainTask = { name: name, cancel: cancelMain, isRunning: true }; | ||
var taskQueue = forkQueue(name, mainTask, end); | ||
/** | ||
cancellation of the main task. We'll simply resume the Generator with a Cancel | ||
**/ | ||
function cancelMain() { | ||
if (mainTask.isRunning && !mainTask.isCancelled) { | ||
mainTask.isCancelled = true; | ||
next(null, Never); | ||
} | ||
} | ||
/** | ||
This may be called by a parent generator to trigger/propagate cancellation | ||
We'll simply cancel the current effect, which will reject that effect | ||
The rejection will throw the injected SagaCancellationException into the flow | ||
of this generator | ||
cancel all pending tasks (including the main task), then end the current task. | ||
Cancellation propagates down to the whole execution tree holded by this Parent task | ||
It's also propagated to all joiners of this task and their execution tree/joiners | ||
Cancellation is noop for terminated/Cancelled tasks tasks | ||
**/ | ||
task.done[CANCEL] = function (_ref) { | ||
var type = _ref.type; | ||
var origin = _ref.origin; | ||
function cancel() { | ||
/** | ||
We need to check both Running and Cancelled status | ||
Tasks can be Cancelled but still Running | ||
**/ | ||
if (iterator._isRunning && !iterator._isCancelled) { | ||
iterator._isCancelled = true; | ||
taskQueue.cancelAll(); | ||
/** | ||
Ending with a Never result will propagate the Cancellation to all joiners | ||
**/ | ||
end(null, Never); | ||
} | ||
} | ||
/** | ||
attaches cancellation logic to this task's continuation | ||
this will permit cancellation to propagate down the call chain | ||
**/ | ||
cont && (cont.cancel = cancel); | ||
next.cancel(new _SagaCancellationException2.default(type, name, origin)); | ||
}; | ||
// tracks the running status | ||
@@ -660,16 +1043,2 @@ iterator._isRunning = true; | ||
/** | ||
Print error in a useful way whether in a browser environment | ||
(with expandable error stack traces), or in a node.js environment | ||
(text-only log output) | ||
**/ | ||
function logError(level, message, error) { | ||
/*eslint-disable no-console*/ | ||
if (typeof window === 'undefined') { | ||
console.log('redux-saga ' + level + ': ' + message + '\n' + error.stack); | ||
} else { | ||
console[level].call(console, message, error); | ||
} | ||
} | ||
/** | ||
This is the generator driver | ||
@@ -681,38 +1050,60 @@ It's a recursive async/continuation function which calls itself | ||
// Preventive measure. If we end up here, then there is really something wrong | ||
if (!iterator._isRunning) throw new Error('Trying to resume an already finished generator'); | ||
if (!mainTask.isRunning) throw new Error('Trying to resume an already finished generator'); | ||
try { | ||
// calling iterator.throw on a generator that doesn't define a correponding try/Catch | ||
// will throw an exception and jump to the catch block below | ||
var result = error ? iterator.throw(error) : iterator.next(arg); | ||
var result = void 0; | ||
if (error) result = iterator.throw(error);else if (arg === Never) { | ||
/** | ||
getting Never autoamtically cancels the main task | ||
We can get this value here | ||
- By cancelling the parent task manually | ||
- By joining a Cancelled task | ||
- By taking from a channel that ended using `take` (and not `takem` used to trap End of channels) | ||
**/ | ||
mainTask.isCancelled = true; | ||
/** | ||
Cancels the current effect; this will propagate the cancellation down to any called tasks | ||
**/ | ||
next.cancel(); | ||
/** | ||
If this Generator has a `return` method then invokes it | ||
Thill will jump to the finally block | ||
**/ | ||
result = _utils.is.func(iterator.return) ? iterator.return(Never) : { done: true, value: Never }; | ||
} else result = iterator.next(arg); | ||
if (!result.done) { | ||
runEffect(result.value, parentEffectId, '', next); | ||
} else { | ||
end(result.value); | ||
/** | ||
This Generator has ended, terminate the main task and notify the fork queue | ||
**/ | ||
mainTask.isMainRunning = false; | ||
mainTask.cont && mainTask.cont(null, result.value); | ||
} | ||
} catch (error) { | ||
end(error, true); | ||
if (error instanceof _SagaCancellationException2.default) { | ||
if (_utils.isDev) { | ||
logError('warn', name + ': uncaught', error); | ||
} | ||
} else { | ||
logError('error', name + ': uncaught', error); | ||
//if(!forked) | ||
// throw error | ||
} | ||
if (mainTask.isCancelled) (0, _utils.log)('error', 'uncaught at ' + name, error.message); | ||
mainTask.isMainRunning = false; | ||
mainTask.cont(error); | ||
} | ||
} | ||
function end(result, isError) { | ||
function end(error, result) { | ||
iterator._isRunning = false; | ||
if (!isError) { | ||
stdChannel.close(); | ||
if (!error) { | ||
if (result === Never && _utils.isDev) (0, _utils.log)('info', name + ' has been cancelled', ''); | ||
iterator._result = result; | ||
deferredEnd.resolve(result); | ||
iterator._deferredEnd && iterator._deferredEnd.resolve(result); | ||
} else { | ||
iterator._error = result; | ||
deferredEnd.reject(result); | ||
if (error instanceof Error) error.sagaStack = 'at ' + name + ' \n ' + (error.sagaStack || error.message); | ||
if (!task.cont) (0, _utils.log)('error', 'uncaught', error.sagaStack || error.message); | ||
iterator._error = error; | ||
iterator._deferredEnd && iterator._deferredEnd.reject(error); | ||
} | ||
unsubscribe(); | ||
task.cont && task.cont(error, result); | ||
task.joiners.forEach(function (j) { | ||
return j.cb(error, result); | ||
}); | ||
task.joiners = null; | ||
} | ||
@@ -725,3 +1116,3 @@ | ||
var effectId = nextEffectId(); | ||
monitor(monitorActions.effectTriggered(effectId, parentEffectId, label, effect)); | ||
monitor && monitor.effectTriggered({ effectId: effectId, parentEffectId: parentEffectId, label: label, effect: effect }); | ||
@@ -733,3 +1124,3 @@ /** | ||
**/ | ||
var effectSettled = undefined; | ||
var effectSettled = void 0; | ||
@@ -742,3 +1133,5 @@ // Completion callback passed to the appropriate effect runner | ||
cb.cancel = _utils.noop; // defensive measure | ||
err ? monitor(monitorActions.effectRejected(effectId, err)) : monitor(monitorActions.effectResolved(effectId, res)); | ||
if (monitor) { | ||
err ? monitor.effectRejected(effectId, err) : monitor.effectResolved(effectId, res); | ||
} | ||
@@ -751,3 +1144,3 @@ cb(err, res); | ||
// setup cancellation logic on the parent cb | ||
cb.cancel = function (cancelError) { | ||
cb.cancel = function () { | ||
// prevents cancelling an already completed effect | ||
@@ -759,17 +1152,13 @@ if (effectSettled) return; | ||
propagates cancel downward | ||
catch uncaught cancellations errors, | ||
because w'll throw our own cancellation error inside this generator | ||
catch uncaught cancellations errors; since we can no longer call the completion | ||
callback, log errors raised during cancellations into the console | ||
**/ | ||
try { | ||
currCb.cancel(cancelError); | ||
currCb.cancel(); | ||
} catch (err) { | ||
void 0; | ||
(0, _utils.log)('error', 'uncaught at ' + name, err.message); | ||
} | ||
currCb.cancel = _utils.noop; // defensive measure | ||
/** | ||
triggers/propagates the cancellation error | ||
**/ | ||
cb(cancelError); | ||
monitor(monitorActions.effectRejected(effectId, cancelError)); | ||
monitor && monitor.effectCancelled(effectId); | ||
}; | ||
@@ -789,3 +1178,3 @@ | ||
**/ | ||
var data = undefined; | ||
var data = void 0; | ||
return( | ||
@@ -796,3 +1185,3 @@ // Non declarative effect | ||
// declarative effects | ||
: _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.take(effect)) ? runTakeEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.put(effect)) ? runPutEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.race(effect)) ? runRaceEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.call(effect)) ? runCallEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.cps(effect)) ? runCPSEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.fork(effect)) ? runForkEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.join(effect)) ? runJoinEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.cancel(effect)) ? runCancelEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.select(effect)) ? runSelectEffect(data, currCb) : /* anything else returned as is */currCb(null, effect) | ||
: _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.take(effect)) ? runTakeEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.put(effect)) ? runPutEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.race(effect)) ? runRaceEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.call(effect)) ? runCallEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.cps(effect)) ? runCPSEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.fork(effect)) ? runForkEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.join(effect)) ? runJoinEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.cancel(effect)) ? runCancelEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.select(effect)) ? runSelectEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.actionChannel(effect)) ? runChannelEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.cancelled(effect)) ? runCancelledEffect(data, currCb) : /* anything else returned as is */currCb(null, effect) | ||
); | ||
@@ -814,27 +1203,45 @@ } | ||
function resolveIterator(iterator, effectId, name, cb) { | ||
resolvePromise(proc(iterator, subscribe, dispatch, getState, monitor, effectId, name).done, cb); | ||
proc(iterator, subscribe, dispatch, getState, monitor, effectId, name, cb); | ||
} | ||
function runTakeEffect(pattern, cb) { | ||
var def = { | ||
match: (0, _io.matcher)(pattern), | ||
pattern: pattern, | ||
resolve: function resolve(input) { | ||
return cb(null, input); | ||
} | ||
function runTakeEffect(_ref, cb) { | ||
var channel = _ref.channel; | ||
var pattern = _ref.pattern; | ||
var maybe = _ref.maybe; | ||
channel = channel || stdChannel; | ||
var takeCb = function takeCb(inp) { | ||
return inp instanceof Error ? cb(inp) : inp === _channel.END && !maybe ? cb(null, Never) : cb(null, inp); | ||
}; | ||
deferredInputs.push(def); | ||
// cancellation logic for take effect | ||
cb.cancel = function () { | ||
return (0, _utils.remove)(deferredInputs, def); | ||
}; | ||
try { | ||
channel.take(takeCb, matcher(pattern)); | ||
} catch (err) { | ||
return cb(err); | ||
} | ||
cb.cancel = takeCb.cancel; | ||
} | ||
function runPutEffect(action, cb) { | ||
//synchronously nested dispatches can not be performed | ||
// because on a sync interleaved take/put the receiver will dispatch the | ||
// action before the sender can take the aknowledge | ||
// this workaround allows the dispatch to occur on the next microtask | ||
(0, _utils.asap)(function () { | ||
return cb(null, dispatch(action)); | ||
function runPutEffect(_ref2, cb) { | ||
var channel = _ref2.channel; | ||
var action = _ref2.action; | ||
/* | ||
Use a reentrant lock `asap` to flatten all nested dispatches | ||
If this put cause another Saga to take this action an then immediately | ||
put an action that will be taken by this Saga. Then the outer Saga will miss | ||
the action from the inner Saga b/c this put has not yet returned. | ||
*/ | ||
(0, _asap2.default)(function () { | ||
var result = void 0; | ||
try { | ||
result = (channel ? channel.put : dispatch)(action); | ||
} catch (error) { | ||
return cb(error); | ||
} | ||
if (_utils.is.promise(result)) { | ||
resolvePromise(result, cb); | ||
} else { | ||
return cb(null, result); | ||
} | ||
}); | ||
@@ -844,8 +1251,8 @@ // Put effects are non cancellables | ||
function runCallEffect(_ref2, effectId, cb) { | ||
var context = _ref2.context; | ||
var fn = _ref2.fn; | ||
var args = _ref2.args; | ||
function runCallEffect(_ref3, effectId, cb) { | ||
var context = _ref3.context; | ||
var fn = _ref3.fn; | ||
var args = _ref3.args; | ||
var result = undefined; | ||
var result = void 0; | ||
// catch synchronous failures; see #152 | ||
@@ -860,6 +1267,6 @@ try { | ||
function runCPSEffect(_ref3, cb) { | ||
var context = _ref3.context; | ||
var fn = _ref3.fn; | ||
var args = _ref3.args; | ||
function runCPSEffect(_ref4, cb) { | ||
var context = _ref4.context; | ||
var fn = _ref4.fn; | ||
var args = _ref4.args; | ||
@@ -877,10 +1284,11 @@ // CPS (ie node style functions) can define their own cancellation logic | ||
function runForkEffect(_ref4, effectId, cb) { | ||
var context = _ref4.context; | ||
var fn = _ref4.fn; | ||
var args = _ref4.args; | ||
function runForkEffect(_ref5, effectId, cb) { | ||
var context = _ref5.context; | ||
var fn = _ref5.fn; | ||
var args = _ref5.args; | ||
var detached = _ref5.detached; | ||
var result = undefined, | ||
error = undefined, | ||
_iterator = undefined; | ||
var result = void 0, | ||
error = void 0, | ||
_iterator = void 0; | ||
@@ -894,3 +1302,3 @@ // we run the function, next we'll check if this is a generator function | ||
} catch (err) { | ||
error = error; | ||
if (!detached) return cb(err);else error = err; | ||
} | ||
@@ -904,49 +1312,49 @@ | ||
//simple effect: wrap in a generator | ||
// do not bubble up synchronous failures, instead create a failed task. See #152 | ||
// do not bubble up synchronous failures for detached forks, instead create a failed task. See #152 | ||
else { | ||
_iterator = (error ? regeneratorRuntime.mark(function _callee() { | ||
return regeneratorRuntime.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
throw error; | ||
case 1: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
_iterator = error ? (0, _utils.makeIterator)(function () { | ||
throw error; | ||
}) : (0, _utils.makeIterator)(function () { | ||
var pc = void 0; | ||
var eff = { done: false, value: result }; | ||
var ret = function ret(value) { | ||
return { done: true, value: value }; | ||
}; | ||
return function (arg) { | ||
if (!pc) { | ||
pc = true; | ||
return eff; | ||
} else { | ||
return ret(arg); | ||
} | ||
}, _callee, this); | ||
}) : regeneratorRuntime.mark(function _callee2() { | ||
return regeneratorRuntime.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context2.next = 2; | ||
return result; | ||
case 2: | ||
return _context2.abrupt('return', _context2.sent); | ||
case 3: | ||
case 'end': | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2, this); | ||
}))(); | ||
}; | ||
}()); | ||
} | ||
cb(null, proc(_iterator, subscribe, dispatch, getState, monitor, effectId, fn.name, true)); | ||
var task = proc(_iterator, subscribe, dispatch, getState, monitor, effectId, fn.name, detached ? null : _utils.noop); | ||
if (!detached) { | ||
if (_iterator._isRunning) taskQueue.addTask(task);else if (_iterator._error) return cb(_iterator._error); | ||
} | ||
cb(null, task); | ||
// Fork effects are non cancellables | ||
} | ||
function runJoinEffect(task, cb) { | ||
resolvePromise(task.done, cb); | ||
function runJoinEffect(t, cb) { | ||
if (t.isRunning()) { | ||
(function () { | ||
var joiner = { task: task, cb: cb }; | ||
cb.cancel = function () { | ||
return (0, _utils.remove)(t.joiners, joiner); | ||
}; | ||
t.joiners.push(joiner); | ||
})(); | ||
} else { | ||
cb(t.error(), t.result()); | ||
} | ||
} | ||
function runCancelEffect(task, cb) { | ||
// cancel the given task | ||
// uncaught cancellations errors bubbles upward | ||
task.done[CANCEL](new _SagaCancellationException2.default(MANUAL_CANCEL, name, name)); | ||
if (task.isRunning()) { | ||
task.cancel(); | ||
} | ||
cb(); | ||
@@ -956,3 +1364,2 @@ // cancel effects are non cancellables | ||
// Reimplementing Promise.all. We're in 2016 | ||
function runParallelEffect(effects, effectId, cb) { | ||
@@ -965,3 +1372,3 @@ if (!effects.length) { | ||
var completedCount = 0; | ||
var completed = undefined; | ||
var completed = void 0; | ||
var results = Array(effects.length); | ||
@@ -978,17 +1385,6 @@ | ||
var chCbAtIdx = function chCbAtIdx(err, res) { | ||
// Either we've been cancelled, or an error aborted the whole effect | ||
if (completed) return; | ||
// one of the effects failed | ||
if (err) { | ||
// cancel all other effects | ||
// This is an AUTO_CANCEL (not triggered by a manual cancel) | ||
// Catch uncaught cancellation errors, because w'll only throw the actual | ||
// rejection error (err) inside this generator | ||
try { | ||
cb.cancel(new _SagaCancellationException2.default(PARALLEL_AUTO_CANCEL, name, name)); | ||
} catch (err) { | ||
void 0; | ||
} | ||
cb(err); | ||
if (err || res === _channel.END || res === Never) { | ||
cb.cancel(); | ||
err ? cb(err) : cb(null, res); | ||
} else { | ||
@@ -1004,11 +1400,7 @@ results[idx] = res; | ||
// This is different, a cancellation coming from upward | ||
// either a MANUAL_CANCEL or a parent AUTO_CANCEL | ||
// No need to catch, will be swallowed by the caller | ||
cb.cancel = function (cancelError) { | ||
// prevents unnecessary cancellation | ||
cb.cancel = function () { | ||
if (!completed) { | ||
completed = true; | ||
childCbs.forEach(function (chCb) { | ||
return chCb.cancel(cancelError); | ||
return chCb.cancel(); | ||
}); | ||
@@ -1023,5 +1415,4 @@ } | ||
// And yet; Promise.race | ||
function runRaceEffect(effects, effectId, cb) { | ||
var completed = undefined; | ||
var completed = void 0; | ||
var keys = Object.keys(effects); | ||
@@ -1032,3 +1423,2 @@ var childCbs = {}; | ||
var chCbAtKey = function chCbAtKey(err, res) { | ||
// Either we've been cancelled, or an error aborted the whole effect | ||
if (completed) return; | ||
@@ -1038,15 +1428,6 @@ | ||
// Race Auto cancellation | ||
try { | ||
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name)); | ||
} catch (err) { | ||
void 0; | ||
} | ||
cb(_defineProperty({}, key, err)); | ||
} else { | ||
try { | ||
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name)); | ||
} catch (err) { | ||
void 0; | ||
} | ||
cb.cancel(); | ||
cb(err); | ||
} else if (res !== _channel.END && res !== Never) { | ||
cb.cancel(); | ||
completed = true; | ||
@@ -1060,3 +1441,3 @@ cb(null, _defineProperty({}, key, res)); | ||
cb.cancel = function (cancelError) { | ||
cb.cancel = function () { | ||
// prevents unnecessary cancellation | ||
@@ -1066,3 +1447,3 @@ if (!completed) { | ||
keys.forEach(function (key) { | ||
return childCbs[key].cancel(cancelError); | ||
return childCbs[key].cancel(); | ||
}); | ||
@@ -1076,5 +1457,5 @@ } | ||
function runSelectEffect(_ref5, cb) { | ||
var selector = _ref5.selector; | ||
var args = _ref5.args; | ||
function runSelectEffect(_ref6, cb) { | ||
var selector = _ref6.selector; | ||
var args = _ref6.args; | ||
@@ -1089,17 +1470,35 @@ try { | ||
function newTask(id, name, iterator, done, forked) { | ||
var _ref6; | ||
function runChannelEffect(_ref7, cb) { | ||
var pattern = _ref7.pattern; | ||
var buffer = _ref7.buffer; | ||
return _ref6 = {}, _defineProperty(_ref6, _utils.TASK, true), _defineProperty(_ref6, 'id', id), _defineProperty(_ref6, 'name', name), _defineProperty(_ref6, 'done', done), _defineProperty(_ref6, 'forked', forked), _defineProperty(_ref6, 'cancel', function cancel(error) { | ||
if (!(error instanceof _SagaCancellationException2.default)) { | ||
error = new _SagaCancellationException2.default(MANUAL_CANCEL, name, error); | ||
var match = matcher(pattern); | ||
match.pattern = pattern; | ||
cb(null, (0, _channel.eventChannel)(subscribe, buffer || _buffers.buffers.fixed(), match)); | ||
} | ||
function runCancelledEffect(data, cb) { | ||
cb(null, !!mainTask.isCancelled); | ||
} | ||
function newTask(id, name, iterator, cont) { | ||
var _done, _ref8, _mutatorMap; | ||
iterator._deferredEnd = null; | ||
return _ref8 = {}, _defineProperty(_ref8, _utils.TASK, true), _defineProperty(_ref8, 'id', id), _defineProperty(_ref8, 'name', name), _done = 'done', _mutatorMap = {}, _mutatorMap[_done] = _mutatorMap[_done] || {}, _mutatorMap[_done].get = function () { | ||
if (iterator._deferredEnd) return iterator._deferredEnd.promise;else { | ||
var def = (0, _utils.deferred)(); | ||
iterator._deferredEnd = def; | ||
if (!iterator._isRunning) iterator._error ? def.reject(iterator._error) : def.resolve(iterator._result); | ||
return def.promise; | ||
} | ||
done[CANCEL](error); | ||
}), _defineProperty(_ref6, 'isRunning', function isRunning() { | ||
}, _defineProperty(_ref8, 'cont', cont), _defineProperty(_ref8, 'joiners', []), _defineProperty(_ref8, 'cancel', cancel), _defineProperty(_ref8, 'isRunning', function isRunning() { | ||
return iterator._isRunning; | ||
}), _defineProperty(_ref6, 'result', function result() { | ||
}), _defineProperty(_ref8, 'isCancelled', function isCancelled() { | ||
return iterator._isCancelled; | ||
}), _defineProperty(_ref8, 'result', function result() { | ||
return iterator._result; | ||
}), _defineProperty(_ref6, 'error', function error() { | ||
}), _defineProperty(_ref8, 'error', function error() { | ||
return iterator._error; | ||
}), _ref6; | ||
}), _defineEnumerableProperties(_ref8, _mutatorMap), _ref8; | ||
} | ||
@@ -1117,34 +1516,95 @@ } | ||
}); | ||
exports.default = emitter; | ||
var _utils = __webpack_require__(1); | ||
var _io = __webpack_require__(3); | ||
function emitter() { | ||
var cbs = []; | ||
function subscribe(cb) { | ||
cbs.push(cb); | ||
return function () { | ||
return (0, _utils.remove)(cbs, cb); | ||
}; | ||
Object.defineProperty(exports, 'take', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.take; | ||
} | ||
function emit(item) { | ||
cbs.slice().forEach(function (cb) { | ||
return cb(item); | ||
}); | ||
}); | ||
Object.defineProperty(exports, 'takem', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.takem; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'put', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.put; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'race', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.race; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'call', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.call; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'apply', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.apply; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'cps', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.cps; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'fork', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.fork; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'spawn', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.spawn; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'join', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.join; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'cancel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.cancel; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'select', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.select; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'actionChannel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.actionChannel; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'cancelled', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.cancelled; | ||
} | ||
}); | ||
return { | ||
subscribe: subscribe, | ||
emit: emit | ||
}; | ||
} | ||
/***/ }, | ||
/* 7 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ function(module, exports) { | ||
'use strict'; | ||
"use strict"; | ||
@@ -1154,16 +1614,26 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.select = exports.cancel = exports.join = exports.fork = exports.cps = exports.apply = exports.call = exports.race = exports.put = exports.take = undefined; | ||
exports.default = asap; | ||
var queue = []; | ||
var isSuspended = false; | ||
var _io = __webpack_require__(3); | ||
function asap(task) { | ||
if (!isSuspended) { | ||
isSuspended = true; | ||
queue.push(task); | ||
asap.flush(); | ||
} else { | ||
queue.push(task); | ||
} | ||
} | ||
exports.take = _io.take; | ||
exports.put = _io.put; | ||
exports.race = _io.race; | ||
exports.call = _io.call; | ||
exports.apply = _io.apply; | ||
exports.cps = _io.cps; | ||
exports.fork = _io.fork; | ||
exports.join = _io.join; | ||
exports.cancel = _io.cancel; | ||
exports.select = _io.select; | ||
asap.suspend = function () { | ||
return isSuspended = true; | ||
}; | ||
asap.flush = function () { | ||
var nextTask = void 0; | ||
while (nextTask = queue.shift()) { | ||
nextTask(); | ||
} | ||
isSuspended = false; | ||
}; | ||
@@ -1179,3 +1649,2 @@ /***/ }, | ||
}); | ||
exports.GET_STATE_DEPRECATED_WARNING = exports.RUN_SAGA_DYNAMIC_ERROR = exports.sagaArgError = undefined; | ||
exports.default = sagaMiddlewareFactory; | ||
@@ -1189,33 +1658,15 @@ | ||
var _emitter = __webpack_require__(6); | ||
var _channel = __webpack_require__(2); | ||
var _emitter2 = _interopRequireDefault(_emitter); | ||
var _monitorActions = __webpack_require__(4); | ||
var _SagaCancellationException = __webpack_require__(2); | ||
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var sagaArgError = exports.sagaArgError = function sagaArgError(fn, pos, saga) { | ||
return '\n ' + fn + ' can only be called on Generator functions\n Argument ' + saga + ' at position ' + pos + ' is not function!\n'; | ||
}; | ||
function sagaMiddlewareFactory() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
var RUN_SAGA_DYNAMIC_ERROR = exports.RUN_SAGA_DYNAMIC_ERROR = 'Before running a Saga dynamically using middleware.run, you must mount the Saga middleware on the Store using applyMiddleware'; | ||
var runSagaDynamically = void 0; | ||
var GET_STATE_DEPRECATED_WARNING = exports.GET_STATE_DEPRECATED_WARNING = '\n Using the \'getState\' param of Sagas to access the state is deprecated since 0.9.1\n To access the Store\'s state use \'yield select()\' instead\n For more infos see http://yelouafi.github.io/redux-saga/docs/api/index.html#selectselector-args\n'; | ||
function sagaMiddlewareFactory() { | ||
for (var _len = arguments.length, sagas = Array(_len), _key = 0; _key < _len; _key++) { | ||
sagas[_key] = arguments[_key]; | ||
if (_utils.is.func(options)) { | ||
throw new Error('You passed a function to the Saga middleware. You are likely trying to start a Saga by directly passing it to the middleware. This is no longer possible starting from 0.10.0. To run a Saga, you must do it dynamically AFTER mounting the middleware into the store.\n Example:\n import createSagaMiddleware from \'redux-saga\'\n ... other imports\n\n const sagaMiddleware = createSagaMiddleware()\n const store = createStore(reducer, applyMiddleware(sagaMiddleware))\n sagaMiddleware.run(saga, ...args)\n '); | ||
} | ||
var runSagaDynamically = undefined; | ||
sagas.forEach(function (saga, idx) { | ||
return (0, _utils.check)(saga, _utils.is.func, sagaArgError('createSagaMiddleware', idx, saga)); | ||
}); | ||
function sagaMiddleware(_ref) { | ||
@@ -1225,32 +1676,17 @@ var getState = _ref.getState; | ||
var sagaEmitter = (0, _emitter2.default)(); | ||
var monitor = _utils.isDev ? function (action) { | ||
return (0, _utils.asap)(function () { | ||
return dispatch(action); | ||
}); | ||
} : undefined; | ||
runSagaDynamically = runSaga; | ||
var sagaEmitter = (0, _channel.emitter)(); | ||
var getStateDeprecated = function getStateDeprecated() { | ||
(0, _utils.warnDeprecated)(GET_STATE_DEPRECATED_WARNING); | ||
return getState(); | ||
}; | ||
function runSaga(saga) { | ||
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
args[_key2 - 1] = arguments[_key2]; | ||
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
args[_key - 1] = arguments[_key]; | ||
} | ||
return (0, _proc2.default)(saga.apply(undefined, [getStateDeprecated].concat(args)), sagaEmitter.subscribe, dispatch, getState, monitor, 0, saga.name); | ||
return (0, _proc2.default)(saga.apply(undefined, args), sagaEmitter.subscribe, dispatch, getState, options.sagaMonitor, 0, saga.name); | ||
} | ||
runSagaDynamically = runSaga; | ||
sagas.forEach(runSaga); | ||
return function (next) { | ||
return function (action) { | ||
var result = next(action); // hit reducers | ||
// filter out monitor actions to avoid endless loops | ||
// see https://github.com/yelouafi/redux-saga/issues/61 | ||
if (!action[_monitorActions.MONITOR_ACTION]) sagaEmitter.emit(action); | ||
sagaEmitter.emit(action); | ||
return result; | ||
@@ -1262,16 +1698,9 @@ }; | ||
sagaMiddleware.run = function (saga) { | ||
for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { | ||
args[_key3 - 1] = arguments[_key3]; | ||
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
args[_key2 - 1] = arguments[_key2]; | ||
} | ||
if (!runSagaDynamically) { | ||
throw new Error(RUN_SAGA_DYNAMIC_ERROR); | ||
} | ||
(0, _utils.check)(saga, _utils.is.func, sagaArgError('sagaMiddleware.run', 0, saga)); | ||
var task = runSagaDynamically.apply(undefined, [saga].concat(args)); | ||
task.done.catch(function (err) { | ||
if (!(err instanceof _SagaCancellationException2.default)) throw err; | ||
}); | ||
return task; | ||
(0, _utils.check)(runSagaDynamically, _utils.is.notUndef, 'Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware'); | ||
(0, _utils.check)(saga, _utils.is.func, 'sagaMiddleware.run(saga, ...args): saga argument must be a Generator function!'); | ||
return runSagaDynamically.apply(undefined, [saga].concat(args)); | ||
}; | ||
@@ -1291,4 +1720,2 @@ | ||
}); | ||
exports.NOT_ITERATOR_ERROR = undefined; | ||
exports.storeIO = storeIO; | ||
exports.runSaga = runSaga; | ||
@@ -1302,50 +1729,11 @@ | ||
var _emitter = __webpack_require__(6); | ||
var _emitter2 = _interopRequireDefault(_emitter); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = "runSaga must be called on an iterator"; | ||
/** | ||
@deprecated | ||
ATTENTION! this method can have some potential issues | ||
For more infos, see issue https://github.com/yelouafi/redux-saga/issues/48 | ||
memoize the result of storeChannel. It avoids monkey patching the same store | ||
multiple times unnecessarly. We need only one channel per store | ||
**/ | ||
var IO = (0, _utils.sym)('IO'); | ||
function storeIO(store) { | ||
(0, _utils.warnDeprecated)('storeIO is deprecated, to run Saga dynamically, use \'run\' method of the middleware'); | ||
if (store[IO]) return store[IO]; | ||
var storeEmitter = (0, _emitter2.default)(); | ||
var _dispatch = store.dispatch; | ||
store.dispatch = function (action) { | ||
var result = _dispatch(action); | ||
storeEmitter.emit(action); | ||
return result; | ||
}; | ||
store[IO] = { | ||
subscribe: storeEmitter.subscribe, | ||
dispatch: store.dispatch, | ||
getState: store.getState | ||
}; | ||
return store[IO]; | ||
} | ||
function runSaga(iterator, _ref) { | ||
function runSaga(iterator, _ref, monitor) { | ||
var subscribe = _ref.subscribe; | ||
var dispatch = _ref.dispatch; | ||
var getState = _ref.getState; | ||
var monitor = arguments.length <= 2 || arguments[2] === undefined ? _utils.noop : arguments[2]; | ||
(0, _utils.check)(iterator, _utils.is.iterator, NOT_ITERATOR_ERROR); | ||
(0, _utils.check)(iterator, _utils.is.iterator, "runSaga must be called on an iterator"); | ||
@@ -1370,2 +1758,4 @@ return (0, _proc2.default)(iterator, subscribe, dispatch, getState, monitor); | ||
var _channel = __webpack_require__(2); | ||
var _utils = __webpack_require__(1); | ||
@@ -1375,54 +1765,37 @@ | ||
var _SagaCancellationException = __webpack_require__(2); | ||
var done = { done: true, value: undefined }; | ||
var qEnd = {}; | ||
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var resume = function resume(fnOrValue, arg) { | ||
return _utils.is.func(fnOrValue) ? fnOrValue(arg) : fnOrValue; | ||
}; | ||
var done = { done: true }; | ||
function fsmIterator(fsm, nextState) { | ||
function fsmIterator(fsm, q0) { | ||
var name = arguments.length <= 2 || arguments[2] === undefined ? 'iterator' : arguments[2]; | ||
var aborted = undefined, | ||
updateState = undefined; | ||
var updateState = void 0, | ||
qNext = q0; | ||
function next(arg, error) { | ||
if (aborted) return done; | ||
if (qNext === qEnd) return done; | ||
if (error) { | ||
aborted = true; | ||
if (!(error instanceof _SagaCancellationException2.default)) throw error; | ||
return done; | ||
qNext = qEnd; | ||
throw error; | ||
} else { | ||
if (updateState) updateState(arg); | ||
updateState && updateState(arg); | ||
var _fsm$nextState = _slicedToArray(fsm[nextState], 3); | ||
var _fsm$qNext = fsm[qNext](); | ||
var output = _fsm$nextState[0]; | ||
var transition = _fsm$nextState[1]; | ||
var _updateState = _fsm$nextState[2]; | ||
var _fsm$qNext2 = _slicedToArray(_fsm$qNext, 3); | ||
var q = _fsm$qNext2[0]; | ||
var output = _fsm$qNext2[1]; | ||
var _updateState = _fsm$qNext2[2]; | ||
qNext = q; | ||
updateState = _updateState; | ||
nextState = resume(transition, arg); | ||
return resume(output, arg); | ||
return qNext === qEnd ? done : output; | ||
} | ||
} | ||
var iterator = { | ||
name: name, | ||
next: next, | ||
throw: function _throw(error) { | ||
return next(null, error); | ||
} | ||
}; | ||
if (typeof Symbol !== 'undefined') { | ||
iterator[Symbol.iterator] = function () { | ||
return iterator; | ||
}; | ||
} | ||
return iterator; | ||
return (0, _utils.makeIterator)(next, function (error) { | ||
return next(null, error); | ||
}, name); | ||
} | ||
@@ -1435,11 +1808,19 @@ | ||
var yieldTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yieldFork = function yieldFork(action) { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [action])) }; | ||
var yTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yFork = function yFork(ac) { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [ac])) }; | ||
}; | ||
var action = void 0, | ||
setAction = function setAction(ac) { | ||
return action = ac; | ||
}; | ||
return fsmIterator({ | ||
'take': [yieldTake, 'fork'], | ||
'fork': [yieldFork, 'take'] | ||
}, 'take', 'takeEvery(' + pattern + ', ' + worker.name + ')'); | ||
q1: function q1() { | ||
return ['q2', yTake, setAction]; | ||
}, | ||
q2: function q2() { | ||
return action === _channel.END ? [qEnd] : ['q1', yFork(action)]; | ||
} | ||
}, 'q1', 'takeEvery(' + String(pattern) + ', ' + worker.name + ')'); | ||
} | ||
@@ -1452,24 +1833,29 @@ | ||
var yieldTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yieldFork = function yieldFork() { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [currentAction])) }; | ||
var yTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yFork = function yFork(ac) { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [ac])) }; | ||
}; | ||
var yieldCancel = function yieldCancel() { | ||
return { done: false, value: (0, _io.cancel)(currentTask) }; | ||
var yCancel = function yCancel(task) { | ||
return { done: false, value: (0, _io.cancel)(task) }; | ||
}; | ||
var forkOrCancel = function forkOrCancel() { | ||
return currentTask ? 'cancel' : 'fork'; | ||
var task = void 0, | ||
action = void 0; | ||
var setTask = function setTask(t) { | ||
return task = t; | ||
}; | ||
var currentTask = undefined, | ||
currentAction = undefined; | ||
var setAction = function setAction(ac) { | ||
return action = ac; | ||
}; | ||
return fsmIterator({ | ||
'take': [yieldTake, forkOrCancel, function (action) { | ||
return currentAction = action; | ||
}], | ||
'cancel': [yieldCancel, 'fork'], | ||
'fork': [yieldFork, 'take', function (task) { | ||
return currentTask = task; | ||
}] | ||
}, 'take', 'takeLatest(' + pattern + ', ' + worker.name + ')'); | ||
q1: function q1() { | ||
return ['q2', yTake, setAction]; | ||
}, | ||
q2: function q2() { | ||
return action === _channel.END ? [qEnd] : task ? ['q3', yCancel(task)] : ['q1', yFork(action), setTask]; | ||
}, | ||
q3: function q3() { | ||
return ['q1', yFork(action), setTask]; | ||
} | ||
}, 'q1', 'takeLatest(' + String(pattern) + ', ' + worker.name + ')'); | ||
} | ||
@@ -1486,71 +1872,53 @@ | ||
}); | ||
exports.createMockTask = createMockTask; | ||
var _utils = __webpack_require__(1); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function createMockTask() { | ||
var _ref; | ||
var running = true; | ||
var _result = undefined, | ||
_error = undefined; | ||
return _ref = {}, _defineProperty(_ref, _utils.TASK, true), _defineProperty(_ref, 'isRunning', function isRunning() { | ||
return running; | ||
}), _defineProperty(_ref, 'result', function result() { | ||
return _result; | ||
}), _defineProperty(_ref, 'error', function error() { | ||
return _error; | ||
}), _defineProperty(_ref, 'setRunning', function setRunning(b) { | ||
return running = b; | ||
}), _defineProperty(_ref, 'setResult', function setResult(r) { | ||
return _result = r; | ||
}), _defineProperty(_ref, 'setError', function setError(e) { | ||
return _error = e; | ||
}), _ref; | ||
} | ||
/***/ }, | ||
/* 12 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
Object.defineProperty(exports, 'TASK', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.TASK; | ||
} | ||
}); | ||
exports.monitorActions = exports.createMockTask = exports.MANUAL_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = exports.CANCEL = exports.asap = exports.arrayOfDeffered = exports.deferred = exports.asEffect = exports.is = exports.noop = exports.TASK = undefined; | ||
Object.defineProperty(exports, 'noop', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.noop; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'is', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.is; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deferred', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.deferred; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'arrayOfDeffered', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.arrayOfDeffered; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'createMockTask', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.createMockTask; | ||
} | ||
}); | ||
var _utils = __webpack_require__(1); | ||
var _io = __webpack_require__(3); | ||
var _proc = __webpack_require__(5); | ||
Object.defineProperty(exports, 'asEffect', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.asEffect; | ||
} | ||
}); | ||
var _testUtils = __webpack_require__(11); | ||
var _monitorActions = __webpack_require__(4); | ||
var monitorActions = _interopRequireWildcard(_monitorActions); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
exports.TASK = _utils.TASK; | ||
exports.noop = _utils.noop; | ||
exports.is = _utils.is; | ||
exports.asEffect = _io.asEffect; | ||
exports.deferred = _utils.deferred; | ||
exports.arrayOfDeffered = _utils.arrayOfDeffered; | ||
exports.asap = _utils.asap; | ||
exports.CANCEL = _proc.CANCEL; | ||
exports.RACE_AUTO_CANCEL = _proc.RACE_AUTO_CANCEL; | ||
exports.PARALLEL_AUTO_CANCEL = _proc.PARALLEL_AUTO_CANCEL; | ||
exports.MANUAL_CANCEL = _proc.MANUAL_CANCEL; | ||
exports.createMockTask = _testUtils.createMockTask; | ||
exports.monitorActions = monitorActions; | ||
/***/ }, | ||
/* 13 */ | ||
/* 12 */ | ||
/***/ function(module, exports) { | ||
@@ -1557,0 +1925,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.ReduxSaga=n():e.ReduxSaga=n()}(this,function(){return function(e){function n(r){if(t[r])return t[r].exports;var a=t[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,n),a.loaded=!0,a.exports}var t={};return n.m=e,n.c=t,n.p="",n(0)}([function(e,n,t){"use strict";function r(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n}function a(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0}),n.utils=n.effects=n.takeLatest=n.takeEvery=n.storeIO=n.runSaga=n.isCancelError=n.SagaCancellationException=void 0;var u=t(9);Object.defineProperty(n,"runSaga",{enumerable:!0,get:function(){return u.runSaga}}),Object.defineProperty(n,"storeIO",{enumerable:!0,get:function(){return u.storeIO}});var o=t(10);Object.defineProperty(n,"takeEvery",{enumerable:!0,get:function(){return o.takeEvery}}),Object.defineProperty(n,"takeLatest",{enumerable:!0,get:function(){return o.takeLatest}});var i=t(8),c=a(i),f=t(2),s=a(f),l=t(7),d=r(l),v=t(12),g=r(v);n.default=c.default;var p=n.SagaCancellationException=s.default;n.isCancelError=function(e){return e instanceof p};n.effects=d,n.utils=g},function(e,n,t){(function(e){"use strict";function t(e){return e}function r(e,n,t){if(!n(e))throw new Error(t)}function a(e,n){var t=e.indexOf(n);t>=0&&e.splice(t,1)}function u(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=s({},e),t=new Promise(function(e,t){n.resolve=e,n.reject=t});return n.promise=t,n}function o(e){for(var n=[],t=0;e>t;t++)n.push(u());return n}function i(){var e=arguments.length<=0||void 0===arguments[0]?0:arguments[0];return function(){return++e}}function c(e){return Promise.resolve(1).then(function(){return e()})}function f(e){v&&console.warn("DEPRECATION WARNING",e)}Object.defineProperty(n,"__esModule",{value:!0});var s=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e};n.ident=t,n.check=r,n.remove=a,n.deferred=u,n.arrayOfDeffered=o,n.autoInc=i,n.asap=c,n.warnDeprecated=f;var l=n.sym=function(e){return"@@redux-saga/"+e},d=n.TASK=l("TASK"),v=(n.kTrue=function(){return!0},n.noop=function(){},n.isDev="undefined"!=typeof e&&e.env&&!1),g=n.is={undef:function(e){return null===e||void 0===e},notUndef:function(e){return null!==e&&void 0!==e},func:function(e){return"function"==typeof e},array:Array.isArray,promise:function(e){return e&&g.func(e.then)},iterator:function(e){return e&&g.func(e.next)&&g.func(e.throw)},task:function(e){return e&&e[d]}}}).call(n,t(13))},function(e,n){"use strict";function t(e,n,t){var r="SagaCancellationException; type: "+e+", saga: "+n+", origin: "+t;this.name="SagaCancellationException",this.message=r,this.type=e,this.saga=n,this.origin=t,this.stack=(new Error).stack}Object.defineProperty(n,"__esModule",{value:!0}),n.default=t,t.prototype=Object.create(Error.prototype),t.prototype.constructor=t},function(e,n,t){"use strict";function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e){return("*"===e?P.wildcard:E.is.array(e)?P.array:E.is.func(e)?P.predicate:P.default)(e)}function u(e){if(arguments.length>0&&E.is.undef(e))throw new Error(_);return I(C,E.is.undef(e)?"*":e)}function o(e){return I(b,e)}function i(e){return I(T,e)}function c(e,n){(0,E.check)(e,E.is.notUndef,h);var t=null;if(E.is.array(e)){var r=e,a=m(r,2);t=a[0],e=a[1]}else if(e.fn){var u=e;t=u.context,e=u.fn}return(0,E.check)(e,E.is.func,h),{context:t,fn:e,args:n}}function f(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return I(k,c(e,t))}function s(e,n){var t=arguments.length<=2||void 0===arguments[2]?[]:arguments[2];return I(k,c({context:e,fn:n},t))}function l(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return I(w,c(e,t))}function d(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return I(L,c(e,t))}function v(e){if(!x(e))throw new Error(y);return I(N,e)}function g(e){if(!x(e))throw new Error(A);return I(S,e)}function p(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return 0===arguments.length?e=E.ident:(0,E.check)(e,E.is.func,R),I(j,{selector:e,args:t})}Object.defineProperty(n,"__esModule",{value:!0}),n.asEffect=n.SELECT_ARG_ERROR=n.INVALID_PATTERN=n.CANCEL_ARG_ERROR=n.JOIN_ARG_ERROR=n.FORK_ARG_ERROR=n.CALL_FUNCTION_ARG_ERROR=void 0;var m=function(){function e(e,n){var t=[],r=!0,a=!1,u=void 0;try{for(var o,i=e[Symbol.iterator]();!(r=(o=i.next()).done)&&(t.push(o.value),!n||t.length!==n);r=!0);}catch(c){a=!0,u=c}finally{try{!r&&i.return&&i.return()}finally{if(a)throw u}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();n.matcher=a,n.take=u,n.put=o,n.race=i,n.call=f,n.apply=s,n.cps=l,n.fork=d,n.join=v,n.cancel=g,n.select=p;var E=t(1),h=n.CALL_FUNCTION_ARG_ERROR="call/cps/fork first argument must be a function, an array [context, function] or an object {context, fn}",y=(n.FORK_ARG_ERROR="fork first argument must be a generator function or an iterator",n.JOIN_ARG_ERROR="join argument must be a valid task (a result of a fork)"),A=n.CANCEL_ARG_ERROR="cancel argument must be a valid task (a result of a fork)",_=n.INVALID_PATTERN="Invalid pattern passed to `take` (HINT: check if you didn't mispell a constant)",R=n.SELECT_ARG_ERROR="select first argument must be a function",O=(0,E.sym)("IO"),C="TAKE",b="PUT",T="RACE",k="CALL",w="CPS",L="FORK",N="JOIN",S="CANCEL",j="SELECT",I=function(e,n){var t;return t={},r(t,O,!0),r(t,e,n),t},P={wildcard:function(){return E.kTrue},"default":function(e){return function(n){return n.type===e}},array:function(e){return function(n){return e.some(function(e){return e===n.type})}},predicate:function(e){return function(n){return e(n)}}},x=function(e){return e[E.TASK]};n.asEffect={take:function(e){return e&&e[O]&&e[C]},put:function(e){return e&&e[O]&&e[b]},race:function(e){return e&&e[O]&&e[T]},call:function(e){return e&&e[O]&&e[k]},cps:function(e){return e&&e[O]&&e[w]},fork:function(e){return e&&e[O]&&e[L]},join:function(e){return e&&e[O]&&e[N]},cancel:function(e){return e&&e[O]&&e[S]},select:function(e){return e&&e[O]&&e[j]}}},function(e,n){"use strict";function t(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n,r,a){var u;return u={},t(u,o,!0),t(u,"type",i),t(u,"effectId",e),t(u,"parentEffectId",n),t(u,"label",r),t(u,"effect",a),u}function a(e,n){var r;return r={},t(r,o,!0),t(r,"type",c),t(r,"effectId",e),t(r,"result",n),r}function u(e,n){var r;return r={},t(r,o,!0),t(r,"type",f),t(r,"effectId",e),t(r,"error",n),r}Object.defineProperty(n,"__esModule",{value:!0}),n.effectTriggered=r,n.effectResolved=a,n.effectRejected=u;var o=n.MONITOR_ACTION="MONITOR_ACTION",i=n.EFFECT_TRIGGERED="EFFECT_TRIGGERED",c=n.EFFECT_RESOLVED="EFFECT_RESOLVED",f=n.EFFECT_REJECTED="EFFECT_REJECTED"},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n}function u(e){if(Array.isArray(e)){for(var n=0,t=Array(e.length);n<e.length;n++)t[n]=e[n];return t}return Array.from(e)}function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e){function n(e,n,t){"undefined"==typeof window?console.log("redux-saga "+e+": "+n+"\n"+t.stack):console[e].call(console,n,t)}function t(u,o){if(!e._isRunning)throw new Error("Trying to resume an already finished generator");try{var i=u?e.throw(u):e.next(o);i.done?r(i.value):a(i.value,M,"",t)}catch(u){r(u,!0),u instanceof v.default?c.isDev&&n("warn",U+": uncaught",u):n("error",U+": uncaught",u)}}function r(n,t){e._isRunning=!1,t?(e._error=n,K.reject(n)):(e._result=n,K.resolve(n)),J()}function a(e,n){function t(e,n){o||(o=!0,a.cancel=c.noop,x(e?l.effectRejected(u,e):l.effectResolved(u,n)),a(e,n))}var r=arguments.length<=2||void 0===arguments[2]?"":arguments[2],a=arguments[3],u=A();x(l.effectTriggered(u,n,r,e));var o=void 0;t.cancel=c.noop,a.cancel=function(e){if(!o){o=!0;try{t.cancel(e)}catch(n){}t.cancel=c.noop,a(e),x(l.effectRejected(u,e))}};var i=void 0;return c.is.promise(e)?s(e,t):c.is.iterator(e)?d(e,u,U,t):c.is.array(e)?w(e,u,t):c.is.notUndef(i=f.asEffect.take(e))?_(i,t):c.is.notUndef(i=f.asEffect.put(e))?R(i,t):c.is.notUndef(i=f.asEffect.race(e))?L(i,u,t):c.is.notUndef(i=f.asEffect.call(e))?O(i,u,t):c.is.notUndef(i=f.asEffect.cps(e))?C(i,t):c.is.notUndef(i=f.asEffect.fork(e))?b(i,u,t):c.is.notUndef(i=f.asEffect.join(e))?T(i,t):c.is.notUndef(i=f.asEffect.cancel(e))?k(i,t):c.is.notUndef(i=f.asEffect.select(e))?N(i,t):t(null,e)}function s(e,n){var t=e[m];"function"==typeof t&&(n.cancel=t),e.then(function(e){return n(null,e)},function(e){return n(e)})}function d(e,n,t,r){s(i(e,j,I,P,x,n,t).done,r)}function _(e,n){var t={match:(0,f.matcher)(e),pattern:e,resolve:function(e){return n(null,e)}};F.push(t),n.cancel=function(){return(0,c.remove)(F,t)}}function R(e,n){(0,c.asap)(function(){return n(null,I(e))})}function O(e,n,t){var r=e.context,a=e.fn,u=e.args,o=void 0;try{o=a.apply(r,u)}catch(i){return t(i)}return c.is.promise(o)?s(o,t):c.is.iterator(o)?d(o,n,a.name,t):t(null,o)}function C(e,n){var t=e.context,r=e.fn,a=e.args;try{r.apply(t,a.concat(n))}catch(u){return n(u)}}function b(e,n,t){var r=e.context,a=e.fn,u=e.args,o=void 0,f=void 0,s=void 0;try{o=a.apply(r,u)}catch(l){f=f}s=c.is.iterator(o)?o:(f?regeneratorRuntime.mark(function d(){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:throw f;case 1:case"end":return e.stop()}},d,this)}):regeneratorRuntime.mark(function v(){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,o;case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},v,this)}))(),t(null,i(s,j,I,P,x,n,a.name,!0))}function T(e,n){s(e.done,n)}function k(e,n){e.done[m](new v.default(y,U,U)),n()}function w(e,n,t){function r(){u===i.length&&(o=!0,t(null,i))}if(!e.length)return void t(null,[]);var u=0,o=void 0,i=Array(e.length),f=e.map(function(e,n){var a=function(e,a){if(!o)if(e){try{t.cancel(new v.default(E,U,U))}catch(e){}t(e)}else i[n]=a,u++,r()};return a.cancel=c.noop,a});t.cancel=function(e){o||(o=!0,f.forEach(function(n){return n.cancel(e)}))},e.forEach(function(e,t){return a(e,n,t,f[t])})}function L(e,n,t){var r=void 0,u=Object.keys(e),i={};u.forEach(function(e){var n=function(n,a){if(!r)if(n){try{t.cancel(new v.default(h,U,U))}catch(n){}t(o({},e,n))}else{try{t.cancel(new v.default(h,U,U))}catch(n){}r=!0,t(null,o({},e,a))}};n.cancel=c.noop,i[e]=n}),t.cancel=function(e){r||(r=!0,u.forEach(function(n){return i[n].cancel(e)}))},u.forEach(function(t){return a(e[t],n,t,i[t])})}function N(e,n){var t=e.selector,r=e.args;try{var a=t.apply(void 0,[P()].concat(u(r)));n(null,a)}catch(o){n(o)}}function S(e,n,t,r,a){var u;return u={},o(u,c.TASK,!0),o(u,"id",e),o(u,"name",n),o(u,"done",r),o(u,"forked",a),o(u,"cancel",function(e){e instanceof v.default||(e=new v.default(y,n,e)),r[m](e)}),o(u,"isRunning",function(){return t._isRunning}),o(u,"result",function(){return t._result}),o(u,"error",function(){return t._error}),u}var j=arguments.length<=1||void 0===arguments[1]?function(){return c.noop}:arguments[1],I=arguments.length<=2||void 0===arguments[2]?c.noop:arguments[2],P=arguments.length<=3||void 0===arguments[3]?c.noop:arguments[3],x=arguments.length<=4||void 0===arguments[4]?c.noop:arguments[4],M=arguments.length<=5||void 0===arguments[5]?0:arguments[5],U=arguments.length<=6||void 0===arguments[6]?"anonymous":arguments[6],D=arguments[7];(0,c.check)(e,c.is.iterator,g);var G=p(U),F=[],K=(0,c.deferred)(),J=j(function(e){if(void 0===e)throw G;for(var n=0;n<F.length;n++){var t=F[n];t.match(e)&&(F=[],t.resolve(e))}});t.cancel=c.noop;var V=S(M,U,e,K.promise,D);return V.done[m]=function(e){var n=e.type,r=e.origin;t.cancel(new v.default(n,U,r))},e._isRunning=!0,t(),V}Object.defineProperty(n,"__esModule",{value:!0}),n.MANUAL_CANCEL=n.RACE_AUTO_CANCEL=n.PARALLEL_AUTO_CANCEL=n.CANCEL=n.undefindInputError=n.NOT_ITERATOR_ERROR=void 0,n.default=i;var c=t(1),f=t(3),s=t(4),l=a(s),d=t(2),v=r(d),g=n.NOT_ITERATOR_ERROR="proc first argument (Saga function result) must be an iterator",p=n.undefindInputError=function(e){return"\n "+e+" saga was provided with an undefined input action\n Hints :\n - check that your Action Creator returns a non undefined value\n - if the Saga was started using runSaga, check that your subscribe source provides the action to its listeners\n"},m=n.CANCEL=(0,c.sym)("@@redux-saga/cancelPromise"),E=n.PARALLEL_AUTO_CANCEL="PARALLEL_AUTO_CANCEL",h=n.RACE_AUTO_CANCEL="RACE_AUTO_CANCEL",y=n.MANUAL_CANCEL="MANUAL_CANCEL",A=(0,c.autoInc)()},function(e,n,t){"use strict";function r(){function e(e){return t.push(e),function(){return(0,a.remove)(t,e)}}function n(e){t.slice().forEach(function(n){return n(e)})}var t=[];return{subscribe:e,emit:n}}Object.defineProperty(n,"__esModule",{value:!0}),n.default=r;var a=t(1)},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.select=n.cancel=n.join=n.fork=n.cps=n.apply=n.call=n.race=n.put=n.take=void 0;var r=t(3);n.take=r.take,n.put=r.put,n.race=r.race,n.call=r.call,n.apply=r.apply,n.cps=r.cps,n.fork=r.fork,n.join=r.join,n.cancel=r.cancel,n.select=r.select},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(){function e(e){function n(e){for(var n=arguments.length,t=Array(n>1?n-1:0),a=1;n>a;a++)t[a-1]=arguments[a];return(0,i.default)(e.apply(void 0,[d].concat(t)),c.subscribe,o,r,l,0,e.name)}var r=e.getState,o=e.dispatch,c=(0,f.default)(),l=u.isDev?function(e){return(0,u.asap)(function(){return o(e)})}:void 0,d=function(){return(0,u.warnDeprecated)(p),r()};return a=n,t.forEach(n),function(e){return function(n){var t=e(n);return n[s.MONITOR_ACTION]||c.emit(n),t}}}for(var n=arguments.length,t=Array(n),r=0;n>r;r++)t[r]=arguments[r];var a=void 0;return t.forEach(function(e,n){return(0,u.check)(e,u.is.func,v("createSagaMiddleware",n,e))}),e.run=function(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];if(!a)throw new Error(g);(0,u.check)(e,u.is.func,v("sagaMiddleware.run",0,e));var o=a.apply(void 0,[e].concat(t));return o.done.catch(function(e){if(!(e instanceof d.default))throw e}),o},e}Object.defineProperty(n,"__esModule",{value:!0}),n.GET_STATE_DEPRECATED_WARNING=n.RUN_SAGA_DYNAMIC_ERROR=n.sagaArgError=void 0,n.default=a;var u=t(1),o=t(5),i=r(o),c=t(6),f=r(c),s=t(4),l=t(2),d=r(l),v=n.sagaArgError=function(e,n,t){return"\n "+e+" can only be called on Generator functions\n Argument "+t+" at position "+n+" is not function!\n"},g=n.RUN_SAGA_DYNAMIC_ERROR="Before running a Saga dynamically using middleware.run, you must mount the Saga middleware on the Store using applyMiddleware",p=n.GET_STATE_DEPRECATED_WARNING="\n Using the 'getState' param of Sagas to access the state is deprecated since 0.9.1\n To access the Store's state use 'yield select()' instead\n For more infos see http://yelouafi.github.io/redux-saga/docs/api/index.html#selectselector-args\n"},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){if((0,o.warnDeprecated)("storeIO is deprecated, to run Saga dynamically, use 'run' method of the middleware"),e[d])return e[d];var n=(0,s.default)(),t=e.dispatch;return e.dispatch=function(e){var r=t(e);return n.emit(e),r},e[d]={subscribe:n.subscribe,dispatch:e.dispatch,getState:e.getState},e[d]}function u(e,n){var t=n.subscribe,r=n.dispatch,a=n.getState,u=arguments.length<=2||void 0===arguments[2]?o.noop:arguments[2];return(0,o.check)(e,o.is.iterator,l),(0,c.default)(e,t,r,a,u)}Object.defineProperty(n,"__esModule",{value:!0}),n.NOT_ITERATOR_ERROR=void 0,n.storeIO=a,n.runSaga=u;var o=t(1),i=t(5),c=r(i),f=t(6),s=r(f),l=n.NOT_ITERATOR_ERROR="runSaga must be called on an iterator",d=(0,o.sym)("IO")},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,n){function t(t,r){if(a)return v;if(r){if(a=!0,!(r instanceof l.default))throw r;return v}u&&u(t);var o=i(e[n],3),c=o[0],f=o[1],s=o[2];return u=s,n=d(f,t),d(c,t)}var r=arguments.length<=2||void 0===arguments[2]?"iterator":arguments[2],a=void 0,u=void 0,o={name:r,next:t,"throw":function(e){return t(null,e)}};return"undefined"!=typeof Symbol&&(o[Symbol.iterator]=function(){return o}),o}function u(e,n){for(var t=arguments.length,r=Array(t>2?t-2:0),u=2;t>u;u++)r[u-2]=arguments[u];var o={done:!1,value:(0,f.take)(e)},i=function(e){return{done:!1,value:f.fork.apply(void 0,[n].concat(r,[e]))}};return a({take:[o,"fork"],fork:[i,"take"]},"take","takeEvery("+e+", "+n.name+")")}function o(e,n){for(var t=arguments.length,r=Array(t>2?t-2:0),u=2;t>u;u++)r[u-2]=arguments[u];var o={done:!1,value:(0,f.take)(e)},i=function(){return{done:!1,value:f.fork.apply(void 0,[n].concat(r,[d]))}},c=function(){return{done:!1,value:(0,f.cancel)(l)}},s=function(){return l?"cancel":"fork"},l=void 0,d=void 0;return a({take:[o,s,function(e){return d=e}],cancel:[c,"fork"],fork:[i,"take",function(e){return l=e}]},"take","takeLatest("+e+", "+n.name+")")}Object.defineProperty(n,"__esModule",{value:!0});var i=function(){function e(e,n){var t=[],r=!0,a=!1,u=void 0;try{for(var o,i=e[Symbol.iterator]();!(r=(o=i.next()).done)&&(t.push(o.value),!n||t.length!==n);r=!0);}catch(c){a=!0,u=c}finally{try{!r&&i.return&&i.return()}finally{if(a)throw u}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();n.takeEvery=u,n.takeLatest=o;var c=t(1),f=t(3),s=t(2),l=r(s),d=function(e,n){return c.is.func(e)?e(n):e},v={done:!0}},function(e,n,t){"use strict";function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(){var e,n=!0,t=void 0,a=void 0;return e={},r(e,u.TASK,!0),r(e,"isRunning",function(){return n}),r(e,"result",function(){return t}),r(e,"error",function(){return a}),r(e,"setRunning",function(e){return n=e}),r(e,"setResult",function(e){return t=e}),r(e,"setError",function(e){return a=e}),e}Object.defineProperty(n,"__esModule",{value:!0}),n.createMockTask=a;var u=t(1)},function(e,n,t){"use strict";function r(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n}Object.defineProperty(n,"__esModule",{value:!0}),n.monitorActions=n.createMockTask=n.MANUAL_CANCEL=n.PARALLEL_AUTO_CANCEL=n.RACE_AUTO_CANCEL=n.CANCEL=n.asap=n.arrayOfDeffered=n.deferred=n.asEffect=n.is=n.noop=n.TASK=void 0;var a=t(1),u=t(3),o=t(5),i=t(11),c=t(4),f=r(c);n.TASK=a.TASK,n.noop=a.noop,n.is=a.is,n.asEffect=u.asEffect,n.deferred=a.deferred,n.arrayOfDeffered=a.arrayOfDeffered,n.asap=a.asap,n.CANCEL=o.CANCEL,n.RACE_AUTO_CANCEL=o.RACE_AUTO_CANCEL,n.PARALLEL_AUTO_CANCEL=o.PARALLEL_AUTO_CANCEL,n.MANUAL_CANCEL=o.MANUAL_CANCEL,n.createMockTask=i.createMockTask,n.monitorActions=f},function(e,n){function t(){f=!1,o.length?c=o.concat(c):s=-1,c.length&&r()}function r(){if(!f){var e=setTimeout(t);f=!0;for(var n=c.length;n;){for(o=c,c=[];++s<n;)o&&o[s].run();s=-1,n=c.length}o=null,f=!1,clearTimeout(e)}}function a(e,n){this.fun=e,this.array=n}function u(){}var o,i=e.exports={},c=[],f=!1,s=-1;i.nextTick=function(e){var n=new Array(arguments.length-1);if(arguments.length>1)for(var t=1;t<arguments.length;t++)n[t-1]=arguments[t];c.push(new a(e,n)),1!==c.length||f||setTimeout(r,0)},a.prototype.run=function(){this.fun.apply(null,this.array)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.versions={},i.on=u,i.addListener=u,i.once=u,i.off=u,i.removeListener=u,i.removeAllListeners=u,i.emit=u,i.binding=function(e){throw new Error("process.binding is not supported")},i.cwd=function(){return"/"},i.chdir=function(e){throw new Error("process.chdir is not supported")},i.umask=function(){return 0}}])}); | ||
!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.ReduxSaga=n():e.ReduxSaga=n()}(this,function(){return function(e){function n(r){if(t[r])return t[r].exports;var u=t[r]={exports:{},id:r,loaded:!1};return e[r].call(u.exports,u,u.exports,n),u.loaded=!0,u.exports}var t={};return n.m=e,n.c=t,n.p="",n(0)}([function(e,n,t){"use strict";function r(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n}function u(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0}),n.utils=n.effects=n.delay=n.takeLatest=n.takeEvery=n.buffers=n.channel=n.eventChannel=n.END=n.CANCEL=n.runSaga=void 0;var o=t(9);Object.defineProperty(n,"runSaga",{enumerable:!0,get:function(){return o.runSaga}});var a=t(5);Object.defineProperty(n,"CANCEL",{enumerable:!0,get:function(){return a.CANCEL}});var i=t(2);Object.defineProperty(n,"END",{enumerable:!0,get:function(){return i.END}}),Object.defineProperty(n,"eventChannel",{enumerable:!0,get:function(){return i.eventChannel}}),Object.defineProperty(n,"channel",{enumerable:!0,get:function(){return i.channel}});var c=t(4);Object.defineProperty(n,"buffers",{enumerable:!0,get:function(){return c.buffers}});var f=t(10);Object.defineProperty(n,"takeEvery",{enumerable:!0,get:function(){return f.takeEvery}}),Object.defineProperty(n,"takeLatest",{enumerable:!0,get:function(){return f.takeLatest}});var l=t(1);Object.defineProperty(n,"delay",{enumerable:!0,get:function(){return l.delay}});var s=t(8),d=u(s),v=t(6),p=r(v),h=t(11),g=r(h);n.default=d.default,n.effects=p,n.utils=g},function(e,n,t){(function(e){"use strict";function t(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e){return e}function u(e,n,t){if(!n(e))throw new Error(t)}function o(e,n){var t=e.indexOf(n);t>=0&&e.splice(t,1)}function a(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=v({},e),t=new Promise(function(e,t){n.resolve=e,n.reject=t});return n.promise=t,n}function i(e){for(var n=[],t=0;e>t;t++)n.push(a());return n}function c(e){var n=arguments.length<=1||void 0===arguments[1]?!0:arguments[1];return new Promise(function(t){return setTimeout(function(){return t(n)},e)})}function f(){var e,n=!0,r=void 0,u=void 0;return e={},t(e,h,!0),t(e,"isRunning",function(){return n}),t(e,"result",function(){return r}),t(e,"error",function(){return u}),t(e,"setRunning",function(e){return n=e}),t(e,"setResult",function(e){return r=e}),t(e,"setError",function(e){return u=e}),e}function l(){var e=arguments.length<=0||void 0===arguments[0]?0:arguments[0];return function(){return++e}}function s(e){var n=arguments.length<=1||void 0===arguments[1]?b:arguments[1],t=arguments.length<=2||void 0===arguments[2]?"":arguments[2],r={name:t,next:e,"throw":n};return"undefined"!=typeof Symbol&&(r[Symbol.iterator]=function(){return r}),r}function d(e,n,t){"undefined"==typeof window?console.log("redux-saga "+e+": "+n+"\n"+(t&&t.stack||t)):console[e].call(console,n,t)}Object.defineProperty(n,"__esModule",{value:!0});var v=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e};n.ident=r,n.check=u,n.remove=o,n.deferred=a,n.arrayOfDeffered=i,n.delay=c,n.createMockTask=f,n.autoInc=l,n.makeIterator=s,n.log=d;var p=n.sym=function(e){return"@@redux-saga/"+e},h=n.TASK=p("TASK"),g=(n.MATCH=p("MATCH"),n.konst=function(e){return function(){return e}}),y=(n.kTrue=g(!0),n.kFalse=g(!1),n.noop=function(){},n.isDev="undefined"!=typeof e&&e.env&&!1,n.is={undef:function(e){return null===e||void 0===e},notUndef:function(e){return null!==e&&void 0!==e},func:function(e){return"function"==typeof e},number:function(e){return"number"==typeof e},array:Array.isArray,promise:function(e){return e&&y.func(e.then)},iterator:function(e){return e&&y.func(e.next)&&y.func(e.throw)},task:function(e){return e&&e[h]},take:function(e){return e&&y.func(e.take)},put:function(e){return e&&y.func(e.put)},observable:function(e){return e&&y.func(e.subscribe)},buffer:function(e){return e&&y.func(e.isEmpty)&&y.func(e.take)&&y.func(e.put)},pattern:function(e){return e&&("string"==typeof e||y.func(e)||y.array(e))}}),b=function(e){throw e};n.internalErr=function(e){return new Error("\n redux-saga: Error checking hooks detected an inconsisten state. This is likely a bug\n in redux-saga code and not yours. Thanks for reporting this in the project's github repo.\n Error: "+e+"\n")}}).call(n,t(12))},function(e,n,t){"use strict";function r(){function e(e){return t.push(e),function(){return(0,a.remove)(t,e)}}function n(e){for(var n=t.slice(),r=0,u=n.length;u>r;r++)n[r](e)}var t=[];return{subscribe:e,emit:n}}function u(e){function n(){if(o&&s.length)throw(0,a.internalErr)("Can not have a closed channel with pending takers");if(s.length&&!e.isEmpty())throw(0,a.internalErr)("Can not have pedning takers with non empty buffer")}function t(t){if(n(),(0,a.check)(t,a.is.notUndef,l),!o)if(s.length)for(var r=0;r<s.length;r++){var u=s[r];if(!u[a.MATCH]||u[a.MATCH](t))return s.splice(r,1),u(t)}else e.put(t)}function r(t,r){n(),(0,a.check)(t,a.is.func,"channel.take's callback must be a function"),arguments.length>1&&((0,a.check)(r,a.is.func,"channel.take's matcher argument must be a function"),t[a.MATCH]=r),o&&e.isEmpty()?t(c):e.isEmpty()?(s.push(t),t.cancel=function(){return(0,a.remove)(s,t)}):t(e.take())}function u(){if(n(),!o&&(o=!0,s.length)){var e=s;s=[];for(var t=0,r=e.length;r>t;t++)e[t](c);s=[]}}var o=!1,s=[];return arguments.length>0?(0,a.check)(e,a.is.buffer,f):e=i.buffers.fixed(),{take:r,put:t,close:u,get __takers__(){return s},get __closed__(){return o}}}function o(e){var n=arguments.length<=1||void 0===arguments[1]?i.buffers.none():arguments[1],t=arguments[2];arguments.length>1&&(0,a.check)(t,a.is.func,"Invalid match function passed to eventChannel");var r=u(n),o=e(function(e){e===c?r.close():t&&!t(e)||r.put(e)});return{take:r.take,close:function(){r.__closed__||(r.close(),o())}}}Object.defineProperty(n,"__esModule",{value:!0}),n.UNDEFINED_INPUT_ERROR=n.INVALID_BUFFER=n.END=void 0,n.emitter=r,n.channel=u,n.eventChannel=o;var a=t(1),i=t(4),c=n.END={type:"@@redux-saga/CHANNEL_END"},f=n.INVALID_BUFFER="invalid buffer passed to channel factory function",l=n.UNDEFINED_INPUT_ERROR="\n Saga was provided with an undefined action\n Hints :\n - check that your Action Creator returns a non undefined value\n - if the Saga was started using runSaga, check that your subscribe source provides the action to its listeners\n"},function(e,n,t){"use strict";function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function u(e,n){if(arguments.length>=2)(0,k.check)(e,k.is.notUndef,"take(channel, pattern): channel is undefined"),(0,k.check)(e,k.is.take,"take(channel, pattern): argument "+e+" is not a valid channel (channel argument must have a take method)"),(0,k.check)(n,k.is.notUndef,"take(channel, pattern): pattern is undefined"),(0,k.check)(n,k.is.pattern,"take(channel, pattern): argument "+n+" is not a valid pattern (pattern must be String | Function: a => boolean | Array<String>)");else if(1===arguments.length)if((0,k.check)(e,k.is.notUndef,"take(patternOrChannel): undefined argument"),k.is.take(e))n="*";else{if(!k.is.pattern(e))throw new Error("take(patternOrChannel): argument "+e+" is not valid channel or a valid pattern");n=e,e=null}else n="*";return x(j,{channel:e,pattern:n})}function o(){var e=u.apply(void 0,arguments);return e[j].maybe=!0,e}function a(e,n){return arguments.length>1?((0,k.check)(e,k.is.notUndef,"put(channel, action): argument channel is undefined"),(0,k.check)(e,k.is.put,"put(channel, action): argument "+e+" is not a valid channel (channel argument must have a put method)"),(0,k.check)(n,k.is.notUndef,"put(channel, action): argument action is undefined")):((0,k.check)(e,k.is.notUndef,"put(action): argument action is undefined"),n=e,e=null),x(O,{channel:e,action:n})}function i(e){return x(_,e)}function c(e,n,t){(0,k.check)(n,k.is.notUndef,e+": argument fn is undefined");var r=null;if(k.is.array(n)){var u=n,o=m(u,2);r=o[0],n=o[1]}else if(n.fn){var a=n;r=a.context,n=a.fn}return(0,k.check)(n,k.is.func,e+": argument "+n+" is not a function"),{context:r,fn:n,args:t}}function f(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return x(w,c("call",e,t))}function l(e,n){var t=arguments.length<=2||void 0===arguments[2]?[]:arguments[2];return x(w,c("apply",{context:e,fn:n},t))}function s(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return x(C,c("cps",e,t))}function d(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return x(A,c("fork",e,t))}function v(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];var u=d.apply(void 0,[e].concat(t));return u[A].detached=!0,u}function p(e){if((0,k.check)(e,k.is.notUndef,"join(task): argument task is undefined"),!M(e))throw new Error("join(task): argument "+e+" is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)");return x(P,e)}function h(e){if((0,k.check)(e,k.is.notUndef,"cancel(task): argument task is undefined"),!M(e))throw new Error("cancel(task): argument "+e+" is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)");return x(T,e)}function g(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return 0===arguments.length?e=k.ident:((0,k.check)(g,k.is.notUndef,"select(selector,[...]): argument selector is undefined"),(0,k.check)(e,k.is.func,"select(selector,[...]): argument "+e+" is not a function")),x(R,{selector:e,args:t})}function y(e,n){return(0,k.check)(e,k.is.notUndef,"actionChannel(pattern,...): argument pattern is undefined"),arguments.length>1&&((0,k.check)(n,k.is.notUndef,"actionChannel(pattern, buffer): argument buffer is undefined"),(0,k.check)(n,k.is.notUndef,"actionChannel(pattern, buffer): argument "+n+" is not a valid buffer")),x(S,{pattern:e,buffer:n})}function b(){return x(N,{})}Object.defineProperty(n,"__esModule",{value:!0}),n.asEffect=void 0;var m=function(){function e(e,n){var t=[],r=!0,u=!1,o=void 0;try{for(var a,i=e[Symbol.iterator]();!(r=(a=i.next()).done)&&(t.push(a.value),!n||t.length!==n);r=!0);}catch(c){u=!0,o=c}finally{try{!r&&i.return&&i.return()}finally{if(u)throw o}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();n.take=u,n.takem=o,n.put=a,n.race=i,n.call=f,n.apply=l,n.cps=s,n.fork=d,n.spawn=v,n.join=p,n.cancel=h,n.select=g,n.actionChannel=y,n.cancelled=b;var k=t(1),E=(0,k.sym)("IO"),j="TAKE",O="PUT",_="RACE",w="CALL",C="CPS",A="FORK",P="JOIN",T="CANCEL",R="SELECT",S="ACTION_CHANNEL",N="CANCELLED",x=function(e,n){var t;return t={},r(t,E,!0),r(t,e,n),t},M=function(e){return e[k.TASK]};n.asEffect={take:function(e){return e&&e[E]&&e[j]},put:function(e){return e&&e[E]&&e[O]},race:function(e){return e&&e[E]&&e[_]},call:function(e){return e&&e[E]&&e[w]},cps:function(e){return e&&e[E]&&e[C]},fork:function(e){return e&&e[E]&&e[A]},join:function(e){return e&&e[E]&&e[P]},cancel:function(e){return e&&e[E]&&e[T]},select:function(e){return e&&e[E]&&e[R]},actionChannel:function(e){return e&&e[E]&&e[S]},cancelled:function(e){return e&&e[E]&&e[N]}}},function(e,n,t){"use strict";function r(){var e=arguments.length<=0||void 0===arguments[0]?1/0:arguments[0],n=arguments[1],t=[];return{isEmpty:function(){return!t.length},put:function(r){if(t.length<e)t.push(r);else switch(n){case a:throw new Error(o);case c:t.shift(),t.push(r)}},take:function(){return t.shift()}}}Object.defineProperty(n,"__esModule",{value:!0}),n.buffers=n.BUFFER_OVERFLOW=void 0;var u=t(1),o=n.BUFFER_OVERFLOW="Channel's Buffer overflow!",a=1,i=2,c=3,f={isEmpty:u.kTrue,put:u.noop,take:u.noop};n.buffers={none:function(){return f},fixed:function(e){return r(e,a)},drop:function(e){return r(e,i)},slide:function(e){return r(e,c)}}},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function u(e,n){for(var t in n){var r=n[t];r.configurable=r.enumerable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,t,r)}return e}function o(e){if(Array.isArray(e)){for(var n=0,t=Array(e.length);n<e.length;n++)t[n]=e[n];return t}return Array.from(e)}function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e){return("*"===e?k.wildcard:l.is.array(e)?k.array:l.is.func(e)?k.predicate:k.default)(e)}function c(e,n,t){function r(e){o.push(e),e.cont=function(r,c){i||((0,l.remove)(o,e),e.cont=l.noop,r?(u(),t(r)):(e===n&&(a=c),o.length||(i=!0,t(null,a))))}}function u(){i||(i=!0,o.forEach(function(e){e.cont=l.noop,e.cancel()}),o=[])}var o=[],a=void 0,i=!1;return r(n),{addTask:r,cancelAll:u,getTasks:function(){return o},taskNames:function(){return o.map(function(e){return e.name})}}}function f(e){function n(){W.isRunning&&!W.isCancelled&&(W.isCancelled=!0,r(null,m))}function t(){e._isRunning&&!e._isCancelled&&(e._isCancelled=!0,Y.cancelAll(),s(null,m))}function r(n,t){if(!W.isRunning)throw new Error("Trying to resume an already finished generator");try{var u=void 0;n?u=e.throw(n):t===m?(W.isCancelled=!0,r.cancel(),u=l.is.func(e.return)?e.return(m):{done:!0,value:m}):u=e.next(t),u.done?(W.isMainRunning=!1,W.cont&&W.cont(null,u.value)):k(u.value,q,"",r)}catch(n){W.isCancelled&&(0,l.log)("error","uncaught at "+H,n.message),W.isMainRunning=!1,W.cont(n)}}function s(n,t){e._isRunning=!1,B.close(),n?(n instanceof Error&&(n.sagaStack="at "+H+" \n "+(n.sagaStack||n.message)),V.cont||(0,l.log)("error","uncaught",n.sagaStack||n.message),e._error=n,e._deferredEnd&&e._deferredEnd.reject(n)):(t===m&&l.isDev&&(0,l.log)("info",H+" has been cancelled",""),e._result=t,e._deferredEnd&&e._deferredEnd.resolve(t)),V.cont&&V.cont(n,t),V.joiners.forEach(function(e){return e.cb(n,t)}),V.joiners=null}function k(e,n){function t(e,n){a||(a=!0,u.cancel=l.noop,F&&(e?F.effectRejected(o,e):F.effectResolved(o,n)),u(e,n))}var r=arguments.length<=2||void 0===arguments[2]?"":arguments[2],u=arguments[3],o=b();F&&F.effectTriggered({effectId:o,parentEffectId:n,label:r,effect:e});var a=void 0;t.cancel=l.noop,u.cancel=function(){if(!a){a=!0;try{t.cancel()}catch(e){(0,l.log)("error","uncaught at "+H,e.message)}t.cancel=l.noop,F&&F.effectCancelled(o)}};var i=void 0;return l.is.promise(e)?E(e,t):l.is.iterator(e)?j(e,o,H,t):l.is.array(e)?R(e,o,t):l.is.notUndef(i=v.asEffect.take(e))?O(i,t):l.is.notUndef(i=v.asEffect.put(e))?_(i,t):l.is.notUndef(i=v.asEffect.race(e))?S(i,o,t):l.is.notUndef(i=v.asEffect.call(e))?w(i,o,t):l.is.notUndef(i=v.asEffect.cps(e))?C(i,t):l.is.notUndef(i=v.asEffect.fork(e))?A(i,o,t):l.is.notUndef(i=v.asEffect.join(e))?P(i,t):l.is.notUndef(i=v.asEffect.cancel(e))?T(i,t):l.is.notUndef(i=v.asEffect.select(e))?N(i,t):l.is.notUndef(i=v.asEffect.actionChannel(e))?x(i,t):l.is.notUndef(i=v.asEffect.cancelled(e))?M(i,t):t(null,e)}function E(e,n){var t=e[y];"function"==typeof t&&(n.cancel=t),e.then(function(e){return n(null,e)},function(e){return n(e)})}function j(e,n,t,r){f(e,I,L,D,F,n,t,r)}function O(e,n){var t=e.channel,r=e.pattern,u=e.maybe;t=t||B;var o=function(e){return e instanceof Error?n(e):e!==p.END||u?n(null,e):n(null,m)};try{t.take(o,i(r))}catch(a){return n(a)}n.cancel=o.cancel}function _(e,n){var t=e.channel,r=e.action;(0,d.default)(function(){var e=void 0;try{e=(t?t.put:L)(r)}catch(u){return n(u)}return l.is.promise(e)?void E(e,n):n(null,e)})}function w(e,n,t){var r=e.context,u=e.fn,o=e.args,a=void 0;try{a=u.apply(r,o)}catch(i){return t(i)}return l.is.promise(a)?E(a,t):l.is.iterator(a)?j(a,n,u.name,t):t(null,a)}function C(e,n){var t=e.context,r=e.fn,u=e.args;try{r.apply(t,u.concat(n))}catch(o){return n(o)}}function A(e,n,t){var r=e.context,u=e.fn,o=e.args,a=e.detached,i=void 0,c=void 0,s=void 0;try{i=u.apply(r,o)}catch(d){if(!a)return t(d);c=d}s=l.is.iterator(i)?i:c?(0,l.makeIterator)(function(){throw c}):(0,l.makeIterator)(function(){var e=void 0,n={done:!1,value:i},t=function(e){return{done:!0,value:e}};return function(r){return e?t(r):(e=!0,n)}}());var v=f(s,I,L,D,F,n,u.name,a?null:l.noop);if(!a)if(s._isRunning)Y.addTask(v);else if(s._error)return t(s._error);t(null,v)}function P(e,n){e.isRunning()?!function(){var t={task:V,cb:n};n.cancel=function(){return(0,l.remove)(e.joiners,t)},e.joiners.push(t)}():n(e.error(),e.result())}function T(e,n){e.isRunning()&&e.cancel(),n()}function R(e,n,t){function r(){u===a.length&&(o=!0,t(null,a))}if(!e.length)return void t(null,[]);var u=0,o=void 0,a=Array(e.length),i=e.map(function(e,n){var i=function(e,i){o||(e||i===p.END||i===m?(t.cancel(),e?t(e):t(null,i)):(a[n]=i,u++,r()))};return i.cancel=l.noop,i});t.cancel=function(){o||(o=!0,i.forEach(function(e){return e.cancel()}))},e.forEach(function(e,t){return k(e,n,t,i[t])})}function S(e,n,t){var r=void 0,u=Object.keys(e),o={};u.forEach(function(e){var n=function(n,u){r||(n?(t.cancel(),t(n)):u!==p.END&&u!==m&&(t.cancel(),r=!0,t(null,a({},e,u))))};n.cancel=l.noop,o[e]=n}),t.cancel=function(){r||(r=!0,u.forEach(function(e){return o[e].cancel()}))},u.forEach(function(t){return k(e[t],n,t,o[t])})}function N(e,n){var t=e.selector,r=e.args;try{var u=t.apply(void 0,[D()].concat(o(r)));n(null,u)}catch(a){n(a)}}function x(e,n){var t=e.pattern,r=e.buffer,u=i(t);u.pattern=t,n(null,(0,p.eventChannel)(I,r||h.buffers.fixed(),u))}function M(e,n){n(null,!!W.isCancelled)}function U(e,n,r,o){var i,c,f;return r._deferredEnd=null,c={},a(c,l.TASK,!0),a(c,"id",e),a(c,"name",n),i="done",f={},f[i]=f[i]||{},f[i].get=function(){if(r._deferredEnd)return r._deferredEnd.promise;var e=(0,l.deferred)();return r._deferredEnd=e,r._isRunning||(r._error?e.reject(r._error):e.resolve(r._result)),e.promise},a(c,"cont",o),a(c,"joiners",[]),a(c,"cancel",t),a(c,"isRunning",function(){return r._isRunning}),a(c,"isCancelled",function(){return r._isCancelled}),a(c,"result",function(){return r._result}),a(c,"error",function(){return r._error}),u(c,f),c}var I=arguments.length<=1||void 0===arguments[1]?function(){return l.noop}:arguments[1],L=arguments.length<=2||void 0===arguments[2]?l.noop:arguments[2],D=arguments.length<=3||void 0===arguments[3]?l.noop:arguments[3],F=arguments[4],q=arguments.length<=5||void 0===arguments[5]?0:arguments[5],H=arguments.length<=6||void 0===arguments[6]?"anonymous":arguments[6],K=arguments[7];(0,l.check)(e,l.is.iterator,g);var B=(0,p.eventChannel)(I);r.cancel=l.noop;var V=U(q,H,e,K),W={name:H,cancel:n,isRunning:!0},Y=c(H,W,s);return K&&(K.cancel=t),e._isRunning=!0,r(),V}Object.defineProperty(n,"__esModule",{value:!0}),n.Never=n.CANCEL=n.NOT_ITERATOR_ERROR=void 0,n.default=f;var l=t(1),s=t(7),d=r(s),v=t(3),p=t(2),h=t(4),g=n.NOT_ITERATOR_ERROR="proc first argument (Saga function result) must be an iterator",y=n.CANCEL=(0,l.sym)("cancelPromise"),b=(0,l.autoInc)(),m=n.Never={toString:function(){return"@@redux-saga/Never"}};Object.freeze(m);var k={wildcard:function(){return l.kTrue},"default":function(e){return function(n){return n.type===e}},array:function(e){return function(n){return e.some(function(e){return e===n.type})}},predicate:function(e){return function(n){return e(n)}}}},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=t(3);Object.defineProperty(n,"take",{enumerable:!0,get:function(){return r.take}}),Object.defineProperty(n,"takem",{enumerable:!0,get:function(){return r.takem}}),Object.defineProperty(n,"put",{enumerable:!0,get:function(){return r.put}}),Object.defineProperty(n,"race",{enumerable:!0,get:function(){return r.race}}),Object.defineProperty(n,"call",{enumerable:!0,get:function(){return r.call}}),Object.defineProperty(n,"apply",{enumerable:!0,get:function(){return r.apply}}),Object.defineProperty(n,"cps",{enumerable:!0,get:function(){return r.cps}}),Object.defineProperty(n,"fork",{enumerable:!0,get:function(){return r.fork}}),Object.defineProperty(n,"spawn",{enumerable:!0,get:function(){return r.spawn}}),Object.defineProperty(n,"join",{enumerable:!0,get:function(){return r.join}}),Object.defineProperty(n,"cancel",{enumerable:!0,get:function(){return r.cancel}}),Object.defineProperty(n,"select",{enumerable:!0,get:function(){return r.select}}),Object.defineProperty(n,"actionChannel",{enumerable:!0,get:function(){return r.actionChannel}}),Object.defineProperty(n,"cancelled",{enumerable:!0,get:function(){return r.cancelled}})},function(e,n){"use strict";function t(e){u?r.push(e):(u=!0,r.push(e),t.flush())}Object.defineProperty(n,"__esModule",{value:!0}),n.default=t;var r=[],u=!1;t.suspend=function(){return u=!0},t.flush=function(){for(var e=void 0;e=r.shift();)e();u=!1}},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function u(){function e(e){function r(e){for(var t=arguments.length,r=Array(t>1?t-1:0),c=1;t>c;c++)r[c-1]=arguments[c];return(0,i.default)(e.apply(void 0,r),a.subscribe,o,u,n.sagaMonitor,0,e.name)}var u=e.getState,o=e.dispatch;t=r;var a=(0,c.emitter)();return function(e){return function(n){var t=e(n);return a.emit(n),t}}}var n=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],t=void 0;if(o.is.func(n))throw new Error("You passed a function to the Saga middleware. You are likely trying to start a Saga by directly passing it to the middleware. This is no longer possible starting from 0.10.0. To run a Saga, you must do it dynamically AFTER mounting the middleware into the store.\n Example:\n import createSagaMiddleware from 'redux-saga'\n ... other imports\n\n const sagaMiddleware = createSagaMiddleware()\n const store = createStore(reducer, applyMiddleware(sagaMiddleware))\n sagaMiddleware.run(saga, ...args)\n ");return e.run=function(e){for(var n=arguments.length,r=Array(n>1?n-1:0),u=1;n>u;u++)r[u-1]=arguments[u];return(0,o.check)(t,o.is.notUndef,"Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware"),(0,o.check)(e,o.is.func,"sagaMiddleware.run(saga, ...args): saga argument must be a Generator function!"),t.apply(void 0,[e].concat(r))},e}Object.defineProperty(n,"__esModule",{value:!0}),n.default=u;var o=t(1),a=t(5),i=r(a),c=t(2)},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function u(e,n,t){var r=n.subscribe,u=n.dispatch,a=n.getState;return(0,o.check)(e,o.is.iterator,"runSaga must be called on an iterator"),(0,i.default)(e,r,u,a,t)}Object.defineProperty(n,"__esModule",{value:!0}),n.runSaga=u;var o=t(1),a=t(5),i=r(a)},function(e,n,t){"use strict";function r(e,n){function t(n,t){if(o===s)return l;if(t)throw o=s,t;u&&u(n);var r=e[o](),i=a(r,3),c=i[0],f=i[1],d=i[2];return o=c,u=d,o===s?l:f}var r=arguments.length<=2||void 0===arguments[2]?"iterator":arguments[2],u=void 0,o=n;return(0,c.makeIterator)(t,function(e){return t(null,e)},r)}function u(e,n){for(var t=arguments.length,u=Array(t>2?t-2:0),o=2;t>o;o++)u[o-2]=arguments[o];var a={done:!1,value:(0,f.take)(e)},c=function(e){return{done:!1,value:f.fork.apply(void 0,[n].concat(u,[e]))}},l=void 0,d=function(e){return l=e};return r({q1:function(){return["q2",a,d]},q2:function(){return l===i.END?[s]:["q1",c(l)]}},"q1","takeEvery("+String(e)+", "+n.name+")")}function o(e,n){for(var t=arguments.length,u=Array(t>2?t-2:0),o=2;t>o;o++)u[o-2]=arguments[o];var a={done:!1,value:(0,f.take)(e)},c=function(e){return{done:!1,value:f.fork.apply(void 0,[n].concat(u,[e]))}},l=function(e){return{done:!1,value:(0,f.cancel)(e)}},d=void 0,v=void 0,p=function(e){return d=e},h=function(e){return v=e};return r({q1:function(){return["q2",a,h]},q2:function(){return v===i.END?[s]:d?["q3",l(d)]:["q1",c(v),p]},q3:function(){return["q1",c(v),p]}},"q1","takeLatest("+String(e)+", "+n.name+")")}Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function e(e,n){var t=[],r=!0,u=!1,o=void 0;try{for(var a,i=e[Symbol.iterator]();!(r=(a=i.next()).done)&&(t.push(a.value),!n||t.length!==n);r=!0);}catch(c){u=!0,o=c}finally{try{!r&&i.return&&i.return()}finally{if(u)throw o}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();n.takeEvery=u,n.takeLatest=o;var i=t(2),c=t(1),f=t(3),l={done:!0,value:void 0},s={}},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=t(1);Object.defineProperty(n,"TASK",{enumerable:!0,get:function(){return r.TASK}}),Object.defineProperty(n,"noop",{enumerable:!0,get:function(){return r.noop}}),Object.defineProperty(n,"is",{enumerable:!0,get:function(){return r.is}}),Object.defineProperty(n,"deferred",{enumerable:!0,get:function(){return r.deferred}}),Object.defineProperty(n,"arrayOfDeffered",{enumerable:!0,get:function(){return r.arrayOfDeffered}}),Object.defineProperty(n,"createMockTask",{enumerable:!0,get:function(){return r.createMockTask}});var u=t(3);Object.defineProperty(n,"asEffect",{enumerable:!0,get:function(){return u.asEffect}})},function(e,n){function t(){f=!1,a.length?c=a.concat(c):l=-1,c.length&&r()}function r(){if(!f){var e=setTimeout(t);f=!0;for(var n=c.length;n;){for(a=c,c=[];++l<n;)a&&a[l].run();l=-1,n=c.length}a=null,f=!1,clearTimeout(e)}}function u(e,n){this.fun=e,this.array=n}function o(){}var a,i=e.exports={},c=[],f=!1,l=-1;i.nextTick=function(e){var n=new Array(arguments.length-1);if(arguments.length>1)for(var t=1;t<arguments.length;t++)n[t-1]=arguments[t];c.push(new u(e,n)),1!==c.length||f||setTimeout(r,0)},u.prototype.run=function(){this.fun.apply(null,this.array)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.versions={},i.on=o,i.addListener=o,i.once=o,i.off=o,i.removeListener=o,i.removeAllListeners=o,i.emit=o,i.binding=function(e){throw new Error("process.binding is not supported")},i.cwd=function(){return"/"},i.chdir=function(e){throw new Error("process.chdir is not supported")},i.umask=function(){return 0}}])}); |
@@ -6,15 +6,88 @@ 'use strict'; | ||
}); | ||
exports.select = exports.cancel = exports.join = exports.fork = exports.cps = exports.apply = exports.call = exports.race = exports.put = exports.take = undefined; | ||
var _io = require('./internal/io'); | ||
exports.take = _io.take; | ||
exports.put = _io.put; | ||
exports.race = _io.race; | ||
exports.call = _io.call; | ||
exports.apply = _io.apply; | ||
exports.cps = _io.cps; | ||
exports.fork = _io.fork; | ||
exports.join = _io.join; | ||
exports.cancel = _io.cancel; | ||
exports.select = _io.select; | ||
Object.defineProperty(exports, 'take', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.take; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'takem', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.takem; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'put', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.put; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'race', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.race; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'call', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.call; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'apply', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.apply; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'cps', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.cps; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'fork', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.fork; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'spawn', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.spawn; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'join', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.join; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'cancel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.cancel; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'select', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.select; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'actionChannel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.actionChannel; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'cancelled', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.cancelled; | ||
} | ||
}); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.utils = exports.effects = exports.takeLatest = exports.takeEvery = exports.storeIO = exports.runSaga = exports.isCancelError = exports.SagaCancellationException = undefined; | ||
exports.utils = exports.effects = exports.delay = exports.takeLatest = exports.takeEvery = exports.buffers = exports.channel = exports.eventChannel = exports.END = exports.CANCEL = exports.runSaga = undefined; | ||
@@ -17,9 +17,42 @@ var _runSaga = require('./internal/runSaga'); | ||
}); | ||
Object.defineProperty(exports, 'storeIO', { | ||
var _proc = require('./internal/proc'); | ||
Object.defineProperty(exports, 'CANCEL', { | ||
enumerable: true, | ||
get: function get() { | ||
return _runSaga.storeIO; | ||
return _proc.CANCEL; | ||
} | ||
}); | ||
var _channel = require('./internal/channel'); | ||
Object.defineProperty(exports, 'END', { | ||
enumerable: true, | ||
get: function get() { | ||
return _channel.END; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'eventChannel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _channel.eventChannel; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'channel', { | ||
enumerable: true, | ||
get: function get() { | ||
return _channel.channel; | ||
} | ||
}); | ||
var _buffers = require('./internal/buffers'); | ||
Object.defineProperty(exports, 'buffers', { | ||
enumerable: true, | ||
get: function get() { | ||
return _buffers.buffers; | ||
} | ||
}); | ||
var _sagaHelpers = require('./internal/sagaHelpers'); | ||
@@ -40,2 +73,11 @@ | ||
var _utils = require('./internal/utils'); | ||
Object.defineProperty(exports, 'delay', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.delay; | ||
} | ||
}); | ||
var _middleware = require('./internal/middleware'); | ||
@@ -45,6 +87,2 @@ | ||
var _SagaCancellationException2 = require('./internal/SagaCancellationException'); | ||
var _SagaCancellationException3 = _interopRequireDefault(_SagaCancellationException2); | ||
var _effects = require('./effects'); | ||
@@ -54,5 +92,5 @@ | ||
var _utils = require('./utils'); | ||
var _utils2 = require('./utils'); | ||
var utils = _interopRequireWildcard(_utils); | ||
var utils = _interopRequireWildcard(_utils2); | ||
@@ -64,8 +102,3 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
exports.default = _middleware2.default; | ||
var SagaCancellationException = exports.SagaCancellationException = _SagaCancellationException3.default; | ||
var isCancelError = exports.isCancelError = function isCancelError(error) { | ||
return error instanceof SagaCancellationException; | ||
}; | ||
exports.effects = effects; | ||
exports.utils = utils; |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.asEffect = exports.SELECT_ARG_ERROR = exports.INVALID_PATTERN = exports.CANCEL_ARG_ERROR = exports.JOIN_ARG_ERROR = exports.FORK_ARG_ERROR = exports.CALL_FUNCTION_ARG_ERROR = undefined; | ||
exports.asEffect = undefined; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
exports.matcher = matcher; | ||
exports.take = take; | ||
exports.takem = takem; | ||
exports.put = put; | ||
@@ -19,17 +19,13 @@ exports.race = race; | ||
exports.fork = fork; | ||
exports.spawn = spawn; | ||
exports.join = join; | ||
exports.cancel = cancel; | ||
exports.select = select; | ||
exports.actionChannel = actionChannel; | ||
exports.cancelled = cancelled; | ||
var _utils = require("./utils"); | ||
var _utils = require('./utils'); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var CALL_FUNCTION_ARG_ERROR = exports.CALL_FUNCTION_ARG_ERROR = "call/cps/fork first argument must be a function, an array [context, function] or an object {context, fn}"; | ||
var FORK_ARG_ERROR = exports.FORK_ARG_ERROR = "fork first argument must be a generator function or an iterator"; | ||
var JOIN_ARG_ERROR = exports.JOIN_ARG_ERROR = "join argument must be a valid task (a result of a fork)"; | ||
var CANCEL_ARG_ERROR = exports.CANCEL_ARG_ERROR = "cancel argument must be a valid task (a result of a fork)"; | ||
var INVALID_PATTERN = exports.INVALID_PATTERN = "Invalid pattern passed to `take` (HINT: check if you didn't mispell a constant)"; | ||
var SELECT_ARG_ERROR = exports.SELECT_ARG_ERROR = "select first argument must be a function"; | ||
var IO = (0, _utils.sym)('IO'); | ||
@@ -45,2 +41,4 @@ var TAKE = 'TAKE'; | ||
var SELECT = 'SELECT'; | ||
var ACTION_CHANNEL = 'ACTION_CHANNEL'; | ||
var CANCELLED = 'CANCELLED'; | ||
@@ -53,39 +51,38 @@ var effect = function effect(type, payload) { | ||
var matchers = { | ||
wildcard: function wildcard() { | ||
return _utils.kTrue; | ||
}, | ||
default: function _default(pattern) { | ||
return function (input) { | ||
return input.type === pattern; | ||
}; | ||
}, | ||
array: function array(patterns) { | ||
return function (input) { | ||
return patterns.some(function (p) { | ||
return p === input.type; | ||
}); | ||
}; | ||
}, | ||
predicate: function predicate(_predicate) { | ||
return function (input) { | ||
return _predicate(input); | ||
}; | ||
} | ||
}; | ||
function take(channel, pattern) { | ||
if (arguments.length >= 2) { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'take(channel, pattern): channel is undefined'); | ||
(0, _utils.check)(channel, _utils.is.take, 'take(channel, pattern): argument ' + channel + ' is not a valid channel (channel argument must have a take method)'); | ||
(0, _utils.check)(pattern, _utils.is.notUndef, 'take(channel, pattern): pattern is undefined'); | ||
(0, _utils.check)(pattern, _utils.is.pattern, 'take(channel, pattern): argument ' + pattern + ' is not a valid pattern (pattern must be String | Function: a => boolean | Array<String>)'); | ||
} else if (arguments.length === 1) { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'take(patternOrChannel): undefined argument'); | ||
if (!_utils.is.take(channel)) { | ||
if (_utils.is.pattern(channel)) { | ||
pattern = channel; | ||
channel = null; | ||
} else throw new Error('take(patternOrChannel): argument ' + channel + ' is not valid channel or a valid pattern'); | ||
} else pattern = '*'; | ||
} else pattern = '*'; | ||
function matcher(pattern) { | ||
return (pattern === '*' ? matchers.wildcard : _utils.is.array(pattern) ? matchers.array : _utils.is.func(pattern) ? matchers.predicate : matchers.default)(pattern); | ||
return effect(TAKE, { channel: channel, pattern: pattern }); | ||
} | ||
function take(pattern) { | ||
if (arguments.length > 0 && _utils.is.undef(pattern)) { | ||
throw new Error(INVALID_PATTERN); | ||
} | ||
return effect(TAKE, _utils.is.undef(pattern) ? '*' : pattern); | ||
function takem() { | ||
var eff = take.apply(undefined, arguments); | ||
eff[TAKE].maybe = true; | ||
return eff; | ||
} | ||
function put(action) { | ||
return effect(PUT, action); | ||
function put(channel, action) { | ||
if (arguments.length > 1) { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'put(channel, action): argument channel is undefined'); | ||
(0, _utils.check)(channel, _utils.is.put, 'put(channel, action): argument ' + channel + ' is not a valid channel (channel argument must have a put method)'); | ||
(0, _utils.check)(action, _utils.is.notUndef, 'put(channel, action): argument action is undefined'); | ||
} else { | ||
(0, _utils.check)(channel, _utils.is.notUndef, 'put(action): argument action is undefined'); | ||
action = channel; | ||
channel = null; | ||
} | ||
return effect(PUT, { channel: channel, action: action }); | ||
} | ||
@@ -97,4 +94,4 @@ | ||
function getFnCallDesc(fn, args) { | ||
(0, _utils.check)(fn, _utils.is.notUndef, CALL_FUNCTION_ARG_ERROR); | ||
function getFnCallDesc(meth, fn, args) { | ||
(0, _utils.check)(fn, _utils.is.notUndef, meth + ': argument fn is undefined'); | ||
@@ -114,3 +111,3 @@ var context = null; | ||
} | ||
(0, _utils.check)(fn, _utils.is.func, CALL_FUNCTION_ARG_ERROR); | ||
(0, _utils.check)(fn, _utils.is.func, meth + ': argument ' + fn + ' is not a function'); | ||
@@ -125,3 +122,3 @@ return { context: context, fn: fn, args: args }; | ||
return effect(CALL, getFnCallDesc(fn, args)); | ||
return effect(CALL, getFnCallDesc('call', fn, args)); | ||
} | ||
@@ -132,3 +129,3 @@ | ||
return effect(CALL, getFnCallDesc({ context: context, fn: fn }, args)); | ||
return effect(CALL, getFnCallDesc('apply', { context: context, fn: fn }, args)); | ||
} | ||
@@ -141,3 +138,3 @@ | ||
return effect(CPS, getFnCallDesc(fn, args)); | ||
return effect(CPS, getFnCallDesc('cps', fn, args)); | ||
} | ||
@@ -150,5 +147,15 @@ | ||
return effect(FORK, getFnCallDesc(fn, args)); | ||
return effect(FORK, getFnCallDesc('fork', fn, args)); | ||
} | ||
function spawn(fn) { | ||
for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | ||
args[_key4 - 1] = arguments[_key4]; | ||
} | ||
var eff = fork.apply(undefined, [fn].concat(args)); | ||
eff[FORK].detached = true; | ||
return eff; | ||
} | ||
var isForkedTask = function isForkedTask(task) { | ||
@@ -158,17 +165,19 @@ return task[_utils.TASK]; | ||
function join(taskDesc) { | ||
if (!isForkedTask(taskDesc)) throw new Error(JOIN_ARG_ERROR); | ||
function join(task) { | ||
(0, _utils.check)(task, _utils.is.notUndef, 'join(task): argument task is undefined'); | ||
if (!isForkedTask(task)) throw new Error('join(task): argument ' + task + ' is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)'); | ||
return effect(JOIN, taskDesc); | ||
return effect(JOIN, task); | ||
} | ||
function cancel(taskDesc) { | ||
if (!isForkedTask(taskDesc)) throw new Error(CANCEL_ARG_ERROR); | ||
function cancel(task) { | ||
(0, _utils.check)(task, _utils.is.notUndef, 'cancel(task): argument task is undefined'); | ||
if (!isForkedTask(task)) throw new Error('cancel(task): argument ' + task + ' is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)'); | ||
return effect(CANCEL, taskDesc); | ||
return effect(CANCEL, task); | ||
} | ||
function select(selector) { | ||
for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | ||
args[_key4 - 1] = arguments[_key4]; | ||
for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { | ||
args[_key5 - 1] = arguments[_key5]; | ||
} | ||
@@ -179,3 +188,4 @@ | ||
} else { | ||
(0, _utils.check)(selector, _utils.is.func, SELECT_ARG_ERROR); | ||
(0, _utils.check)(select, _utils.is.notUndef, 'select(selector,[...]): argument selector is undefined'); | ||
(0, _utils.check)(selector, _utils.is.func, 'select(selector,[...]): argument ' + selector + ' is not a function'); | ||
} | ||
@@ -185,2 +195,19 @@ return effect(SELECT, { selector: selector, args: args }); | ||
/** | ||
channel(pattern, [buffer]) => creates an event channel for store actions | ||
**/ | ||
function actionChannel(pattern, buffer) { | ||
(0, _utils.check)(pattern, _utils.is.notUndef, 'actionChannel(pattern,...): argument pattern is undefined'); | ||
if (arguments.length > 1) { | ||
(0, _utils.check)(buffer, _utils.is.notUndef, 'actionChannel(pattern, buffer): argument buffer is undefined'); | ||
(0, _utils.check)(buffer, _utils.is.notUndef, 'actionChannel(pattern, buffer): argument ' + buffer + ' is not a valid buffer'); | ||
} | ||
return effect(ACTION_CHANNEL, { pattern: pattern, buffer: buffer }); | ||
} | ||
function cancelled() { | ||
return effect(CANCELLED, {}); | ||
} | ||
var asEffect = exports.asEffect = { | ||
@@ -213,3 +240,9 @@ take: function take(effect) { | ||
return effect && effect[IO] && effect[SELECT]; | ||
}, | ||
actionChannel: function actionChannel(effect) { | ||
return effect && effect[IO] && effect[ACTION_CHANNEL]; | ||
}, | ||
cancelled: function cancelled(effect) { | ||
return effect && effect[IO] && effect[CANCELLED]; | ||
} | ||
}; |
@@ -6,3 +6,2 @@ 'use strict'; | ||
}); | ||
exports.GET_STATE_DEPRECATED_WARNING = exports.RUN_SAGA_DYNAMIC_ERROR = exports.sagaArgError = undefined; | ||
exports.default = sagaMiddlewareFactory; | ||
@@ -16,33 +15,15 @@ | ||
var _emitter = require('./emitter'); | ||
var _channel = require('./channel'); | ||
var _emitter2 = _interopRequireDefault(_emitter); | ||
var _monitorActions = require('./monitorActions'); | ||
var _SagaCancellationException = require('./SagaCancellationException'); | ||
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var sagaArgError = exports.sagaArgError = function sagaArgError(fn, pos, saga) { | ||
return '\n ' + fn + ' can only be called on Generator functions\n Argument ' + saga + ' at position ' + pos + ' is not function!\n'; | ||
}; | ||
function sagaMiddlewareFactory() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
var RUN_SAGA_DYNAMIC_ERROR = exports.RUN_SAGA_DYNAMIC_ERROR = 'Before running a Saga dynamically using middleware.run, you must mount the Saga middleware on the Store using applyMiddleware'; | ||
var runSagaDynamically = void 0; | ||
var GET_STATE_DEPRECATED_WARNING = exports.GET_STATE_DEPRECATED_WARNING = '\n Using the \'getState\' param of Sagas to access the state is deprecated since 0.9.1\n To access the Store\'s state use \'yield select()\' instead\n For more infos see http://yelouafi.github.io/redux-saga/docs/api/index.html#selectselector-args\n'; | ||
function sagaMiddlewareFactory() { | ||
for (var _len = arguments.length, sagas = Array(_len), _key = 0; _key < _len; _key++) { | ||
sagas[_key] = arguments[_key]; | ||
if (_utils.is.func(options)) { | ||
throw new Error('You passed a function to the Saga middleware. You are likely trying to start a Saga by directly passing it to the middleware. This is no longer possible starting from 0.10.0. To run a Saga, you must do it dynamically AFTER mounting the middleware into the store.\n Example:\n import createSagaMiddleware from \'redux-saga\'\n ... other imports\n\n const sagaMiddleware = createSagaMiddleware()\n const store = createStore(reducer, applyMiddleware(sagaMiddleware))\n sagaMiddleware.run(saga, ...args)\n '); | ||
} | ||
var runSagaDynamically = undefined; | ||
sagas.forEach(function (saga, idx) { | ||
return (0, _utils.check)(saga, _utils.is.func, sagaArgError('createSagaMiddleware', idx, saga)); | ||
}); | ||
function sagaMiddleware(_ref) { | ||
@@ -52,32 +33,17 @@ var getState = _ref.getState; | ||
var sagaEmitter = (0, _emitter2.default)(); | ||
var monitor = _utils.isDev ? function (action) { | ||
return (0, _utils.asap)(function () { | ||
return dispatch(action); | ||
}); | ||
} : undefined; | ||
runSagaDynamically = runSaga; | ||
var sagaEmitter = (0, _channel.emitter)(); | ||
var getStateDeprecated = function getStateDeprecated() { | ||
(0, _utils.warnDeprecated)(GET_STATE_DEPRECATED_WARNING); | ||
return getState(); | ||
}; | ||
function runSaga(saga) { | ||
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
args[_key2 - 1] = arguments[_key2]; | ||
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
args[_key - 1] = arguments[_key]; | ||
} | ||
return (0, _proc2.default)(saga.apply(undefined, [getStateDeprecated].concat(args)), sagaEmitter.subscribe, dispatch, getState, monitor, 0, saga.name); | ||
return (0, _proc2.default)(saga.apply(undefined, args), sagaEmitter.subscribe, dispatch, getState, options.sagaMonitor, 0, saga.name); | ||
} | ||
runSagaDynamically = runSaga; | ||
sagas.forEach(runSaga); | ||
return function (next) { | ||
return function (action) { | ||
var result = next(action); // hit reducers | ||
// filter out monitor actions to avoid endless loops | ||
// see https://github.com/yelouafi/redux-saga/issues/61 | ||
if (!action[_monitorActions.MONITOR_ACTION]) sagaEmitter.emit(action); | ||
sagaEmitter.emit(action); | ||
return result; | ||
@@ -89,16 +55,9 @@ }; | ||
sagaMiddleware.run = function (saga) { | ||
for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { | ||
args[_key3 - 1] = arguments[_key3]; | ||
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { | ||
args[_key2 - 1] = arguments[_key2]; | ||
} | ||
if (!runSagaDynamically) { | ||
throw new Error(RUN_SAGA_DYNAMIC_ERROR); | ||
} | ||
(0, _utils.check)(saga, _utils.is.func, sagaArgError('sagaMiddleware.run', 0, saga)); | ||
var task = runSagaDynamically.apply(undefined, [saga].concat(args)); | ||
task.done.catch(function (err) { | ||
if (!(err instanceof _SagaCancellationException2.default)) throw err; | ||
}); | ||
return task; | ||
(0, _utils.check)(runSagaDynamically, _utils.is.notUndef, 'Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware'); | ||
(0, _utils.check)(saga, _utils.is.func, 'sagaMiddleware.run(saga, ...args): saga argument must be a Generator function!'); | ||
return runSagaDynamically.apply(undefined, [saga].concat(args)); | ||
}; | ||
@@ -105,0 +64,0 @@ |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.MANUAL_CANCEL = exports.RACE_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.CANCEL = exports.undefindInputError = exports.NOT_ITERATOR_ERROR = undefined; | ||
exports.Never = exports.CANCEL = exports.NOT_ITERATOR_ERROR = undefined; | ||
exports.default = proc; | ||
@@ -12,15 +12,15 @@ | ||
var _io = require('./io'); | ||
var _asap = require('./asap'); | ||
var _monitorActions = require('./monitorActions'); | ||
var _asap2 = _interopRequireDefault(_asap); | ||
var monitorActions = _interopRequireWildcard(_monitorActions); | ||
var _io = require('./io'); | ||
var _SagaCancellationException = require('./SagaCancellationException'); | ||
var _channel = require('./channel'); | ||
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException); | ||
var _buffers = require('./buffers'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
function _defineEnumerableProperties(obj, descs) { for (var key in descs) { var desc = descs[key]; desc.configurable = desc.enumerable = true; if ("value" in desc) desc.writable = true; Object.defineProperty(obj, key, desc); } return obj; } | ||
@@ -32,13 +32,106 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator'; | ||
var undefindInputError = exports.undefindInputError = function undefindInputError(name) { | ||
return '\n ' + name + ' saga was provided with an undefined input action\n Hints :\n - check that your Action Creator returns a non undefined value\n - if the Saga was started using runSaga, check that your subscribe source provides the action to its listeners\n'; | ||
}; | ||
var CANCEL = exports.CANCEL = (0, _utils.sym)('@@redux-saga/cancelPromise'); | ||
var PARALLEL_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = 'PARALLEL_AUTO_CANCEL'; | ||
var RACE_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = 'RACE_AUTO_CANCEL'; | ||
var MANUAL_CANCEL = exports.MANUAL_CANCEL = 'MANUAL_CANCEL'; | ||
var CANCEL = exports.CANCEL = (0, _utils.sym)('cancelPromise'); | ||
var nextEffectId = (0, _utils.autoInc)(); | ||
var Never = exports.Never = { | ||
toString: function toString() { | ||
return '@@redux-saga/Never'; | ||
} | ||
}; | ||
Object.freeze(Never); | ||
var matchers = { | ||
wildcard: function wildcard() { | ||
return _utils.kTrue; | ||
}, | ||
default: function _default(pattern) { | ||
return function (input) { | ||
return input.type === pattern; | ||
}; | ||
}, | ||
array: function array(patterns) { | ||
return function (input) { | ||
return patterns.some(function (p) { | ||
return p === input.type; | ||
}); | ||
}; | ||
}, | ||
predicate: function predicate(_predicate) { | ||
return function (input) { | ||
return _predicate(input); | ||
}; | ||
} | ||
}; | ||
function matcher(pattern) { | ||
return (pattern === '*' ? matchers.wildcard : _utils.is.array(pattern) ? matchers.array : _utils.is.func(pattern) ? matchers.predicate : matchers.default)(pattern); | ||
} | ||
/** | ||
Used to track a parent task and its forks | ||
In the new fork model, forked tasks are attached by default to their parent | ||
We model this using the concept of Parent task && main Task | ||
main task is the main flow of the current Generator, the parent tasks is the | ||
aggregation of the main tasks + all its forked tasks. | ||
Thus the whole model represents an execution tree with multiple branches (vs the | ||
linear execution tree in sequential (non parallel) programming) | ||
A parent tasks has the following semantics | ||
- It completes iff all its forks either complete or all cancelled | ||
- If it's cancelled, all forks are cancelled as well | ||
- It aborts if any uncaught error bubbles up from forks | ||
- If it completes, the return value is the one returned by the main task | ||
**/ | ||
function forkQueue(name, mainTask, cb) { | ||
var tasks = [], | ||
result = void 0, | ||
completed = false; | ||
addTask(mainTask); | ||
function addTask(task) { | ||
tasks.push(task); | ||
task.cont = function (err, res) { | ||
if (completed) return; | ||
(0, _utils.remove)(tasks, task); | ||
task.cont = _utils.noop; | ||
if (err) { | ||
cancelAll(); | ||
cb(err); | ||
} else { | ||
if (task === mainTask) result = res; | ||
if (!tasks.length) { | ||
completed = true; | ||
cb(null, result); | ||
} | ||
} | ||
}; | ||
//task.cont.cancel = task.cancel | ||
} | ||
function cancelAll() { | ||
if (completed) return; | ||
completed = true; | ||
tasks.forEach(function (t) { | ||
t.cont = _utils.noop; | ||
t.cancel(); | ||
}); | ||
tasks = []; | ||
} | ||
return { | ||
addTask: addTask, | ||
cancelAll: cancelAll, | ||
getTasks: function getTasks() { | ||
return tasks; | ||
}, | ||
taskNames: function taskNames() { | ||
return tasks.map(function (t) { | ||
return t.name; | ||
}); | ||
} | ||
}; | ||
} | ||
function proc(iterator) { | ||
@@ -50,6 +143,6 @@ var subscribe = arguments.length <= 1 || arguments[1] === undefined ? function () { | ||
var getState = arguments.length <= 3 || arguments[3] === undefined ? _utils.noop : arguments[3]; | ||
var monitor = arguments.length <= 4 || arguments[4] === undefined ? _utils.noop : arguments[4]; | ||
var monitor = arguments[4]; | ||
var parentEffectId = arguments.length <= 5 || arguments[5] === undefined ? 0 : arguments[5]; | ||
var name = arguments.length <= 6 || arguments[6] === undefined ? 'anonymous' : arguments[6]; | ||
var forked = arguments[7]; | ||
var cont = arguments[7]; | ||
@@ -59,28 +152,5 @@ | ||
var UNDEFINED_INPUT_ERROR = undefindInputError(name); | ||
// tracks the current `take` effects | ||
var deferredInputs = []; | ||
// Promise to be resolved/rejected when this generator terminates (or throws) | ||
var deferredEnd = (0, _utils.deferred)(); | ||
// subscribe to input events, this will resolve the current `take` effects | ||
var unsubscribe = subscribe(function (input) { | ||
if (input === undefined) throw UNDEFINED_INPUT_ERROR; | ||
for (var i = 0; i < deferredInputs.length; i++) { | ||
var def = deferredInputs[i]; | ||
if (def.match(input)) { | ||
// cancel all deferredInputs; parallel takes are disallowed | ||
// and in concurrent takes, first wins | ||
deferredInputs = []; | ||
def.resolve(input); | ||
} | ||
} | ||
}); | ||
var stdChannel = (0, _channel.eventChannel)(subscribe); | ||
/** | ||
cancel : (SagaCancellationException) -> () | ||
Tracks the current effect cancellation | ||
Tracks the current effect cancellation | ||
Each time the generator progresses. calling runEffect will set a new value | ||
@@ -92,19 +162,46 @@ on it. It allows propagating cancellation to child effects | ||
/** | ||
Creates a new task descriptor for this generator | ||
Creates a new task descriptor for this generator, We'll also create a main task | ||
to track the main flow (besides other forked tasks) | ||
**/ | ||
var task = newTask(parentEffectId, name, iterator, deferredEnd.promise, forked); | ||
var task = newTask(parentEffectId, name, iterator, cont); | ||
var mainTask = { name: name, cancel: cancelMain, isRunning: true }; | ||
var taskQueue = forkQueue(name, mainTask, end); | ||
/** | ||
cancellation of the main task. We'll simply resume the Generator with a Cancel | ||
**/ | ||
function cancelMain() { | ||
if (mainTask.isRunning && !mainTask.isCancelled) { | ||
mainTask.isCancelled = true; | ||
next(null, Never); | ||
} | ||
} | ||
/** | ||
This may be called by a parent generator to trigger/propagate cancellation | ||
We'll simply cancel the current effect, which will reject that effect | ||
The rejection will throw the injected SagaCancellationException into the flow | ||
of this generator | ||
cancel all pending tasks (including the main task), then end the current task. | ||
Cancellation propagates down to the whole execution tree holded by this Parent task | ||
It's also propagated to all joiners of this task and their execution tree/joiners | ||
Cancellation is noop for terminated/Cancelled tasks tasks | ||
**/ | ||
task.done[CANCEL] = function (_ref) { | ||
var type = _ref.type; | ||
var origin = _ref.origin; | ||
function cancel() { | ||
/** | ||
We need to check both Running and Cancelled status | ||
Tasks can be Cancelled but still Running | ||
**/ | ||
if (iterator._isRunning && !iterator._isCancelled) { | ||
iterator._isCancelled = true; | ||
taskQueue.cancelAll(); | ||
/** | ||
Ending with a Never result will propagate the Cancellation to all joiners | ||
**/ | ||
end(null, Never); | ||
} | ||
} | ||
/** | ||
attaches cancellation logic to this task's continuation | ||
this will permit cancellation to propagate down the call chain | ||
**/ | ||
cont && (cont.cancel = cancel); | ||
next.cancel(new _SagaCancellationException2.default(type, name, origin)); | ||
}; | ||
// tracks the running status | ||
@@ -120,16 +217,2 @@ iterator._isRunning = true; | ||
/** | ||
Print error in a useful way whether in a browser environment | ||
(with expandable error stack traces), or in a node.js environment | ||
(text-only log output) | ||
**/ | ||
function logError(level, message, error) { | ||
/*eslint-disable no-console*/ | ||
if (typeof window === 'undefined') { | ||
console.log('redux-saga ' + level + ': ' + message + '\n' + error.stack); | ||
} else { | ||
console[level].call(console, message, error); | ||
} | ||
} | ||
/** | ||
This is the generator driver | ||
@@ -141,38 +224,60 @@ It's a recursive async/continuation function which calls itself | ||
// Preventive measure. If we end up here, then there is really something wrong | ||
if (!iterator._isRunning) throw new Error('Trying to resume an already finished generator'); | ||
if (!mainTask.isRunning) throw new Error('Trying to resume an already finished generator'); | ||
try { | ||
// calling iterator.throw on a generator that doesn't define a correponding try/Catch | ||
// will throw an exception and jump to the catch block below | ||
var result = error ? iterator.throw(error) : iterator.next(arg); | ||
var result = void 0; | ||
if (error) result = iterator.throw(error);else if (arg === Never) { | ||
/** | ||
getting Never autoamtically cancels the main task | ||
We can get this value here | ||
- By cancelling the parent task manually | ||
- By joining a Cancelled task | ||
- By taking from a channel that ended using `take` (and not `takem` used to trap End of channels) | ||
**/ | ||
mainTask.isCancelled = true; | ||
/** | ||
Cancels the current effect; this will propagate the cancellation down to any called tasks | ||
**/ | ||
next.cancel(); | ||
/** | ||
If this Generator has a `return` method then invokes it | ||
Thill will jump to the finally block | ||
**/ | ||
result = _utils.is.func(iterator.return) ? iterator.return(Never) : { done: true, value: Never }; | ||
} else result = iterator.next(arg); | ||
if (!result.done) { | ||
runEffect(result.value, parentEffectId, '', next); | ||
} else { | ||
end(result.value); | ||
/** | ||
This Generator has ended, terminate the main task and notify the fork queue | ||
**/ | ||
mainTask.isMainRunning = false; | ||
mainTask.cont && mainTask.cont(null, result.value); | ||
} | ||
} catch (error) { | ||
end(error, true); | ||
if (error instanceof _SagaCancellationException2.default) { | ||
if (_utils.isDev) { | ||
logError('warn', name + ': uncaught', error); | ||
} | ||
} else { | ||
logError('error', name + ': uncaught', error); | ||
//if(!forked) | ||
// throw error | ||
} | ||
if (mainTask.isCancelled) (0, _utils.log)('error', 'uncaught at ' + name, error.message); | ||
mainTask.isMainRunning = false; | ||
mainTask.cont(error); | ||
} | ||
} | ||
function end(result, isError) { | ||
function end(error, result) { | ||
iterator._isRunning = false; | ||
if (!isError) { | ||
stdChannel.close(); | ||
if (!error) { | ||
if (result === Never && _utils.isDev) (0, _utils.log)('info', name + ' has been cancelled', ''); | ||
iterator._result = result; | ||
deferredEnd.resolve(result); | ||
iterator._deferredEnd && iterator._deferredEnd.resolve(result); | ||
} else { | ||
iterator._error = result; | ||
deferredEnd.reject(result); | ||
if (error instanceof Error) error.sagaStack = 'at ' + name + ' \n ' + (error.sagaStack || error.message); | ||
if (!task.cont) (0, _utils.log)('error', 'uncaught', error.sagaStack || error.message); | ||
iterator._error = error; | ||
iterator._deferredEnd && iterator._deferredEnd.reject(error); | ||
} | ||
unsubscribe(); | ||
task.cont && task.cont(error, result); | ||
task.joiners.forEach(function (j) { | ||
return j.cb(error, result); | ||
}); | ||
task.joiners = null; | ||
} | ||
@@ -185,3 +290,3 @@ | ||
var effectId = nextEffectId(); | ||
monitor(monitorActions.effectTriggered(effectId, parentEffectId, label, effect)); | ||
monitor && monitor.effectTriggered({ effectId: effectId, parentEffectId: parentEffectId, label: label, effect: effect }); | ||
@@ -193,3 +298,3 @@ /** | ||
**/ | ||
var effectSettled = undefined; | ||
var effectSettled = void 0; | ||
@@ -202,3 +307,5 @@ // Completion callback passed to the appropriate effect runner | ||
cb.cancel = _utils.noop; // defensive measure | ||
err ? monitor(monitorActions.effectRejected(effectId, err)) : monitor(monitorActions.effectResolved(effectId, res)); | ||
if (monitor) { | ||
err ? monitor.effectRejected(effectId, err) : monitor.effectResolved(effectId, res); | ||
} | ||
@@ -211,3 +318,3 @@ cb(err, res); | ||
// setup cancellation logic on the parent cb | ||
cb.cancel = function (cancelError) { | ||
cb.cancel = function () { | ||
// prevents cancelling an already completed effect | ||
@@ -219,17 +326,13 @@ if (effectSettled) return; | ||
propagates cancel downward | ||
catch uncaught cancellations errors, | ||
because w'll throw our own cancellation error inside this generator | ||
catch uncaught cancellations errors; since we can no longer call the completion | ||
callback, log errors raised during cancellations into the console | ||
**/ | ||
try { | ||
currCb.cancel(cancelError); | ||
currCb.cancel(); | ||
} catch (err) { | ||
void 0; | ||
(0, _utils.log)('error', 'uncaught at ' + name, err.message); | ||
} | ||
currCb.cancel = _utils.noop; // defensive measure | ||
/** | ||
triggers/propagates the cancellation error | ||
**/ | ||
cb(cancelError); | ||
monitor(monitorActions.effectRejected(effectId, cancelError)); | ||
monitor && monitor.effectCancelled(effectId); | ||
}; | ||
@@ -249,3 +352,3 @@ | ||
**/ | ||
var data = undefined; | ||
var data = void 0; | ||
return( | ||
@@ -256,3 +359,3 @@ // Non declarative effect | ||
// declarative effects | ||
: _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.take(effect)) ? runTakeEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.put(effect)) ? runPutEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.race(effect)) ? runRaceEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.call(effect)) ? runCallEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.cps(effect)) ? runCPSEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.fork(effect)) ? runForkEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.join(effect)) ? runJoinEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.cancel(effect)) ? runCancelEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.select(effect)) ? runSelectEffect(data, currCb) : /* anything else returned as is */currCb(null, effect) | ||
: _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.take(effect)) ? runTakeEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.put(effect)) ? runPutEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.race(effect)) ? runRaceEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.call(effect)) ? runCallEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.cps(effect)) ? runCPSEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.fork(effect)) ? runForkEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.asEffect.join(effect)) ? runJoinEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.cancel(effect)) ? runCancelEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.select(effect)) ? runSelectEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.actionChannel(effect)) ? runChannelEffect(data, currCb) : _utils.is.notUndef(data = _io.asEffect.cancelled(effect)) ? runCancelledEffect(data, currCb) : /* anything else returned as is */currCb(null, effect) | ||
); | ||
@@ -274,27 +377,45 @@ } | ||
function resolveIterator(iterator, effectId, name, cb) { | ||
resolvePromise(proc(iterator, subscribe, dispatch, getState, monitor, effectId, name).done, cb); | ||
proc(iterator, subscribe, dispatch, getState, monitor, effectId, name, cb); | ||
} | ||
function runTakeEffect(pattern, cb) { | ||
var def = { | ||
match: (0, _io.matcher)(pattern), | ||
pattern: pattern, | ||
resolve: function resolve(input) { | ||
return cb(null, input); | ||
} | ||
function runTakeEffect(_ref, cb) { | ||
var channel = _ref.channel; | ||
var pattern = _ref.pattern; | ||
var maybe = _ref.maybe; | ||
channel = channel || stdChannel; | ||
var takeCb = function takeCb(inp) { | ||
return inp instanceof Error ? cb(inp) : inp === _channel.END && !maybe ? cb(null, Never) : cb(null, inp); | ||
}; | ||
deferredInputs.push(def); | ||
// cancellation logic for take effect | ||
cb.cancel = function () { | ||
return (0, _utils.remove)(deferredInputs, def); | ||
}; | ||
try { | ||
channel.take(takeCb, matcher(pattern)); | ||
} catch (err) { | ||
return cb(err); | ||
} | ||
cb.cancel = takeCb.cancel; | ||
} | ||
function runPutEffect(action, cb) { | ||
//synchronously nested dispatches can not be performed | ||
// because on a sync interleaved take/put the receiver will dispatch the | ||
// action before the sender can take the aknowledge | ||
// this workaround allows the dispatch to occur on the next microtask | ||
(0, _utils.asap)(function () { | ||
return cb(null, dispatch(action)); | ||
function runPutEffect(_ref2, cb) { | ||
var channel = _ref2.channel; | ||
var action = _ref2.action; | ||
/* | ||
Use a reentrant lock `asap` to flatten all nested dispatches | ||
If this put cause another Saga to take this action an then immediately | ||
put an action that will be taken by this Saga. Then the outer Saga will miss | ||
the action from the inner Saga b/c this put has not yet returned. | ||
*/ | ||
(0, _asap2.default)(function () { | ||
var result = void 0; | ||
try { | ||
result = (channel ? channel.put : dispatch)(action); | ||
} catch (error) { | ||
return cb(error); | ||
} | ||
if (_utils.is.promise(result)) { | ||
resolvePromise(result, cb); | ||
} else { | ||
return cb(null, result); | ||
} | ||
}); | ||
@@ -304,8 +425,8 @@ // Put effects are non cancellables | ||
function runCallEffect(_ref2, effectId, cb) { | ||
var context = _ref2.context; | ||
var fn = _ref2.fn; | ||
var args = _ref2.args; | ||
function runCallEffect(_ref3, effectId, cb) { | ||
var context = _ref3.context; | ||
var fn = _ref3.fn; | ||
var args = _ref3.args; | ||
var result = undefined; | ||
var result = void 0; | ||
// catch synchronous failures; see #152 | ||
@@ -320,6 +441,6 @@ try { | ||
function runCPSEffect(_ref3, cb) { | ||
var context = _ref3.context; | ||
var fn = _ref3.fn; | ||
var args = _ref3.args; | ||
function runCPSEffect(_ref4, cb) { | ||
var context = _ref4.context; | ||
var fn = _ref4.fn; | ||
var args = _ref4.args; | ||
@@ -337,10 +458,11 @@ // CPS (ie node style functions) can define their own cancellation logic | ||
function runForkEffect(_ref4, effectId, cb) { | ||
var context = _ref4.context; | ||
var fn = _ref4.fn; | ||
var args = _ref4.args; | ||
function runForkEffect(_ref5, effectId, cb) { | ||
var context = _ref5.context; | ||
var fn = _ref5.fn; | ||
var args = _ref5.args; | ||
var detached = _ref5.detached; | ||
var result = undefined, | ||
error = undefined, | ||
_iterator = undefined; | ||
var result = void 0, | ||
error = void 0, | ||
_iterator = void 0; | ||
@@ -354,3 +476,3 @@ // we run the function, next we'll check if this is a generator function | ||
} catch (err) { | ||
error = error; | ||
if (!detached) return cb(err);else error = err; | ||
} | ||
@@ -364,49 +486,49 @@ | ||
//simple effect: wrap in a generator | ||
// do not bubble up synchronous failures, instead create a failed task. See #152 | ||
// do not bubble up synchronous failures for detached forks, instead create a failed task. See #152 | ||
else { | ||
_iterator = (error ? regeneratorRuntime.mark(function _callee() { | ||
return regeneratorRuntime.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
throw error; | ||
case 1: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
_iterator = error ? (0, _utils.makeIterator)(function () { | ||
throw error; | ||
}) : (0, _utils.makeIterator)(function () { | ||
var pc = void 0; | ||
var eff = { done: false, value: result }; | ||
var ret = function ret(value) { | ||
return { done: true, value: value }; | ||
}; | ||
return function (arg) { | ||
if (!pc) { | ||
pc = true; | ||
return eff; | ||
} else { | ||
return ret(arg); | ||
} | ||
}, _callee, this); | ||
}) : regeneratorRuntime.mark(function _callee2() { | ||
return regeneratorRuntime.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context2.next = 2; | ||
return result; | ||
case 2: | ||
return _context2.abrupt('return', _context2.sent); | ||
case 3: | ||
case 'end': | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2, this); | ||
}))(); | ||
}; | ||
}()); | ||
} | ||
cb(null, proc(_iterator, subscribe, dispatch, getState, monitor, effectId, fn.name, true)); | ||
var task = proc(_iterator, subscribe, dispatch, getState, monitor, effectId, fn.name, detached ? null : _utils.noop); | ||
if (!detached) { | ||
if (_iterator._isRunning) taskQueue.addTask(task);else if (_iterator._error) return cb(_iterator._error); | ||
} | ||
cb(null, task); | ||
// Fork effects are non cancellables | ||
} | ||
function runJoinEffect(task, cb) { | ||
resolvePromise(task.done, cb); | ||
function runJoinEffect(t, cb) { | ||
if (t.isRunning()) { | ||
(function () { | ||
var joiner = { task: task, cb: cb }; | ||
cb.cancel = function () { | ||
return (0, _utils.remove)(t.joiners, joiner); | ||
}; | ||
t.joiners.push(joiner); | ||
})(); | ||
} else { | ||
cb(t.error(), t.result()); | ||
} | ||
} | ||
function runCancelEffect(task, cb) { | ||
// cancel the given task | ||
// uncaught cancellations errors bubbles upward | ||
task.done[CANCEL](new _SagaCancellationException2.default(MANUAL_CANCEL, name, name)); | ||
if (task.isRunning()) { | ||
task.cancel(); | ||
} | ||
cb(); | ||
@@ -416,3 +538,2 @@ // cancel effects are non cancellables | ||
// Reimplementing Promise.all. We're in 2016 | ||
function runParallelEffect(effects, effectId, cb) { | ||
@@ -425,3 +546,3 @@ if (!effects.length) { | ||
var completedCount = 0; | ||
var completed = undefined; | ||
var completed = void 0; | ||
var results = Array(effects.length); | ||
@@ -438,17 +559,6 @@ | ||
var chCbAtIdx = function chCbAtIdx(err, res) { | ||
// Either we've been cancelled, or an error aborted the whole effect | ||
if (completed) return; | ||
// one of the effects failed | ||
if (err) { | ||
// cancel all other effects | ||
// This is an AUTO_CANCEL (not triggered by a manual cancel) | ||
// Catch uncaught cancellation errors, because w'll only throw the actual | ||
// rejection error (err) inside this generator | ||
try { | ||
cb.cancel(new _SagaCancellationException2.default(PARALLEL_AUTO_CANCEL, name, name)); | ||
} catch (err) { | ||
void 0; | ||
} | ||
cb(err); | ||
if (err || res === _channel.END || res === Never) { | ||
cb.cancel(); | ||
err ? cb(err) : cb(null, res); | ||
} else { | ||
@@ -464,11 +574,7 @@ results[idx] = res; | ||
// This is different, a cancellation coming from upward | ||
// either a MANUAL_CANCEL or a parent AUTO_CANCEL | ||
// No need to catch, will be swallowed by the caller | ||
cb.cancel = function (cancelError) { | ||
// prevents unnecessary cancellation | ||
cb.cancel = function () { | ||
if (!completed) { | ||
completed = true; | ||
childCbs.forEach(function (chCb) { | ||
return chCb.cancel(cancelError); | ||
return chCb.cancel(); | ||
}); | ||
@@ -483,5 +589,4 @@ } | ||
// And yet; Promise.race | ||
function runRaceEffect(effects, effectId, cb) { | ||
var completed = undefined; | ||
var completed = void 0; | ||
var keys = Object.keys(effects); | ||
@@ -492,3 +597,2 @@ var childCbs = {}; | ||
var chCbAtKey = function chCbAtKey(err, res) { | ||
// Either we've been cancelled, or an error aborted the whole effect | ||
if (completed) return; | ||
@@ -498,15 +602,6 @@ | ||
// Race Auto cancellation | ||
try { | ||
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name)); | ||
} catch (err) { | ||
void 0; | ||
} | ||
cb(_defineProperty({}, key, err)); | ||
} else { | ||
try { | ||
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name)); | ||
} catch (err) { | ||
void 0; | ||
} | ||
cb.cancel(); | ||
cb(err); | ||
} else if (res !== _channel.END && res !== Never) { | ||
cb.cancel(); | ||
completed = true; | ||
@@ -520,3 +615,3 @@ cb(null, _defineProperty({}, key, res)); | ||
cb.cancel = function (cancelError) { | ||
cb.cancel = function () { | ||
// prevents unnecessary cancellation | ||
@@ -526,3 +621,3 @@ if (!completed) { | ||
keys.forEach(function (key) { | ||
return childCbs[key].cancel(cancelError); | ||
return childCbs[key].cancel(); | ||
}); | ||
@@ -536,5 +631,5 @@ } | ||
function runSelectEffect(_ref5, cb) { | ||
var selector = _ref5.selector; | ||
var args = _ref5.args; | ||
function runSelectEffect(_ref6, cb) { | ||
var selector = _ref6.selector; | ||
var args = _ref6.args; | ||
@@ -549,18 +644,36 @@ try { | ||
function newTask(id, name, iterator, done, forked) { | ||
var _ref6; | ||
function runChannelEffect(_ref7, cb) { | ||
var pattern = _ref7.pattern; | ||
var buffer = _ref7.buffer; | ||
return _ref6 = {}, _defineProperty(_ref6, _utils.TASK, true), _defineProperty(_ref6, 'id', id), _defineProperty(_ref6, 'name', name), _defineProperty(_ref6, 'done', done), _defineProperty(_ref6, 'forked', forked), _defineProperty(_ref6, 'cancel', function cancel(error) { | ||
if (!(error instanceof _SagaCancellationException2.default)) { | ||
error = new _SagaCancellationException2.default(MANUAL_CANCEL, name, error); | ||
var match = matcher(pattern); | ||
match.pattern = pattern; | ||
cb(null, (0, _channel.eventChannel)(subscribe, buffer || _buffers.buffers.fixed(), match)); | ||
} | ||
function runCancelledEffect(data, cb) { | ||
cb(null, !!mainTask.isCancelled); | ||
} | ||
function newTask(id, name, iterator, cont) { | ||
var _done, _ref8, _mutatorMap; | ||
iterator._deferredEnd = null; | ||
return _ref8 = {}, _defineProperty(_ref8, _utils.TASK, true), _defineProperty(_ref8, 'id', id), _defineProperty(_ref8, 'name', name), _done = 'done', _mutatorMap = {}, _mutatorMap[_done] = _mutatorMap[_done] || {}, _mutatorMap[_done].get = function () { | ||
if (iterator._deferredEnd) return iterator._deferredEnd.promise;else { | ||
var def = (0, _utils.deferred)(); | ||
iterator._deferredEnd = def; | ||
if (!iterator._isRunning) iterator._error ? def.reject(iterator._error) : def.resolve(iterator._result); | ||
return def.promise; | ||
} | ||
done[CANCEL](error); | ||
}), _defineProperty(_ref6, 'isRunning', function isRunning() { | ||
}, _defineProperty(_ref8, 'cont', cont), _defineProperty(_ref8, 'joiners', []), _defineProperty(_ref8, 'cancel', cancel), _defineProperty(_ref8, 'isRunning', function isRunning() { | ||
return iterator._isRunning; | ||
}), _defineProperty(_ref6, 'result', function result() { | ||
}), _defineProperty(_ref8, 'isCancelled', function isCancelled() { | ||
return iterator._isCancelled; | ||
}), _defineProperty(_ref8, 'result', function result() { | ||
return iterator._result; | ||
}), _defineProperty(_ref6, 'error', function error() { | ||
}), _defineProperty(_ref8, 'error', function error() { | ||
return iterator._error; | ||
}), _ref6; | ||
}), _defineEnumerableProperties(_ref8, _mutatorMap), _ref8; | ||
} | ||
} |
@@ -6,4 +6,2 @@ 'use strict'; | ||
}); | ||
exports.NOT_ITERATOR_ERROR = undefined; | ||
exports.storeIO = storeIO; | ||
exports.runSaga = runSaga; | ||
@@ -17,52 +15,13 @@ | ||
var _emitter = require('./emitter'); | ||
var _emitter2 = _interopRequireDefault(_emitter); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = "runSaga must be called on an iterator"; | ||
/** | ||
@deprecated | ||
ATTENTION! this method can have some potential issues | ||
For more infos, see issue https://github.com/yelouafi/redux-saga/issues/48 | ||
memoize the result of storeChannel. It avoids monkey patching the same store | ||
multiple times unnecessarly. We need only one channel per store | ||
**/ | ||
var IO = (0, _utils.sym)('IO'); | ||
function storeIO(store) { | ||
(0, _utils.warnDeprecated)('storeIO is deprecated, to run Saga dynamically, use \'run\' method of the middleware'); | ||
if (store[IO]) return store[IO]; | ||
var storeEmitter = (0, _emitter2.default)(); | ||
var _dispatch = store.dispatch; | ||
store.dispatch = function (action) { | ||
var result = _dispatch(action); | ||
storeEmitter.emit(action); | ||
return result; | ||
}; | ||
store[IO] = { | ||
subscribe: storeEmitter.subscribe, | ||
dispatch: store.dispatch, | ||
getState: store.getState | ||
}; | ||
return store[IO]; | ||
} | ||
function runSaga(iterator, _ref) { | ||
function runSaga(iterator, _ref, monitor) { | ||
var subscribe = _ref.subscribe; | ||
var dispatch = _ref.dispatch; | ||
var getState = _ref.getState; | ||
var monitor = arguments.length <= 2 || arguments[2] === undefined ? _utils.noop : arguments[2]; | ||
(0, _utils.check)(iterator, _utils.is.iterator, NOT_ITERATOR_ERROR); | ||
(0, _utils.check)(iterator, _utils.is.iterator, "runSaga must be called on an iterator"); | ||
return (0, _proc2.default)(iterator, subscribe, dispatch, getState, monitor); | ||
} |
@@ -12,2 +12,4 @@ 'use strict'; | ||
var _channel = require('./channel'); | ||
var _utils = require('./utils'); | ||
@@ -17,54 +19,37 @@ | ||
var _SagaCancellationException = require('./SagaCancellationException'); | ||
var done = { done: true, value: undefined }; | ||
var qEnd = {}; | ||
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var resume = function resume(fnOrValue, arg) { | ||
return _utils.is.func(fnOrValue) ? fnOrValue(arg) : fnOrValue; | ||
}; | ||
var done = { done: true }; | ||
function fsmIterator(fsm, nextState) { | ||
function fsmIterator(fsm, q0) { | ||
var name = arguments.length <= 2 || arguments[2] === undefined ? 'iterator' : arguments[2]; | ||
var aborted = undefined, | ||
updateState = undefined; | ||
var updateState = void 0, | ||
qNext = q0; | ||
function next(arg, error) { | ||
if (aborted) return done; | ||
if (qNext === qEnd) return done; | ||
if (error) { | ||
aborted = true; | ||
if (!(error instanceof _SagaCancellationException2.default)) throw error; | ||
return done; | ||
qNext = qEnd; | ||
throw error; | ||
} else { | ||
if (updateState) updateState(arg); | ||
updateState && updateState(arg); | ||
var _fsm$nextState = _slicedToArray(fsm[nextState], 3); | ||
var _fsm$qNext = fsm[qNext](); | ||
var output = _fsm$nextState[0]; | ||
var transition = _fsm$nextState[1]; | ||
var _updateState = _fsm$nextState[2]; | ||
var _fsm$qNext2 = _slicedToArray(_fsm$qNext, 3); | ||
var q = _fsm$qNext2[0]; | ||
var output = _fsm$qNext2[1]; | ||
var _updateState = _fsm$qNext2[2]; | ||
qNext = q; | ||
updateState = _updateState; | ||
nextState = resume(transition, arg); | ||
return resume(output, arg); | ||
return qNext === qEnd ? done : output; | ||
} | ||
} | ||
var iterator = { | ||
name: name, | ||
next: next, | ||
throw: function _throw(error) { | ||
return next(null, error); | ||
} | ||
}; | ||
if (typeof Symbol !== 'undefined') { | ||
iterator[Symbol.iterator] = function () { | ||
return iterator; | ||
}; | ||
} | ||
return iterator; | ||
return (0, _utils.makeIterator)(next, function (error) { | ||
return next(null, error); | ||
}, name); | ||
} | ||
@@ -77,11 +62,19 @@ | ||
var yieldTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yieldFork = function yieldFork(action) { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [action])) }; | ||
var yTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yFork = function yFork(ac) { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [ac])) }; | ||
}; | ||
var action = void 0, | ||
setAction = function setAction(ac) { | ||
return action = ac; | ||
}; | ||
return fsmIterator({ | ||
'take': [yieldTake, 'fork'], | ||
'fork': [yieldFork, 'take'] | ||
}, 'take', 'takeEvery(' + pattern + ', ' + worker.name + ')'); | ||
q1: function q1() { | ||
return ['q2', yTake, setAction]; | ||
}, | ||
q2: function q2() { | ||
return action === _channel.END ? [qEnd] : ['q1', yFork(action)]; | ||
} | ||
}, 'q1', 'takeEvery(' + String(pattern) + ', ' + worker.name + ')'); | ||
} | ||
@@ -94,24 +87,29 @@ | ||
var yieldTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yieldFork = function yieldFork() { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [currentAction])) }; | ||
var yTake = { done: false, value: (0, _io.take)(pattern) }; | ||
var yFork = function yFork(ac) { | ||
return { done: false, value: _io.fork.apply(undefined, [worker].concat(args, [ac])) }; | ||
}; | ||
var yieldCancel = function yieldCancel() { | ||
return { done: false, value: (0, _io.cancel)(currentTask) }; | ||
var yCancel = function yCancel(task) { | ||
return { done: false, value: (0, _io.cancel)(task) }; | ||
}; | ||
var forkOrCancel = function forkOrCancel() { | ||
return currentTask ? 'cancel' : 'fork'; | ||
var task = void 0, | ||
action = void 0; | ||
var setTask = function setTask(t) { | ||
return task = t; | ||
}; | ||
var currentTask = undefined, | ||
currentAction = undefined; | ||
var setAction = function setAction(ac) { | ||
return action = ac; | ||
}; | ||
return fsmIterator({ | ||
'take': [yieldTake, forkOrCancel, function (action) { | ||
return currentAction = action; | ||
}], | ||
'cancel': [yieldCancel, 'fork'], | ||
'fork': [yieldFork, 'take', function (task) { | ||
return currentTask = task; | ||
}] | ||
}, 'take', 'takeLatest(' + pattern + ', ' + worker.name + ')'); | ||
q1: function q1() { | ||
return ['q2', yTake, setAction]; | ||
}, | ||
q2: function q2() { | ||
return action === _channel.END ? [qEnd] : task ? ['q3', yCancel(task)] : ['q1', yFork(action), setTask]; | ||
}, | ||
q3: function q3() { | ||
return ['q1', yFork(action), setTask]; | ||
} | ||
}, 'q1', 'takeLatest(' + String(pattern) + ', ' + worker.name + ')'); | ||
} |
@@ -14,13 +14,22 @@ 'use strict'; | ||
exports.arrayOfDeffered = arrayOfDeffered; | ||
exports.delay = delay; | ||
exports.createMockTask = createMockTask; | ||
exports.autoInc = autoInc; | ||
exports.asap = asap; | ||
exports.warnDeprecated = warnDeprecated; | ||
exports.makeIterator = makeIterator; | ||
exports.log = log; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var sym = exports.sym = function sym(id) { | ||
return '@@redux-saga/' + id; | ||
}; | ||
var TASK = exports.TASK = sym('TASK'); | ||
var kTrue = exports.kTrue = function kTrue() { | ||
return true; | ||
var MATCH = exports.MATCH = sym('MATCH'); | ||
var konst = exports.konst = function konst(v) { | ||
return function () { | ||
return v; | ||
}; | ||
}; | ||
var kTrue = exports.kTrue = konst(true); | ||
var kFalse = exports.kFalse = konst(false); | ||
var noop = exports.noop = function noop() {}; | ||
@@ -47,2 +56,5 @@ function ident(v) { | ||
}, | ||
number: function number(n) { | ||
return typeof n === 'number'; | ||
}, | ||
array: Array.isArray, | ||
@@ -55,4 +67,19 @@ promise: function promise(p) { | ||
}, | ||
task: function task(it) { | ||
return it && it[TASK]; | ||
task: function task(t) { | ||
return t && t[TASK]; | ||
}, | ||
take: function take(ch) { | ||
return ch && is.func(ch.take); | ||
}, | ||
put: function put(ch) { | ||
return ch && is.func(ch.put); | ||
}, | ||
observable: function observable(ob) { | ||
return ob && is.func(ob.subscribe); | ||
}, | ||
buffer: function buffer(buf) { | ||
return buf && is.func(buf.isEmpty) && is.func(buf.take) && is.func(buf.put); | ||
}, | ||
pattern: function pattern(pat) { | ||
return pat && (typeof pat === 'string' || is.func(pat) || is.array(pat)); | ||
} | ||
@@ -86,2 +113,34 @@ }; | ||
function delay(ms) { | ||
var val = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; | ||
return new Promise(function (resolve) { | ||
return setTimeout(function () { | ||
return resolve(val); | ||
}, ms); | ||
}); | ||
} | ||
function createMockTask() { | ||
var _ref; | ||
var running = true; | ||
var _result = void 0, | ||
_error = void 0; | ||
return _ref = {}, _defineProperty(_ref, TASK, true), _defineProperty(_ref, 'isRunning', function isRunning() { | ||
return running; | ||
}), _defineProperty(_ref, 'result', function result() { | ||
return _result; | ||
}), _defineProperty(_ref, 'error', function error() { | ||
return _error; | ||
}), _defineProperty(_ref, 'setRunning', function setRunning(b) { | ||
return running = b; | ||
}), _defineProperty(_ref, 'setResult', function setResult(r) { | ||
return _result = r; | ||
}), _defineProperty(_ref, 'setError', function setError(e) { | ||
return _error = e; | ||
}), _ref; | ||
} | ||
function autoInc() { | ||
@@ -95,13 +154,34 @@ var seed = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; | ||
function asap(action) { | ||
return Promise.resolve(1).then(function () { | ||
return action(); | ||
}); | ||
var kThrow = function kThrow(err) { | ||
throw err; | ||
}; | ||
function makeIterator(next) { | ||
var thro = arguments.length <= 1 || arguments[1] === undefined ? kThrow : arguments[1]; | ||
var name = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2]; | ||
var iterator = { name: name, next: next, throw: thro }; | ||
if (typeof Symbol !== 'undefined') { | ||
iterator[Symbol.iterator] = function () { | ||
return iterator; | ||
}; | ||
} | ||
return iterator; | ||
} | ||
/* eslint-disable no-console */ | ||
function warnDeprecated(msg) { | ||
if (isDev) { | ||
console.warn('DEPRECATION WARNING', msg); | ||
/** | ||
Print error in a useful way whether in a browser environment | ||
(with expandable error stack traces), or in a node.js environment | ||
(text-only log output) | ||
**/ | ||
function log(level, message, error) { | ||
/*eslint-disable no-console*/ | ||
if (typeof window === 'undefined') { | ||
console.log('redux-saga ' + level + ': ' + message + '\n' + (error && error.stack || error)); | ||
} else { | ||
console[level].call(console, message, error); | ||
} | ||
} | ||
} | ||
var internalErr = exports.internalErr = function internalErr(err) { | ||
return new Error('\n redux-saga: Error checking hooks detected an inconsisten state. This is likely a bug\n in redux-saga code and not yours. Thanks for reporting this in the project\'s github repo.\n Error: ' + err + '\n'); | ||
}; |
@@ -6,30 +6,49 @@ 'use strict'; | ||
}); | ||
exports.monitorActions = exports.createMockTask = exports.MANUAL_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = exports.CANCEL = exports.asap = exports.arrayOfDeffered = exports.deferred = exports.asEffect = exports.is = exports.noop = exports.TASK = undefined; | ||
var _utils = require('./internal/utils'); | ||
Object.defineProperty(exports, 'TASK', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.TASK; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'noop', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.noop; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'is', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.is; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'deferred', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.deferred; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'arrayOfDeffered', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.arrayOfDeffered; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'createMockTask', { | ||
enumerable: true, | ||
get: function get() { | ||
return _utils.createMockTask; | ||
} | ||
}); | ||
var _io = require('./internal/io'); | ||
var _proc = require('./internal/proc'); | ||
var _testUtils = require('./internal/testUtils'); | ||
var _monitorActions = require('./internal/monitorActions'); | ||
var monitorActions = _interopRequireWildcard(_monitorActions); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
exports.TASK = _utils.TASK; | ||
exports.noop = _utils.noop; | ||
exports.is = _utils.is; | ||
exports.asEffect = _io.asEffect; | ||
exports.deferred = _utils.deferred; | ||
exports.arrayOfDeffered = _utils.arrayOfDeffered; | ||
exports.asap = _utils.asap; | ||
exports.CANCEL = _proc.CANCEL; | ||
exports.RACE_AUTO_CANCEL = _proc.RACE_AUTO_CANCEL; | ||
exports.PARALLEL_AUTO_CANCEL = _proc.PARALLEL_AUTO_CANCEL; | ||
exports.MANUAL_CANCEL = _proc.MANUAL_CANCEL; | ||
exports.createMockTask = _testUtils.createMockTask; | ||
exports.monitorActions = monitorActions; | ||
Object.defineProperty(exports, 'asEffect', { | ||
enumerable: true, | ||
get: function get() { | ||
return _io.asEffect; | ||
} | ||
}); |
{ | ||
"name": "redux-saga", | ||
"version": "0.9.5", | ||
"version": "0.10.0", | ||
"description": "Saga middleware for Redux to handle Side Effects", | ||
@@ -22,3 +22,3 @@ "main": "lib/index.js", | ||
"async": "node examples/async/server.js", | ||
"real-world": "npm --prefix examples/real-world install examples/real-world && node examples/real-world/server.js", | ||
"real-world": "npm --prefix examples/real-world install examples/real-world && node --require babel-register examples/real-world/server.js", | ||
"docs:clean": "rimraf _book", | ||
@@ -51,22 +51,22 @@ "docs:prepare": "gitbook install", | ||
"babel-cli": "^6.1.18", | ||
"babel-core": "6.4.0", | ||
"babel-eslint": "^4.1.5", | ||
"babel-loader": "6.2.1", | ||
"babel-polyfill": "6.3.14", | ||
"babel-core": "^6.7.6", | ||
"babel-eslint": "^6.0.3", | ||
"babel-loader": "^6.2.4", | ||
"babel-polyfill": "^6.7.4", | ||
"babel-preset-es2015": "^6.1.18", | ||
"babel-preset-react": "^6.1.18", | ||
"babel-preset-stage-2": "^6.1.18", | ||
"eslint": "^1.9.0", | ||
"eslint": "^2.8.0", | ||
"express": "^4.13.3", | ||
"gitbook-cli": "1.0.1", | ||
"isomorphic-fetch": "^2.2.0", | ||
"react": "^0.14.3", | ||
"react-dom": "^0.14.3", | ||
"react-redux": "^4.0.0", | ||
"redux": "^3.3.1", | ||
"redux-logger": "^2.0.4", | ||
"react": "^15.0.0", | ||
"react-dom": "^15.0.0", | ||
"react-redux": "^4.4.5", | ||
"redux": "^3.5.1", | ||
"redux-logger": "^2.6.1", | ||
"rimraf": "^2.4.3", | ||
"tap-spec": "^4.1.1", | ||
"tape": "^4.2.2", | ||
"webpack": "1.12.10", | ||
"webpack": "1.13.0", | ||
"webpack-dev-middleware": "^1.4.0", | ||
@@ -73,0 +73,0 @@ "webpack-hot-middleware": "^2.6.0" |
@@ -17,3 +17,3 @@ # redux-saga | ||
Sagas are created using Generator functions. If you're not familiar with them you may find | ||
[some useful links here](http://yelouafi.github.io/redux-saga/docs/ExternalResources.html) | ||
[some useful links here.](http://yelouafi.github.io/redux-saga/docs/ExternalResources.html) | ||
@@ -53,3 +53,3 @@ Unlike Thunks which get invoked on every action by Action Creators, Sagas are fired only | ||
Alternatively, you may use the provided UMD builds directly in the `<script>` tag of | ||
an HTML page. See [this section](#using-umd-build-in-the-browser) | ||
an HTML page. See [this section.](#using-umd-build-in-the-browser) | ||
@@ -74,3 +74,3 @@ ## Usage Example | ||
watches for all `USER_FETCH_REQUESTED` actions and triggers an API call to fetch the | ||
user data | ||
user data. | ||
@@ -89,3 +89,3 @@ #### `sagas.js` | ||
} catch (e) { | ||
yield put({type: "USER_FETCH_FAILED",message: e.message}); | ||
yield put({type: "USER_FETCH_FAILED", message: e.message}); | ||
} | ||
@@ -114,3 +114,3 @@ } | ||
To run our Saga, we'll have to connect it to the Redux Store using the `redux-saga` middleware | ||
To run our Saga, we'll have to connect it to the Redux Store using the `redux-saga` middleware. | ||
@@ -125,3 +125,5 @@ #### `main.js` | ||
const sagaMiddleware = createSagaMiddleware(mySaga) | ||
// create the saga middleware | ||
const sagaMiddleware = createSagaMiddleware() | ||
// mount it on the Store | ||
const store = createStore( | ||
@@ -132,2 +134,5 @@ reducer, | ||
// then run the saga | ||
sagaMiddleware.run(mySaga) | ||
// render the application | ||
@@ -179,7 +184,7 @@ ``` | ||
Below are the examples ported (so far) from the Redux repos | ||
Below are the examples ported (so far) from the Redux repos. | ||
### Counter examples | ||
There are 3 counter examples | ||
There are 3 counter examples. | ||
@@ -190,3 +195,3 @@ #### counter-vanilla | ||
To launch the example, just open `index.html` in your browser | ||
To launch the example, just open `index.html` in your browser. | ||
@@ -210,3 +215,3 @@ >Important | ||
Demo using low level API. Demonstrate task cancellation | ||
Demo using low level API. Demonstrate task cancellation. | ||
@@ -213,0 +218,0 @@ ``` |
@@ -1,3 +0,1 @@ | ||
import { take, put, race, call, apply, cps, fork, join, cancel, select } from './internal/io' | ||
export { take, put, race, call, apply, cps, fork, join, cancel, select } | ||
export { take, takem, put, race, call, apply, cps, fork, spawn, join, cancel, select, actionChannel, cancelled } from './internal/io' |
@@ -5,9 +5,8 @@ import middleware from './internal/middleware' | ||
import _SagaCancellationException from './internal/SagaCancellationException' | ||
export const SagaCancellationException = _SagaCancellationException | ||
export const isCancelError = error => error instanceof SagaCancellationException | ||
export { runSaga, storeIO } from './internal/runSaga' | ||
export { runSaga } from './internal/runSaga' | ||
export { CANCEL } from './internal/proc' | ||
export { END, eventChannel, channel } from './internal/channel' | ||
export { buffers } from './internal/buffers' | ||
export { takeEvery, takeLatest } from './internal/sagaHelpers' | ||
export { delay } from './internal/utils' | ||
@@ -14,0 +13,0 @@ import * as effects from './effects' |
@@ -1,12 +0,3 @@ | ||
import { sym, is, kTrue, ident, check, TASK } from './utils' | ||
import { sym, is, ident, check, TASK } from './utils' | ||
export const CALL_FUNCTION_ARG_ERROR = "call/cps/fork first argument must be a function, an array [context, function] or an object {context, fn}" | ||
export const FORK_ARG_ERROR = "fork first argument must be a generator function or an iterator" | ||
export const JOIN_ARG_ERROR = "join argument must be a valid task (a result of a fork)" | ||
export const CANCEL_ARG_ERROR = "cancel argument must be a valid task (a result of a fork)" | ||
export const INVALID_PATTERN = "Invalid pattern passed to `take` (HINT: check if you didn't mispell a constant)" | ||
export const SELECT_ARG_ERROR = "select first argument must be a function" | ||
const IO = sym('IO') | ||
@@ -22,33 +13,45 @@ const TAKE = 'TAKE' | ||
const SELECT = 'SELECT' | ||
const ACTION_CHANNEL = 'ACTION_CHANNEL' | ||
const CANCELLED = 'CANCELLED' | ||
const effect = (type, payload) => ({ [IO]: true, [type]: payload }) | ||
const matchers = { | ||
wildcard : () => kTrue, | ||
default : pattern => input => input.type === pattern, | ||
array : patterns => input => patterns.some( p => p === input.type ), | ||
predicate : predicate => input => predicate(input) | ||
export function take(channel, pattern) { | ||
if(arguments.length >= 2) { | ||
check(channel, is.notUndef, 'take(channel, pattern): channel is undefined') | ||
check(channel, is.take, `take(channel, pattern): argument ${channel} is not a valid channel (channel argument must have a take method)`) | ||
check(pattern, is.notUndef, 'take(channel, pattern): pattern is undefined') | ||
check(pattern, is.pattern, `take(channel, pattern): argument ${pattern} is not a valid pattern (pattern must be String | Function: a => boolean | Array<String>)`) | ||
} else if(arguments.length === 1) { | ||
check(channel, is.notUndef, 'take(patternOrChannel): undefined argument') | ||
if(!is.take(channel)) { | ||
if(is.pattern(channel)) { | ||
pattern = channel | ||
channel = null | ||
} else throw new Error(`take(patternOrChannel): argument ${channel} is not valid channel or a valid pattern`) | ||
} else pattern = '*' | ||
} else pattern = '*' | ||
return effect(TAKE, {channel, pattern}) | ||
} | ||
export function matcher(pattern) { | ||
return ( | ||
pattern === '*' ? matchers.wildcard | ||
: is.array(pattern) ? matchers.array | ||
: is.func(pattern) ? matchers.predicate | ||
: matchers.default | ||
)(pattern) | ||
export function takem(...args) { | ||
const eff = take(...args) | ||
eff[TAKE].maybe = true | ||
return eff | ||
} | ||
export function take(pattern){ | ||
if (arguments.length > 0 && is.undef(pattern)) { | ||
throw new Error(INVALID_PATTERN) | ||
export function put(channel, action) { | ||
if(arguments.length > 1) { | ||
check(channel, is.notUndef, 'put(channel, action): argument channel is undefined') | ||
check(channel, is.put, `put(channel, action): argument ${channel} is not a valid channel (channel argument must have a put method)`) | ||
check(action, is.notUndef, 'put(channel, action): argument action is undefined') | ||
} else { | ||
check(channel, is.notUndef, 'put(action): argument action is undefined') | ||
action = channel | ||
channel = null | ||
} | ||
return effect(TAKE, is.undef(pattern) ? '*' : pattern) | ||
return effect(PUT, {channel, action}) | ||
} | ||
export function put(action) { | ||
return effect(PUT, action) | ||
} | ||
export function race(effects) { | ||
@@ -58,4 +61,4 @@ return effect(RACE, effects) | ||
function getFnCallDesc(fn, args) { | ||
check(fn, is.notUndef, CALL_FUNCTION_ARG_ERROR) | ||
function getFnCallDesc(meth,fn, args) { | ||
check(fn, is.notUndef, `${meth}: argument fn is undefined`) | ||
@@ -68,3 +71,3 @@ let context = null | ||
} | ||
check(fn, is.func, CALL_FUNCTION_ARG_ERROR) | ||
check(fn, is.func, `${meth}: argument ${fn} is not a function`) | ||
@@ -75,31 +78,39 @@ return {context, fn, args} | ||
export function call(fn, ...args) { | ||
return effect(CALL, getFnCallDesc(fn, args)) | ||
return effect(CALL, getFnCallDesc('call', fn, args)) | ||
} | ||
export function apply(context, fn, args = []) { | ||
return effect(CALL, getFnCallDesc({context, fn}, args)) | ||
return effect(CALL, getFnCallDesc('apply', {context, fn}, args)) | ||
} | ||
export function cps(fn, ...args) { | ||
return effect(CPS, getFnCallDesc(fn, args)) | ||
return effect(CPS, getFnCallDesc('cps', fn, args)) | ||
} | ||
export function fork(fn, ...args) { | ||
return effect(FORK, getFnCallDesc(fn, args)) | ||
return effect(FORK, getFnCallDesc('fork', fn, args)) | ||
} | ||
export function spawn(fn, ...args) { | ||
const eff = fork(fn, ...args) | ||
eff[FORK].detached = true | ||
return eff | ||
} | ||
const isForkedTask = task => task[TASK] | ||
export function join(taskDesc) { | ||
if(!isForkedTask(taskDesc)) | ||
throw new Error(JOIN_ARG_ERROR) | ||
export function join(task) { | ||
check(task, is.notUndef, 'join(task): argument task is undefined') | ||
if(!isForkedTask(task)) | ||
throw new Error(`join(task): argument ${task} is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)`) | ||
return effect(JOIN, taskDesc) | ||
return effect(JOIN, task) | ||
} | ||
export function cancel(taskDesc) { | ||
if(!isForkedTask(taskDesc)) | ||
throw new Error(CANCEL_ARG_ERROR) | ||
export function cancel(task) { | ||
check(task, is.notUndef, 'cancel(task): argument task is undefined') | ||
if(!isForkedTask(task)) | ||
throw new Error(`cancel(task): argument ${task} is not a valid Task object \n(HINT: if you are getting this errors in tests, consider using createMockTask from redux-saga/utils)`) | ||
return effect(CANCEL, taskDesc) | ||
return effect(CANCEL, task) | ||
} | ||
@@ -111,3 +122,4 @@ | ||
} else { | ||
check(selector, is.func, SELECT_ARG_ERROR) | ||
check(select, is.notUndef, 'select(selector,[...]): argument selector is undefined') | ||
check(selector, is.func, `select(selector,[...]): argument ${selector} is not a function`) | ||
} | ||
@@ -117,3 +129,20 @@ return effect(SELECT, {selector, args}) | ||
/** | ||
channel(pattern, [buffer]) => creates an event channel for store actions | ||
**/ | ||
export function actionChannel(pattern, buffer) { | ||
check(pattern, is.notUndef, 'actionChannel(pattern,...): argument pattern is undefined') | ||
if(arguments.length > 1) { | ||
check(buffer, is.notUndef, 'actionChannel(pattern, buffer): argument buffer is undefined') | ||
check(buffer, is.notUndef, `actionChannel(pattern, buffer): argument ${buffer} is not a valid buffer`) | ||
} | ||
return effect(ACTION_CHANNEL, {pattern, buffer}) | ||
} | ||
export function cancelled() { | ||
return effect(CANCELLED, {}) | ||
} | ||
export const asEffect = { | ||
@@ -128,3 +157,5 @@ take : effect => effect && effect[IO] && effect[TAKE], | ||
cancel : effect => effect && effect[IO] && effect[CANCEL], | ||
select : effect => effect && effect[IO] && effect[SELECT] | ||
select : effect => effect && effect[IO] && effect[SELECT], | ||
actionChannel : effect => effect && effect[IO] && effect[ACTION_CHANNEL], | ||
cancelled : effect => effect && effect[IO] && effect[CANCELLED] | ||
} |
@@ -1,41 +0,35 @@ | ||
import { is, asap, isDev, check, warnDeprecated } from './utils' | ||
import { is, check } from './utils' | ||
import proc from './proc' | ||
import emitter from './emitter' | ||
import { MONITOR_ACTION } from './monitorActions' | ||
import SagaCancellationException from './SagaCancellationException' | ||
import {emitter} from './channel' | ||
export const sagaArgError = (fn, pos, saga) => (` | ||
${fn} can only be called on Generator functions | ||
Argument ${saga} at position ${pos} is not function! | ||
`) | ||
export const RUN_SAGA_DYNAMIC_ERROR = 'Before running a Saga dynamically using middleware.run, you must mount the Saga middleware on the Store using applyMiddleware' | ||
export default function sagaMiddlewareFactory(options={}) { | ||
let runSagaDynamically | ||
export const GET_STATE_DEPRECATED_WARNING = ` | ||
Using the 'getState' param of Sagas to access the state is deprecated since 0.9.1 | ||
To access the Store's state use 'yield select()' instead | ||
For more infos see http://yelouafi.github.io/redux-saga/docs/api/index.html#selectselector-args | ||
` | ||
export default function sagaMiddlewareFactory(...sagas) { | ||
let runSagaDynamically | ||
if(is.func(options)) { | ||
throw new Error(`You passed a function to the Saga middleware. You are likely trying to start a\ | ||
Saga by directly passing it to the middleware. This is no longer possible starting from 0.10.0.\ | ||
To run a Saga, you must do it dynamically AFTER mounting the middleware into the store. | ||
Example: | ||
import createSagaMiddleware from 'redux-saga' | ||
... other imports | ||
sagas.forEach((saga, idx) => check(saga, is.func, sagaArgError('createSagaMiddleware', idx, saga))) | ||
const sagaMiddleware = createSagaMiddleware() | ||
const store = createStore(reducer, applyMiddleware(sagaMiddleware)) | ||
sagaMiddleware.run(saga, ...args) | ||
`) | ||
} | ||
function sagaMiddleware({getState, dispatch}) { | ||
runSagaDynamically = runSaga | ||
const sagaEmitter = emitter() | ||
const monitor = isDev ? action => asap(() => dispatch(action)) : undefined | ||
const getStateDeprecated = () => { | ||
warnDeprecated(GET_STATE_DEPRECATED_WARNING) | ||
return getState() | ||
} | ||
function runSaga(saga, ...args) { | ||
return proc( | ||
saga(getStateDeprecated, ...args), | ||
saga(...args), | ||
sagaEmitter.subscribe, | ||
dispatch, | ||
getState, | ||
monitor, | ||
options.sagaMonitor, | ||
0, | ||
@@ -46,12 +40,5 @@ saga.name | ||
runSagaDynamically = runSaga | ||
sagas.forEach(runSaga) | ||
return next => action => { | ||
const result = next(action) // hit reducers | ||
// filter out monitor actions to avoid endless loops | ||
// see https://github.com/yelouafi/redux-saga/issues/61 | ||
if(!action[MONITOR_ACTION]) | ||
sagaEmitter.emit(action) | ||
sagaEmitter.emit(action) | ||
return result; | ||
@@ -62,13 +49,5 @@ } | ||
sagaMiddleware.run = (saga, ...args) => { | ||
if(!runSagaDynamically) { | ||
throw new Error(RUN_SAGA_DYNAMIC_ERROR) | ||
} | ||
check(saga, is.func, sagaArgError('sagaMiddleware.run', 0, saga)) | ||
const task = runSagaDynamically(saga, ...args) | ||
task.done.catch(err => { | ||
if(!(err instanceof SagaCancellationException)) | ||
throw err | ||
}) | ||
return task | ||
check(runSagaDynamically, is.notUndef, 'Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware') | ||
check(saga, is.func, `sagaMiddleware.run(saga, ...args): saga argument must be a Generator function!`) | ||
return runSagaDynamically(saga, ...args) | ||
} | ||
@@ -75,0 +54,0 @@ |
@@ -1,22 +0,93 @@ | ||
import { sym, noop, is, isDev, check, remove, deferred, autoInc, asap, TASK } from './utils' | ||
import { asEffect, matcher } from './io' | ||
import * as monitorActions from './monitorActions' | ||
import SagaCancellationException from './SagaCancellationException' | ||
import { sym, noop, kTrue, is, log, check, deferred, isDev, autoInc, remove, TASK, makeIterator } from './utils' | ||
import asap from './asap' | ||
import { asEffect } from './io' | ||
import { eventChannel, END } from './channel' | ||
import { buffers } from './buffers' | ||
export const NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator' | ||
export const undefindInputError = name => ` | ||
${name} saga was provided with an undefined input action | ||
Hints : | ||
- check that your Action Creator returns a non undefined value | ||
- if the Saga was started using runSaga, check that your subscribe source provides the action to its listeners | ||
` | ||
export const CANCEL = sym('@@redux-saga/cancelPromise') | ||
export const PARALLEL_AUTO_CANCEL = 'PARALLEL_AUTO_CANCEL' | ||
export const RACE_AUTO_CANCEL = 'RACE_AUTO_CANCEL' | ||
export const MANUAL_CANCEL = 'MANUAL_CANCEL' | ||
export const CANCEL = sym('cancelPromise') | ||
const nextEffectId = autoInc() | ||
export const Never = { toString() { return '@@redux-saga/Never' } } | ||
Object.freeze(Never) | ||
const matchers = { | ||
wildcard : () => kTrue, | ||
default : pattern => input => input.type === pattern, | ||
array : patterns => input => patterns.some( p => p === input.type ), | ||
predicate : predicate => input => predicate(input) | ||
} | ||
function matcher(pattern) { | ||
return ( | ||
pattern === '*' ? matchers.wildcard | ||
: is.array(pattern) ? matchers.array | ||
: is.func(pattern) ? matchers.predicate | ||
: matchers.default | ||
)(pattern) | ||
} | ||
/** | ||
Used to track a parent task and its forks | ||
In the new fork model, forked tasks are attached by default to their parent | ||
We model this using the concept of Parent task && main Task | ||
main task is the main flow of the current Generator, the parent tasks is the | ||
aggregation of the main tasks + all its forked tasks. | ||
Thus the whole model represents an execution tree with multiple branches (vs the | ||
linear execution tree in sequential (non parallel) programming) | ||
A parent tasks has the following semantics | ||
- It completes iff all its forks either complete or all cancelled | ||
- If it's cancelled, all forks are cancelled as well | ||
- It aborts if any uncaught error bubbles up from forks | ||
- If it completes, the return value is the one returned by the main task | ||
**/ | ||
function forkQueue(name, mainTask, cb) { | ||
let tasks = [], result, completed = false | ||
addTask(mainTask) | ||
function addTask(task) { | ||
tasks.push(task) | ||
task.cont = (err, res) => { | ||
if(completed) | ||
return | ||
remove(tasks, task) | ||
task.cont = noop | ||
if(err) { | ||
cancelAll() | ||
cb(err) | ||
} else { | ||
if(task === mainTask) | ||
result = res | ||
if(!tasks.length) { | ||
completed = true | ||
cb(null, result) | ||
} | ||
} | ||
} | ||
//task.cont.cancel = task.cancel | ||
} | ||
function cancelAll() { | ||
if(completed) | ||
return | ||
completed = true | ||
tasks.forEach(t => { | ||
t.cont = noop | ||
t.cancel() | ||
}) | ||
tasks = [] | ||
} | ||
return { | ||
addTask, | ||
cancelAll, | ||
getTasks: () => tasks, | ||
taskNames: () => tasks.map(t => t.name) | ||
} | ||
} | ||
export default function proc( | ||
@@ -27,6 +98,6 @@ iterator, | ||
getState = noop, | ||
monitor = noop, | ||
monitor, | ||
parentEffectId = 0, | ||
name = 'anonymous', | ||
forked | ||
cont | ||
) { | ||
@@ -36,29 +107,4 @@ | ||
const UNDEFINED_INPUT_ERROR = undefindInputError(name) | ||
// tracks the current `take` effects | ||
let deferredInputs = [] | ||
// Promise to be resolved/rejected when this generator terminates (or throws) | ||
const deferredEnd = deferred() | ||
// subscribe to input events, this will resolve the current `take` effects | ||
const unsubscribe = subscribe(input => { | ||
if(input === undefined) | ||
throw UNDEFINED_INPUT_ERROR | ||
for (let i = 0; i < deferredInputs.length; i++) { | ||
const def = deferredInputs[i] | ||
if(def.match(input)) { | ||
// cancel all deferredInputs; parallel takes are disallowed | ||
// and in concurrent takes, first wins | ||
deferredInputs = [] | ||
def.resolve(input) | ||
} | ||
} | ||
}) | ||
const stdChannel = eventChannel(subscribe) | ||
/** | ||
cancel : (SagaCancellationException) -> () | ||
Tracks the current effect cancellation | ||
@@ -71,20 +117,50 @@ Each time the generator progresses. calling runEffect will set a new value | ||
/** | ||
Creates a new task descriptor for this generator | ||
Creates a new task descriptor for this generator, We'll also create a main task | ||
to track the main flow (besides other forked tasks) | ||
**/ | ||
const task = newTask( | ||
parentEffectId, name, iterator, deferredEnd.promise, forked | ||
) | ||
const task = newTask(parentEffectId, name, iterator, cont) | ||
const mainTask = { name, cancel: cancelMain, isRunning: true } | ||
const taskQueue = forkQueue(name, mainTask, end) | ||
/** | ||
cancellation of the main task. We'll simply resume the Generator with a Cancel | ||
**/ | ||
function cancelMain() { | ||
if(mainTask.isRunning && !mainTask.isCancelled) { | ||
mainTask.isCancelled = true | ||
next(null, Never) | ||
} | ||
} | ||
/** | ||
This may be called by a parent generator to trigger/propagate cancellation | ||
We'll simply cancel the current effect, which will reject that effect | ||
The rejection will throw the injected SagaCancellationException into the flow | ||
of this generator | ||
cancel all pending tasks (including the main task), then end the current task. | ||
Cancellation propagates down to the whole execution tree holded by this Parent task | ||
It's also propagated to all joiners of this task and their execution tree/joiners | ||
Cancellation is noop for terminated/Cancelled tasks tasks | ||
**/ | ||
task.done[CANCEL] = ({type, origin}) => { | ||
next.cancel( | ||
new SagaCancellationException(type, name, origin) | ||
) | ||
function cancel() { | ||
/** | ||
We need to check both Running and Cancelled status | ||
Tasks can be Cancelled but still Running | ||
**/ | ||
if(iterator._isRunning && !iterator._isCancelled) { | ||
iterator._isCancelled = true | ||
taskQueue.cancelAll() | ||
/** | ||
Ending with a Never result will propagate the Cancellation to all joiners | ||
**/ | ||
end(null, Never) | ||
} | ||
} | ||
/** | ||
attaches cancellation logic to this task's continuation | ||
this will permit cancellation to propagate down the call chain | ||
**/ | ||
cont && (cont.cancel = cancel) | ||
// tracks the running status | ||
@@ -100,16 +176,2 @@ iterator._isRunning = true | ||
/** | ||
Print error in a useful way whether in a browser environment | ||
(with expandable error stack traces), or in a node.js environment | ||
(text-only log output) | ||
**/ | ||
function logError(level, message, error) { | ||
/*eslint-disable no-console*/ | ||
if (typeof window === 'undefined') { | ||
console.log(`redux-saga ${level}: ${message}\n${error.stack}`) | ||
} else { | ||
console[level].call(console, message, error) | ||
} | ||
} | ||
/** | ||
This is the generator driver | ||
@@ -121,45 +183,73 @@ It's a recursive async/continuation function which calls itself | ||
// Preventive measure. If we end up here, then there is really something wrong | ||
if(!iterator._isRunning) | ||
if(!mainTask.isRunning) | ||
throw new Error('Trying to resume an already finished generator') | ||
try { | ||
let result | ||
if(error) | ||
result = iterator.throw(error) | ||
else if(arg === Never) { | ||
/** | ||
getting Never autoamtically cancels the main task | ||
We can get this value here | ||
try { | ||
// calling iterator.throw on a generator that doesn't define a correponding try/Catch | ||
// will throw an exception and jump to the catch block below | ||
const result = error ? iterator.throw(error) : iterator.next(arg) | ||
- By cancelling the parent task manually | ||
- By joining a Cancelled task | ||
- By taking from a channel that ended using `take` (and not `takem` used to trap End of channels) | ||
**/ | ||
mainTask.isCancelled = true | ||
/** | ||
Cancels the current effect; this will propagate the cancellation down to any called tasks | ||
**/ | ||
next.cancel() | ||
/** | ||
If this Generator has a `return` method then invokes it | ||
Thill will jump to the finally block | ||
**/ | ||
result = is.func(iterator.return) ? iterator.return(Never) : {done: true, value: Never} | ||
} else | ||
result = iterator.next(arg) | ||
if(!result.done) { | ||
runEffect(result.value, parentEffectId, '', next) | ||
} else { | ||
end(result.value) | ||
/** | ||
This Generator has ended, terminate the main task and notify the fork queue | ||
**/ | ||
mainTask.isMainRunning = false | ||
mainTask.cont && mainTask.cont(null, result.value) | ||
} | ||
} catch(error) { | ||
end(error, true) | ||
if(error instanceof SagaCancellationException) { | ||
if(isDev) { | ||
logError('warn', `${name}: uncaught`, error) | ||
} | ||
} else { | ||
logError('error', `${name}: uncaught`, error) | ||
//if(!forked) | ||
// throw error | ||
} | ||
if(mainTask.isCancelled) | ||
log('error', `uncaught at ${name}`, error.message) | ||
mainTask.isMainRunning = false | ||
mainTask.cont(error) | ||
} | ||
} | ||
function end(result, isError) { | ||
function end(error, result) { | ||
iterator._isRunning = false | ||
if(!isError) { | ||
stdChannel.close() | ||
if(!error) { | ||
if(result === Never && isDev) | ||
log('info', `${name} has been cancelled`,'') | ||
iterator._result = result | ||
deferredEnd.resolve(result) | ||
iterator._deferredEnd && iterator._deferredEnd.resolve(result) | ||
} else { | ||
iterator._error = result | ||
deferredEnd.reject(result) | ||
if(error instanceof Error) | ||
error.sagaStack = `at ${name} \n ${error.sagaStack || error.message}` | ||
if(!task.cont) | ||
log('error', `uncaught`, error.sagaStack || error.message) | ||
iterator._error = error | ||
iterator._deferredEnd && iterator._deferredEnd.reject(error) | ||
} | ||
unsubscribe() | ||
task.cont && task.cont(error, result) | ||
task.joiners.forEach(j => j.cb(error, result)) | ||
task.joiners = null | ||
} | ||
function runEffect(effect, parentEffectId, label = '', cb) { | ||
const effectId = nextEffectId() | ||
monitor( monitorActions.effectTriggered(effectId, parentEffectId, label, effect) ) | ||
monitor && monitor.effectTriggered({effectId, parentEffectId, label, effect}) | ||
@@ -180,5 +270,7 @@ /** | ||
cb.cancel = noop // defensive measure | ||
err ? | ||
monitor( monitorActions.effectRejected(effectId, err) ) | ||
: monitor( monitorActions.effectResolved(effectId, res) ) | ||
if(monitor) { | ||
err ? | ||
monitor.effectRejected(effectId, err) | ||
: monitor.effectResolved(effectId, res) | ||
} | ||
@@ -191,3 +283,3 @@ cb(err, res) | ||
// setup cancellation logic on the parent cb | ||
cb.cancel = (cancelError) => { | ||
cb.cancel = () => { | ||
// prevents cancelling an already completed effect | ||
@@ -200,13 +292,9 @@ if(effectSettled) | ||
propagates cancel downward | ||
catch uncaught cancellations errors, | ||
because w'll throw our own cancellation error inside this generator | ||
catch uncaught cancellations errors; since we can no longer call the completion | ||
callback, log errors raised during cancellations into the console | ||
**/ | ||
try { currCb.cancel(cancelError) } catch(err) { void(0); } | ||
try { currCb.cancel() } catch(err) { log('error', `uncaught at ${name}`, err.message) } | ||
currCb.cancel = noop // defensive measure | ||
/** | ||
triggers/propagates the cancellation error | ||
**/ | ||
cb(cancelError) | ||
monitor( monitorActions.effectRejected(effectId, cancelError) ) | ||
monitor && monitor.effectCancelled(effectId) | ||
} | ||
@@ -247,2 +335,4 @@ | ||
: (is.notUndef(data = asEffect.select(effect))) ? runSelectEffect(data, currCb) | ||
: (is.notUndef(data = asEffect.actionChannel(effect))) ? runChannelEffect(data, currCb) | ||
: (is.notUndef(data = asEffect.cancelled(effect))) ? runCancelledEffect(data, currCb) | ||
: /* anything else returned as is */ currCb(null, effect) | ||
@@ -267,25 +357,42 @@ ) | ||
function resolveIterator(iterator, effectId, name, cb) { | ||
resolvePromise( | ||
proc(iterator, subscribe, dispatch, getState, monitor, effectId, name).done, | ||
cb | ||
) | ||
proc(iterator, subscribe, dispatch, getState, monitor, effectId, name, cb) | ||
} | ||
function runTakeEffect(pattern, cb) { | ||
const def = { | ||
match : matcher(pattern), | ||
pattern, | ||
resolve: input => cb(null, input) | ||
function runTakeEffect({channel, pattern, maybe}, cb) { | ||
channel = channel || stdChannel | ||
const takeCb = inp => ( | ||
inp instanceof Error ? cb(inp) | ||
: inp === END && !maybe ? cb(null, Never) | ||
: cb(null, inp) | ||
) | ||
try { | ||
channel.take(takeCb, matcher(pattern)) | ||
} catch(err) { | ||
return cb(err) | ||
} | ||
deferredInputs.push(def) | ||
// cancellation logic for take effect | ||
cb.cancel = () => remove(deferredInputs, def) | ||
cb.cancel = takeCb.cancel | ||
} | ||
function runPutEffect(action, cb) { | ||
//synchronously nested dispatches can not be performed | ||
// because on a sync interleaved take/put the receiver will dispatch the | ||
// action before the sender can take the aknowledge | ||
// this workaround allows the dispatch to occur on the next microtask | ||
asap(() => cb(null, dispatch(action))) | ||
function runPutEffect({channel, action}, cb) { | ||
/* | ||
Use a reentrant lock `asap` to flatten all nested dispatches | ||
If this put cause another Saga to take this action an then immediately | ||
put an action that will be taken by this Saga. Then the outer Saga will miss | ||
the action from the inner Saga b/c this put has not yet returned. | ||
*/ | ||
asap(() => { | ||
let result | ||
try { | ||
result = (channel ? channel.put : dispatch)(action) | ||
} catch(error) { | ||
return cb(error) | ||
} | ||
if(is.promise(result)) { | ||
resolvePromise(result, cb) | ||
} else { | ||
return cb(null, result) | ||
} | ||
}) | ||
// Put effects are non cancellables | ||
@@ -321,3 +428,3 @@ } | ||
function runForkEffect({context, fn, args}, effectId, cb) { | ||
function runForkEffect({context, fn, args, detached}, effectId, cb) { | ||
let result, error, _iterator | ||
@@ -332,3 +439,6 @@ | ||
} catch(err) { | ||
error = error | ||
if(!detached) | ||
return cb(err) | ||
else | ||
error = err | ||
} | ||
@@ -342,27 +452,48 @@ | ||
//simple effect: wrap in a generator | ||
// do not bubble up synchronous failures, instead create a failed task. See #152 | ||
// do not bubble up synchronous failures for detached forks, instead create a failed task. See #152 | ||
else { | ||
_iterator = (error ? | ||
function*() { throw error } | ||
: function*() { return (yield result) } | ||
)() | ||
makeIterator(()=> { throw error }) | ||
: makeIterator((function() { | ||
let pc | ||
const eff = {done: false, value: result} | ||
const ret = value => ({done: true, value}) | ||
return arg => { | ||
if(!pc) { | ||
pc = true | ||
return eff | ||
} else { | ||
return ret(arg) | ||
} | ||
} | ||
})()) | ||
) | ||
} | ||
cb( | ||
null, | ||
proc(_iterator, subscribe, dispatch, getState, monitor, effectId, fn.name, true) | ||
) | ||
let task = proc(_iterator, subscribe, dispatch, getState, monitor, effectId, fn.name, (detached ? null : noop)) | ||
if(!detached) { | ||
if(_iterator._isRunning) | ||
taskQueue.addTask(task) | ||
else if(_iterator._error) | ||
return cb(_iterator._error) | ||
} | ||
cb(null, task) | ||
// Fork effects are non cancellables | ||
} | ||
function runJoinEffect(task, cb) { | ||
resolvePromise(task.done, cb) | ||
function runJoinEffect(t, cb) { | ||
if(t.isRunning()) { | ||
const joiner = {task, cb} | ||
cb.cancel = () => remove(t.joiners, joiner) | ||
t.joiners.push(joiner) | ||
} else { | ||
cb(t.error(), t.result()) | ||
} | ||
} | ||
function runCancelEffect(task, cb) { | ||
// cancel the given task | ||
// uncaught cancellations errors bubbles upward | ||
task.done[CANCEL]( | ||
new SagaCancellationException(MANUAL_CANCEL, name, name) | ||
) | ||
if(task.isRunning()) { | ||
task.cancel() | ||
} | ||
cb() | ||
@@ -372,3 +503,2 @@ // cancel effects are non cancellables | ||
// Reimplementing Promise.all. We're in 2016 | ||
function runParallelEffect(effects, effectId, cb) { | ||
@@ -393,18 +523,7 @@ if(!effects.length) { | ||
const chCbAtIdx = (err, res) => { | ||
// Either we've been cancelled, or an error aborted the whole effect | ||
if(completed) | ||
return | ||
// one of the effects failed | ||
if(err) { | ||
// cancel all other effects | ||
// This is an AUTO_CANCEL (not triggered by a manual cancel) | ||
// Catch uncaught cancellation errors, because w'll only throw the actual | ||
// rejection error (err) inside this generator | ||
try { | ||
cb.cancel( | ||
new SagaCancellationException(PARALLEL_AUTO_CANCEL, name, name) | ||
) | ||
} catch(err) { void(0) } | ||
cb(err) | ||
if(err || res === END || res === Never) { | ||
cb.cancel() | ||
err ? cb(err) : cb(null, res) | ||
} else { | ||
@@ -420,10 +539,6 @@ results[idx] = res | ||
// This is different, a cancellation coming from upward | ||
// either a MANUAL_CANCEL or a parent AUTO_CANCEL | ||
// No need to catch, will be swallowed by the caller | ||
cb.cancel = cancelError => { | ||
// prevents unnecessary cancellation | ||
cb.cancel = () => { | ||
if(!completed) { | ||
completed = true | ||
childCbs.forEach(chCb => chCb.cancel(cancelError)) | ||
childCbs.forEach(chCb => chCb.cancel()) | ||
} | ||
@@ -435,3 +550,2 @@ } | ||
// And yet; Promise.race | ||
function runRaceEffect(effects, effectId, cb) { | ||
@@ -444,3 +558,2 @@ let completed | ||
const chCbAtKey = (err, res) => { | ||
// Either we've been cancelled, or an error aborted the whole effect | ||
if(completed) | ||
@@ -451,15 +564,6 @@ return | ||
// Race Auto cancellation | ||
try { | ||
cb.cancel( | ||
new SagaCancellationException(RACE_AUTO_CANCEL, name, name) | ||
) | ||
} catch(err) { void(0) } | ||
cb({[key]: err}) | ||
} else { | ||
try { | ||
cb.cancel( | ||
new SagaCancellationException(RACE_AUTO_CANCEL, name, name) | ||
) | ||
} catch(err) { void(0) } | ||
cb.cancel() | ||
cb(err) | ||
} else if(res !== END && res !== Never) { | ||
cb.cancel() | ||
completed = true | ||
@@ -473,7 +577,7 @@ cb(null, {[key]: res}) | ||
cb.cancel = cancelError => { | ||
cb.cancel = () => { | ||
// prevents unnecessary cancellation | ||
if(!completed) { | ||
completed = true | ||
keys.forEach(key => childCbs[key].cancel(cancelError)) | ||
keys.forEach(key => childCbs[key].cancel()) | ||
} | ||
@@ -493,3 +597,14 @@ } | ||
function newTask(id, name, iterator, done, forked) { | ||
function runChannelEffect({pattern, buffer}, cb) { | ||
const match = matcher(pattern) | ||
match.pattern = pattern | ||
cb(null, eventChannel(subscribe, buffer || buffers.fixed(), match)) | ||
} | ||
function runCancelledEffect(data, cb) { | ||
cb(null, !!mainTask.isCancelled) | ||
} | ||
function newTask(id, name, iterator, cont) { | ||
iterator._deferredEnd = null | ||
return { | ||
@@ -499,11 +614,18 @@ [TASK]: true, | ||
name, | ||
done, | ||
forked, | ||
cancel: error => { | ||
if(!(error instanceof SagaCancellationException)) { | ||
error = new SagaCancellationException(MANUAL_CANCEL, name, error) | ||
get done() { | ||
if(iterator._deferredEnd) | ||
return iterator._deferredEnd.promise | ||
else { | ||
const def = deferred() | ||
iterator._deferredEnd = def | ||
if(!iterator._isRunning) | ||
iterator._error ? def.reject(iterator._error) : def.resolve(iterator._result) | ||
return def.promise | ||
} | ||
done[CANCEL](error) | ||
}, | ||
cont, | ||
joiners: [], | ||
cancel, | ||
isRunning: () => iterator._isRunning, | ||
isCancelled: () => iterator._isCancelled, | ||
result: () => iterator._result, | ||
@@ -510,0 +632,0 @@ error: () => iterator._error |
@@ -1,40 +0,4 @@ | ||
import { sym, is, check, noop, warnDeprecated } from './utils' | ||
import { is, check } from './utils' | ||
import proc from './proc' | ||
import emitter from './emitter' | ||
export const NOT_ITERATOR_ERROR = "runSaga must be called on an iterator" | ||
/** | ||
@deprecated | ||
ATTENTION! this method can have some potential issues | ||
For more infos, see issue https://github.com/yelouafi/redux-saga/issues/48 | ||
memoize the result of storeChannel. It avoids monkey patching the same store | ||
multiple times unnecessarly. We need only one channel per store | ||
**/ | ||
const IO = sym('IO') | ||
export function storeIO(store) { | ||
warnDeprecated(`storeIO is deprecated, to run Saga dynamically, use 'run' method of the middleware`) | ||
if(store[IO]) | ||
return store[IO] | ||
const storeEmitter = emitter() | ||
const _dispatch = store.dispatch | ||
store.dispatch = action => { | ||
const result = _dispatch(action) | ||
storeEmitter.emit(action) | ||
return result | ||
} | ||
store[IO] = { | ||
subscribe: storeEmitter.subscribe, | ||
dispatch : store.dispatch, | ||
getState : store.getState | ||
} | ||
return store[IO] | ||
} | ||
export function runSaga( | ||
@@ -47,6 +11,6 @@ iterator, | ||
}, | ||
monitor = noop | ||
monitor | ||
) { | ||
check(iterator, is.iterator, NOT_ITERATOR_ERROR) | ||
check(iterator, is.iterator, "runSaga must be called on an iterator") | ||
@@ -53,0 +17,0 @@ return proc( |
@@ -1,64 +0,64 @@ | ||
import { is } from './utils' | ||
import { END } from './channel' | ||
import { makeIterator } from './utils' | ||
import { take, fork, cancel } from './io' | ||
import SagaCancellationException from './SagaCancellationException' | ||
const resume = (fnOrValue, arg) => is.func(fnOrValue) ? fnOrValue(arg) : fnOrValue | ||
const done = { done: true } | ||
const done = { done: true, value: undefined } | ||
const qEnd = {} | ||
function fsmIterator(fsm, nextState, name = 'iterator') { | ||
let aborted, updateState | ||
function fsmIterator(fsm, q0, name = 'iterator') { | ||
let updateState, qNext = q0 | ||
function next(arg, error) { | ||
if(aborted) | ||
return done | ||
if(qNext === qEnd) | ||
return done | ||
if(error) { | ||
aborted = true | ||
if(!(error instanceof SagaCancellationException)) | ||
throw error | ||
return done | ||
qNext = qEnd | ||
throw error | ||
} else { | ||
if(updateState) | ||
updateState(arg) | ||
const [output, transition, _updateState] = fsm[nextState] | ||
updateState && updateState(arg) | ||
let [q, output, _updateState] = fsm[qNext]() | ||
qNext = q | ||
updateState = _updateState | ||
nextState = resume(transition, arg) | ||
return resume(output, arg) | ||
return qNext === qEnd ? done : output | ||
} | ||
} | ||
const iterator = { | ||
name, | ||
return makeIterator( | ||
next, | ||
throw: error => next(null, error) | ||
} | ||
if(typeof Symbol !== 'undefined') { | ||
iterator[Symbol.iterator] = () => iterator | ||
} | ||
return iterator | ||
error => next(null, error), | ||
name | ||
) | ||
} | ||
export function takeEvery(pattern, worker, ...args) { | ||
const yieldTake = { done: false, value: take(pattern)} | ||
const yieldFork = action => ({ done: false, value: fork(worker, ...args, action)}) | ||
const yTake = {done: false, value: take(pattern)} | ||
const yFork = ac => ({done: false, value: fork(worker, ...args, ac)}) | ||
let action, setAction = ac => action = ac | ||
return fsmIterator({ | ||
'take' : [yieldTake, 'fork'], | ||
'fork' : [yieldFork, 'take'] | ||
}, 'take', `takeEvery(${pattern}, ${worker.name})`) | ||
q1() { return ['q2', yTake, setAction] }, | ||
q2() { return action === END ? [qEnd] : ['q1', yFork(action)] } | ||
}, 'q1', `takeEvery(${String(pattern)}, ${worker.name})`) | ||
} | ||
export function takeLatest(pattern, worker, ...args) { | ||
const yieldTake = { done: false, value: take(pattern)} | ||
const yieldFork = () => ({ done: false, value: fork(worker, ...args, currentAction)}) | ||
const yieldCancel = () => ({ done: false, value: cancel(currentTask)}) | ||
const forkOrCancel = () => currentTask ? 'cancel' : 'fork' | ||
const yTake = {done: false, value: take(pattern)} | ||
const yFork = ac => ({done: false, value: fork(worker, ...args, ac)}) | ||
const yCancel = (task) => ({ done: false, value: cancel(task)}) | ||
let currentTask, currentAction | ||
let task, action | ||
const setTask = t => task = t | ||
const setAction = ac => action = ac | ||
return fsmIterator({ | ||
'take' : [ yieldTake, forkOrCancel, action => currentAction = action ], | ||
'cancel' : [yieldCancel, 'fork'], | ||
'fork' : [yieldFork, 'take', task => currentTask = task ] | ||
}, 'take', `takeLatest(${pattern}, ${worker.name})`) | ||
q1() { return ['q2', yTake, setAction] }, | ||
q2() { | ||
return action === END | ||
? [qEnd] | ||
: task ? ['q3', yCancel(task)] : ['q1', yFork(action), setTask] | ||
}, | ||
q3() { | ||
return ['q1', yFork(action), setTask] | ||
} | ||
}, 'q1', `takeLatest(${String(pattern)}, ${worker.name})`) | ||
} |
@@ -1,5 +0,7 @@ | ||
export const sym = id => `@@redux-saga/${id}` | ||
export const sym = (id) => `@@redux-saga/${id}` | ||
export const TASK = sym('TASK') | ||
export const kTrue = () => true | ||
export const MATCH = sym('MATCH') | ||
export const konst = v => () => v | ||
export const kTrue = konst(true) | ||
export const kFalse = konst(false) | ||
export const noop = () => {} | ||
@@ -21,6 +23,12 @@ export function ident(v) { | ||
func : f => typeof f === 'function', | ||
number : n => typeof n === 'number', | ||
array : Array.isArray, | ||
promise : p => p && is.func(p.then), | ||
iterator : it => it && is.func(it.next) && is.func(it.throw), | ||
task : it => it && it[TASK] | ||
task : t => t && t[TASK], | ||
take : ch => ch && is.func(ch.take), | ||
put : ch => ch && is.func(ch.put), | ||
observable: ob => ob && is.func(ob.subscribe), | ||
buffer : buf => buf && is.func(buf.isEmpty) && is.func(buf.take) && is.func(buf.put), | ||
pattern : pat => pat && ((typeof pat === 'string') || is.func(pat) || is.array(pat)) | ||
} | ||
@@ -52,2 +60,24 @@ | ||
export function delay(ms, val=true) { | ||
return new Promise((resolve) => setTimeout(() => resolve(val), ms)) | ||
} | ||
export function createMockTask() { | ||
let running = true | ||
let result, error | ||
return { | ||
[TASK]: true, | ||
isRunning: () => running, | ||
result: () => result, | ||
error: () => error, | ||
setRunning : b => running = b, | ||
setResult : r => result = r, | ||
setError : e => error = e | ||
} | ||
} | ||
export function autoInc(seed = 0) { | ||
@@ -57,11 +87,29 @@ return () => ++seed | ||
export function asap(action) { | ||
return Promise.resolve(1).then( () => action() ) | ||
const kThrow = err => { throw err } | ||
export function makeIterator(next, thro = kThrow, name='') { | ||
const iterator = { name, next, throw: thro } | ||
if(typeof Symbol !== 'undefined') { | ||
iterator[Symbol.iterator] = () => iterator | ||
} | ||
return iterator | ||
} | ||
/* eslint-disable no-console */ | ||
export function warnDeprecated(msg) { | ||
if(isDev) { | ||
console.warn('DEPRECATION WARNING', msg) | ||
/** | ||
Print error in a useful way whether in a browser environment | ||
(with expandable error stack traces), or in a node.js environment | ||
(text-only log output) | ||
**/ | ||
export function log(level, message, error) { | ||
/*eslint-disable no-console*/ | ||
if (typeof window === 'undefined') { | ||
console.log(`redux-saga ${level}: ${message}\n${(error && error.stack) || error}`) | ||
} else { | ||
console[level].call(console, message, error) | ||
} | ||
} | ||
export const internalErr = (err) => new Error(` | ||
redux-saga: Error checking hooks detected an inconsisten state. This is likely a bug | ||
in redux-saga code and not yours. Thanks for reporting this in the project's github repo. | ||
Error: ${err} | ||
`) |
@@ -1,2 +0,2 @@ | ||
import { | ||
export { | ||
TASK, | ||
@@ -7,34 +7,5 @@ noop, | ||
arrayOfDeffered, | ||
asap | ||
createMockTask | ||
} from './internal/utils' | ||
import { asEffect } from './internal/io' | ||
import { | ||
CANCEL, | ||
RACE_AUTO_CANCEL, | ||
PARALLEL_AUTO_CANCEL, | ||
MANUAL_CANCEL | ||
} from './internal/proc' | ||
import { createMockTask } from './internal/testUtils' | ||
import * as monitorActions from './internal/monitorActions' | ||
export { | ||
TASK, | ||
noop, | ||
is, asEffect, | ||
deferred, | ||
arrayOfDeffered, | ||
asap, | ||
CANCEL, | ||
RACE_AUTO_CANCEL, | ||
PARALLEL_AUTO_CANCEL, | ||
MANUAL_CANCEL, | ||
createMockTask, | ||
monitorActions | ||
} | ||
export { asEffect } from './internal/io' |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
282967
4241
236
39
1