Skip to content

Commit

Permalink
chore: add providers
Browse files Browse the repository at this point in the history
  • Loading branch information
cartant committed Jul 27, 2020
1 parent 9421890 commit c54affe
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 15 deletions.
5 changes: 3 additions & 2 deletions spec/operators/timeoutWith-spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing';
import { dateTimestampProvider } from '../../src/internal/scheduler/dateTimestampProvider';
import { timeoutWith, mergeMap } from 'rxjs/operators';
import { TestScheduler } from 'rxjs/testing';
import { of } from 'rxjs';
Expand Down Expand Up @@ -226,7 +227,7 @@ describe('timeoutWith operator', () => {
const e2subs: string[] = [];
const expected = '--a--b--c--d--e--|';

const timeoutValue = new Date(Date.now() + (expected.length + 2) * 10);
const timeoutValue = new Date(dateTimestampProvider.now() + (expected.length + 2) * 10);

const result = e1.pipe(timeoutWith(timeoutValue, e2, rxTestScheduler));

Expand All @@ -242,7 +243,7 @@ describe('timeoutWith operator', () => {
const e2subs: string[] = [];
const expected = '---a---#';

const result = e1.pipe(timeoutWith(new Date(Date.now() + 100), e2, rxTestScheduler));
const result = e1.pipe(timeoutWith(new Date(dateTimestampProvider.now() + 100), e2, rxTestScheduler));

expectObservable(result).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
Expand Down
5 changes: 3 additions & 2 deletions src/internal/ReplaySubject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Subscriber } from './Subscriber';
import { Subscription } from './Subscription';
import { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';
import { SubjectSubscription } from './SubjectSubscription';
import { dateTimestampProvider } from "./scheduler/dateTimestampProvider";

/**
* A variant of {@link Subject} that "replays" old values to new subscribers by emitting them when they first subscribe.
Expand Down Expand Up @@ -49,7 +50,7 @@ export class ReplaySubject<T> extends Subject<T> {
*/
constructor(bufferSize: number = Infinity,
windowTime: number = Infinity,
private timestampProvider: TimestampProvider = Date) {
private timestampProvider: TimestampProvider = dateTimestampProvider) {
super();
this._bufferSize = bufferSize < 1 ? 1 : bufferSize;
this._windowTime = windowTime < 1 ? 1 : windowTime;
Expand Down Expand Up @@ -120,7 +121,7 @@ export class ReplaySubject<T> extends Subject<T> {

private _getNow(): number {
const { timestampProvider: scheduler } = this;
return scheduler ? scheduler.now() : Date.now();
return scheduler ? scheduler.now() : dateTimestampProvider.now();
}

private _trimBufferThenGetEvents(): ReplayEvent<T>[] {
Expand Down
8 changes: 2 additions & 6 deletions src/internal/Scheduler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Action } from './scheduler/Action';
import { Subscription } from './Subscription';
import { SchedulerLike, SchedulerAction } from './types';
import { dateTimestampProvider } from "./scheduler/dateTimestampProvider";

/**
* An execution context and a data structure to order tasks and schedule their
Expand All @@ -23,12 +24,7 @@ import { SchedulerLike, SchedulerAction } from './types';
*/
export class Scheduler implements SchedulerLike {

/**
* Note: the extra arrow function wrapper is to make testing by overriding
* Date.now easier.
* @nocollapse
*/
public static now: () => number = () => Date.now();
public static now: () => number = dateTimestampProvider.now;

constructor(private SchedulerAction: typeof Action,
now: () => number = Scheduler.now) {
Expand Down
7 changes: 4 additions & 3 deletions src/internal/observable/dom/animationFrames.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Observable } from '../../Observable';
import { TimestampProvider } from "../../types";
import { dateTimestampProvider } from 'rxjs/internal/scheduler/dateTimestampProvider';

/**
* An observable of animation frames
Expand Down Expand Up @@ -73,8 +74,8 @@ import { TimestampProvider } from "../../types";
*
* @param timestampProvider An object with a `now` method that provides a numeric timestamp
*/
export function animationFrames(timestampProvider: TimestampProvider = Date) {
return timestampProvider === Date ? DEFAULT_ANIMATION_FRAMES : animationFramesFactory(timestampProvider);
export function animationFrames(timestampProvider: TimestampProvider = dateTimestampProvider) {
return timestampProvider === dateTimestampProvider ? DEFAULT_ANIMATION_FRAMES : animationFramesFactory(timestampProvider);
}

/**
Expand All @@ -100,4 +101,4 @@ function animationFramesFactory(timestampProvider: TimestampProvider) {
* In the common case, where `Date` is passed to `animationFrames` as the default,
* we use this shared observable to reduce overhead.
*/
const DEFAULT_ANIMATION_FRAMES = animationFramesFactory(Date);
const DEFAULT_ANIMATION_FRAMES = animationFramesFactory(dateTimestampProvider);
3 changes: 2 additions & 1 deletion src/internal/operators/timestamp.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { OperatorFunction, TimestampProvider, Timestamp } from '../types';
import { dateTimestampProvider } from '../scheduler/dateTimestampProvider';
import { map } from './map';

/**
Expand Down Expand Up @@ -32,6 +33,6 @@ import { map } from './map';
*
* @param timestampProvider An object with a `now()` method used to get the current timestamp.
*/
export function timestamp<T>(timestampProvider: TimestampProvider = Date): OperatorFunction<T, Timestamp<T>> {
export function timestamp<T>(timestampProvider: TimestampProvider = dateTimestampProvider): OperatorFunction<T, Timestamp<T>> {
return map((value: T) => ({ value, timestamp: timestampProvider.now()}));
}
14 changes: 14 additions & 0 deletions src/internal/scheduler/dateTimestampProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { TimestampProvider } from "../types";

interface DateTimestampProvider extends TimestampProvider {
delegate: TimestampProvider | undefined;
}

export const dateTimestampProvider: DateTimestampProvider = {
now() {
// Use the variable rather than `this` so that the function can be called
// without being bound to the provider.
return (dateTimestampProvider.delegate || Date).now();
},
delegate: undefined
};
14 changes: 14 additions & 0 deletions src/internal/scheduler/performanceTimestampProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { TimestampProvider } from "../types";

interface PerformanceTimestampProvider extends TimestampProvider {
delegate: TimestampProvider | undefined;
}

export const performanceTimestampProvider: PerformanceTimestampProvider = {
now() {
// Use the variable rather than `this` so that the function can be called
// without being bound to the provider.
return (performanceTimestampProvider.delegate || performance).now();
},
delegate: undefined
};
26 changes: 26 additions & 0 deletions src/internal/scheduler/requestAnimationFrameProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Subscription } from "../Subscription";

type RequestAnimationFrameProvider = {
schedule(callback: FrameRequestCallback): Subscription;
delegate: {
requestAnimationFrame: typeof requestAnimationFrame;
cancelAnimationFrame: typeof cancelAnimationFrame;
} | undefined;
};

export const requestAnimationFrameProvider: RequestAnimationFrameProvider = {
schedule(callback) {
let request = requestAnimationFrame;
let cancel = cancelAnimationFrame;
// Use the variable rather than `this` so that the function can be called
// without being bound to the provider.
const { delegate } = requestAnimationFrameProvider;
if (delegate) {
request = delegate.requestAnimationFrame;
cancel = delegate.cancelAnimationFrame;
}
const handle = request(callback);
return new Subscription(() => cancel(handle));
},
delegate: undefined
};
13 changes: 12 additions & 1 deletion src/internal/testing/TestScheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { VirtualTimeScheduler, VirtualAction } from '../scheduler/VirtualTimeSch
import { AsyncScheduler } from '../scheduler/AsyncScheduler';
import { ObservableNotification } from '../types';
import { COMPLETE_NOTIFICATION, errorNotification, nextNotification } from '../Notification';
import { dateTimestampProvider } from '../scheduler/dateTimestampProvider';
import { performanceTimestampProvider } from '../scheduler/performanceTimestampProvider';
import { requestAnimationFrameProvider } from '../scheduler/requestAnimationFrameProvider';

const defaultMaxFrame: number = 750;

Expand All @@ -18,6 +21,7 @@ export interface RunHelpers {
time: typeof TestScheduler.prototype.createTime;
expectObservable: typeof TestScheduler.prototype.expectObservable;
expectSubscriptions: typeof TestScheduler.prototype.expectSubscriptions;
repaints: (marbles: string) => void;
}

interface FlushableTest {
Expand Down Expand Up @@ -409,14 +413,18 @@ export class TestScheduler extends VirtualTimeScheduler {
this.maxFrames = Infinity;
this.runMode = true;
AsyncScheduler.delegate = this;
dateTimestampProvider.delegate = this;
performanceTimestampProvider.delegate = this;
requestAnimationFrameProvider.delegate = undefined; // TODO

const helpers = {
const helpers: RunHelpers = {
cold: this.createColdObservable.bind(this),
hot: this.createHotObservable.bind(this),
flush: this.flush.bind(this),
time: this.createTime.bind(this),
expectObservable: this.expectObservable.bind(this),
expectSubscriptions: this.expectSubscriptions.bind(this),
repaints: (marbles) => { /* TODO */ },
};
try {
const ret = callback(helpers);
Expand All @@ -427,6 +435,9 @@ export class TestScheduler extends VirtualTimeScheduler {
this.maxFrames = prevMaxFrames;
this.runMode = false;
AsyncScheduler.delegate = undefined;
dateTimestampProvider.delegate = undefined;
performanceTimestampProvider.delegate = undefined;
requestAnimationFrameProvider.delegate = undefined;
}
}
}

0 comments on commit c54affe

Please sign in to comment.