import { isArray } from './util/isArray'; import { isObject } from './util/isObject'; import { isFunction } from './util/isFunction'; import { UnsubscriptionError } from './util/UnsubscriptionError'; export class Subscription { constructor(unsubscribe) { this.closed = false; this._parentOrParents = null; this._subscriptions = null; if (unsubscribe) { this._ctorUnsubscribe = true; this._unsubscribe = unsubscribe; } } unsubscribe() { let errors; if (this.closed) { return; } let { _parentOrParents, _ctorUnsubscribe, _unsubscribe, _subscriptions } = this; this.closed = true; this._parentOrParents = null; this._subscriptions = null; if (_parentOrParents instanceof Subscription) { _parentOrParents.remove(this); } else if (_parentOrParents !== null) { for (let index = 0; index < _parentOrParents.length; ++index) { const parent = _parentOrParents[index]; parent.remove(this); } } if (isFunction(_unsubscribe)) { if (_ctorUnsubscribe) { this._unsubscribe = undefined; } try { _unsubscribe.call(this); } catch (e) { errors = e instanceof UnsubscriptionError ? flattenUnsubscriptionErrors(e.errors) : [e]; } } if (isArray(_subscriptions)) { let index = -1; let len = _subscriptions.length; while (++index < len) { const sub = _subscriptions[index]; if (isObject(sub)) { try { sub.unsubscribe(); } catch (e) { errors = errors || []; if (e instanceof UnsubscriptionError) { errors = errors.concat(flattenUnsubscriptionErrors(e.errors)); } else { errors.push(e); } } } } } if (errors) { throw new UnsubscriptionError(errors); } } add(teardown) { let subscription = teardown; if (!teardown) { return Subscription.EMPTY; } switch (typeof teardown) { case 'function': subscription = new Subscription(teardown); case 'object': if (subscription === this || subscription.closed || typeof subscription.unsubscribe !== 'function') { return subscription; } else if (this.closed) { subscription.unsubscribe(); return subscription; } else if (!(subscription instanceof Subscription)) { const tmp = subscription; subscription = new Subscription(); subscription._subscriptions = [tmp]; } break; default: { throw new Error('unrecognized teardown ' + teardown + ' added to Subscription.'); } } let { _parentOrParents } = subscription; if (_parentOrParents === null) { subscription._parentOrParents = this; } else if (_parentOrParents instanceof Subscription) { if (_parentOrParents === this) { return subscription; } subscription._parentOrParents = [_parentOrParents, this]; } else if (_parentOrParents.indexOf(this) === -1) { _parentOrParents.push(this); } else { return subscription; } const subscriptions = this._subscriptions; if (subscriptions === null) { this._subscriptions = [subscription]; } else { subscriptions.push(subscription); } return subscription; } remove(subscription) { const subscriptions = this._subscriptions; if (subscriptions) { const subscriptionIndex = subscriptions.indexOf(subscription); if (subscriptionIndex !== -1) { subscriptions.splice(subscriptionIndex, 1); } } } } Subscription.EMPTY = (function (empty) { empty.closed = true; return empty; }(new Subscription())); function flattenUnsubscriptionErrors(errors) { return errors.reduce((errs, err) => errs.concat((err instanceof UnsubscriptionError) ? err.errors : err), []); } //# sourceMappingURL=Subscription.js.map