Code coverage report for src/subject/ReplaySubject.ts

Statements: 100% (48 / 48)      Branches: 88.89% (16 / 18)      Functions: 100% (8 / 8)      Lines: 100% (43 / 43)      Ignored: none     

All files » src/subject/ » ReplaySubject.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 781   1       1       29   33 38   29 29 29 29     1 105 105 105 105     1 67 67 67 67 71   67     1 172     1 172 172 172   172 172         172 165 154   11     172 53     172 60     172   1   1 105   1    
import {Subject} from '../Subject';
import {Scheduler} from '../Scheduler';
import {queue} from '../scheduler/queue';
import {Subscriber} from '../Subscriber';
import {Subscription} from '../Subscription';
 
export class ReplaySubject<T> extends Subject<T> {
  private bufferSize: number;
  private _windowTime: number;
  private scheduler: Scheduler;
  private events: ReplayEvent<T>[] = [];
 
  constructor(bufferSize: number = Number.POSITIVE_INFINITY,
              windowTime: number = Number.POSITIVE_INFINITY,
              scheduler?: Scheduler) {
    super();
    this.bufferSize = bufferSize < 1 ? 1 : bufferSize;
    this._windowTime = windowTime < 1 ? 1 : windowTime;
    this.scheduler = scheduler;
  }
 
  _next(value: T): void {
    const now = this._getNow();
    this.events.push(new ReplayEvent(now, value));
    this._trimBufferThenGetEvents(now);
    super._next(value);
  }
 
  _subscribe(subscriber: Subscriber<any>): Subscription<T> {
    const events = this._trimBufferThenGetEvents(this._getNow());
    let index = -1;
    const len = events.length;
    while (!subscriber.isUnsubscribed && ++index < len) {
      subscriber.next(events[index].value);
    }
    return super._subscribe(subscriber);
  }
 
  private _getNow(): number {
    return (this.scheduler || queue).now();
  }
 
  private _trimBufferThenGetEvents(now): ReplayEvent<T>[] {
    const bufferSize = this.bufferSize;
    const _windowTime = this._windowTime;
    const events = this.events;
 
    let eventsCount = events.length;
    let spliceCount = 0;
 
    // Trim events that fall out of the time window.
    // Start at the front of the list. Break early once
    // we encounter an event that falls within the window.
    while (spliceCount < eventsCount) {
      if ((now - events[spliceCount].time) < _windowTime) {
        break;
      }
      spliceCount += 1;
    }
 
    if (eventsCount > bufferSize) {
      spliceCount = Math.max(spliceCount, eventsCount - bufferSize);
    }
 
    if (spliceCount > 0) {
      events.splice(0, spliceCount);
    }
 
    return events;
  }
}
 
class ReplayEvent<T> {
  constructor(public time: number, public value: T) {
  }
}