  /**
   *  Projects each element of an observable sequence into a window that is completed when either it's full or a given amount of time has elapsed.
   * @param {Number} timeSpan Maximum time length of a window.
   * @param {Number} count Maximum element count of a window.
   * @param {Scheduler} [scheduler]  Scheduler to run windowing timers on. If not specified, the timeout scheduler is used.
   * @returns {Observable} An observable sequence of windows.
   */
  observableProto.windowWithTimeOrCount = function (timeSpan, count, scheduler) {
    var source = this;
    isScheduler(scheduler) || (scheduler = timeoutScheduler);
    return new AnonymousObservable(function (observer) {
      var createTimer,
          groupDisposable,
          n = 0,
          refCountDisposable,
          s,
          timerD = new SerialDisposable(),
          windowId = 0;
      groupDisposable = new CompositeDisposable(timerD);
      refCountDisposable = new RefCountDisposable(groupDisposable);
      createTimer = function (id) {
        var m = new SingleAssignmentDisposable();
        timerD.setDisposable(m);
        m.setDisposable(scheduler.scheduleWithRelative(timeSpan, function () {
          var newId;
          if (id !== windowId) {
            return;
          }
          n = 0;
          newId = ++windowId;
          s.onCompleted();
          s = new Subject();
          observer.onNext(addRef(s, refCountDisposable));
          createTimer(newId);
        }));
      };
      s = new Subject();
      observer.onNext(addRef(s, refCountDisposable));
      createTimer(0);
      groupDisposable.add(source.subscribe(function (x) {
        var newId = 0, newWindow = false;
        s.onNext(x);
        n++;
        if (n === count) {
          newWindow = true;
          n = 0;
          newId = ++windowId;
          s.onCompleted();
          s = new Subject();
          observer.onNext(addRef(s, refCountDisposable));
        }
        if (newWindow) {
          createTimer(newId);
        }
      }, function (e) {
        s.onError(e);
        observer.onError(e);
      }, function () {
        s.onCompleted();
        observer.onCompleted();
      }));
      return refCountDisposable;
    });
  };