Code coverage report for src/scheduler/VirtualTimeScheduler.ts

Statements: 97.44% (76 / 78)      Branches: 86.36% (19 / 22)      Functions: 100% (11 / 11)      Lines: 97.26% (71 / 73)      Ignored: none     

All files » src/scheduler/ » VirtualTimeScheduler.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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118  1     2 1911 1911 1911 1911 1911 1911 1911   1   1 5960     1 1931 1931 1931 12482 12482 12482 12478   4     1927 1927     1 13197   13197   13197 96820 7650 7 7643 988   6655   89170 30301   58869         13009 13009 13009   1   1     13115   13115 13115 13115 13115     13272 13197     13197 13197 13197   13091       106 106   13197 13197 13197 13197     1 12478     12478     1 3856 3856   3856 3856 3856   3856 715     3856   1  
import {Scheduler} from '../Scheduler';
import {Subscription} from '../Subscription';
import {Action} from './Action';
 
export class VirtualTimeScheduler implements Scheduler {
  actions: Action[] = [];
  active: boolean = false;
  scheduledId: number = null;
  index: number = 0;
  sorted: boolean = false;
  frame: number = 0;
  maxFrames: number = 750;
 
  protected static frameTimeFactor: number = 10;
 
  now() {
    return this.frame;
  }
 
  flush() {
    const actions = this.actions;
    const maxFrames = this.maxFrames;
    while (actions.length > 0) {
      let action = actions.shift();
      this.frame = action.delay;
      if (this.frame <= maxFrames) {
        action.execute();
      } else {
        break;
      }
    }
    actions.length = 0;
    this.frame = 0;
  }
 
  addAction<T>(action: Action) {
    const actions = this.actions;
 
    actions.push(action);
 
    actions.sort((a: VirtualAction<T>, b: VirtualAction<T>) => {
      if (a.delay === b.delay) {
        if (a.index === b.index) {
          return 0;
        } else if (a.index > b.index) {
          return 1;
        } else {
          return -1;
        }
      } else if (a.delay > b.delay) {
        return 1;
      } else {
        return -1;
      }
    });
  }
 
  schedule<T>(work: (x?: any) => Subscription | void, Idelay: number = 0, state?: any): Subscription {
    this.sorted = false;
    return new VirtualAction(this, work, this.index++).schedule(state, delay);
  }
}
 
class VirtualAction<T> extends Subscription implements Action {
  state: any;
  delay: number;
  calls = 0;
 
  constructor(public scheduler: VirtualTimeScheduler,
              public work: (x?: any) => Subscription | void,
              public index: number) {
    super();
  }
 
  schedule(state?: any, delay: number = 0): VirtualAction<T> {
    Iif (this.isUnsubscribed) {
      return this;
    }
    const scheduler = this.scheduler;
    let action: Action;
    if (this.calls++ === 0) {
      // the action is not being rescheduled.
      action = this;
    } else {
      // the action is being rescheduled, and we can't mutate the one in the actions list
      // in the scheduler, so we'll create a new one.
      action = new VirtualAction(scheduler, this.work, scheduler.index += 1);
      this.add(action);
    }
    action.state = state;
    action.delay = scheduler.frame + delay;
    scheduler.addAction(action);
    return this;
  }
 
  execute() {
    Iif (this.isUnsubscribed) {
      throw new Error('How did did we execute a canceled Action?');
    }
    this.work(this.state);
  }
 
  unsubscribe() {
    const actions = this.scheduler.actions;
    const index = actions.indexOf(this);
 
    this.work = void 0;
    this.state = void 0;
    this.scheduler = void 0;
 
    if (index !== -1) {
      actions.splice(index, 1);
    }
 
    super.unsubscribe();
  }
}