UNPKG

24.8 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4exports.TASK_CANCEL = exports.CHANNEL_END = exports.NOT_ITERATOR_ERROR = undefined;
5
6var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
7
8var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
9
10exports.default = proc;
11
12var _utils = require('./utils');
13
14var _scheduler = require('./scheduler');
15
16var _io = require('./io');
17
18var _channel = require('./channel');
19
20var _buffers = require('./buffers');
21
22function _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; }
23
24var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator';
25
26var CHANNEL_END = exports.CHANNEL_END = {
27 toString: function toString() {
28 return '@@redux-saga/CHANNEL_END';
29 }
30};
31var TASK_CANCEL = exports.TASK_CANCEL = {
32 toString: function toString() {
33 return '@@redux-saga/TASK_CANCEL';
34 }
35};
36
37var matchers = {
38 wildcard: function wildcard() {
39 return _utils.kTrue;
40 },
41 default: function _default(pattern) {
42 return (typeof pattern === 'undefined' ? 'undefined' : _typeof(pattern)) === 'symbol' ? function (input) {
43 return input.type === pattern;
44 } : function (input) {
45 return input.type === String(pattern);
46 };
47 },
48 array: function array(patterns) {
49 return function (input) {
50 return patterns.some(function (p) {
51 return matcher(p)(input);
52 });
53 };
54 },
55 predicate: function predicate(_predicate) {
56 return function (input) {
57 return _predicate(input);
58 };
59 }
60};
61
62function matcher(pattern) {
63 // prettier-ignore
64 return (pattern === '*' ? matchers.wildcard : _utils.is.array(pattern) ? matchers.array : _utils.is.stringableFunc(pattern) ? matchers.default : _utils.is.func(pattern) ? matchers.predicate : matchers.default)(pattern);
65}
66
67/**
68 Used to track a parent task and its forks
69 In the new fork model, forked tasks are attached by default to their parent
70 We model this using the concept of Parent task && main Task
71 main task is the main flow of the current Generator, the parent tasks is the
72 aggregation of the main tasks + all its forked tasks.
73 Thus the whole model represents an execution tree with multiple branches (vs the
74 linear execution tree in sequential (non parallel) programming)
75
76 A parent tasks has the following semantics
77 - It completes if all its forks either complete or all cancelled
78 - If it's cancelled, all forks are cancelled as well
79 - It aborts if any uncaught error bubbles up from forks
80 - If it completes, the return value is the one returned by the main task
81**/
82function forkQueue(name, mainTask, cb) {
83 var tasks = [],
84 result = void 0,
85 completed = false;
86 addTask(mainTask);
87
88 function abort(err) {
89 cancelAll();
90 cb(err, true);
91 }
92
93 function addTask(task) {
94 tasks.push(task);
95 task.cont = function (res, isErr) {
96 if (completed) {
97 return;
98 }
99
100 (0, _utils.remove)(tasks, task);
101 task.cont = _utils.noop;
102 if (isErr) {
103 abort(res);
104 } else {
105 if (task === mainTask) {
106 result = res;
107 }
108 if (!tasks.length) {
109 completed = true;
110 cb(result);
111 }
112 }
113 };
114 // task.cont.cancel = task.cancel
115 }
116
117 function cancelAll() {
118 if (completed) {
119 return;
120 }
121 completed = true;
122 tasks.forEach(function (t) {
123 t.cont = _utils.noop;
124 t.cancel();
125 });
126 tasks = [];
127 }
128
129 return {
130 addTask: addTask,
131 cancelAll: cancelAll,
132 abort: abort,
133 getTasks: function getTasks() {
134 return tasks;
135 },
136 taskNames: function taskNames() {
137 return tasks.map(function (t) {
138 return t.name;
139 });
140 }
141 };
142}
143
144function createTaskIterator(_ref) {
145 var context = _ref.context,
146 fn = _ref.fn,
147 args = _ref.args;
148
149 if (_utils.is.iterator(fn)) {
150 return fn;
151 }
152
153 // catch synchronous failures; see #152 and #441
154 var result = void 0,
155 error = void 0;
156 try {
157 result = fn.apply(context, args);
158 } catch (err) {
159 error = err;
160 }
161
162 // i.e. a generator function returns an iterator
163 if (_utils.is.iterator(result)) {
164 return result;
165 }
166
167 // do not bubble up synchronous failures for detached forks
168 // instead create a failed task. See #152 and #441
169 return error ? (0, _utils.makeIterator)(function () {
170 throw error;
171 }) : (0, _utils.makeIterator)(function () {
172 var pc = void 0;
173 var eff = { done: false, value: result };
174 var ret = function ret(value) {
175 return { done: true, value: value };
176 };
177 return function (arg) {
178 if (!pc) {
179 pc = true;
180 return eff;
181 } else {
182 return ret(arg);
183 }
184 };
185 }());
186}
187
188var wrapHelper = function wrapHelper(helper) {
189 return { fn: helper };
190};
191
192function proc(iterator) {
193 var subscribe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
194 return _utils.noop;
195 };
196 var dispatch = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _utils.noop;
197 var getState = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _utils.noop;
198 var parentContext = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
199 var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
200 var parentEffectId = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 0;
201 var name = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 'anonymous';
202 var cont = arguments[8];
203
204 (0, _utils.check)(iterator, _utils.is.iterator, NOT_ITERATOR_ERROR);
205
206 var effectsString = '[...effects]';
207 var runParallelEffect = (0, _utils.deprecate)(runAllEffect, (0, _utils.updateIncentive)(effectsString, 'all(' + effectsString + ')'));
208
209 var sagaMonitor = options.sagaMonitor,
210 logger = options.logger,
211 onError = options.onError;
212
213 var log = logger || _utils.log;
214 var stdChannel = (0, _channel.stdChannel)(subscribe);
215 var taskContext = Object.create(parentContext);
216 /**
217 Tracks the current effect cancellation
218 Each time the generator progresses. calling runEffect will set a new value
219 on it. It allows propagating cancellation to child effects
220 **/
221 next.cancel = _utils.noop;
222
223 /**
224 Creates a new task descriptor for this generator, We'll also create a main task
225 to track the main flow (besides other forked tasks)
226 **/
227 var task = newTask(parentEffectId, name, iterator, cont);
228 var mainTask = { name: name, cancel: cancelMain, isRunning: true };
229 var taskQueue = forkQueue(name, mainTask, end);
230
231 /**
232 cancellation of the main task. We'll simply resume the Generator with a Cancel
233 **/
234 function cancelMain() {
235 if (mainTask.isRunning && !mainTask.isCancelled) {
236 mainTask.isCancelled = true;
237 next(TASK_CANCEL);
238 }
239 }
240
241 /**
242 This may be called by a parent generator to trigger/propagate cancellation
243 cancel all pending tasks (including the main task), then end the current task.
244 Cancellation propagates down to the whole execution tree holded by this Parent task
245 It's also propagated to all joiners of this task and their execution tree/joiners
246 Cancellation is noop for terminated/Cancelled tasks tasks
247 **/
248 function cancel() {
249 /**
250 We need to check both Running and Cancelled status
251 Tasks can be Cancelled but still Running
252 **/
253 if (iterator._isRunning && !iterator._isCancelled) {
254 iterator._isCancelled = true;
255 taskQueue.cancelAll();
256 /**
257 Ending with a Never result will propagate the Cancellation to all joiners
258 **/
259 end(TASK_CANCEL);
260 }
261 }
262 /**
263 attaches cancellation logic to this task's continuation
264 this will permit cancellation to propagate down the call chain
265 **/
266 cont && (cont.cancel = cancel);
267
268 // tracks the running status
269 iterator._isRunning = true;
270
271 // kicks up the generator
272 next();
273
274 // then return the task descriptor to the caller
275 return task;
276
277 /**
278 This is the generator driver
279 It's a recursive async/continuation function which calls itself
280 until the generator terminates or throws
281 **/
282 function next(arg, isErr) {
283 // Preventive measure. If we end up here, then there is really something wrong
284 if (!mainTask.isRunning) {
285 throw new Error('Trying to resume an already finished generator');
286 }
287
288 try {
289 var result = void 0;
290 if (isErr) {
291 result = iterator.throw(arg);
292 } else if (arg === TASK_CANCEL) {
293 /**
294 getting TASK_CANCEL automatically cancels the main task
295 We can get this value here
296 - By cancelling the parent task manually
297 - By joining a Cancelled task
298 **/
299 mainTask.isCancelled = true;
300 /**
301 Cancels the current effect; this will propagate the cancellation down to any called tasks
302 **/
303 next.cancel();
304 /**
305 If this Generator has a `return` method then invokes it
306 This will jump to the finally block
307 **/
308 result = _utils.is.func(iterator.return) ? iterator.return(TASK_CANCEL) : { done: true, value: TASK_CANCEL };
309 } else if (arg === CHANNEL_END) {
310 // We get CHANNEL_END by taking from a channel that ended using `take` (and not `takem` used to trap End of channels)
311 result = _utils.is.func(iterator.return) ? iterator.return() : { done: true };
312 } else {
313 result = iterator.next(arg);
314 }
315
316 if (!result.done) {
317 runEffect(result.value, parentEffectId, '', next);
318 } else {
319 /**
320 This Generator has ended, terminate the main task and notify the fork queue
321 **/
322 mainTask.isMainRunning = false;
323 mainTask.cont && mainTask.cont(result.value);
324 }
325 } catch (error) {
326 if (mainTask.isCancelled) {
327 log('error', 'uncaught at ' + name, error.message);
328 }
329 mainTask.isMainRunning = false;
330 mainTask.cont(error, true);
331 }
332 }
333
334 function end(result, isErr) {
335 iterator._isRunning = false;
336 stdChannel.close();
337 if (!isErr) {
338 if (process.env.NODE_ENV === 'development' && result === TASK_CANCEL) {
339 log('info', name + ' has been cancelled', '');
340 }
341 iterator._result = result;
342 iterator._deferredEnd && iterator._deferredEnd.resolve(result);
343 } else {
344 if (result instanceof Error) {
345 result.sagaStack = 'at ' + name + ' \n ' + (result.sagaStack || result.stack);
346 }
347 if (!task.cont) {
348 log('error', 'uncaught', result.sagaStack || result.stack);
349 if (result instanceof Error && onError) {
350 onError(result);
351 }
352 }
353 iterator._error = result;
354 iterator._isAborted = true;
355 iterator._deferredEnd && iterator._deferredEnd.reject(result);
356 }
357 task.cont && task.cont(result, isErr);
358 task.joiners.forEach(function (j) {
359 return j.cb(result, isErr);
360 });
361 task.joiners = null;
362 }
363
364 function runEffect(effect, parentEffectId) {
365 var label = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
366 var cb = arguments[3];
367
368 var effectId = (0, _utils.uid)();
369 sagaMonitor && sagaMonitor.effectTriggered({ effectId: effectId, parentEffectId: parentEffectId, label: label, effect: effect });
370
371 /**
372 completion callback and cancel callback are mutually exclusive
373 We can't cancel an already completed effect
374 And We can't complete an already cancelled effectId
375 **/
376 var effectSettled = void 0;
377
378 // Completion callback passed to the appropriate effect runner
379 function currCb(res, isErr) {
380 if (effectSettled) {
381 return;
382 }
383
384 effectSettled = true;
385 cb.cancel = _utils.noop; // defensive measure
386 if (sagaMonitor) {
387 isErr ? sagaMonitor.effectRejected(effectId, res) : sagaMonitor.effectResolved(effectId, res);
388 }
389 cb(res, isErr);
390 }
391 // tracks down the current cancel
392 currCb.cancel = _utils.noop;
393
394 // setup cancellation logic on the parent cb
395 cb.cancel = function () {
396 // prevents cancelling an already completed effect
397 if (effectSettled) {
398 return;
399 }
400
401 effectSettled = true;
402 /**
403 propagates cancel downward
404 catch uncaught cancellations errors; since we can no longer call the completion
405 callback, log errors raised during cancellations into the console
406 **/
407 try {
408 currCb.cancel();
409 } catch (err) {
410 log('error', 'uncaught at ' + name, err.message);
411 }
412 currCb.cancel = _utils.noop; // defensive measure
413
414 sagaMonitor && sagaMonitor.effectCancelled(effectId);
415 };
416
417 /**
418 each effect runner must attach its own logic of cancellation to the provided callback
419 it allows this generator to propagate cancellation downward.
420 ATTENTION! effect runners must setup the cancel logic by setting cb.cancel = [cancelMethod]
421 And the setup must occur before calling the callback
422 This is a sort of inversion of control: called async functions are responsible
423 for completing the flow by calling the provided continuation; while caller functions
424 are responsible for aborting the current flow by calling the attached cancel function
425 Library users can attach their own cancellation logic to promises by defining a
426 promise[CANCEL] method in their returned promises
427 ATTENTION! calling cancel must have no effect on an already completed or cancelled effect
428 **/
429 var data = void 0;
430 // prettier-ignore
431 return (
432 // Non declarative effect
433 _utils.is.promise(effect) ? resolvePromise(effect, currCb) : _utils.is.helper(effect) ? runForkEffect(wrapHelper(effect), effectId, currCb) : _utils.is.iterator(effect) ? resolveIterator(effect, effectId, name, currCb)
434
435 // declarative effects
436 : _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : (data = _io.asEffect.take(effect)) ? runTakeEffect(data, currCb) : (data = _io.asEffect.put(effect)) ? runPutEffect(data, currCb) : (data = _io.asEffect.all(effect)) ? runAllEffect(data, effectId, currCb) : (data = _io.asEffect.race(effect)) ? runRaceEffect(data, effectId, currCb) : (data = _io.asEffect.call(effect)) ? runCallEffect(data, effectId, currCb) : (data = _io.asEffect.cps(effect)) ? runCPSEffect(data, currCb) : (data = _io.asEffect.fork(effect)) ? runForkEffect(data, effectId, currCb) : (data = _io.asEffect.join(effect)) ? runJoinEffect(data, currCb) : (data = _io.asEffect.cancel(effect)) ? runCancelEffect(data, currCb) : (data = _io.asEffect.select(effect)) ? runSelectEffect(data, currCb) : (data = _io.asEffect.actionChannel(effect)) ? runChannelEffect(data, currCb) : (data = _io.asEffect.flush(effect)) ? runFlushEffect(data, currCb) : (data = _io.asEffect.cancelled(effect)) ? runCancelledEffect(data, currCb) : (data = _io.asEffect.getContext(effect)) ? runGetContextEffect(data, currCb) : (data = _io.asEffect.setContext(effect)) ? runSetContextEffect(data, currCb) : /* anything else returned as is */currCb(effect)
437 );
438 }
439
440 function resolvePromise(promise, cb) {
441 var cancelPromise = promise[_utils.CANCEL];
442 if (_utils.is.func(cancelPromise)) {
443 cb.cancel = cancelPromise;
444 } else if (_utils.is.func(promise.abort)) {
445 cb.cancel = function () {
446 return promise.abort();
447 };
448 // TODO: add support for the fetch API, whenever they get around to
449 // adding cancel support
450 }
451 promise.then(cb, function (error) {
452 return cb(error, true);
453 });
454 }
455
456 function resolveIterator(iterator, effectId, name, cb) {
457 proc(iterator, subscribe, dispatch, getState, taskContext, options, effectId, name, cb);
458 }
459
460 function runTakeEffect(_ref2, cb) {
461 var channel = _ref2.channel,
462 pattern = _ref2.pattern,
463 maybe = _ref2.maybe;
464
465 channel = channel || stdChannel;
466 var takeCb = function takeCb(inp) {
467 return inp instanceof Error ? cb(inp, true) : (0, _channel.isEnd)(inp) && !maybe ? cb(CHANNEL_END) : cb(inp);
468 };
469 try {
470 channel.take(takeCb, matcher(pattern));
471 } catch (err) {
472 return cb(err, true);
473 }
474 cb.cancel = takeCb.cancel;
475 }
476
477 function runPutEffect(_ref3, cb) {
478 var channel = _ref3.channel,
479 action = _ref3.action,
480 resolve = _ref3.resolve;
481
482 /**
483 Schedule the put in case another saga is holding a lock.
484 The put will be executed atomically. ie nested puts will execute after
485 this put has terminated.
486 **/
487 (0, _scheduler.asap)(function () {
488 var result = void 0;
489 try {
490 result = (channel ? channel.put : dispatch)(action);
491 } catch (error) {
492 // If we have a channel or `put.resolve` was used then bubble up the error.
493 if (channel || resolve) return cb(error, true);
494 log('error', 'uncaught at ' + name, error.stack || error.message || error);
495 }
496
497 if (resolve && _utils.is.promise(result)) {
498 resolvePromise(result, cb);
499 } else {
500 return cb(result);
501 }
502 });
503 // Put effects are non cancellables
504 }
505
506 function runCallEffect(_ref4, effectId, cb) {
507 var context = _ref4.context,
508 fn = _ref4.fn,
509 args = _ref4.args;
510
511 var result = void 0;
512 // catch synchronous failures; see #152
513 try {
514 result = fn.apply(context, args);
515 } catch (error) {
516 return cb(error, true);
517 }
518 return _utils.is.promise(result) ? resolvePromise(result, cb) : _utils.is.iterator(result) ? resolveIterator(result, effectId, fn.name, cb) : cb(result);
519 }
520
521 function runCPSEffect(_ref5, cb) {
522 var context = _ref5.context,
523 fn = _ref5.fn,
524 args = _ref5.args;
525
526 // CPS (ie node style functions) can define their own cancellation logic
527 // by setting cancel field on the cb
528
529 // catch synchronous failures; see #152
530 try {
531 var cpsCb = function cpsCb(err, res) {
532 return _utils.is.undef(err) ? cb(res) : cb(err, true);
533 };
534 fn.apply(context, args.concat(cpsCb));
535 if (cpsCb.cancel) {
536 cb.cancel = function () {
537 return cpsCb.cancel();
538 };
539 }
540 } catch (error) {
541 return cb(error, true);
542 }
543 }
544
545 function runForkEffect(_ref6, effectId, cb) {
546 var context = _ref6.context,
547 fn = _ref6.fn,
548 args = _ref6.args,
549 detached = _ref6.detached;
550
551 var taskIterator = createTaskIterator({ context: context, fn: fn, args: args });
552
553 try {
554 (0, _scheduler.suspend)();
555 var _task = proc(taskIterator, subscribe, dispatch, getState, taskContext, options, effectId, fn.name, detached ? null : _utils.noop);
556
557 if (detached) {
558 cb(_task);
559 } else {
560 if (taskIterator._isRunning) {
561 taskQueue.addTask(_task);
562 cb(_task);
563 } else if (taskIterator._error) {
564 taskQueue.abort(taskIterator._error);
565 } else {
566 cb(_task);
567 }
568 }
569 } finally {
570 (0, _scheduler.flush)();
571 }
572 // Fork effects are non cancellables
573 }
574
575 function runJoinEffect(t, cb) {
576 if (t.isRunning()) {
577 var joiner = { task: task, cb: cb };
578 cb.cancel = function () {
579 return (0, _utils.remove)(t.joiners, joiner);
580 };
581 t.joiners.push(joiner);
582 } else {
583 t.isAborted() ? cb(t.error(), true) : cb(t.result());
584 }
585 }
586
587 function runCancelEffect(taskToCancel, cb) {
588 if (taskToCancel === _utils.SELF_CANCELLATION) {
589 taskToCancel = task;
590 }
591 if (taskToCancel.isRunning()) {
592 taskToCancel.cancel();
593 }
594 cb();
595 // cancel effects are non cancellables
596 }
597
598 function runAllEffect(effects, effectId, cb) {
599 var keys = Object.keys(effects);
600
601 if (!keys.length) {
602 return cb(_utils.is.array(effects) ? [] : {});
603 }
604
605 var completedCount = 0;
606 var completed = void 0;
607 var results = {};
608 var childCbs = {};
609
610 function checkEffectEnd() {
611 if (completedCount === keys.length) {
612 completed = true;
613 cb(_utils.is.array(effects) ? _utils.array.from(_extends({}, results, { length: keys.length })) : results);
614 }
615 }
616
617 keys.forEach(function (key) {
618 var chCbAtKey = function chCbAtKey(res, isErr) {
619 if (completed) {
620 return;
621 }
622 if (isErr || (0, _channel.isEnd)(res) || res === CHANNEL_END || res === TASK_CANCEL) {
623 cb.cancel();
624 cb(res, isErr);
625 } else {
626 results[key] = res;
627 completedCount++;
628 checkEffectEnd();
629 }
630 };
631 chCbAtKey.cancel = _utils.noop;
632 childCbs[key] = chCbAtKey;
633 });
634
635 cb.cancel = function () {
636 if (!completed) {
637 completed = true;
638 keys.forEach(function (key) {
639 return childCbs[key].cancel();
640 });
641 }
642 };
643
644 keys.forEach(function (key) {
645 return runEffect(effects[key], effectId, key, childCbs[key]);
646 });
647 }
648
649 function runRaceEffect(effects, effectId, cb) {
650 var completed = void 0;
651 var keys = Object.keys(effects);
652 var childCbs = {};
653
654 keys.forEach(function (key) {
655 var chCbAtKey = function chCbAtKey(res, isErr) {
656 if (completed) {
657 return;
658 }
659
660 if (isErr) {
661 // Race Auto cancellation
662 cb.cancel();
663 cb(res, true);
664 } else if (!(0, _channel.isEnd)(res) && res !== CHANNEL_END && res !== TASK_CANCEL) {
665 var _cb;
666
667 cb.cancel();
668 completed = true;
669 cb((_cb = {}, _cb[key] = res, _cb));
670 }
671 };
672 chCbAtKey.cancel = _utils.noop;
673 childCbs[key] = chCbAtKey;
674 });
675
676 cb.cancel = function () {
677 // prevents unnecessary cancellation
678 if (!completed) {
679 completed = true;
680 keys.forEach(function (key) {
681 return childCbs[key].cancel();
682 });
683 }
684 };
685 keys.forEach(function (key) {
686 if (completed) {
687 return;
688 }
689 runEffect(effects[key], effectId, key, childCbs[key]);
690 });
691 }
692
693 function runSelectEffect(_ref7, cb) {
694 var selector = _ref7.selector,
695 args = _ref7.args;
696
697 try {
698 var state = selector.apply(undefined, [getState()].concat(args));
699 cb(state);
700 } catch (error) {
701 cb(error, true);
702 }
703 }
704
705 function runChannelEffect(_ref8, cb) {
706 var pattern = _ref8.pattern,
707 buffer = _ref8.buffer;
708
709 var match = matcher(pattern);
710 match.pattern = pattern;
711 cb((0, _channel.eventChannel)(subscribe, buffer || _buffers.buffers.fixed(), match));
712 }
713
714 function runCancelledEffect(data, cb) {
715 cb(!!mainTask.isCancelled);
716 }
717
718 function runFlushEffect(channel, cb) {
719 channel.flush(cb);
720 }
721
722 function runGetContextEffect(prop, cb) {
723 cb(taskContext[prop]);
724 }
725
726 function runSetContextEffect(props, cb) {
727 _utils.object.assign(taskContext, props);
728 cb();
729 }
730
731 function newTask(id, name, iterator, cont) {
732 var _done, _ref9, _mutatorMap;
733
734 iterator._deferredEnd = null;
735 return _ref9 = {}, _ref9[_utils.TASK] = true, _ref9.id = id, _ref9.name = name, _done = 'done', _mutatorMap = {}, _mutatorMap[_done] = _mutatorMap[_done] || {}, _mutatorMap[_done].get = function () {
736 if (iterator._deferredEnd) {
737 return iterator._deferredEnd.promise;
738 } else {
739 var def = (0, _utils.deferred)();
740 iterator._deferredEnd = def;
741 if (!iterator._isRunning) {
742 iterator._error ? def.reject(iterator._error) : def.resolve(iterator._result);
743 }
744 return def.promise;
745 }
746 }, _ref9.cont = cont, _ref9.joiners = [], _ref9.cancel = cancel, _ref9.isRunning = function isRunning() {
747 return iterator._isRunning;
748 }, _ref9.isCancelled = function isCancelled() {
749 return iterator._isCancelled;
750 }, _ref9.isAborted = function isAborted() {
751 return iterator._isAborted;
752 }, _ref9.result = function result() {
753 return iterator._result;
754 }, _ref9.error = function error() {
755 return iterator._error;
756 }, _ref9.setContext = function setContext(props) {
757 (0, _utils.check)(props, _utils.is.object, (0, _utils.createSetContextWarning)('task', props));
758 _utils.object.assign(taskContext, props);
759 }, _defineEnumerableProperties(_ref9, _mutatorMap), _ref9;
760 }
761}
\No newline at end of file