baconjs
Version:
A small functional reactive programming lib for JavaScript.
1,574 lines (1,573 loc) • 134 kB
JavaScript
(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();