kefir
Version:
Reactive Programming library for JavaScript inspired by Bacon.js and RxJS with focus on high performance and low memory usage
2,237 lines (1,937 loc) • 88 kB
JavaScript
/*! Kefir.js v3.8.8
* https://github.com/kefirjs/kefir
*/
function createObj(proto) {
var F = function () {};
F.prototype = proto;
return new F();
}
function extend(target /*, mixin1, mixin2...*/) {
var length = arguments.length,
i = void 0,
prop = void 0;
for (i = 1; i < length; i++) {
for (prop in arguments[i]) {
target[prop] = arguments[i][prop];
}
}
return target;
}
function inherit(Child, Parent /*, mixin1, mixin2...*/) {
var length = arguments.length,
i = void 0;
Child.prototype = createObj(Parent.prototype);
Child.prototype.constructor = Child;
for (i = 2; i < length; i++) {
extend(Child.prototype, arguments[i]);
}
return Child;
}
var NOTHING = ['<nothing>'];
var END = 'end';
var VALUE = 'value';
var ERROR = 'error';
var ANY = 'any';
function concat(a, b) {
var result = void 0,
length = void 0,
i = void 0,
j = void 0;
if (a.length === 0) {
return b;
}
if (b.length === 0) {
return a;
}
j = 0;
result = new Array(a.length + b.length);
length = a.length;
for (i = 0; i < length; i++, j++) {
result[j] = a[i];
}
length = b.length;
for (i = 0; i < length; i++, j++) {
result[j] = b[i];
}
return result;
}
function find(arr, value) {
var length = arr.length,
i = void 0;
for (i = 0; i < length; i++) {
if (arr[i] === value) {
return i;
}
}
return -1;
}
function findByPred(arr, pred) {
var length = arr.length,
i = void 0;
for (i = 0; i < length; i++) {
if (pred(arr[i])) {
return i;
}
}
return -1;
}
function cloneArray(input) {
var length = input.length,
result = new Array(length),
i = void 0;
for (i = 0; i < length; i++) {
result[i] = input[i];
}
return result;
}
function remove(input, index) {
var length = input.length,
result = void 0,
i = void 0,
j = void 0;
if (index >= 0 && index < length) {
if (length === 1) {
return [];
} else {
result = new Array(length - 1);
for (i = 0, j = 0; i < length; i++) {
if (i !== index) {
result[j] = input[i];
j++;
}
}
return result;
}
} else {
return input;
}
}
function map(input, fn) {
var length = input.length,
result = new Array(length),
i = void 0;
for (i = 0; i < length; i++) {
result[i] = fn(input[i]);
}
return result;
}
function forEach(arr, fn) {
var length = arr.length,
i = void 0;
for (i = 0; i < length; i++) {
fn(arr[i]);
}
}
function fillArray(arr, value) {
var length = arr.length,
i = void 0;
for (i = 0; i < length; i++) {
arr[i] = value;
}
}
function contains(arr, value) {
return find(arr, value) !== -1;
}
function slide(cur, next, max) {
var length = Math.min(max, cur.length + 1),
offset = cur.length - length + 1,
result = new Array(length),
i = void 0;
for (i = offset; i < length; i++) {
result[i - offset] = cur[i];
}
result[length - 1] = next;
return result;
}
function callSubscriber(type, fn, event) {
if (type === ANY) {
fn(event);
} else if (type === event.type) {
if (type === VALUE || type === ERROR) {
fn(event.value);
} else {
fn();
}
}
}
function Dispatcher() {
this._items = [];
this._spies = [];
this._inLoop = 0;
this._removedItems = null;
}
extend(Dispatcher.prototype, {
add: function (type, fn) {
this._items = concat(this._items, [{ type: type, fn: fn }]);
return this._items.length;
},
remove: function (type, fn) {
var index = findByPred(this._items, function (x) {
return x.type === type && x.fn === fn;
});
// if we're currently in a notification loop,
// remember this subscriber was removed
if (this._inLoop !== 0 && index !== -1) {
if (this._removedItems === null) {
this._removedItems = [];
}
this._removedItems.push(this._items[index]);
}
this._items = remove(this._items, index);
return this._items.length;
},
addSpy: function (fn) {
this._spies = concat(this._spies, [fn]);
return this._spies.length;
},
// Because spies are only ever a function that perform logging as
// their only side effect, we don't need the same complicated
// removal logic like in remove()
removeSpy: function (fn) {
this._spies = remove(this._spies, this._spies.indexOf(fn));
return this._spies.length;
},
dispatch: function (event) {
this._inLoop++;
for (var i = 0, spies = this._spies; this._spies !== null && i < spies.length; i++) {
spies[i](event);
}
for (var _i = 0, items = this._items; _i < items.length; _i++) {
// cleanup was called
if (this._items === null) {
break;
}
// this subscriber was removed
if (this._removedItems !== null && contains(this._removedItems, items[_i])) {
continue;
}
callSubscriber(items[_i].type, items[_i].fn, event);
}
this._inLoop--;
if (this._inLoop === 0) {
this._removedItems = null;
}
},
cleanup: function () {
this._items = null;
this._spies = null;
}
});
function Observable() {
this._dispatcher = new Dispatcher();
this._active = false;
this._alive = true;
this._activating = false;
this._logHandlers = null;
this._spyHandlers = null;
}
extend(Observable.prototype, {
_name: 'observable',
_onActivation: function () {},
_onDeactivation: function () {},
_setActive: function (active) {
if (this._active !== active) {
this._active = active;
if (active) {
this._activating = true;
this._onActivation();
this._activating = false;
} else {
this._onDeactivation();
}
}
},
_clear: function () {
this._setActive(false);
this._dispatcher.cleanup();
this._dispatcher = null;
this._logHandlers = null;
},
_emit: function (type, x) {
switch (type) {
case VALUE:
return this._emitValue(x);
case ERROR:
return this._emitError(x);
case END:
return this._emitEnd();
}
},
_emitValue: function (value) {
if (this._alive) {
this._dispatcher.dispatch({ type: VALUE, value: value });
}
},
_emitError: function (value) {
if (this._alive) {
this._dispatcher.dispatch({ type: ERROR, value: value });
}
},
_emitEnd: function () {
if (this._alive) {
this._alive = false;
this._dispatcher.dispatch({ type: END });
this._clear();
}
},
_on: function (type, fn) {
if (this._alive) {
this._dispatcher.add(type, fn);
this._setActive(true);
} else {
callSubscriber(type, fn, { type: END });
}
return this;
},
_off: function (type, fn) {
if (this._alive) {
var count = this._dispatcher.remove(type, fn);
if (count === 0) {
this._setActive(false);
}
}
return this;
},
onValue: function (fn) {
return this._on(VALUE, fn);
},
onError: function (fn) {
return this._on(ERROR, fn);
},
onEnd: function (fn) {
return this._on(END, fn);
},
onAny: function (fn) {
return this._on(ANY, fn);
},
offValue: function (fn) {
return this._off(VALUE, fn);
},
offError: function (fn) {
return this._off(ERROR, fn);
},
offEnd: function (fn) {
return this._off(END, fn);
},
offAny: function (fn) {
return this._off(ANY, fn);
},
observe: function (observerOrOnValue, onError, onEnd) {
var _this = this;
var closed = false;
var observer = !observerOrOnValue || typeof observerOrOnValue === 'function' ? { value: observerOrOnValue, error: onError, end: onEnd } : observerOrOnValue;
var handler = function (event) {
if (event.type === END) {
closed = true;
}
if (event.type === VALUE && observer.value) {
observer.value(event.value);
} else if (event.type === ERROR && observer.error) {
observer.error(event.value);
} else if (event.type === END && observer.end) {
observer.end(event.value);
}
};
this.onAny(handler);
return {
unsubscribe: function () {
if (!closed) {
_this.offAny(handler);
closed = true;
}
},
get closed() {
return closed;
}
};
},
// A and B must be subclasses of Stream and Property (order doesn't matter)
_ofSameType: function (A, B) {
return A.prototype.getType() === this.getType() ? A : B;
},
setName: function (sourceObs /* optional */, selfName) {
this._name = selfName ? sourceObs._name + '.' + selfName : sourceObs;
return this;
},
log: function () {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.toString();
var isCurrent = void 0;
var handler = function (event) {
var type = '<' + event.type + (isCurrent ? ':current' : '') + '>';
if (event.type === END) {
console.log(name, type);
} else {
console.log(name, type, event.value);
}
};
if (this._alive) {
if (!this._logHandlers) {
this._logHandlers = [];
}
this._logHandlers.push({ name: name, handler: handler });
}
isCurrent = true;
this.onAny(handler);
isCurrent = false;
return this;
},
offLog: function () {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.toString();
if (this._logHandlers) {
var handlerIndex = findByPred(this._logHandlers, function (obj) {
return obj.name === name;
});
if (handlerIndex !== -1) {
this.offAny(this._logHandlers[handlerIndex].handler);
this._logHandlers.splice(handlerIndex, 1);
}
}
return this;
},
spy: function () {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.toString();
var handler = function (event) {
var type = '<' + event.type + '>';
if (event.type === END) {
console.log(name, type);
} else {
console.log(name, type, event.value);
}
};
if (this._alive) {
if (!this._spyHandlers) {
this._spyHandlers = [];
}
this._spyHandlers.push({ name: name, handler: handler });
this._dispatcher.addSpy(handler);
}
return this;
},
offSpy: function () {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.toString();
if (this._spyHandlers) {
var handlerIndex = findByPred(this._spyHandlers, function (obj) {
return obj.name === name;
});
if (handlerIndex !== -1) {
this._dispatcher.removeSpy(this._spyHandlers[handlerIndex].handler);
this._spyHandlers.splice(handlerIndex, 1);
}
}
return this;
}
});
// extend() can't handle `toString` in IE8
Observable.prototype.toString = function () {
return '[' + this._name + ']';
};
function Stream() {
Observable.call(this);
}
inherit(Stream, Observable, {
_name: 'stream',
getType: function () {
return 'stream';
}
});
function Property() {
Observable.call(this);
this._currentEvent = null;
}
inherit(Property, Observable, {
_name: 'property',
_emitValue: function (value) {
if (this._alive) {
this._currentEvent = { type: VALUE, value: value };
if (!this._activating) {
this._dispatcher.dispatch({ type: VALUE, value: value });
}
}
},
_emitError: function (value) {
if (this._alive) {
this._currentEvent = { type: ERROR, value: value };
if (!this._activating) {
this._dispatcher.dispatch({ type: ERROR, value: value });
}
}
},
_emitEnd: function () {
if (this._alive) {
this._alive = false;
if (!this._activating) {
this._dispatcher.dispatch({ type: END });
}
this._clear();
}
},
_on: function (type, fn) {
if (this._alive) {
this._dispatcher.add(type, fn);
this._setActive(true);
}
if (this._currentEvent !== null) {
callSubscriber(type, fn, this._currentEvent);
}
if (!this._alive) {
callSubscriber(type, fn, { type: END });
}
return this;
},
getType: function () {
return 'property';
}
});
var neverS = new Stream();
neverS._emitEnd();
neverS._name = 'never';
function never() {
return neverS;
}
function timeBased(mixin) {
function AnonymousStream(wait, options) {
var _this = this;
Stream.call(this);
this._wait = wait;
this._intervalId = null;
this._$onTick = function () {
return _this._onTick();
};
this._init(options);
}
inherit(AnonymousStream, Stream, {
_init: function () {},
_free: function () {},
_onTick: function () {},
_onActivation: function () {
this._intervalId = setInterval(this._$onTick, this._wait);
},
_onDeactivation: function () {
if (this._intervalId !== null) {
clearInterval(this._intervalId);
this._intervalId = null;
}
},
_clear: function () {
Stream.prototype._clear.call(this);
this._$onTick = null;
this._free();
}
}, mixin);
return AnonymousStream;
}
var S = timeBased({
_name: 'later',
_init: function (_ref) {
var x = _ref.x;
this._x = x;
},
_free: function () {
this._x = null;
},
_onTick: function () {
this._emitValue(this._x);
this._emitEnd();
}
});
function later(wait, x) {
return new S(wait, { x: x });
}
var S$1 = timeBased({
_name: 'interval',
_init: function (_ref) {
var x = _ref.x;
this._x = x;
},
_free: function () {
this._x = null;
},
_onTick: function () {
this._emitValue(this._x);
}
});
function interval(wait, x) {
return new S$1(wait, { x: x });
}
var S$2 = timeBased({
_name: 'sequentially',
_init: function (_ref) {
var xs = _ref.xs;
this._xs = cloneArray(xs);
},
_free: function () {
this._xs = null;
},
_onTick: function () {
if (this._xs.length === 1) {
this._emitValue(this._xs[0]);
this._emitEnd();
} else {
this._emitValue(this._xs.shift());
}
}
});
function sequentially(wait, xs) {
return xs.length === 0 ? never() : new S$2(wait, { xs: xs });
}
var S$3 = timeBased({
_name: 'fromPoll',
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_onTick: function () {
var fn = this._fn;
this._emitValue(fn());
}
});
function fromPoll(wait, fn) {
return new S$3(wait, { fn: fn });
}
function emitter(obs) {
function value(x) {
obs._emitValue(x);
return obs._active;
}
function error(x) {
obs._emitError(x);
return obs._active;
}
function end() {
obs._emitEnd();
return obs._active;
}
function event(e) {
obs._emit(e.type, e.value);
return obs._active;
}
return {
value: value,
error: error,
end: end,
event: event,
// legacy
emit: value,
emitEvent: event
};
}
var S$4 = timeBased({
_name: 'withInterval',
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
this._emitter = emitter(this);
},
_free: function () {
this._fn = null;
this._emitter = null;
},
_onTick: function () {
var fn = this._fn;
fn(this._emitter);
}
});
function withInterval(wait, fn) {
return new S$4(wait, { fn: fn });
}
function S$5(fn) {
Stream.call(this);
this._fn = fn;
this._unsubscribe = null;
}
inherit(S$5, Stream, {
_name: 'stream',
_onActivation: function () {
var fn = this._fn;
var unsubscribe = fn(emitter(this));
this._unsubscribe = typeof unsubscribe === 'function' ? unsubscribe : null;
// fix https://github.com/kefirjs/kefir/issues/35
if (!this._active) {
this._callUnsubscribe();
}
},
_callUnsubscribe: function () {
if (this._unsubscribe !== null) {
this._unsubscribe();
this._unsubscribe = null;
}
},
_onDeactivation: function () {
this._callUnsubscribe();
},
_clear: function () {
Stream.prototype._clear.call(this);
this._fn = null;
}
});
function stream(fn) {
return new S$5(fn);
}
function fromCallback(callbackConsumer) {
var called = false;
return stream(function (emitter) {
if (!called) {
callbackConsumer(function (x) {
emitter.emit(x);
emitter.end();
});
called = true;
}
}).setName('fromCallback');
}
function fromNodeCallback(callbackConsumer) {
var called = false;
return stream(function (emitter) {
if (!called) {
callbackConsumer(function (error, x) {
if (error) {
emitter.error(error);
} else {
emitter.emit(x);
}
emitter.end();
});
called = true;
}
}).setName('fromNodeCallback');
}
function spread(fn, length) {
switch (length) {
case 0:
return function () {
return fn();
};
case 1:
return function (a) {
return fn(a[0]);
};
case 2:
return function (a) {
return fn(a[0], a[1]);
};
case 3:
return function (a) {
return fn(a[0], a[1], a[2]);
};
case 4:
return function (a) {
return fn(a[0], a[1], a[2], a[3]);
};
default:
return function (a) {
return fn.apply(null, a);
};
}
}
function apply(fn, c, a) {
var aLength = a ? a.length : 0;
if (c == null) {
switch (aLength) {
case 0:
return fn();
case 1:
return fn(a[0]);
case 2:
return fn(a[0], a[1]);
case 3:
return fn(a[0], a[1], a[2]);
case 4:
return fn(a[0], a[1], a[2], a[3]);
default:
return fn.apply(null, a);
}
} else {
switch (aLength) {
case 0:
return fn.call(c);
default:
return fn.apply(c, a);
}
}
}
function fromSubUnsub(sub, unsub, transformer /* Function | falsey */) {
return stream(function (emitter) {
var handler = transformer ? function () {
emitter.emit(apply(transformer, this, arguments));
} : function (x) {
emitter.emit(x);
};
sub(handler);
return function () {
return unsub(handler);
};
}).setName('fromSubUnsub');
}
var pairs = [['addEventListener', 'removeEventListener'], ['addListener', 'removeListener'], ['on', 'off']];
function fromEvents(target, eventName, transformer) {
var sub = void 0,
unsub = void 0;
for (var i = 0; i < pairs.length; i++) {
if (typeof target[pairs[i][0]] === 'function' && typeof target[pairs[i][1]] === 'function') {
sub = pairs[i][0];
unsub = pairs[i][1];
break;
}
}
if (sub === undefined) {
throw new Error("target don't support any of " + 'addEventListener/removeEventListener, addListener/removeListener, on/off method pair');
}
return fromSubUnsub(function (handler) {
return target[sub](eventName, handler);
}, function (handler) {
return target[unsub](eventName, handler);
}, transformer).setName('fromEvents');
}
// HACK:
// We don't call parent Class constructor, but instead putting all necessary
// properties into prototype to simulate ended Property
// (see Propperty and Observable classes).
function P(value) {
this._currentEvent = { type: 'value', value: value, current: true };
}
inherit(P, Property, {
_name: 'constant',
_active: false,
_activating: false,
_alive: false,
_dispatcher: null,
_logHandlers: null
});
function constant(x) {
return new P(x);
}
// HACK:
// We don't call parent Class constructor, but instead putting all necessary
// properties into prototype to simulate ended Property
// (see Propperty and Observable classes).
function P$1(value) {
this._currentEvent = { type: 'error', value: value, current: true };
}
inherit(P$1, Property, {
_name: 'constantError',
_active: false,
_activating: false,
_alive: false,
_dispatcher: null,
_logHandlers: null
});
function constantError(x) {
return new P$1(x);
}
function createConstructor(BaseClass, name) {
return function AnonymousObservable(source, options) {
var _this = this;
BaseClass.call(this);
this._source = source;
this._name = source._name + '.' + name;
this._init(options);
this._$handleAny = function (event) {
return _this._handleAny(event);
};
};
}
function createClassMethods(BaseClass) {
return {
_init: function () {},
_free: function () {},
_handleValue: function (x) {
this._emitValue(x);
},
_handleError: function (x) {
this._emitError(x);
},
_handleEnd: function () {
this._emitEnd();
},
_handleAny: function (event) {
switch (event.type) {
case VALUE:
return this._handleValue(event.value);
case ERROR:
return this._handleError(event.value);
case END:
return this._handleEnd();
}
},
_onActivation: function () {
this._source.onAny(this._$handleAny);
},
_onDeactivation: function () {
this._source.offAny(this._$handleAny);
},
_clear: function () {
BaseClass.prototype._clear.call(this);
this._source = null;
this._$handleAny = null;
this._free();
}
};
}
function createStream(name, mixin) {
var S = createConstructor(Stream, name);
inherit(S, Stream, createClassMethods(Stream), mixin);
return S;
}
function createProperty(name, mixin) {
var P = createConstructor(Property, name);
inherit(P, Property, createClassMethods(Property), mixin);
return P;
}
var P$2 = createProperty('toProperty', {
_init: function (_ref) {
var fn = _ref.fn;
this._getInitialCurrent = fn;
},
_onActivation: function () {
if (this._getInitialCurrent !== null) {
var getInitial = this._getInitialCurrent;
this._emitValue(getInitial());
}
this._source.onAny(this._$handleAny); // copied from patterns/one-source
}
});
function toProperty(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
if (fn !== null && typeof fn !== 'function') {
throw new Error('You should call toProperty() with a function or no arguments.');
}
return new P$2(obs, { fn: fn });
}
var S$6 = createStream('changes', {
_handleValue: function (x) {
if (!this._activating) {
this._emitValue(x);
}
},
_handleError: function (x) {
if (!this._activating) {
this._emitError(x);
}
}
});
function changes(obs) {
return new S$6(obs);
}
function fromPromise(promise) {
var called = false;
var result = stream(function (emitter) {
if (!called) {
var onValue = function (x) {
emitter.emit(x);
emitter.end();
};
var onError = function (x) {
emitter.error(x);
emitter.end();
};
var _promise = promise.then(onValue, onError);
// prevent libraries like 'Q' or 'when' from swallowing exceptions
if (_promise && typeof _promise.done === 'function') {
_promise.done();
}
called = true;
}
});
return toProperty(result, null).setName('fromPromise');
}
function getGlodalPromise() {
if (typeof Promise === 'function') {
return Promise;
} else {
throw new Error("There isn't default Promise, use shim or parameter");
}
}
var toPromise = function (obs) {
var Promise = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getGlodalPromise();
var last = null;
return new Promise(function (resolve, reject) {
obs.onAny(function (event) {
if (event.type === END && last !== null) {
(last.type === VALUE ? resolve : reject)(last.value);
last = null;
} else {
last = event;
}
});
});
};
function symbolObservablePonyfill(root) {
var result;
var Symbol = root.Symbol;
if (typeof Symbol === 'function') {
if (Symbol.observable) {
result = Symbol.observable;
} else {
result = Symbol('observable');
Symbol.observable = result;
}
} else {
result = '@@observable';
}
return result;
}
/* global window */
var root;
if (typeof self !== 'undefined') {
root = self;
} else if (typeof window !== 'undefined') {
root = window;
} else if (typeof global !== 'undefined') {
root = global;
} else if (typeof module !== 'undefined') {
root = module;
} else {
root = Function('return this')();
}
var result = symbolObservablePonyfill(root);
// this file contains some hot JS modules systems stuff
var $$observable = result.default ? result.default : result;
function fromESObservable(_observable) {
var observable = _observable[$$observable] ? _observable[$$observable]() : _observable;
return stream(function (emitter) {
var unsub = observable.subscribe({
error: function (error) {
emitter.error(error);
emitter.end();
},
next: function (value) {
emitter.emit(value);
},
complete: function () {
emitter.end();
}
});
if (unsub.unsubscribe) {
return function () {
unsub.unsubscribe();
};
} else {
return unsub;
}
}).setName('fromESObservable');
}
function ESObservable(observable) {
this._observable = observable.takeErrors(1);
}
extend(ESObservable.prototype, {
subscribe: function (observerOrOnNext, onError, onComplete) {
var _this = this;
var observer = typeof observerOrOnNext === 'function' ? { next: observerOrOnNext, error: onError, complete: onComplete } : observerOrOnNext;
var fn = function (event) {
if (event.type === END) {
closed = true;
}
if (event.type === VALUE && observer.next) {
observer.next(event.value);
} else if (event.type === ERROR && observer.error) {
observer.error(event.value);
} else if (event.type === END && observer.complete) {
observer.complete(event.value);
}
};
this._observable.onAny(fn);
var closed = false;
var subscription = {
unsubscribe: function () {
closed = true;
_this._observable.offAny(fn);
},
get closed() {
return closed;
}
};
return subscription;
}
});
// Need to assign directly b/c Symbols aren't enumerable.
ESObservable.prototype[$$observable] = function () {
return this;
};
function toESObservable() {
return new ESObservable(this);
}
function collect(source, keys, values) {
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
keys.push(prop);
values.push(source[prop]);
}
}
}
function defaultErrorsCombinator(errors) {
var latestError = void 0;
for (var i = 0; i < errors.length; i++) {
if (errors[i] !== undefined) {
if (latestError === undefined || latestError.index < errors[i].index) {
latestError = errors[i];
}
}
}
return latestError.error;
}
function Combine(active, passive, combinator) {
var _this = this;
Stream.call(this);
this._activeCount = active.length;
this._sources = concat(active, passive);
this._combinator = combinator;
this._aliveCount = 0;
this._latestValues = new Array(this._sources.length);
this._latestErrors = new Array(this._sources.length);
fillArray(this._latestValues, NOTHING);
this._emitAfterActivation = false;
this._endAfterActivation = false;
this._latestErrorIndex = 0;
this._$handlers = [];
var _loop = function (i) {
_this._$handlers.push(function (event) {
return _this._handleAny(i, event);
});
};
for (var i = 0; i < this._sources.length; i++) {
_loop(i);
}
}
inherit(Combine, Stream, {
_name: 'combine',
_onActivation: function () {
this._aliveCount = this._activeCount;
// we need to suscribe to _passive_ sources before _active_
// (see https://github.com/kefirjs/kefir/issues/98)
for (var i = this._activeCount; i < this._sources.length; i++) {
this._sources[i].onAny(this._$handlers[i]);
}
for (var _i = 0; _i < this._activeCount; _i++) {
this._sources[_i].onAny(this._$handlers[_i]);
}
if (this._emitAfterActivation) {
this._emitAfterActivation = false;
this._emitIfFull();
}
if (this._endAfterActivation) {
this._emitEnd();
}
},
_onDeactivation: function () {
var length = this._sources.length,
i = void 0;
for (i = 0; i < length; i++) {
this._sources[i].offAny(this._$handlers[i]);
}
},
_emitIfFull: function () {
var hasAllValues = true;
var hasErrors = false;
var length = this._latestValues.length;
var valuesCopy = new Array(length);
var errorsCopy = new Array(length);
for (var i = 0; i < length; i++) {
valuesCopy[i] = this._latestValues[i];
errorsCopy[i] = this._latestErrors[i];
if (valuesCopy[i] === NOTHING) {
hasAllValues = false;
}
if (errorsCopy[i] !== undefined) {
hasErrors = true;
}
}
if (hasAllValues) {
var combinator = this._combinator;
this._emitValue(combinator(valuesCopy));
}
if (hasErrors) {
this._emitError(defaultErrorsCombinator(errorsCopy));
}
},
_handleAny: function (i, event) {
if (event.type === VALUE || event.type === ERROR) {
if (event.type === VALUE) {
this._latestValues[i] = event.value;
this._latestErrors[i] = undefined;
}
if (event.type === ERROR) {
this._latestValues[i] = NOTHING;
this._latestErrors[i] = {
index: this._latestErrorIndex++,
error: event.value
};
}
if (i < this._activeCount) {
if (this._activating) {
this._emitAfterActivation = true;
} else {
this._emitIfFull();
}
}
} else {
// END
if (i < this._activeCount) {
this._aliveCount--;
if (this._aliveCount === 0) {
if (this._activating) {
this._endAfterActivation = true;
} else {
this._emitEnd();
}
}
}
}
},
_clear: function () {
Stream.prototype._clear.call(this);
this._sources = null;
this._latestValues = null;
this._latestErrors = null;
this._combinator = null;
this._$handlers = null;
}
});
function combineAsArray(active) {
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var combinator = arguments[2];
if (!Array.isArray(passive)) {
throw new Error('Combine can only combine active and passive collections of the same type.');
}
combinator = combinator ? spread(combinator, active.length + passive.length) : function (x) {
return x;
};
return active.length === 0 ? never() : new Combine(active, passive, combinator);
}
function combineAsObject(active) {
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var combinator = arguments[2];
if (typeof passive !== 'object' || Array.isArray(passive)) {
throw new Error('Combine can only combine active and passive collections of the same type.');
}
var keys = [],
activeObservables = [],
passiveObservables = [];
collect(active, keys, activeObservables);
collect(passive, keys, passiveObservables);
var objectify = function (values) {
var event = {};
for (var i = values.length - 1; 0 <= i; i--) {
event[keys[i]] = values[i];
}
return combinator ? combinator(event) : event;
};
return activeObservables.length === 0 ? never() : new Combine(activeObservables, passiveObservables, objectify);
}
function combine(active, passive, combinator) {
if (typeof passive === 'function') {
combinator = passive;
passive = undefined;
}
return Array.isArray(active) ? combineAsArray(active, passive, combinator) : combineAsObject(active, passive, combinator);
}
var Observable$2 = {
empty: function () {
return never();
},
// Monoid based on merge() seems more useful than one based on concat().
concat: function (a, b) {
return a.merge(b);
},
of: function (x) {
return constant(x);
},
map: function (fn, obs) {
return obs.map(fn);
},
bimap: function (fnErr, fnVal, obs) {
return obs.mapErrors(fnErr).map(fnVal);
},
// This ap strictly speaking incompatible with chain. If we derive ap from chain we get
// different (not very useful) behavior. But spec requires that if method can be derived
// it must have the same behavior as hand-written method. We intentionally violate the spec
// in hope that it won't cause many troubles in practice. And in return we have more useful type.
ap: function (obsFn, obsVal) {
return combine([obsFn, obsVal], function (fn, val) {
return fn(val);
});
},
chain: function (fn, obs) {
return obs.flatMap(fn);
}
};
var staticLand = Object.freeze({
Observable: Observable$2
});
var mixin = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleValue: function (x) {
var fn = this._fn;
this._emitValue(fn(x));
}
};
var S$7 = createStream('map', mixin);
var P$3 = createProperty('map', mixin);
var id = function (x) {
return x;
};
function map$1(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id;
return new (obs._ofSameType(S$7, P$3))(obs, { fn: fn });
}
var mixin$1 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleValue: function (x) {
var fn = this._fn;
if (fn(x)) {
this._emitValue(x);
}
}
};
var S$8 = createStream('filter', mixin$1);
var P$4 = createProperty('filter', mixin$1);
var id$1 = function (x) {
return x;
};
function filter(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id$1;
return new (obs._ofSameType(S$8, P$4))(obs, { fn: fn });
}
var mixin$2 = {
_init: function (_ref) {
var n = _ref.n;
this._n = n;
if (n <= 0) {
this._emitEnd();
}
},
_handleValue: function (x) {
if (this._n === 0) {
return;
}
this._n--;
this._emitValue(x);
if (this._n === 0) {
this._emitEnd();
}
}
};
var S$9 = createStream('take', mixin$2);
var P$5 = createProperty('take', mixin$2);
function take(obs, n) {
return new (obs._ofSameType(S$9, P$5))(obs, { n: n });
}
var mixin$3 = {
_init: function (_ref) {
var n = _ref.n;
this._n = n;
if (n <= 0) {
this._emitEnd();
}
},
_handleError: function (x) {
if (this._n === 0) {
return;
}
this._n--;
this._emitError(x);
if (this._n === 0) {
this._emitEnd();
}
}
};
var S$10 = createStream('takeErrors', mixin$3);
var P$6 = createProperty('takeErrors', mixin$3);
function takeErrors(obs, n) {
return new (obs._ofSameType(S$10, P$6))(obs, { n: n });
}
var mixin$4 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleValue: function (x) {
var fn = this._fn;
if (fn(x)) {
this._emitValue(x);
} else {
this._emitEnd();
}
}
};
var S$11 = createStream('takeWhile', mixin$4);
var P$7 = createProperty('takeWhile', mixin$4);
var id$2 = function (x) {
return x;
};
function takeWhile(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id$2;
return new (obs._ofSameType(S$11, P$7))(obs, { fn: fn });
}
var mixin$5 = {
_init: function () {
this._lastValue = NOTHING;
},
_free: function () {
this._lastValue = null;
},
_handleValue: function (x) {
this._lastValue = x;
},
_handleEnd: function () {
if (this._lastValue !== NOTHING) {
this._emitValue(this._lastValue);
}
this._emitEnd();
}
};
var S$12 = createStream('last', mixin$5);
var P$8 = createProperty('last', mixin$5);
function last(obs) {
return new (obs._ofSameType(S$12, P$8))(obs);
}
var mixin$6 = {
_init: function (_ref) {
var n = _ref.n;
this._n = Math.max(0, n);
},
_handleValue: function (x) {
if (this._n === 0) {
this._emitValue(x);
} else {
this._n--;
}
}
};
var S$13 = createStream('skip', mixin$6);
var P$9 = createProperty('skip', mixin$6);
function skip(obs, n) {
return new (obs._ofSameType(S$13, P$9))(obs, { n: n });
}
var mixin$7 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleValue: function (x) {
var fn = this._fn;
if (this._fn !== null && !fn(x)) {
this._fn = null;
}
if (this._fn === null) {
this._emitValue(x);
}
}
};
var S$14 = createStream('skipWhile', mixin$7);
var P$10 = createProperty('skipWhile', mixin$7);
var id$3 = function (x) {
return x;
};
function skipWhile(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id$3;
return new (obs._ofSameType(S$14, P$10))(obs, { fn: fn });
}
var mixin$8 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
this._prev = NOTHING;
},
_free: function () {
this._fn = null;
this._prev = null;
},
_handleValue: function (x) {
var fn = this._fn;
if (this._prev === NOTHING || !fn(this._prev, x)) {
this._prev = x;
this._emitValue(x);
}
}
};
var S$15 = createStream('skipDuplicates', mixin$8);
var P$11 = createProperty('skipDuplicates', mixin$8);
var eq = function (a, b) {
return a === b;
};
function skipDuplicates(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : eq;
return new (obs._ofSameType(S$15, P$11))(obs, { fn: fn });
}
var mixin$9 = {
_init: function (_ref) {
var fn = _ref.fn,
seed = _ref.seed;
this._fn = fn;
this._prev = seed;
},
_free: function () {
this._prev = null;
this._fn = null;
},
_handleValue: function (x) {
if (this._prev !== NOTHING) {
var fn = this._fn;
this._emitValue(fn(this._prev, x));
}
this._prev = x;
}
};
var S$16 = createStream('diff', mixin$9);
var P$12 = createProperty('diff', mixin$9);
function defaultFn(a, b) {
return [a, b];
}
function diff(obs, fn) {
var seed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : NOTHING;
return new (obs._ofSameType(S$16, P$12))(obs, { fn: fn || defaultFn, seed: seed });
}
var P$13 = createProperty('scan', {
_init: function (_ref) {
var fn = _ref.fn,
seed = _ref.seed;
this._fn = fn;
this._seed = seed;
if (seed !== NOTHING) {
this._emitValue(seed);
}
},
_free: function () {
this._fn = null;
this._seed = null;
},
_handleValue: function (x) {
var fn = this._fn;
if (this._currentEvent === null || this._currentEvent.type === ERROR) {
this._emitValue(this._seed === NOTHING ? x : fn(this._seed, x));
} else {
this._emitValue(fn(this._currentEvent.value, x));
}
}
});
function scan(obs, fn) {
var seed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : NOTHING;
return new P$13(obs, { fn: fn, seed: seed });
}
var mixin$10 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleValue: function (x) {
var fn = this._fn;
var xs = fn(x);
for (var i = 0; i < xs.length; i++) {
this._emitValue(xs[i]);
}
}
};
var S$17 = createStream('flatten', mixin$10);
var id$4 = function (x) {
return x;
};
function flatten(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id$4;
return new S$17(obs, { fn: fn });
}
var END_MARKER = {};
var mixin$11 = {
_init: function (_ref) {
var _this = this;
var wait = _ref.wait;
this._wait = Math.max(0, wait);
this._buff = [];
this._$shiftBuff = function () {
var value = _this._buff.shift();
if (value === END_MARKER) {
_this._emitEnd();
} else {
_this._emitValue(value);
}
};
},
_free: function () {
this._buff = null;
this._$shiftBuff = null;
},
_handleValue: function (x) {
if (this._activating) {
this._emitValue(x);
} else {
this._buff.push(x);
setTimeout(this._$shiftBuff, this._wait);
}
},
_handleEnd: function () {
if (this._activating) {
this._emitEnd();
} else {
this._buff.push(END_MARKER);
setTimeout(this._$shiftBuff, this._wait);
}
}
};
var S$18 = createStream('delay', mixin$11);
var P$14 = createProperty('delay', mixin$11);
function delay(obs, wait) {
return new (obs._ofSameType(S$18, P$14))(obs, { wait: wait });
}
var now = Date.now ? function () {
return Date.now();
} : function () {
return new Date().getTime();
};
var mixin$12 = {
_init: function (_ref) {
var _this = this;
var wait = _ref.wait,
leading = _ref.leading,
trailing = _ref.trailing;
this._wait = Math.max(0, wait);
this._leading = leading;
this._trailing = trailing;
this._trailingValue = null;
this._timeoutId = null;
this._endLater = false;
this._lastCallTime = 0;
this._$trailingCall = function () {
return _this._trailingCall();
};
},
_free: function () {
this._trailingValue = null;
this._$trailingCall = null;
},
_handleValue: function (x) {
if (this._activating) {
this._emitValue(x);
} else {
var curTime = now();
if (this._lastCallTime === 0 && !this._leading) {
this._lastCallTime = curTime;
}
var remaining = this._wait - (curTime - this._lastCallTime);
if (remaining <= 0) {
this._cancelTrailing();
this._lastCallTime = curTime;
this._emitValue(x);
} else if (this._trailing) {
this._cancelTrailing();
this._trailingValue = x;
this._timeoutId = setTimeout(this._$trailingCall, remaining);
}
}
},
_handleEnd: function () {
if (this._activating) {
this._emitEnd();
} else {
if (this._timeoutId) {
this._endLater = true;
} else {
this._emitEnd();
}
}
},
_cancelTrailing: function () {
if (this._timeoutId !== null) {
clearTimeout(this._timeoutId);
this._timeoutId = null;
}
},
_trailingCall: function () {
this._emitValue(this._trailingValue);
this._timeoutId = null;
this._trailingValue = null;
this._lastCallTime = !this._leading ? 0 : now();
if (this._endLater) {
this._emitEnd();
}
}
};
var S$19 = createStream('throttle', mixin$12);
var P$15 = createProperty('throttle', mixin$12);
function throttle(obs, wait) {
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref2$leading = _ref2.leading,
leading = _ref2$leading === undefined ? true : _ref2$leading,
_ref2$trailing = _ref2.trailing,
trailing = _ref2$trailing === undefined ? true : _ref2$trailing;
return new (obs._ofSameType(S$19, P$15))(obs, { wait: wait, leading: leading, trailing: trailing });
}
var mixin$13 = {
_init: function (_ref) {
var _this = this;
var wait = _ref.wait,
immediate = _ref.immediate;
this._wait = Math.max(0, wait);
this._immediate = immediate;
this._lastAttempt = 0;
this._timeoutId = null;
this._laterValue = null;
this._endLater = false;
this._$later = function () {
return _this._later();
};
},
_free: function () {
this._laterValue = null;
this._$later = null;
},
_handleValue: function (x) {
if (this._activating) {
this._emitValue(x);
} else {
this._lastAttempt = now();
if (this._immediate && !this._timeoutId) {
this._emitValue(x);
}
if (!this._timeoutId) {
this._timeoutId = setTimeout(this._$later, this._wait);
}
if (!this._immediate) {
this._laterValue = x;
}
}
},
_handleEnd: function () {
if (this._activating) {
this._emitEnd();
} else {
if (this._timeoutId && !this._immediate) {
this._endLater = true;
} else {
this._emitEnd();
}
}
},
_later: function () {
var last = now() - this._lastAttempt;
if (last < this._wait && last >= 0) {
this._timeoutId = setTimeout(this._$later, this._wait - last);
} else {
this._timeoutId = null;
if (!this._immediate) {
var _laterValue = this._laterValue;
this._laterValue = null;
this._emitValue(_laterValue);
}
if (this._endLater) {
this._emitEnd();
}
}
}
};
var S$20 = createStream('debounce', mixin$13);
var P$16 = createProperty('debounce', mixin$13);
function debounce(obs, wait) {
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref2$immediate = _ref2.immediate,
immediate = _ref2$immediate === undefined ? false : _ref2$immediate;
return new (obs._ofSameType(S$20, P$16))(obs, { wait: wait, immediate: immediate });
}
var mixin$14 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleError: function (x) {
var fn = this._fn;
this._emitError(fn(x));
}
};
var S$21 = createStream('mapErrors', mixin$14);
var P$17 = createProperty('mapErrors', mixin$14);
var id$5 = function (x) {
return x;
};
function mapErrors(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id$5;
return new (obs._ofSameType(S$21, P$17))(obs, { fn: fn });
}
var mixin$15 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleError: function (x) {
var fn = this._fn;
if (fn(x)) {
this._emitError(x);
}
}
};
var S$22 = createStream('filterErrors', mixin$15);
var P$18 = createProperty('filterErrors', mixin$15);
var id$6 = function (x) {
return x;
};
function filterErrors(obs) {
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id$6;
return new (obs._ofSameType(S$22, P$18))(obs, { fn: fn });
}
var mixin$16 = {
_handleValue: function () {}
};
var S$23 = createStream('ignoreValues', mixin$16);
var P$19 = createProperty('ignoreValues', mixin$16);
function ignoreValues(obs) {
return new (obs._ofSameType(S$23, P$19))(obs);
}
var mixin$17 = {
_handleError: function () {}
};
var S$24 = createStream('ignoreErrors', mixin$17);
var P$20 = createProperty('ignoreErrors', mixin$17);
function ignoreErrors(obs) {
return new (obs._ofSameType(S$24, P$20))(obs);
}
var mixin$18 = {
_handleEnd: function () {}
};
var S$25 = createStream('ignoreEnd', mixin$18);
var P$21 = createProperty('ignoreEnd', mixin$18);
function ignoreEnd(obs) {
return new (obs._ofSameType(S$25, P$21))(obs);
}
var mixin$19 = {
_init: function (_ref) {
var fn = _ref.fn;
this._fn = fn;
},
_free: function () {
this._fn = null;
},
_handleEnd: function () {
var fn = this._fn;
this._emitValue(fn());
this._emitEnd();
}
};
var S$26 = createStream('beforeEnd', mixin$19);
var P$22 = createProperty('beforeEnd', mixin$19);
function beforeEnd(obs, fn) {
return new (obs._ofSameType(S$26, P$22))(obs, { fn: fn });
}
var mixin$20 = {
_init: function (_ref) {
var min = _ref.min,
max = _ref.max;
this._max = max;
this._min = min;
this._buff = [];
},
_free: function () {
this._buff = null;
},
_handleValue: function (x) {
this._buff = slide(this._buff, x, this._max);
if (this._buff.length >= this._min) {
this._emitValue(this._buff);
}
}
};
var S$27 = createStream('slidingWindow', mixin$20);
var P$23 = createProperty('slidingWindow', mixin$20);
function slidingWindow(obs, max) {
var min = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
return new (obs._ofSameType(S$27, P$23))(obs, { min: min, max: max });
}
var mixin$21 = {
_init: function (_ref) {
var fn = _ref.fn,
flushOnEnd = _ref.flushOnEnd;
this._fn = fn;
this._flushOnEnd = flushOnEnd;
this._buff = [];
},
_free: function () {
this._buff = null;
},
_flush: function () {
if (this._buff !== null && this._buff.length !== 0) {
this._emitValue(this._buff);
this._buff = [];
}
},
_handleValue: function (x) {
this._buff.push(x);
var fn = this._fn;
if (!fn(x)) {
this._flush();
}
},
_handleEnd: function () {
if (this._flushOnEnd) {
this._flush();
}
this._emitEnd();
}
};
var S$28 = createStream('bufferWhile', mixin$21);
var P$24 = createProperty('bufferWhile', mixin$21);
var id$7 = function (x) {
return x;
};
function bufferWhile(obs, fn) {
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref2$flushOnEnd = _ref2.flushOnEnd,
flushOnEnd = _ref2$flushOnEnd === undefined ? true : _ref2$flushOnEnd;
return new (obs._ofSameType(S$28, P$24))(obs, { fn: fn || id$7, flushOnEnd: flushOnEnd });
}
var mixin$22 = {
_init: function (_ref) {
var count = _ref.count,
flushOnEnd = _ref.flushOnEnd;
this._count = count;
this._flushOnEnd = flushOnEnd;
this._buff = [];
},
_free: function () {
this._buff = null;
},
_flush: function () {
if (this._buff !== null && this._buff.length !== 0) {
this._emitValue(this._buff);
this._buff = [];
}
},
_handleValue: function (x) {
this._buff.push(x);
if (this._buff.length >= this._count) {
this._flush();
}
},
_handleEnd: function () {
if (this._flushOnEnd) {
this._flush();
}
this._emitEnd();
}
};
var S$29 = createStream('bufferWithCount', mixin$22)