Fix EsLint Brackets (error markup 'const').

This commit is contained in:
2018-11-22 16:41:46 +01:00
parent 75add7333d
commit d20e8a9d10
6005 changed files with 337788 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import { Scheduler } from '../Scheduler';
import { Subscription } from '../Subscription';
import { SchedulerAction } from '../types';
/**
* A unit of work to be executed in a `scheduler`. An action is typically
* created from within a {@link SchedulerLike} and an RxJS user does not need to concern
* themselves about creating and manipulating an Action.
*
* ```ts
* class Action<T> extends Subscription {
* new (scheduler: Scheduler, work: (state?: T) => void);
* schedule(state?: T, delay: number = 0): Subscription;
* }
* ```
*
* @class Action<T>
*/
export class Action<T> extends Subscription {
constructor(scheduler: Scheduler, work: (this: SchedulerAction<T>, state?: T) => void) {
super();
}
/**
* Schedules this action on its parent {@link SchedulerLike} for execution. May be passed
* some context object, `state`. May happen at some point in the future,
* according to the `delay` parameter, if specified.
* @param {T} [state] Some contextual data that the `work` function uses when
* called by the Scheduler.
* @param {number} [delay] Time to wait before executing the work, where the
* time unit is implicit and defined by the Scheduler.
* @return {void}
*/
public schedule(state?: T, delay: number = 0): Subscription {
return this;
}
}
+47
View File
@@ -0,0 +1,47 @@
import { AsyncAction } from './AsyncAction';
import { AnimationFrameScheduler } from './AnimationFrameScheduler';
import { SchedulerAction } from '../types';
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class AnimationFrameAction<T> extends AsyncAction<T> {
constructor(protected scheduler: AnimationFrameScheduler,
protected work: (this: SchedulerAction<T>, state?: T) => void) {
super(scheduler, work);
}
protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: any, delay: number = 0): any {
// If delay is greater than 0, request as an async action.
if (delay !== null && delay > 0) {
return super.requestAsyncId(scheduler, id, delay);
}
// Push the action to the end of the scheduler queue.
scheduler.actions.push(this);
// If an animation frame has already been requested, don't request another
// one. If an animation frame hasn't been requested yet, request one. Return
// the current animation frame request id.
return scheduler.scheduled || (scheduler.scheduled = requestAnimationFrame(
() => scheduler.flush(null)));
}
protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: any, delay: number = 0): any {
// If delay exists and is greater than 0, or if the delay is null (the
// action wasn't rescheduled) but was originally scheduled as an async
// action, then recycle as an async action.
if ((delay !== null && delay > 0) || (delay === null && this.delay > 0)) {
return super.recycleAsyncId(scheduler, id, delay);
}
// If the scheduler queue is empty, cancel the requested animation frame and
// set the scheduled flag to undefined so the next AnimationFrameAction will
// request its own.
if (scheduler.actions.length === 0) {
cancelAnimationFrame(id);
scheduler.scheduled = undefined;
}
// Return undefined so the action knows to request a new async id if it's rescheduled.
return undefined;
}
}
+31
View File
@@ -0,0 +1,31 @@
import { AsyncAction } from './AsyncAction';
import { AsyncScheduler } from './AsyncScheduler';
export class AnimationFrameScheduler extends AsyncScheduler {
public flush(action?: AsyncAction<any>): void {
this.active = true;
this.scheduled = undefined;
const {actions} = this;
let error: any;
let index: number = -1;
let count: number = actions.length;
action = action || actions.shift();
do {
if (error = action.execute(action.state, action.delay)) {
break;
}
} while (++index < count && (action = actions.shift()));
this.active = false;
if (error) {
while (++index < count && (action = actions.shift())) {
action.unsubscribe();
}
throw error;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
import { Immediate } from '../util/Immediate';
import { AsyncAction } from './AsyncAction';
import { AsapScheduler } from './AsapScheduler';
import { SchedulerAction } from '../types';
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class AsapAction<T> extends AsyncAction<T> {
constructor(protected scheduler: AsapScheduler,
protected work: (this: SchedulerAction<T>, state?: T) => void) {
super(scheduler, work);
}
protected requestAsyncId(scheduler: AsapScheduler, id?: any, delay: number = 0): any {
// If delay is greater than 0, request as an async action.
if (delay !== null && delay > 0) {
return super.requestAsyncId(scheduler, id, delay);
}
// Push the action to the end of the scheduler queue.
scheduler.actions.push(this);
// If a microtask has already been scheduled, don't schedule another
// one. If a microtask hasn't been scheduled yet, schedule one now. Return
// the current scheduled microtask id.
return scheduler.scheduled || (scheduler.scheduled = Immediate.setImmediate(
scheduler.flush.bind(scheduler, null)
));
}
protected recycleAsyncId(scheduler: AsapScheduler, id?: any, delay: number = 0): any {
// If delay exists and is greater than 0, or if the delay is null (the
// action wasn't rescheduled) but was originally scheduled as an async
// action, then recycle as an async action.
if ((delay !== null && delay > 0) || (delay === null && this.delay > 0)) {
return super.recycleAsyncId(scheduler, id, delay);
}
// If the scheduler queue is empty, cancel the requested microtask and
// set the scheduled flag to undefined so the next AsapAction will schedule
// its own.
if (scheduler.actions.length === 0) {
Immediate.clearImmediate(id);
scheduler.scheduled = undefined;
}
// Return undefined so the action knows to request a new async id if it's rescheduled.
return undefined;
}
}
+31
View File
@@ -0,0 +1,31 @@
import { AsyncAction } from './AsyncAction';
import { AsyncScheduler } from './AsyncScheduler';
export class AsapScheduler extends AsyncScheduler {
public flush(action?: AsyncAction<any>): void {
this.active = true;
this.scheduled = undefined;
const {actions} = this;
let error: any;
let index: number = -1;
let count: number = actions.length;
action = action || actions.shift();
do {
if (error = action.execute(action.state, action.delay)) {
break;
}
} while (++index < count && (action = actions.shift()));
this.active = false;
if (error) {
while (++index < count && (action = actions.shift())) {
action.unsubscribe();
}
throw error;
}
}
}
+155
View File
@@ -0,0 +1,155 @@
import { Action } from './Action';
import { SchedulerAction } from '../types';
import { Subscription } from '../Subscription';
import { AsyncScheduler } from './AsyncScheduler';
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class AsyncAction<T> extends Action<T> {
public id: any;
public state: T;
public delay: number;
protected pending: boolean = false;
constructor(protected scheduler: AsyncScheduler,
protected work: (this: SchedulerAction<T>, state?: T) => void) {
super(scheduler, work);
}
public schedule(state?: T, delay: number = 0): Subscription {
if (this.closed) {
return this;
}
// Always replace the current state with the new state.
this.state = state;
const id = this.id;
const scheduler = this.scheduler;
//
// Important implementation note:
//
// Actions only execute once by default, unless rescheduled from within the
// scheduled callback. This allows us to implement single and repeat
// actions via the same code path, without adding API surface area, as well
// as mimic traditional recursion but across asynchronous boundaries.
//
// However, JS runtimes and timers distinguish between intervals achieved by
// serial `setTimeout` calls vs. a single `setInterval` call. An interval of
// serial `setTimeout` calls can be individually delayed, which delays
// scheduling the next `setTimeout`, and so on. `setInterval` attempts to
// guarantee the interval callback will be invoked more precisely to the
// interval period, regardless of load.
//
// Therefore, we use `setInterval` to schedule single and repeat actions.
// If the action reschedules itself with the same delay, the interval is not
// canceled. If the action doesn't reschedule, or reschedules with a
// different delay, the interval will be canceled after scheduled callback
// execution.
//
if (id != null) {
this.id = this.recycleAsyncId(scheduler, id, delay);
}
// Set the pending flag indicating that this action has been scheduled, or
// has recursively rescheduled itself.
this.pending = true;
this.delay = delay;
// If this action has already an async Id, don't request a new one.
this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
return this;
}
protected requestAsyncId(scheduler: AsyncScheduler, id?: any, delay: number = 0): any {
return setInterval(scheduler.flush.bind(scheduler, this), delay);
}
protected recycleAsyncId(scheduler: AsyncScheduler, id: any, delay: number = 0): any {
// If this action is rescheduled with the same delay time, don't clear the interval id.
if (delay !== null && this.delay === delay && this.pending === false) {
return id;
}
// Otherwise, if the action's delay time is different from the current delay,
// or the action has been rescheduled before it's executed, clear the interval id
clearInterval(id);
}
/**
* Immediately executes this action and the `work` it contains.
* @return {any}
*/
public execute(state: T, delay: number): any {
if (this.closed) {
return new Error('executing a cancelled action');
}
this.pending = false;
const error = this._execute(state, delay);
if (error) {
return error;
} else if (this.pending === false && this.id != null) {
// Dequeue if the action didn't reschedule itself. Don't call
// unsubscribe(), because the action could reschedule later.
// For example:
// ```
// scheduler.schedule(function doWork(counter) {
// /* ... I'm a busy worker bee ... */
// var originalAction = this;
// /* wait 100ms before rescheduling the action */
// setTimeout(function () {
// originalAction.schedule(counter + 1);
// }, 100);
// }, 1000);
// ```
this.id = this.recycleAsyncId(this.scheduler, this.id, null);
}
}
protected _execute(state: T, delay: number): any {
let errored: boolean = false;
let errorValue: any = undefined;
try {
this.work(state);
} catch (e) {
errored = true;
errorValue = !!e && e || new Error(e);
}
if (errored) {
this.unsubscribe();
return errorValue;
}
}
/** @deprecated This is an internal implementation detail, do not use. */
_unsubscribe() {
const id = this.id;
const scheduler = this.scheduler;
const actions = scheduler.actions;
const index = actions.indexOf(this);
this.work = null;
this.state = null;
this.pending = false;
this.scheduler = null;
if (index !== -1) {
actions.splice(index, 1);
}
if (id != null) {
this.id = this.recycleAsyncId(scheduler, id, null);
}
this.delay = null;
}
}
+72
View File
@@ -0,0 +1,72 @@
import { Scheduler } from '../Scheduler';
import { Action } from './Action';
import { AsyncAction } from './AsyncAction';
import { SchedulerAction } from '../types';
import { Subscription } from '../Subscription';
export class AsyncScheduler extends Scheduler {
public static delegate?: Scheduler;
public actions: Array<AsyncAction<any>> = [];
/**
* A flag to indicate whether the Scheduler is currently executing a batch of
* queued actions.
* @type {boolean}
* @deprecated internal use only
*/
public active: boolean = false;
/**
* An internal ID used to track the latest asynchronous task such as those
* coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and
* others.
* @type {any}
* @deprecated internal use only
*/
public scheduled: any = undefined;
constructor(SchedulerAction: typeof Action,
now: () => number = Scheduler.now) {
super(SchedulerAction, () => {
if (AsyncScheduler.delegate && AsyncScheduler.delegate !== this) {
return AsyncScheduler.delegate.now();
} else {
return now();
}
});
}
public schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay: number = 0, state?: T): Subscription {
if (AsyncScheduler.delegate && AsyncScheduler.delegate !== this) {
return AsyncScheduler.delegate.schedule(work, delay, state);
} else {
return super.schedule(work, delay, state);
}
}
public flush(action: AsyncAction<any>): void {
const {actions} = this;
if (this.active) {
actions.push(action);
return;
}
let error: any;
this.active = true;
do {
if (error = action.execute(action.state, action.delay)) {
break;
}
} while (action = actions.shift()); // exhaust the scheduler queue
this.active = false;
if (error) {
while (action = actions.shift()) {
action.unsubscribe();
}
throw error;
}
}
}
+44
View File
@@ -0,0 +1,44 @@
import { AsyncAction } from './AsyncAction';
import { Subscription } from '../Subscription';
import { QueueScheduler } from './QueueScheduler';
import { SchedulerAction } from '../types';
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class QueueAction<T> extends AsyncAction<T> {
constructor(protected scheduler: QueueScheduler,
protected work: (this: SchedulerAction<T>, state?: T) => void) {
super(scheduler, work);
}
public schedule(state?: T, delay: number = 0): Subscription {
if (delay > 0) {
return super.schedule(state, delay);
}
this.delay = delay;
this.state = state;
this.scheduler.flush(this);
return this;
}
public execute(state: T, delay: number): any {
return (delay > 0 || this.closed) ?
super.execute(state, delay) :
this._execute(state, delay) ;
}
protected requestAsyncId(scheduler: QueueScheduler, id?: any, delay: number = 0): any {
// If delay exists and is greater than 0, or if the delay is null (the
// action wasn't rescheduled) but was originally scheduled as an async
// action, then recycle as an async action.
if ((delay !== null && delay > 0) || (delay === null && this.delay > 0)) {
return super.requestAsyncId(scheduler, id, delay);
}
// Otherwise flush the scheduler starting with this action.
return scheduler.flush(this);
}
}
+4
View File
@@ -0,0 +1,4 @@
import { AsyncScheduler } from './AsyncScheduler';
export class QueueScheduler extends AsyncScheduler {
}
+105
View File
@@ -0,0 +1,105 @@
import { AsyncAction } from './AsyncAction';
import { Subscription } from '../Subscription';
import { AsyncScheduler } from './AsyncScheduler';
import { SchedulerAction } from '../types';
export class VirtualTimeScheduler extends AsyncScheduler {
protected static frameTimeFactor: number = 10;
public frame: number = 0;
public index: number = -1;
constructor(SchedulerAction: typeof AsyncAction = VirtualAction as any,
public maxFrames: number = Number.POSITIVE_INFINITY) {
super(SchedulerAction, () => this.frame);
}
/**
* Prompt the Scheduler to execute all of its queued actions, therefore
* clearing its queue.
* @return {void}
*/
public flush(): void {
const {actions, maxFrames} = this;
let error: any, action: AsyncAction<any>;
while ((action = actions.shift()) && (this.frame = action.delay) <= maxFrames) {
if (error = action.execute(action.state, action.delay)) {
break;
}
}
if (error) {
while (action = actions.shift()) {
action.unsubscribe();
}
throw error;
}
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @nodoc
*/
export class VirtualAction<T> extends AsyncAction<T> {
protected active: boolean = true;
constructor(protected scheduler: VirtualTimeScheduler,
protected work: (this: SchedulerAction<T>, state?: T) => void,
protected index: number = scheduler.index += 1) {
super(scheduler, work);
this.index = scheduler.index = index;
}
public schedule(state?: T, delay: number = 0): Subscription {
if (!this.id) {
return super.schedule(state, delay);
}
this.active = false;
// If an action is rescheduled, we save allocations by mutating its state,
// pushing it to the end of the scheduler queue, and recycling the action.
// But since the VirtualTimeScheduler is used for testing, VirtualActions
// must be immutable so they can be inspected later.
const action = new VirtualAction(this.scheduler, this.work);
this.add(action);
return action.schedule(state, delay);
}
protected requestAsyncId(scheduler: VirtualTimeScheduler, id?: any, delay: number = 0): any {
this.delay = scheduler.frame + delay;
const {actions} = scheduler;
actions.push(this);
(actions as Array<VirtualAction<T>>).sort(VirtualAction.sortActions);
return true;
}
protected recycleAsyncId(scheduler: VirtualTimeScheduler, id?: any, delay: number = 0): any {
return undefined;
}
protected _execute(state: T, delay: number): any {
if (this.active === true) {
return super._execute(state, delay);
}
}
public static sortActions<T>(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;
}
}
}
+37
View File
@@ -0,0 +1,37 @@
import { AnimationFrameAction } from './AnimationFrameAction';
import { AnimationFrameScheduler } from './AnimationFrameScheduler';
/**
*
* Animation Frame Scheduler
*
* <span class="informal">Perform task when `window.requestAnimationFrame` would fire</span>
*
* When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler
* behaviour.
*
* Without delay, `animationFrame` scheduler can be used to create smooth browser animations.
* It makes sure scheduled task will happen just before next browser content repaint,
* thus performing animations as efficiently as possible.
*
* ## Example
* Schedule div height animation
* ```javascript
* const div = document.querySelector('.some-div');
*
* Rx.Scheduler.animationFrame.schedule(function(height) {
* div.style.height = height + "px";
*
* this.schedule(height + 1); // `this` references currently executing Action,
* // which we reschedule with new state
* }, 0, 0);
*
* // You will see .some-div element growing in height
* ```
*
* @static true
* @name animationFrame
* @owner Scheduler
*/
export const animationFrame = new AnimationFrameScheduler(AnimationFrameAction);
+40
View File
@@ -0,0 +1,40 @@
import { AsapAction } from './AsapAction';
import { AsapScheduler } from './AsapScheduler';
/**
*
* Asap Scheduler
*
* <span class="informal">Perform task as fast as it can be performed asynchronously</span>
*
* `asap` scheduler behaves the same as {@link asyncScheduler} scheduler when you use it to delay task
* in time. If however you set delay to `0`, `asap` will wait for current synchronously executing
* code to end and then it will try to execute given task as fast as possible.
*
* `asap` scheduler will do its best to minimize time between end of currently executing code
* and start of scheduled task. This makes it best candidate for performing so called "deferring".
* Traditionally this was achieved by calling `setTimeout(deferredTask, 0)`, but that technique involves
* some (although minimal) unwanted delay.
*
* Note that using `asap` scheduler does not necessarily mean that your task will be first to process
* after currently executing code. In particular, if some task was also scheduled with `asap` before,
* that task will execute first. That being said, if you need to schedule task asynchronously, but
* as soon as possible, `asap` scheduler is your best bet.
*
* ## Example
* Compare async and asap scheduler<
* ```javascript
* Rx.Scheduler.async.schedule(() => console.log('async')); // scheduling 'async' first...
* Rx.Scheduler.asap.schedule(() => console.log('asap'));
*
* // Logs:
* // "asap"
* // "async"
* // ... but 'asap' goes first!
* ```
* @static true
* @name asap
* @owner Scheduler
*/
export const asap = new AsapScheduler(AsapAction);
+51
View File
@@ -0,0 +1,51 @@
import { AsyncAction } from './AsyncAction';
import { AsyncScheduler } from './AsyncScheduler';
/**
*
* Async Scheduler
*
* <span class="informal">Schedule task as if you used setTimeout(task, duration)</span>
*
* `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript
* event loop queue. It is best used to delay tasks in time or to schedule tasks repeating
* in intervals.
*
* If you just want to "defer" task, that is to perform it right after currently
* executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),
* better choice will be the {@link asapScheduler} scheduler.
*
* ## Examples
* Use async scheduler to delay task
* ```javascript
* const task = () => console.log('it works!');
*
* Rx.Scheduler.async.schedule(task, 2000);
*
* // After 2 seconds logs:
* // "it works!"
* ```
*
* Use async scheduler to repeat task in intervals
* ```javascript
* function task(state) {
* console.log(state);
* this.schedule(state + 1, 1000); // `this` references currently executing Action,
* // which we reschedule with new state and delay
* }
*
* Rx.Scheduler.async.schedule(task, 3000, 0);
*
* // Logs:
* // 0 after 3s
* // 1 after 4s
* // 2 after 5s
* // 3 after 6s
* ```
*
* @static true
* @name async
* @owner Scheduler
*/
export const async = new AsyncScheduler(AsyncAction);
+67
View File
@@ -0,0 +1,67 @@
import { QueueAction } from './QueueAction';
import { QueueScheduler } from './QueueScheduler';
/**
*
* Queue Scheduler
*
* <span class="informal">Put every next task on a queue, instead of executing it immediately</span>
*
* `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.
*
* When used without delay, it schedules given task synchronously - executes it right when
* it is scheduled. However when called recursively, that is when inside the scheduled task,
* another task is scheduled with queue scheduler, instead of executing immediately as well,
* that task will be put on a queue and wait for current one to finish.
*
* This means that when you execute task with `queue` scheduler, you are sure it will end
* before any other task scheduled with that scheduler will start.
*
* ## Examples
* Schedule recursively first, then do something
* ```javascript
* Rx.Scheduler.queue.schedule(() => {
* Rx.Scheduler.queue.schedule(() => console.log('second')); // will not happen now, but will be put on a queue
*
* console.log('first');
* });
*
* // Logs:
* // "first"
* // "second"
* ```
*
* Reschedule itself recursively
* ```javascript
* Rx.Scheduler.queue.schedule(function(state) {
* if (state !== 0) {
* console.log('before', state);
* this.schedule(state - 1); // `this` references currently executing Action,
* // which we reschedule with new state
* console.log('after', state);
* }
* }, 0, 3);
*
* // In scheduler that runs recursively, you would expect:
* // "before", 3
* // "before", 2
* // "before", 1
* // "after", 1
* // "after", 2
* // "after", 3
*
* // But with queue it logs:
* // "before", 3
* // "after", 3
* // "before", 2
* // "after", 2
* // "before", 1
* // "after", 1
* ```
*
* @static true
* @name queue
* @owner Scheduler
*/
export const queue = new QueueScheduler(QueueAction);