Path: blob/main/extensions/github-authentication/src/common/utils.ts
3320 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { EventEmitter, Event, Disposable } from 'vscode';67export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {8return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);9}1011export function onceEvent<T>(event: Event<T>): Event<T> {12return (listener, thisArgs = null, disposables?) => {13const result = event(e => {14result.dispose();15return listener.call(thisArgs, e);16}, null, disposables);1718return result;19};20}212223export interface PromiseAdapter<T, U> {24(25value: T,26resolve:27(value: U | PromiseLike<U>) => void,28reject:29(reason: any) => void30): any;31}3233const passthrough = (value: any, resolve: (value?: any) => void) => resolve(value);3435/**36* Return a promise that resolves with the next emitted event, or with some future37* event as decided by an adapter.38*39* If specified, the adapter is a function that will be called with40* `(event, resolve, reject)`. It will be called once per event until it resolves or41* rejects.42*43* The default adapter is the passthrough function `(value, resolve) => resolve(value)`.44*45* @param event the event46* @param adapter controls resolution of the returned promise47* @returns a promise that resolves or rejects as specified by the adapter48*/49export function promiseFromEvent<T, U>(50event: Event<T>,51adapter: PromiseAdapter<T, U> = passthrough): { promise: Promise<U>; cancel: EventEmitter<void> } {52let subscription: Disposable;53const cancel = new EventEmitter<void>();54return {55promise: new Promise<U>((resolve, reject) => {56cancel.event(_ => reject('Cancelled'));57subscription = event((value: T) => {58try {59Promise.resolve(adapter(value, resolve, reject))60.catch(reject);61} catch (error) {62reject(error);63}64});65}).then(66(result: U) => {67subscription.dispose();68return result;69},70error => {71subscription.dispose();72throw error;73}74),75cancel76};77}7879export function arrayEquals<T>(one: ReadonlyArray<T> | undefined, other: ReadonlyArray<T> | undefined, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {80if (one === other) {81return true;82}8384if (!one || !other) {85return false;86}8788if (one.length !== other.length) {89return false;90}9192for (let i = 0, len = one.length; i < len; i++) {93if (!itemEquals(one[i], other[i])) {94return false;95}96}9798return true;99}100101102export class StopWatch {103104private _startTime: number = Date.now();105private _stopTime: number = -1;106107public stop(): void {108this._stopTime = Date.now();109}110111public elapsed(): number {112if (this._stopTime !== -1) {113return this._stopTime - this._startTime;114}115return Date.now() - this._startTime;116}117}118119120