UNPKG

baconjs

Version:

A small functional reactive programming lib for JavaScript.

1,574 lines (1,573 loc) 134 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.Bacon = {})); }(this, function (exports) { 'use strict'; var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; } || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __spreadArrays() { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; } function nop() { } var isArray = Array.isArray || function (xs) { return xs instanceof Array; }; function isObservable(x) { return x && x._isObservable; } function all(xs, f) { for (var i = 0, x; i < xs.length; i++) { x = xs[i]; if (!f(x)) { return false; } } return true; } function always(x) { return function () { return x; }; } function any(xs, f) { for (var i = 0, x; i < xs.length; i++) { x = xs[i]; if (f(x)) { return true; } } return false; } function bind(fn, me) { return function () { return fn.apply(me, arguments); }; } function contains(xs, x) { return indexOf(xs, x) !== -1; } function each(xs, f) { for (var key in xs) { if (Object.prototype.hasOwnProperty.call(xs, key)) { var value = xs[key]; f(key, value); } } } function empty(xs) { return xs.length === 0; } function filter(f, xs) { var filtered = []; for (var i = 0, x; i < xs.length; i++) { x = xs[i]; if (f(x)) { filtered.push(x); } } return filtered; } function flatMap(f, xs) { return fold(xs, [], function (ys, x) { return ys.concat(f(x)); }); } function flip(f) { return function (a, b) { return f(b, a); }; } function fold(xs, seed, f) { for (var i = 0, x; i < xs.length; i++) { x = xs[i]; seed = f(seed, x); } return seed; } function head(xs) { return xs[0]; } function id(x) { return x; } function indexOfDefault(xs, x) { return xs.indexOf(x); } function indexOfFallback(xs, x) { for (var i = 0, y; i < xs.length; i++) { y = xs[i]; if (x === y) { return i; } } return -1; } var indexOf = Array.prototype.indexOf ? indexOfDefault : indexOfFallback; function indexWhere(xs, f) { for (var i = 0, y; i < xs.length; i++) { y = xs[i]; if (f(y)) { return i; } } return -1; } function isFunction(f) { return typeof f === 'function'; } function last(xs) { return xs[xs.length - 1]; } function map(f, xs) { var result = []; for (var i = 0, x; i < xs.length; i++) { x = xs[i]; result.push(f(x)); } return result; } function negate(f) { return function (x) { return !f(x); }; } function remove(x, xs) { var i = indexOf(xs, x); if (i >= 0) { return xs.splice(i, 1); } } function tail(xs) { return xs.slice(1, xs.length); } function toArray(xs) { return isArray(xs) ? xs : [xs]; } function toFunction(f) { if (typeof f == 'function') { return f; } return function (x) { return f; }; } function toString(obj) { var hasProp = {}.hasOwnProperty; try { recursionDepth++; if (obj == null) { return 'undefined'; } else if (isFunction(obj)) { return 'function'; } else if (isArray(obj)) { if (recursionDepth > 5) { return '[..]'; } return '[' + map(toString, obj).toString() + ']'; } else if ((obj != null ? obj.toString : void 0) != null && obj.toString !== Object.prototype.toString) { return obj.toString(); } else if (typeof obj === 'object') { if (recursionDepth > 5) { return '{..}'; } var results = []; for (var key in obj) { if (!hasProp.call(obj, key)) continue; var value = function () { try { return obj[key]; } catch (error) { return error; } }(); results.push(toString(key) + ':' + toString(value)); } return '{' + results + '}'; } else { return obj; } } finally { recursionDepth--; } } function without(x, xs) { return filter(function (y) { return y !== x; }, xs); } var _ = { indexOf: indexOf, indexWhere: indexWhere, head: head, always: always, negate: negate, empty: empty, tail: tail, filter: filter, map: map, each: each, toArray: toArray, contains: contains, id: id, last: last, all: all, any: any, without: without, remove: remove, fold: fold, flatMap: flatMap, bind: bind, isFunction: isFunction, toFunction: toFunction, toString: toString }; var recursionDepth = 0; var more = undefined; var noMore = '<no-more>'; var defaultScheduler = { setTimeout: function (f, d) { return setTimeout(f, d); }, setInterval: function (f, i) { return setInterval(f, i); }, clearInterval: function (id) { return clearInterval(id); }, clearTimeout: function (id) { return clearTimeout(id); }, now: function () { return new Date().getTime(); } }; var GlobalScheduler = { scheduler: defaultScheduler }; function getScheduler() { return GlobalScheduler.scheduler; } function setScheduler(newScheduler) { GlobalScheduler.scheduler = newScheduler; } var rootEvent = undefined; var waiterObs = []; var waiters = {}; var aftersStack = []; var aftersStackHeight = 0; var flushed = {}; var processingAfters = false; function toString$1() { return _.toString({ rootEvent: rootEvent, processingAfters: processingAfters, waiterObs: waiterObs, waiters: waiters, aftersStack: aftersStack, aftersStackHeight: aftersStackHeight, flushed: flushed }); } function ensureStackHeight(h) { if (h <= aftersStackHeight) return; if (!aftersStack[h - 1]) { aftersStack[h - 1] = [ [], 0 ]; } aftersStackHeight = h; } function isInTransaction() { return rootEvent !== undefined; } function soonButNotYet(obs, f) { if (rootEvent) { whenDoneWith(obs, f); } else { GlobalScheduler.scheduler.setTimeout(f, 0); } } function afterTransaction(obs, f) { if (rootEvent || processingAfters) { ensureStackHeight(1); var stackIndexForThisObs = 0; while (stackIndexForThisObs < aftersStackHeight - 1) { if (containsObs(obs, aftersStack[stackIndexForThisObs][0])) { break; } stackIndexForThisObs++; } var listFromStack = aftersStack[stackIndexForThisObs][0]; listFromStack.push([ obs, f ]); if (!rootEvent) { processAfters(); } } else { return f(); } } function containsObs(obs, aftersList) { for (var i = 0; i < aftersList.length; i++) { if (aftersList[i][0].id == obs.id) return true; } return false; } function processAfters() { var stackSizeAtStart = aftersStackHeight; if (!stackSizeAtStart) return; var isRoot = !processingAfters; processingAfters = true; try { while (aftersStackHeight >= stackSizeAtStart) { var topOfStack = aftersStack[aftersStackHeight - 1]; if (!topOfStack) throw new Error('Unexpected stack top: ' + topOfStack); var topAfters = topOfStack[0], index = topOfStack[1]; if (index < topAfters.length) { var _a = topAfters[index], after = _a[1]; topOfStack[1]++; ensureStackHeight(aftersStackHeight + 1); var callSuccess = false; try { after(); callSuccess = true; while (aftersStackHeight > stackSizeAtStart && aftersStack[aftersStackHeight - 1][0].length == 0) { aftersStackHeight--; } } finally { if (!callSuccess) { aftersStack = []; aftersStackHeight = 0; } } } else { topOfStack[0] = []; topOfStack[1] = 0; break; } } } finally { if (isRoot) processingAfters = false; } } function whenDoneWith(obs, f) { if (rootEvent) { var obsWaiters = waiters[obs.id]; if (obsWaiters === undefined) { obsWaiters = waiters[obs.id] = [f]; return waiterObs.push(obs); } else { return obsWaiters.push(f); } } else { return f(); } } function flush() { while (waiterObs.length > 0) { flushWaiters(0, true); } flushed = {}; } function flushWaiters(index, deps) { var obs = waiterObs[index]; var obsId = obs.id; var obsWaiters = waiters[obsId]; waiterObs.splice(index, 1); delete waiters[obsId]; if (deps && waiterObs.length > 0) { flushDepsOf(obs); } for (var i = 0, f; i < obsWaiters.length; i++) { f = obsWaiters[i]; f(); } } function flushDepsOf(obs) { if (flushed[obs.id]) return; var deps = obs.internalDeps(); for (var i = 0, dep; i < deps.length; i++) { dep = deps[i]; flushDepsOf(dep); if (waiters[dep.id]) { var index = _.indexOf(waiterObs, dep); flushWaiters(index, false); } } flushed[obs.id] = true; } function inTransaction(event, context, f, args) { if (rootEvent) { return f.apply(context, args); } else { rootEvent = event; try { var result = f.apply(context, args); flush(); } finally { rootEvent = undefined; processAfters(); } return result; } } function currentEventId() { return rootEvent ? rootEvent.id : undefined; } function wrappedSubscribe(obs, subscribe, sink) { var unsubd = false; var shouldUnsub = false; var doUnsub = function () { shouldUnsub = true; }; var unsub = function () { unsubd = true; doUnsub(); }; doUnsub = subscribe(function (event) { afterTransaction(obs, function () { if (!unsubd) { var reply = sink(event); if (reply === noMore) { unsub(); } } }); return more; }); if (shouldUnsub) { doUnsub(); } return unsub; } function hasWaiters() { return waiterObs.length > 0; } var UpdateBarrier = { toString: toString$1, whenDoneWith: whenDoneWith, hasWaiters: hasWaiters, inTransaction: inTransaction, currentEventId: currentEventId, wrappedSubscribe: wrappedSubscribe, afterTransaction: afterTransaction, soonButNotYet: soonButNotYet, isInTransaction: isInTransaction }; var Desc = function () { function Desc(context, method, args) { if (args === void 0) { args = []; } this._isDesc = true; this.context = context; this.method = method; this.args = args; } Desc.prototype.deps = function () { if (!this.cachedDeps) { this.cachedDeps = findDeps([this.context].concat(this.args)); } return this.cachedDeps; }; Desc.prototype.toString = function () { var args = _.map(_.toString, this.args); return _.toString(this.context) + '.' + _.toString(this.method) + '(' + args + ')'; }; return Desc; }(); function describe(context, method) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } var ref = context || method; if (ref && ref._isDesc) { return context || method; } else { return new Desc(context, method, args); } } function findDeps(x) { if (isArray(x)) { return _.flatMap(findDeps, x); } else if (isObservable(x)) { return [x]; } else if (typeof x !== 'undefined' && x !== null ? x._isSource : undefined) { return [x.obs]; } else { return []; } } var nullSink = function () { return more; }; var nullVoidSink = function () { return more; }; function withStateMachine(initState, f, src) { return src.transform(withStateMachineT(initState, f), new Desc(src, 'withStateMachine', [ initState, f ])); } function withStateMachineT(initState, f) { var state = initState; return function (event, sink) { var fromF = f(state, event); var newState = fromF[0], outputs = fromF[1]; state = newState; var reply = more; for (var i = 0; i < outputs.length; i++) { var output = outputs[i]; reply = sink(output); if (reply === noMore) { return reply; } } return reply; }; } var Some = function () { function Some(value) { this._isSome = true; this.isDefined = true; this.value = value; } Some.prototype.getOrElse = function (arg) { return this.value; }; Some.prototype.get = function () { return this.value; }; Some.prototype.filter = function (f) { if (f(this.value)) { return new Some(this.value); } else { return None; } }; Some.prototype.map = function (f) { return new Some(f(this.value)); }; Some.prototype.forEach = function (f) { f(this.value); }; Some.prototype.toArray = function () { return [this.value]; }; Some.prototype.inspect = function () { return 'Some(' + this.value + ')'; }; Some.prototype.toString = function () { return this.inspect(); }; return Some; }(); var None = { _isNone: true, getOrElse: function (value) { return value; }, get: function () { throw new Error('None.get()'); }, filter: function () { return None; }, map: function () { return None; }, forEach: function () { }, isDefined: false, toArray: function () { return []; }, inspect: function () { return 'None'; }, toString: function () { return this.inspect(); } }; function none() { return None; } function toOption(v) { if (v && (v._isSome || v._isNone)) { return v; } else { return new Some(v); } } function isNone(object) { return typeof object !== 'undefined' && object !== null ? object._isNone : false; } var eventIdCounter = 0; var Event = function () { function Event() { this.id = ++eventIdCounter; this.isEvent = true; this._isEvent = true; this.isEnd = false; this.isInitial = false; this.isNext = false; this.isError = false; this.hasValue = false; } Event.prototype.filter = function (f) { return true; }; Event.prototype.inspect = function () { return this.toString(); }; Event.prototype.log = function () { return this.toString(); }; Event.prototype.toNext = function () { return this; }; return Event; }(); var Value = function (_super) { __extends(Value, _super); function Value(value) { var _this = _super.call(this) || this; _this.hasValue = true; if (value instanceof Event) { throw new Error$1('Wrapping an event inside other event'); } _this.value = value; return _this; } Value.prototype.fmap = function (f) { return this.apply(f(this.value)); }; Value.prototype.filter = function (f) { return f(this.value); }; Value.prototype.toString = function () { return _.toString(this.value); }; Value.prototype.log = function () { return this.value; }; return Value; }(Event); var Next = function (_super) { __extends(Next, _super); function Next(value) { var _this = _super.call(this, value) || this; _this.isNext = true; _this._isNext = true; return _this; } Next.prototype.apply = function (value) { return new Next(value); }; return Next; }(Value); var Initial = function (_super) { __extends(Initial, _super); function Initial(value) { var _this = _super.call(this, value) || this; _this.isInitial = true; _this._isInitial = true; return _this; } Initial.prototype.apply = function (value) { return new Initial(value); }; Initial.prototype.toNext = function () { return new Next(this.value); }; return Initial; }(Value); var NoValue = function (_super) { __extends(NoValue, _super); function NoValue() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.hasValue = false; return _this; } NoValue.prototype.fmap = function (f) { return this; }; return NoValue; }(Event); var End = function (_super) { __extends(End, _super); function End() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.isEnd = true; return _this; } End.prototype.toString = function () { return '<end>'; }; return End; }(NoValue); var Error$1 = function (_super) { __extends(Error, _super); function Error(error) { var _this = _super.call(this) || this; _this.isError = true; _this.error = error; return _this; } Error.prototype.toString = function () { return '<error> ' + _.toString(this.error); }; return Error; }(NoValue); function initialEvent(value) { return new Initial(value); } function nextEvent(value) { return new Next(value); } function endEvent() { return new End(); } function toEvent(x) { if (x && x._isEvent) { return x; } else { return nextEvent(x); } } function isEvent(e) { return e && e._isEvent; } function isInitial(e) { return e && e._isInitial; } function isError(e) { return e.isError; } function hasValue(e) { return e.hasValue; } function isEnd(e) { return e.isEnd; } function isNext(e) { return e.isNext; } function equals(a, b) { return a === b; } function skipDuplicates(src, isEqual) { if (isEqual === void 0) { isEqual = equals; } var desc = new Desc(src, 'skipDuplicates', []); return withStateMachine(none(), function (prev, event) { if (!hasValue(event)) { return [ prev, [event] ]; } else if (event.isInitial || isNone(prev) || !isEqual(prev.get(), event.value)) { return [ new Some(event.value), [event] ]; } else { return [ prev, [] ]; } }, src).withDesc(desc); } function take(count, src, desc) { return src.transform(takeT(count), desc || new Desc(src, 'take', [count])); } function takeT(count) { return function (e, sink) { if (!e.hasValue) { return sink(e); } else { count--; if (count > 0) { return sink(e); } else { if (count === 0) { sink(e); } sink(endEvent()); return noMore; } } }; } function log(args, src) { src.subscribe(function (event) { if (typeof console !== 'undefined' && typeof console.log === 'function') { console.log.apply(console, args.concat([event.log()])); } return more; }); } function doLogT(args) { return function (event, sink) { if (typeof console !== 'undefined' && console !== null && typeof console.log === 'function') { console.log.apply(console, args.concat([event.log()])); } return sink(event); }; } function doErrorT(f) { return function (event, sink) { if (isError(event)) { f(event.error); } return sink(event); }; } function doActionT(f) { return function (event, sink) { if (hasValue(event)) { f(event.value); } return sink(event); }; } function doEndT(f) { return function (event, sink) { if (isEnd(event)) { f(); } return sink(event); }; } function scan(src, seed, f) { var resultProperty; var acc = seed; var initHandled = false; var subscribe = function (sink) { var initSent = false; var unsub = nop; var reply = more; var sendInit = function () { if (!initSent) { initSent = initHandled = true; reply = sink(new Initial(acc)); if (reply === noMore) { unsub(); unsub = nop; } } return reply; }; unsub = src.subscribeInternal(function (event) { if (hasValue(event)) { if (initHandled && event.isInitial) { return more; } else { if (!event.isInitial) { sendInit(); } initSent = initHandled = true; var prev = acc; var next = f(prev, event.value); acc = next; return sink(event.apply(next)); } } else { if (event.isEnd) { reply = sendInit(); } if (reply !== noMore) { return sink(event); } return reply; } }); UpdateBarrier.whenDoneWith(resultProperty, sendInit); return unsub; }; return resultProperty = new Property(new Desc(src, 'scan', [ seed, f ]), subscribe); } function mapEndT(f) { var theF = _.toFunction(f); return function (event, sink) { if (isEnd(event)) { sink(nextEvent(theF(event))); sink(endEvent()); return noMore; } else { return sink(event); } }; } function mapErrorT(f) { var theF = _.toFunction(f); return function (event, sink) { if (isError(event)) { return sink(nextEvent(theF(event.error))); } else { return sink(event); } }; } function skipErrors(src) { return src.transform(function (event, sink) { if (isError(event)) { return more; } else { return sink(event); } }, new Desc(src, 'skipErrors', [])); } function last$1(src) { var lastEvent; return src.transform(function (event, sink) { if (isEnd(event)) { if (lastEvent) { sink(lastEvent); } sink(endEvent()); return noMore; } else if (hasValue(event)) { lastEvent = event; return more; } else { return sink(event); } }).withDesc(new Desc(src, 'last', [])); } var CompositeUnsubscribe = function () { function CompositeUnsubscribe(ss) { if (ss === void 0) { ss = []; } this.unsubscribed = false; this.unsubscribe = _.bind(this.unsubscribe, this); this.unsubscribed = false; this.subscriptions = []; this.starting = []; for (var i = 0, s; i < ss.length; i++) { s = ss[i]; this.add(s); } } CompositeUnsubscribe.prototype.add = function (subscription) { var _this = this; if (!this.unsubscribed) { var ended = false; var unsub = nop; this.starting.push(subscription); var unsubMe = function () { if (_this.unsubscribed) { return; } ended = true; _this.remove(unsub); _.remove(subscription, _this.starting); }; unsub = subscription(this.unsubscribe, unsubMe); if (!(this.unsubscribed || ended)) { this.subscriptions.push(unsub); } else { unsub(); } _.remove(subscription, this.starting); } }; CompositeUnsubscribe.prototype.remove = function (unsub) { if (this.unsubscribed) { return; } if (_.remove(unsub, this.subscriptions) !== undefined) { return unsub(); } }; CompositeUnsubscribe.prototype.unsubscribe = function () { if (this.unsubscribed) { return; } this.unsubscribed = true; var iterable = this.subscriptions; for (var i = 0; i < iterable.length; i++) { iterable[i](); } this.subscriptions = []; this.starting = []; }; CompositeUnsubscribe.prototype.count = function () { if (this.unsubscribed) { return 0; } return this.subscriptions.length + this.starting.length; }; CompositeUnsubscribe.prototype.empty = function () { return this.count() === 0; }; return CompositeUnsubscribe; }(); function streamSubscribeToPropertySubscribe(initValue, streamSubscribe) { return function (sink) { var initSent = false; var subbed = false; var unsub = nop; var reply = more; var sendInit = function () { if (!initSent) { return initValue.forEach(function (value) { initSent = true; reply = sink(new Initial(value)); if (reply === noMore) { unsub(); unsub = nop; return nop; } }); } }; unsub = streamSubscribe(function (event) { if (event instanceof Value) { if (event.isInitial && !subbed) { initValue = new Some(event.value); return more; } else { if (!event.isInitial) { sendInit(); } initSent = true; initValue = new Some(event.value); return sink(event); } } else { if (event.isEnd) { reply = sendInit(); } if (reply !== noMore) { return sink(event); } return reply; } }); subbed = true; sendInit(); return unsub; }; } function propertyFromStreamSubscribe(desc, subscribe) { return new Property(desc, streamSubscribeToPropertySubscribe(none(), subscribe)); } function once(value) { var s = new EventStream(new Desc('Bacon', 'once', [value]), function (sink) { UpdateBarrier.soonButNotYet(s, function () { sink(toEvent(value)); sink(endEvent()); }); return nop; }); return s; } function flatMap_(spawner, src, params) { if (params === void 0) { params = {}; } var root = src; var rootDep = [root]; var childDeps = []; var isProperty = src._isProperty; var ctor = isProperty ? propertyFromStreamSubscribe : newEventStreamAllowSync; var initialSpawned = false; var desc = params.desc || new Desc(src, 'flatMap_', [spawner]); var result = ctor(desc, function (sink) { var composite = new CompositeUnsubscribe(); var queue = []; function spawn(event) { if (isProperty && event.isInitial) { if (initialSpawned) { return more; } initialSpawned = true; } var child = makeObservable(spawner(event)); childDeps.push(child); return composite.add(function (unsubAll, unsubMe) { var unsub = child.subscribeInternal(function (event) { if (event.isEnd) { checkQueue(); checkEnd(unsubMe); return noMore; } else { event = event.toNext(); var reply = sink(event); if (reply === noMore) { unsubAll(); } return reply; } }); return function () { _.remove(child, childDeps); unsub(); }; }); } function checkQueue() { var event = queue.shift(); if (event) { spawn(event); } } function checkEnd(unsub) { unsub(); if (composite.empty()) { return sink(endEvent()); } return more; } composite.add(function (__, unsubRoot) { return root.subscribeInternal(function (event) { if (event.isEnd) { return checkEnd(unsubRoot); } else if (event.isError && !params.mapError) { return sink(event); } else if (params.firstOnly && composite.count() > 1) { return more; } else { if (composite.unsubscribed) { return noMore; } if (params.limit && composite.count() > params.limit) { queue.push(event); } else { spawn(event); } return more; } }); }); return composite.unsubscribe; }); result.internalDeps = function () { if (childDeps.length) { return rootDep.concat(childDeps); } else { return rootDep; } }; return result; } function handleEventValueWith(f) { if (typeof f == 'function') { return function (event) { if (hasValue(event)) { return f(event.value); } return event; }; } return function (event) { return f; }; } function makeObservable(x) { if (isObservable(x)) { return x; } else { return once(x); } } function flatMapEvent(src, f) { return flatMap_(f, src, { mapError: true, desc: new Desc(src, 'flatMapEvent', [f]) }); } function endAsValue(src) { return src.transform(function (event, sink) { if (isEnd(event)) { sink(nextEvent({})); sink(endEvent()); return noMore; } return more; }); } function endOnError(src, predicate) { if (predicate === void 0) { predicate = function (x) { return true; }; } return src.transform(function (event, sink) { if (isError(event) && predicate(event.error)) { sink(event); return sink(endEvent()); } else { return sink(event); } }, new Desc(src, 'endOnError', [])); } var Source = function () { function Source(obs, sync) { this._isSource = true; this.flatten = true; this.ended = false; this.obs = obs; this.sync = sync; } Source.prototype.subscribe = function (sink) { return this.obs.subscribeInternal(sink); }; Source.prototype.toString = function () { return this.obs.toString(); }; Source.prototype.markEnded = function () { this.ended = true; }; Source.prototype.mayHave = function (count) { return true; }; return Source; }(); var DefaultSource = function (_super) { __extends(DefaultSource, _super); function DefaultSource() { return _super !== null && _super.apply(this, arguments) || this; } DefaultSource.prototype.consume = function () { return this.value; }; DefaultSource.prototype.push = function (x) { this.value = x; }; DefaultSource.prototype.hasAtLeast = function (c) { return !!this.value; }; return DefaultSource; }(Source); var ConsumingSource = function (_super) { __extends(ConsumingSource, _super); function ConsumingSource(obs, sync) { var _this = _super.call(this, obs, sync) || this; _this.flatten = false; _this.queue = []; return _this; } ConsumingSource.prototype.consume = function () { return this.queue.shift(); }; ConsumingSource.prototype.push = function (x) { this.queue.push(x); }; ConsumingSource.prototype.mayHave = function (count) { return !this.ended || this.queue.length >= count; }; ConsumingSource.prototype.hasAtLeast = function (count) { return this.queue.length >= count; }; return ConsumingSource; }(Source); var BufferingSource = function (_super) { __extends(BufferingSource, _super); function BufferingSource(obs) { var _this = _super.call(this, obs, true) || this; _this.queue = []; return _this; } BufferingSource.prototype.consume = function () { var values = this.queue; this.queue = []; return { value: values }; }; BufferingSource.prototype.push = function (x) { return this.queue.push(x.value); }; BufferingSource.prototype.hasAtLeast = function (count) { return true; }; return BufferingSource; }(Source); function isTrigger(s) { if (s == null) return false; if (s._isSource) { return s.sync; } else { return s._isEventStream; } } function fromObservable(s) { if (s != null && s._isSource) { return s; } else if (s != null && s._isProperty) { return new DefaultSource(s, false); } else { return new ConsumingSource(s, true); } } function never() { return new EventStream(describe('Bacon', 'never'), function (sink) { sink(endEvent()); return nop; }); } function when() { var patterns = []; for (var _i = 0; _i < arguments.length; _i++) { patterns[_i] = arguments[_i]; } return when_(newEventStream, patterns); } function whenP() { var patterns = []; for (var _i = 0; _i < arguments.length; _i++) { patterns[_i] = arguments[_i]; } return when_(propertyFromStreamSubscribe, patterns); } function when_(ctor, patterns) { if (patterns.length === 0) { return never(); } var _a = processRawPatterns(extractRawPatterns(patterns)), sources = _a[0], ixPats = _a[1]; if (!sources.length) { return never(); } var needsBarrier = any(sources, function (s) { return s.flatten; }) && containsDuplicateDeps(map(function (s) { return s.obs; }, sources)); var desc = new Desc('Bacon', 'when', Array.prototype.slice.call(patterns)); var resultStream = ctor(desc, function (sink) { var triggers = []; var ends = false; function match(p) { for (var i = 0; i < p.ixs.length; i++) { var ix = p.ixs[i]; if (!sources[ix.index].hasAtLeast(ix.count)) { return false; } } return true; } function cannotMatch(p) { for (var i = 0; i < p.ixs.length; i++) { var ix = p.ixs[i]; if (!sources[ix.index].mayHave(ix.count)) { return true; } } return false; } function nonFlattened(trigger) { return !trigger.source.flatten; } function part(source) { return function (unsubAll) { function flushLater() { return UpdateBarrier.whenDoneWith(resultStream, flush); } function flushWhileTriggers() { var trigger; if ((trigger = triggers.pop()) !== undefined) { var reply = more; for (var i = 0, p; i < ixPats.length; i++) { p = ixPats[i]; if (match(p)) { var values = []; for (var j = 0; j < p.ixs.length; j++) { var event_1 = sources[p.ixs[j].index].consume(); if (!event_1) throw new Error('Event was undefined'); values.push(event_1.value); } var applied = p.f.apply(null, values); reply = sink(trigger.e.apply(applied)); if (triggers.length) { triggers = filter(nonFlattened, triggers); } if (reply === noMore) { return reply; } else { return flushWhileTriggers(); } } } } return more; } function flush() { var reply = flushWhileTriggers(); if (ends) { if (all(sources, cannotSync) || all(ixPats, cannotMatch)) { reply = noMore; sink(endEvent()); } } if (reply === noMore) { unsubAll(); } } return source.subscribe(function (e) { var reply = more; if (e.isEnd) { ends = true; source.markEnded(); flushLater(); } else if (e.isError) { reply = sink(e); } else { var valueEvent = e; source.push(valueEvent); if (source.sync) { triggers.push({ source: source, e: valueEvent }); if (needsBarrier || UpdateBarrier.hasWaiters()) { flushLater(); } else { flush(); } } } if (reply === noMore) { unsubAll(); } return reply; }); }; } return new CompositeUnsubscribe(map(part, sources)).unsubscribe; }); return resultStream; } function processRawPatterns(rawPatterns) { var sources = []; var pats = []; for (var i = 0; i < rawPatterns.length; i++) { var _a = rawPatterns[i], patSources = _a[0], f = _a[1]; var pat = { f: f, ixs: [] }; var triggerFound = false; for (var j = 0, s; j < patSources.length; j++) { s = patSources[j]; var index = indexOf(sources, s); if (!triggerFound) { triggerFound = isTrigger(s); } if (index < 0) { sources.push(s); index = sources.length - 1; } for (var k = 0; k < pat.ixs.length; k++) { var ix = pat.ixs[k]; if (ix.index === index) { ix.count++; } } pat.ixs.push({ index: index, count: 1 }); } if (patSources.length > 0 && !triggerFound) { throw new Error('At least one EventStream required, none found in ' + patSources); } if (patSources.length > 0) { pats.push(pat); } } return [ map(fromObservable, sources), pats ]; } function extractLegacyPatterns(sourceArgs) { var i = 0; var len = sourceArgs.length; var rawPatterns = []; while (i < len) { var patSources = toArray(sourceArgs[i++]); var f = toFunction(sourceArgs[i++]); rawPatterns.push([ patSources, f ]); } var usage = 'when: expecting arguments in the form (Observable+,function)+'; return rawPatterns; } function isTypedOrRawPattern(pattern) { return pattern instanceof Array && !isObservable(pattern[pattern.length - 1]); } function isRawPattern(pattern) { return pattern[0] instanceof Array; } function extractRawPatterns(patterns) { var rawPatterns = []; for (var i = 0; i < patterns.length; i++) { var pattern = patterns[i]; if (!isTypedOrRawPattern(pattern)) { return extractLegacyPatterns(patterns); } if (isRawPattern(pattern)) { rawPatterns.push([ pattern[0], toFunction(pattern[1]) ]); } else { var sources = pattern.slice(0, pattern.length - 1); var f = toFunction(pattern[pattern.length - 1]); rawPatterns.push([ sources, f ]); } } return rawPatterns; } function containsDuplicateDeps(observables, state) { if (state === void 0) { state = []; } function checkObservable(obs) { if (contains(state, obs)) { return true; } else { var deps = obs.internalDeps();