| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 | // 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.virtualtime', 'exports'], function (Rx, exports) {      root.Rx = factory(root, exports, Rx);      return root.Rx;    });  } else if (typeof module === 'object' && module && module.exports === freeExports) {    module.exports = factory(root, module.exports, require('./rx'));  } else {    root.Rx = factory(root, {}, root.Rx);  }}.call(this, function (root, exp, Rx, undefined) {  // Defaults  var Observer = Rx.Observer,    Observable = Rx.Observable,    Notification = Rx.Notification,    VirtualTimeScheduler = Rx.VirtualTimeScheduler,    Disposable = Rx.Disposable,    disposableEmpty = Disposable.empty,    disposableCreate = Disposable.create,    CompositeDisposable = Rx.CompositeDisposable,    inherits = Rx.internals.inherits,    defaultComparer = Rx.internals.isEqual;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;}));
 |