| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187 |
- // Copyright (c) Microsoft, All rights reserved. See License.txt in the project root for license information.
- ;(function (factory) {
- var objectTypes = {
- 'function': true,
- 'object': true
- };
- function checkGlobal(value) {
- return (value && value.Object === Object) ? value : null;
- }
- var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null;
- var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null;
- var freeGlobal = checkGlobal(freeExports && freeModule && typeof global === 'object' && global);
- var freeSelf = checkGlobal(objectTypes[typeof self] && self);
- var freeWindow = checkGlobal(objectTypes[typeof window] && window);
- var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : null;
- var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
- var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
- // Because of build optimizers
- if (typeof define === 'function' && define.amd) {
- define(['./rx.core'], function (Rx, exports) {
- return factory(root, exports, Rx);
- });
- } else if (typeof module === 'object' && module && module.exports === freeExports) {
- module.exports = factory(root, module.exports, require('./rx.core'));
- } else {
- root.Rx = factory(root, {}, root.Rx);
- }
- }.call(this, function (root, exp, Rx, undefined) {
- // Defaults
- var Observer = Rx.Observer,
- Observable = Rx.Observable,
- Disposable = Rx.Disposable,
- disposableEmpty = Disposable.empty,
- disposableCreate = Disposable.create,
- CompositeDisposable = Rx.CompositeDisposable,
- SingleAssignmentDisposable = Rx.SingleAssignmentDisposable,
- Scheduler = Rx.Scheduler,
- ScheduledItem = Rx.internals.ScheduledItem,
- SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive,
- PriorityQueue = Rx.internals.PriorityQueue,
- inherits = Rx.internals.inherits,
- notImplemented = Rx.helpers.notImplemented,
- defaultComparer = Rx.helpers.defaultComparer = function (a, b) { return isEqual(a, b); };
- /**
- * Represents a notification to an observer.
- */
- var Notification = Rx.Notification = (function () {
- function Notification() {
- }
- Notification.prototype._accept = function (onNext, onError, onCompleted) {
- throw new NotImplementedError();
- };
- Notification.prototype._acceptObserver = function (onNext, onError, onCompleted) {
- throw new NotImplementedError();
- };
- /**
- * Invokes the delegate corresponding to the notification or the observer's method corresponding to the notification and returns the produced result.
- * @param {Function | Observer} observerOrOnNext Function to invoke for an OnNext notification or Observer to invoke the notification on..
- * @param {Function} onError Function to invoke for an OnError notification.
- * @param {Function} onCompleted Function to invoke for an OnCompleted notification.
- * @returns {Any} Result produced by the observation.
- */
- Notification.prototype.accept = function (observerOrOnNext, onError, onCompleted) {
- return observerOrOnNext && typeof observerOrOnNext === 'object' ?
- this._acceptObserver(observerOrOnNext) :
- this._accept(observerOrOnNext, onError, onCompleted);
- };
- /**
- * Returns an observable sequence with a single notification.
- *
- * @memberOf Notifications
- * @param {Scheduler} [scheduler] Scheduler to send out the notification calls on.
- * @returns {Observable} The observable sequence that surfaces the behavior of the notification upon subscription.
- */
- Notification.prototype.toObservable = function (scheduler) {
- var self = this;
- isScheduler(scheduler) || (scheduler = immediateScheduler);
- return new AnonymousObservable(function (o) {
- return scheduler.schedule(self, function (_, notification) {
- notification._acceptObserver(o);
- notification.kind === 'N' && o.onCompleted();
- });
- });
- };
- return Notification;
- })();
- var OnNextNotification = (function (__super__) {
- inherits(OnNextNotification, __super__);
- function OnNextNotification(value) {
- this.value = value;
- this.kind = 'N';
- }
- OnNextNotification.prototype._accept = function (onNext) {
- return onNext(this.value);
- };
- OnNextNotification.prototype._acceptObserver = function (o) {
- return o.onNext(this.value);
- };
- OnNextNotification.prototype.toString = function () {
- return 'OnNext(' + this.value + ')';
- };
- return OnNextNotification;
- }(Notification));
- var OnErrorNotification = (function (__super__) {
- inherits(OnErrorNotification, __super__);
- function OnErrorNotification(error) {
- this.error = error;
- this.kind = 'E';
- }
- OnErrorNotification.prototype._accept = function (onNext, onError) {
- return onError(this.error);
- };
- OnErrorNotification.prototype._acceptObserver = function (o) {
- return o.onError(this.error);
- };
- OnErrorNotification.prototype.toString = function () {
- return 'OnError(' + this.error + ')';
- };
- return OnErrorNotification;
- }(Notification));
- var OnCompletedNotification = (function (__super__) {
- inherits(OnCompletedNotification, __super__);
- function OnCompletedNotification() {
- this.kind = 'C';
- }
- OnCompletedNotification.prototype._accept = function (onNext, onError, onCompleted) {
- return onCompleted();
- };
- OnCompletedNotification.prototype._acceptObserver = function (o) {
- return o.onCompleted();
- };
- OnCompletedNotification.prototype.toString = function () {
- return 'OnCompleted()';
- };
- return OnCompletedNotification;
- }(Notification));
- /**
- * Creates an object that represents an OnNext notification to an observer.
- * @param {Any} value The value contained in the notification.
- * @returns {Notification} The OnNext notification containing the value.
- */
- var notificationCreateOnNext = Notification.createOnNext = function (value) {
- return new OnNextNotification(value);
- };
- /**
- * Creates an object that represents an OnError notification to an observer.
- * @param {Any} error The exception contained in the notification.
- * @returns {Notification} The OnError notification containing the exception.
- */
- var notificationCreateOnError = Notification.createOnError = function (error) {
- return new OnErrorNotification(error);
- };
- /**
- * Creates an object that represents an OnCompleted notification to an observer.
- * @returns {Notification} The OnCompleted notification.
- */
- var notificationCreateOnCompleted = Notification.createOnCompleted = function () {
- return new OnCompletedNotification();
- };
- /** Used to determine if values are of the language type Object */
- var dontEnums = ['toString',
- 'toLocaleString',
- 'valueOf',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'constructor'],
- dontEnumsLength = dontEnums.length;
- var argsTag = '[object Arguments]',
- arrayTag = '[object Array]',
- boolTag = '[object Boolean]',
- dateTag = '[object Date]',
- errorTag = '[object Error]',
- funcTag = '[object Function]',
- mapTag = '[object Map]',
- numberTag = '[object Number]',
- objectTag = '[object Object]',
- regexpTag = '[object RegExp]',
- setTag = '[object Set]',
- stringTag = '[object String]',
- weakMapTag = '[object WeakMap]';
- var arrayBufferTag = '[object ArrayBuffer]',
- float32Tag = '[object Float32Array]',
- float64Tag = '[object Float64Array]',
- int8Tag = '[object Int8Array]',
- int16Tag = '[object Int16Array]',
- int32Tag = '[object Int32Array]',
- uint8Tag = '[object Uint8Array]',
- uint8ClampedTag = '[object Uint8ClampedArray]',
- uint16Tag = '[object Uint16Array]',
- uint32Tag = '[object Uint32Array]';
- var typedArrayTags = {};
- typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
- typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
- typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
- typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
- typedArrayTags[uint32Tag] = true;
- typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
- typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
- typedArrayTags[dateTag] = typedArrayTags[errorTag] =
- typedArrayTags[funcTag] = typedArrayTags[mapTag] =
- typedArrayTags[numberTag] = typedArrayTags[objectTag] =
- typedArrayTags[regexpTag] = typedArrayTags[setTag] =
- typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
- var objectProto = Object.prototype,
- hasOwnProperty = objectProto.hasOwnProperty,
- objToString = objectProto.toString,
- MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
- var keys = Object.keys || (function() {
- var hasOwnProperty = Object.prototype.hasOwnProperty,
- hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
- dontEnums = [
- 'toString',
- 'toLocaleString',
- 'valueOf',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'constructor'
- ],
- dontEnumsLength = dontEnums.length;
- return function(obj) {
- if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
- throw new TypeError('Object.keys called on non-object');
- }
- var result = [], prop, i;
- for (prop in obj) {
- if (hasOwnProperty.call(obj, prop)) {
- result.push(prop);
- }
- }
- if (hasDontEnumBug) {
- for (i = 0; i < dontEnumsLength; i++) {
- if (hasOwnProperty.call(obj, dontEnums[i])) {
- result.push(dontEnums[i]);
- }
- }
- }
- return result;
- };
- }());
- function equalObjects(object, other, equalFunc, isLoose, stackA, stackB) {
- var objProps = keys(object),
- objLength = objProps.length,
- othProps = keys(other),
- othLength = othProps.length;
- if (objLength !== othLength && !isLoose) {
- return false;
- }
- var index = objLength, key;
- while (index--) {
- key = objProps[index];
- if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
- return false;
- }
- }
- var skipCtor = isLoose;
- while (++index < objLength) {
- key = objProps[index];
- var objValue = object[key],
- othValue = other[key],
- result;
- if (!(result === undefined ? equalFunc(objValue, othValue, isLoose, stackA, stackB) : result)) {
- return false;
- }
- skipCtor || (skipCtor = key === 'constructor');
- }
- if (!skipCtor) {
- var objCtor = object.constructor,
- othCtor = other.constructor;
- if (objCtor !== othCtor &&
- ('constructor' in object && 'constructor' in other) &&
- !(typeof objCtor === 'function' && objCtor instanceof objCtor &&
- typeof othCtor === 'function' && othCtor instanceof othCtor)) {
- return false;
- }
- }
- return true;
- }
- function equalByTag(object, other, tag) {
- switch (tag) {
- case boolTag:
- case dateTag:
- return +object === +other;
- case errorTag:
- return object.name === other.name && object.message === other.message;
- case numberTag:
- return (object !== +object) ?
- other !== +other :
- object === +other;
- case regexpTag:
- case stringTag:
- return object === (other + '');
- }
- return false;
- }
- var isObject = Rx.internals.isObject = function(value) {
- var type = typeof value;
- return !!value && (type === 'object' || type === 'function');
- };
- function isObjectLike(value) {
- return !!value && typeof value === 'object';
- }
- function isLength(value) {
- return typeof value === 'number' && value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER;
- }
- var isHostObject = (function() {
- try {
- Object({ 'toString': 0 } + '');
- } catch(e) {
- return function() { return false; };
- }
- return function(value) {
- return typeof value.toString !== 'function' && typeof (value + '') === 'string';
- };
- }());
- function isTypedArray(value) {
- return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
- }
- var isArray = Array.isArray || function(value) {
- return isObjectLike(value) && isLength(value.length) && objToString.call(value) === arrayTag;
- };
- function arraySome (array, predicate) {
- var index = -1,
- length = array.length;
- while (++index < length) {
- if (predicate(array[index], index, array)) {
- return true;
- }
- }
- return false;
- }
- function equalArrays(array, other, equalFunc, isLoose, stackA, stackB) {
- var index = -1,
- arrLength = array.length,
- othLength = other.length;
- if (arrLength !== othLength && !(isLoose && othLength > arrLength)) {
- return false;
- }
- // Ignore non-index properties.
- while (++index < arrLength) {
- var arrValue = array[index],
- othValue = other[index],
- result;
- if (result !== undefined) {
- if (result) {
- continue;
- }
- return false;
- }
- // Recursively compare arrays (susceptible to call stack limits).
- if (isLoose) {
- if (!arraySome(other, function(othValue) {
- return arrValue === othValue || equalFunc(arrValue, othValue, isLoose, stackA, stackB);
- })) {
- return false;
- }
- } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, isLoose, stackA, stackB))) {
- return false;
- }
- }
- return true;
- }
- function baseIsEqualDeep(object, other, equalFunc, isLoose, stackA, stackB) {
- var objIsArr = isArray(object),
- othIsArr = isArray(other),
- objTag = arrayTag,
- othTag = arrayTag;
- if (!objIsArr) {
- objTag = objToString.call(object);
- if (objTag === argsTag) {
- objTag = objectTag;
- } else if (objTag !== objectTag) {
- objIsArr = isTypedArray(object);
- }
- }
- if (!othIsArr) {
- othTag = objToString.call(other);
- if (othTag === argsTag) {
- othTag = objectTag;
- }
- }
- var objIsObj = objTag === objectTag && !isHostObject(object),
- othIsObj = othTag === objectTag && !isHostObject(other),
- isSameTag = objTag === othTag;
- if (isSameTag && !(objIsArr || objIsObj)) {
- return equalByTag(object, other, objTag);
- }
- if (!isLoose) {
- var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
- othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
- if (objIsWrapped || othIsWrapped) {
- return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, isLoose, stackA, stackB);
- }
- }
- if (!isSameTag) {
- return false;
- }
- // Assume cyclic values are equal.
- // For more information on detecting circular references see https://es5.github.io/#JO.
- stackA || (stackA = []);
- stackB || (stackB = []);
- var length = stackA.length;
- while (length--) {
- if (stackA[length] === object) {
- return stackB[length] === other;
- }
- }
- // Add `object` and `other` to the stack of traversed objects.
- stackA.push(object);
- stackB.push(other);
- var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, isLoose, stackA, stackB);
- stackA.pop();
- stackB.pop();
- return result;
- }
- function baseIsEqual(value, other, isLoose, stackA, stackB) {
- if (value === other) {
- return true;
- }
- if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
- return value !== value && other !== other;
- }
- return baseIsEqualDeep(value, other, baseIsEqual, isLoose, stackA, stackB);
- }
- var isEqual = Rx.internals.isEqual = function (value, other) {
- return baseIsEqual(value, other);
- };
- var SchedulePeriodicRecursive = Rx.internals.SchedulePeriodicRecursive = (function () {
- function createTick(self) {
- return function tick(command, recurse) {
- recurse(0, self._period);
- var state = tryCatch(self._action)(self._state);
- if (state === errorObj) {
- self._cancel.dispose();
- thrower(state.e);
- }
- self._state = state;
- };
- }
- function SchedulePeriodicRecursive(scheduler, state, period, action) {
- this._scheduler = scheduler;
- this._state = state;
- this._period = period;
- this._action = action;
- }
- SchedulePeriodicRecursive.prototype.start = function () {
- var d = new SingleAssignmentDisposable();
- this._cancel = d;
- d.setDisposable(this._scheduler.scheduleRecursiveFuture(0, this._period, createTick(this)));
- return d;
- };
- return SchedulePeriodicRecursive;
- }());
- /** Provides a set of extension methods for virtual time scheduling. */
- var VirtualTimeScheduler = Rx.VirtualTimeScheduler = (function (__super__) {
- inherits(VirtualTimeScheduler, __super__);
- /**
- * Creates a new virtual time scheduler with the specified initial clock value and absolute time comparer.
- *
- * @constructor
- * @param {Number} initialClock Initial value for the clock.
- * @param {Function} comparer Comparer to determine causality of events based on absolute time.
- */
- function VirtualTimeScheduler(initialClock, comparer) {
- this.clock = initialClock;
- this.comparer = comparer;
- this.isEnabled = false;
- this.queue = new PriorityQueue(1024);
- __super__.call(this);
- }
- var VirtualTimeSchedulerPrototype = VirtualTimeScheduler.prototype;
- VirtualTimeSchedulerPrototype.now = function () {
- return this.toAbsoluteTime(this.clock);
- };
- VirtualTimeSchedulerPrototype.schedule = function (state, action) {
- return this.scheduleAbsolute(state, this.clock, action);
- };
- VirtualTimeSchedulerPrototype.scheduleFuture = function (state, dueTime, action) {
- var dt = dueTime instanceof Date ?
- this.toRelativeTime(dueTime - this.now()) :
- this.toRelativeTime(dueTime);
- return this.scheduleRelative(state, dt, action);
- };
- /**
- * Adds a relative time value to an absolute time value.
- * @param {Number} absolute Absolute virtual time value.
- * @param {Number} relative Relative virtual time value to add.
- * @return {Number} Resulting absolute virtual time sum value.
- */
- VirtualTimeSchedulerPrototype.add = notImplemented;
- /**
- * Converts an absolute time to a number
- * @param {Any} The absolute time.
- * @returns {Number} The absolute time in ms
- */
- VirtualTimeSchedulerPrototype.toAbsoluteTime = notImplemented;
- /**
- * Converts the TimeSpan value to a relative virtual time value.
- * @param {Number} timeSpan TimeSpan value to convert.
- * @return {Number} Corresponding relative virtual time value.
- */
- VirtualTimeSchedulerPrototype.toRelativeTime = notImplemented;
- /**
- * Schedules a periodic piece of work by dynamically discovering the scheduler's capabilities. The periodic task will be emulated using recursive scheduling.
- * @param {Mixed} state Initial state passed to the action upon the first iteration.
- * @param {Number} period Period for running the work periodically.
- * @param {Function} action Action to be executed, potentially updating the state.
- * @returns {Disposable} The disposable object used to cancel the scheduled recurring action (best effort).
- */
- VirtualTimeSchedulerPrototype.schedulePeriodic = function (state, period, action) {
- var s = new SchedulePeriodicRecursive(this, state, period, action);
- return s.start();
- };
- /**
- * Schedules an action to be executed after dueTime.
- * @param {Mixed} state State passed to the action to be executed.
- * @param {Number} dueTime Relative time after which to execute the action.
- * @param {Function} action Action to be executed.
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
- */
- VirtualTimeSchedulerPrototype.scheduleRelative = function (state, dueTime, action) {
- var runAt = this.add(this.clock, dueTime);
- return this.scheduleAbsolute(state, runAt, action);
- };
- /**
- * Starts the virtual time scheduler.
- */
- VirtualTimeSchedulerPrototype.start = function () {
- if (!this.isEnabled) {
- this.isEnabled = true;
- do {
- var next = this.getNext();
- if (next !== null) {
- this.comparer(next.dueTime, this.clock) > 0 && (this.clock = next.dueTime);
- next.invoke();
- } else {
- this.isEnabled = false;
- }
- } while (this.isEnabled);
- }
- };
- /**
- * Stops the virtual time scheduler.
- */
- VirtualTimeSchedulerPrototype.stop = function () {
- this.isEnabled = false;
- };
- /**
- * Advances the scheduler's clock to the specified time, running all work till that point.
- * @param {Number} time Absolute time to advance the scheduler's clock to.
- */
- VirtualTimeSchedulerPrototype.advanceTo = function (time) {
- var dueToClock = this.comparer(this.clock, time);
- if (this.comparer(this.clock, time) > 0) { throw new ArgumentOutOfRangeError(); }
- if (dueToClock === 0) { return; }
- if (!this.isEnabled) {
- this.isEnabled = true;
- do {
- var next = this.getNext();
- if (next !== null && this.comparer(next.dueTime, time) <= 0) {
- this.comparer(next.dueTime, this.clock) > 0 && (this.clock = next.dueTime);
- next.invoke();
- } else {
- this.isEnabled = false;
- }
- } while (this.isEnabled);
- this.clock = time;
- }
- };
- /**
- * Advances the scheduler's clock by the specified relative time, running all work scheduled for that timespan.
- * @param {Number} time Relative time to advance the scheduler's clock by.
- */
- VirtualTimeSchedulerPrototype.advanceBy = function (time) {
- var dt = this.add(this.clock, time),
- dueToClock = this.comparer(this.clock, dt);
- if (dueToClock > 0) { throw new ArgumentOutOfRangeError(); }
- if (dueToClock === 0) { return; }
- this.advanceTo(dt);
- };
- /**
- * Advances the scheduler's clock by the specified relative time.
- * @param {Number} time Relative time to advance the scheduler's clock by.
- */
- VirtualTimeSchedulerPrototype.sleep = function (time) {
- var dt = this.add(this.clock, time);
- if (this.comparer(this.clock, dt) >= 0) { throw new ArgumentOutOfRangeError(); }
- this.clock = dt;
- };
- /**
- * Gets the next scheduled item to be executed.
- * @returns {ScheduledItem} The next scheduled item.
- */
- VirtualTimeSchedulerPrototype.getNext = function () {
- while (this.queue.length > 0) {
- var next = this.queue.peek();
- if (next.isCancelled()) {
- this.queue.dequeue();
- } else {
- return next;
- }
- }
- return null;
- };
- /**
- * Schedules an action to be executed at dueTime.
- * @param {Mixed} state State passed to the action to be executed.
- * @param {Number} dueTime Absolute time at which to execute the action.
- * @param {Function} action Action to be executed.
- * @returns {Disposable} The disposable object used to cancel the scheduled action (best effort).
- */
- VirtualTimeSchedulerPrototype.scheduleAbsolute = function (state, dueTime, action) {
- var self = this;
- function run(scheduler, state1) {
- self.queue.remove(si);
- return action(scheduler, state1);
- }
- var si = new ScheduledItem(this, state, run, dueTime, this.comparer);
- this.queue.enqueue(si);
- return si.disposable;
- };
- return VirtualTimeScheduler;
- }(Scheduler));
- function OnNextPredicate(predicate) {
- this.predicate = predicate;
- }
- OnNextPredicate.prototype.equals = function (other) {
- if (other === this) { return true; }
- if (other == null) { return false; }
- if (other.kind !== 'N') { return false; }
- return this.predicate(other.value);
- };
- function OnErrorPredicate(predicate) {
- this.predicate = predicate;
- }
- OnErrorPredicate.prototype.equals = function (other) {
- if (other === this) { return true; }
- if (other == null) { return false; }
- if (other.kind !== 'E') { return false; }
- return this.predicate(other.error);
- };
- var ReactiveTest = Rx.ReactiveTest = {
- /** Default virtual time used for creation of observable sequences in unit tests. */
- created: 100,
- /** Default virtual time used to subscribe to observable sequences in unit tests. */
- subscribed: 200,
- /** Default virtual time used to dispose subscriptions in unit tests. */
- disposed: 1000,
- /**
- * Factory method for an OnNext notification record at a given time with a given value or a predicate function.
- *
- * 1 - ReactiveTest.onNext(200, 42);
- * 2 - ReactiveTest.onNext(200, function (x) { return x.length == 2; });
- *
- * @param ticks Recorded virtual time the OnNext notification occurs.
- * @param value Recorded value stored in the OnNext notification or a predicate.
- * @return Recorded OnNext notification.
- */
- onNext: function (ticks, value) {
- return typeof value === 'function' ?
- new Recorded(ticks, new OnNextPredicate(value)) :
- new Recorded(ticks, Notification.createOnNext(value));
- },
- /**
- * Factory method for an OnError notification record at a given time with a given error.
- *
- * 1 - ReactiveTest.onNext(200, new Error('error'));
- * 2 - ReactiveTest.onNext(200, function (e) { return e.message === 'error'; });
- *
- * @param ticks Recorded virtual time the OnError notification occurs.
- * @param exception Recorded exception stored in the OnError notification.
- * @return Recorded OnError notification.
- */
- onError: function (ticks, error) {
- return typeof error === 'function' ?
- new Recorded(ticks, new OnErrorPredicate(error)) :
- new Recorded(ticks, Notification.createOnError(error));
- },
- /**
- * Factory method for an OnCompleted notification record at a given time.
- *
- * @param ticks Recorded virtual time the OnCompleted notification occurs.
- * @return Recorded OnCompleted notification.
- */
- onCompleted: function (ticks) {
- return new Recorded(ticks, Notification.createOnCompleted());
- },
- /**
- * Factory method for a subscription record based on a given subscription and disposal time.
- *
- * @param start Virtual time indicating when the subscription was created.
- * @param end Virtual time indicating when the subscription was disposed.
- * @return Subscription object.
- */
- subscribe: function (start, end) {
- return new Subscription(start, end);
- }
- };
- /**
- * Creates a new object recording the production of the specified value at the given virtual time.
- *
- * @constructor
- * @param {Number} time Virtual time the value was produced on.
- * @param {Mixed} value Value that was produced.
- * @param {Function} comparer An optional comparer.
- */
- var Recorded = Rx.Recorded = function (time, value, comparer) {
- this.time = time;
- this.value = value;
- this.comparer = comparer || defaultComparer;
- };
- /**
- * Checks whether the given recorded object is equal to the current instance.
- *
- * @param {Recorded} other Recorded object to check for equality.
- * @returns {Boolean} true if both objects are equal; false otherwise.
- */
- Recorded.prototype.equals = function (other) {
- return this.time === other.time && this.comparer(this.value, other.value);
- };
- /**
- * Returns a string representation of the current Recorded value.
- *
- * @returns {String} String representation of the current Recorded value.
- */
- Recorded.prototype.toString = function () {
- return this.value.toString() + '@' + this.time;
- };
- /**
- * Creates a new subscription object with the given virtual subscription and unsubscription time.
- *
- * @constructor
- * @param {Number} subscribe Virtual time at which the subscription occurred.
- * @param {Number} unsubscribe Virtual time at which the unsubscription occurred.
- */
- var Subscription = Rx.Subscription = function (start, end) {
- this.subscribe = start;
- this.unsubscribe = end || Number.MAX_VALUE;
- };
- /**
- * Checks whether the given subscription is equal to the current instance.
- * @param other Subscription object to check for equality.
- * @returns {Boolean} true if both objects are equal; false otherwise.
- */
- Subscription.prototype.equals = function (other) {
- return this.subscribe === other.subscribe && this.unsubscribe === other.unsubscribe;
- };
- /**
- * Returns a string representation of the current Subscription value.
- * @returns {String} String representation of the current Subscription value.
- */
- Subscription.prototype.toString = function () {
- return '(' + this.subscribe + ', ' + (this.unsubscribe === Number.MAX_VALUE ? 'Infinite' : this.unsubscribe) + ')';
- };
- var MockDisposable = Rx.MockDisposable = function (scheduler) {
- this.scheduler = scheduler;
- this.disposes = [];
- this.disposes.push(this.scheduler.clock);
- };
- MockDisposable.prototype.dispose = function () {
- this.disposes.push(this.scheduler.clock);
- };
- var MockObserver = (function (__super__) {
- inherits(MockObserver, __super__);
- function MockObserver(scheduler) {
- __super__.call(this);
- this.scheduler = scheduler;
- this.messages = [];
- }
- var MockObserverPrototype = MockObserver.prototype;
- MockObserverPrototype.onNext = function (value) {
- this.messages.push(new Recorded(this.scheduler.clock, Notification.createOnNext(value)));
- };
- MockObserverPrototype.onError = function (e) {
- this.messages.push(new Recorded(this.scheduler.clock, Notification.createOnError(e)));
- };
- MockObserverPrototype.onCompleted = function () {
- this.messages.push(new Recorded(this.scheduler.clock, Notification.createOnCompleted()));
- };
- return MockObserver;
- })(Observer);
- function MockPromise(scheduler, messages) {
- var self = this;
- this.scheduler = scheduler;
- this.messages = messages;
- this.subscriptions = [];
- this.observers = [];
- for (var i = 0, len = this.messages.length; i < len; i++) {
- var message = this.messages[i],
- notification = message.value;
- (function (innerNotification) {
- scheduler.scheduleAbsolute(null, message.time, function () {
- var obs = self.observers.slice(0);
- for (var j = 0, jLen = obs.length; j < jLen; j++) {
- innerNotification.accept(obs[j]);
- }
- return disposableEmpty;
- });
- })(notification);
- }
- }
- MockPromise.prototype.then = function (onResolved, onRejected) {
- var self = this;
- this.subscriptions.push(new Subscription(this.scheduler.clock));
- var index = this.subscriptions.length - 1;
- var newPromise;
- var observer = Rx.Observer.create(
- function (x) {
- var retValue = onResolved(x);
- if (retValue && typeof retValue.then === 'function') {
- newPromise = retValue;
- } else {
- var ticks = self.scheduler.clock;
- newPromise = new MockPromise(self.scheduler, [Rx.ReactiveTest.onNext(ticks, undefined), Rx.ReactiveTest.onCompleted(ticks)]);
- }
- var idx = self.observers.indexOf(observer);
- self.observers.splice(idx, 1);
- self.subscriptions[index] = new Subscription(self.subscriptions[index].subscribe, self.scheduler.clock);
- },
- function (err) {
- onRejected(err);
- var idx = self.observers.indexOf(observer);
- self.observers.splice(idx, 1);
- self.subscriptions[index] = new Subscription(self.subscriptions[index].subscribe, self.scheduler.clock);
- }
- );
- this.observers.push(observer);
- return newPromise || new MockPromise(this.scheduler, this.messages);
- };
- var HotObservable = (function (__super__) {
- inherits(HotObservable, __super__);
- function HotObservable(scheduler, messages) {
- __super__.call(this);
- var message, notification, observable = this;
- this.scheduler = scheduler;
- this.messages = messages;
- this.subscriptions = [];
- this.observers = [];
- for (var i = 0, len = this.messages.length; i < len; i++) {
- message = this.messages[i];
- notification = message.value;
- (function (innerNotification) {
- scheduler.scheduleAbsolute(null, message.time, function () {
- var obs = observable.observers.slice(0);
- for (var j = 0, jLen = obs.length; j < jLen; j++) {
- innerNotification.accept(obs[j]);
- }
- return disposableEmpty;
- });
- })(notification);
- }
- }
- HotObservable.prototype._subscribe = function (o) {
- var observable = this;
- this.observers.push(o);
- this.subscriptions.push(new Subscription(this.scheduler.clock));
- var index = this.subscriptions.length - 1;
- return disposableCreate(function () {
- var idx = observable.observers.indexOf(o);
- observable.observers.splice(idx, 1);
- observable.subscriptions[index] = new Subscription(observable.subscriptions[index].subscribe, observable.scheduler.clock);
- });
- };
- return HotObservable;
- })(Observable);
- var ColdObservable = (function (__super__) {
- inherits(ColdObservable, __super__);
- function ColdObservable(scheduler, messages) {
- __super__.call(this);
- this.scheduler = scheduler;
- this.messages = messages;
- this.subscriptions = [];
- }
- ColdObservable.prototype._subscribe = function (o) {
- var message, notification, observable = this;
- this.subscriptions.push(new Subscription(this.scheduler.clock));
- var index = this.subscriptions.length - 1;
- var d = new CompositeDisposable();
- for (var i = 0, len = this.messages.length; i < len; i++) {
- message = this.messages[i];
- notification = message.value;
- (function (innerNotification) {
- d.add(observable.scheduler.scheduleRelative(null, message.time, function () {
- innerNotification.accept(o);
- return disposableEmpty;
- }));
- })(notification);
- }
- return disposableCreate(function () {
- observable.subscriptions[index] = new Subscription(observable.subscriptions[index].subscribe, observable.scheduler.clock);
- d.dispose();
- });
- };
- return ColdObservable;
- })(Observable);
- /** Virtual time scheduler used for testing applications and libraries built using Reactive Extensions. */
- Rx.TestScheduler = (function (__super__) {
- inherits(TestScheduler, __super__);
- function baseComparer(x, y) {
- return x > y ? 1 : (x < y ? -1 : 0);
- }
- function TestScheduler() {
- __super__.call(this, 0, baseComparer);
- }
- /**
- * Schedules an action to be executed at the specified virtual time.
- *
- * @param state State passed to the action to be executed.
- * @param dueTime Absolute virtual time at which to execute the action.
- * @param action Action to be executed.
- * @return Disposable object used to cancel the scheduled action (best effort).
- */
- TestScheduler.prototype.scheduleAbsolute = function (state, dueTime, action) {
- dueTime <= this.clock && (dueTime = this.clock + 1);
- return __super__.prototype.scheduleAbsolute.call(this, state, dueTime, action);
- };
- /**
- * Adds a relative virtual time to an absolute virtual time value.
- *
- * @param absolute Absolute virtual time value.
- * @param relative Relative virtual time value to add.
- * @return Resulting absolute virtual time sum value.
- */
- TestScheduler.prototype.add = function (absolute, relative) {
- return absolute + relative;
- };
- /**
- * Converts the absolute virtual time value to a DateTimeOffset value.
- *
- * @param absolute Absolute virtual time value to convert.
- * @return Corresponding DateTimeOffset value.
- */
- TestScheduler.prototype.toAbsoluteTime = function (absolute) {
- return new Date(absolute).getTime();
- };
- /**
- * Converts the TimeSpan value to a relative virtual time value.
- *
- * @param timeSpan TimeSpan value to convert.
- * @return Corresponding relative virtual time value.
- */
- TestScheduler.prototype.toRelativeTime = function (timeSpan) {
- return timeSpan;
- };
- /**
- * Starts the test scheduler and uses the specified virtual times to invoke the factory function, subscribe to the resulting sequence, and dispose the subscription.
- *
- * @param create Factory method to create an observable sequence.
- * @param created Virtual time at which to invoke the factory to create an observable sequence.
- * @param subscribed Virtual time at which to subscribe to the created observable sequence.
- * @param disposed Virtual time at which to dispose the subscription.
- * @return Observer with timestamped recordings of notification messages that were received during the virtual time window when the subscription to the source sequence was active.
- */
- TestScheduler.prototype.startScheduler = function (createFn, settings) {
- settings || (settings = {});
- settings.created == null && (settings.created = ReactiveTest.created);
- settings.subscribed == null && (settings.subscribed = ReactiveTest.subscribed);
- settings.disposed == null && (settings.disposed = ReactiveTest.disposed);
- var observer = this.createObserver(), source, subscription;
- this.scheduleAbsolute(null, settings.created, function () {
- source = createFn();
- return disposableEmpty;
- });
- this.scheduleAbsolute(null, settings.subscribed, function () {
- subscription = source.subscribe(observer);
- return disposableEmpty;
- });
- this.scheduleAbsolute(null, settings.disposed, function () {
- subscription.dispose();
- return disposableEmpty;
- });
- this.start();
- return observer;
- };
- /**
- * Creates a hot observable using the specified timestamped notification messages either as an array or arguments.
- * @param messages Notifications to surface through the created sequence at their specified absolute virtual times.
- * @return Hot observable sequence that can be used to assert the timing of subscriptions and notifications.
- */
- TestScheduler.prototype.createHotObservable = function () {
- var len = arguments.length, args;
- if (Array.isArray(arguments[0])) {
- args = arguments[0];
- } else {
- args = new Array(len);
- for (var i = 0; i < len; i++) { args[i] = arguments[i]; }
- }
- return new HotObservable(this, args);
- };
- /**
- * Creates a cold observable using the specified timestamped notification messages either as an array or arguments.
- * @param messages Notifications to surface through the created sequence at their specified virtual time offsets from the sequence subscription time.
- * @return Cold observable sequence that can be used to assert the timing of subscriptions and notifications.
- */
- TestScheduler.prototype.createColdObservable = function () {
- var len = arguments.length, args;
- if (Array.isArray(arguments[0])) {
- args = arguments[0];
- } else {
- args = new Array(len);
- for (var i = 0; i < len; i++) { args[i] = arguments[i]; }
- }
- return new ColdObservable(this, args);
- };
- /**
- * Creates a resolved promise with the given value and ticks
- * @param {Number} ticks The absolute time of the resolution.
- * @param {Any} value The value to yield at the given tick.
- * @returns {MockPromise} A mock Promise which fulfills with the given value.
- */
- TestScheduler.prototype.createResolvedPromise = function (ticks, value) {
- return new MockPromise(this, [Rx.ReactiveTest.onNext(ticks, value), Rx.ReactiveTest.onCompleted(ticks)]);
- };
- /**
- * Creates a rejected promise with the given reason and ticks
- * @param {Number} ticks The absolute time of the resolution.
- * @param {Any} reason The reason for rejection to yield at the given tick.
- * @returns {MockPromise} A mock Promise which rejects with the given reason.
- */
- TestScheduler.prototype.createRejectedPromise = function (ticks, reason) {
- return new MockPromise(this, [Rx.ReactiveTest.onError(ticks, reason)]);
- };
- /**
- * Creates an observer that records received notification messages and timestamps those.
- * @return Observer that can be used to assert the timing of received notifications.
- */
- TestScheduler.prototype.createObserver = function () {
- return new MockObserver(this);
- };
- return TestScheduler;
- })(VirtualTimeScheduler);
- return Rx;
- }));
|