chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EventEmitter, Event, Disposable } from 'vscode';
|
||||
|
||||
export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {
|
||||
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
|
||||
}
|
||||
|
||||
export function onceEvent<T>(event: Event<T>): Event<T> {
|
||||
return (listener, thisArgs = null, disposables?) => {
|
||||
const result = event(e => {
|
||||
result.dispose();
|
||||
return listener.call(thisArgs, e);
|
||||
}, null, disposables);
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export interface PromiseAdapter<T, U> {
|
||||
(
|
||||
value: T,
|
||||
resolve:
|
||||
(value: U | PromiseLike<U>) => void,
|
||||
reject:
|
||||
(reason: any) => void
|
||||
): any;
|
||||
}
|
||||
|
||||
const passthrough = (value: any, resolve: (value?: any) => void) => resolve(value);
|
||||
|
||||
/**
|
||||
* Return a promise that resolves with the next emitted event, or with some future
|
||||
* event as decided by an adapter.
|
||||
*
|
||||
* If specified, the adapter is a function that will be called with
|
||||
* `(event, resolve, reject)`. It will be called once per event until it resolves or
|
||||
* rejects.
|
||||
*
|
||||
* The default adapter is the passthrough function `(value, resolve) => resolve(value)`.
|
||||
*
|
||||
* @param event the event
|
||||
* @param adapter controls resolution of the returned promise
|
||||
* @returns a promise that resolves or rejects as specified by the adapter
|
||||
*/
|
||||
export function promiseFromEvent<T, U>(
|
||||
event: Event<T>,
|
||||
adapter: PromiseAdapter<T, U> = passthrough): { promise: Promise<U>; cancel: EventEmitter<void> } {
|
||||
let subscription: Disposable;
|
||||
const cancel = new EventEmitter<void>();
|
||||
return {
|
||||
promise: new Promise<U>((resolve, reject) => {
|
||||
cancel.event(_ => reject('Cancelled'));
|
||||
subscription = event((value: T) => {
|
||||
try {
|
||||
Promise.resolve(adapter(value, resolve, reject))
|
||||
.catch(reject);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}).then(
|
||||
(result: U) => {
|
||||
subscription.dispose();
|
||||
return result;
|
||||
},
|
||||
error => {
|
||||
subscription.dispose();
|
||||
throw error;
|
||||
}
|
||||
),
|
||||
cancel
|
||||
};
|
||||
}
|
||||
|
||||
export function arrayEquals<T>(one: ReadonlyArray<T> | undefined, other: ReadonlyArray<T> | undefined, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
|
||||
if (one === other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!one || !other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (one.length !== other.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0, len = one.length; i < len; i++) {
|
||||
if (!itemEquals(one[i], other[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export class StopWatch {
|
||||
|
||||
private _startTime: number = Date.now();
|
||||
private _stopTime: number = -1;
|
||||
|
||||
public stop(): void {
|
||||
this._stopTime = Date.now();
|
||||
}
|
||||
|
||||
public elapsed(): number {
|
||||
if (this._stopTime !== -1) {
|
||||
return this._stopTime - this._startTime;
|
||||
}
|
||||
return Date.now() - this._startTime;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user