Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/github-authentication/src/common/utils.ts
3320 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { EventEmitter, Event, Disposable } from 'vscode';
7
8
export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {
9
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
10
}
11
12
export function onceEvent<T>(event: Event<T>): Event<T> {
13
return (listener, thisArgs = null, disposables?) => {
14
const result = event(e => {
15
result.dispose();
16
return listener.call(thisArgs, e);
17
}, null, disposables);
18
19
return result;
20
};
21
}
22
23
24
export interface PromiseAdapter<T, U> {
25
(
26
value: T,
27
resolve:
28
(value: U | PromiseLike<U>) => void,
29
reject:
30
(reason: any) => void
31
): any;
32
}
33
34
const passthrough = (value: any, resolve: (value?: any) => void) => resolve(value);
35
36
/**
37
* Return a promise that resolves with the next emitted event, or with some future
38
* event as decided by an adapter.
39
*
40
* If specified, the adapter is a function that will be called with
41
* `(event, resolve, reject)`. It will be called once per event until it resolves or
42
* rejects.
43
*
44
* The default adapter is the passthrough function `(value, resolve) => resolve(value)`.
45
*
46
* @param event the event
47
* @param adapter controls resolution of the returned promise
48
* @returns a promise that resolves or rejects as specified by the adapter
49
*/
50
export function promiseFromEvent<T, U>(
51
event: Event<T>,
52
adapter: PromiseAdapter<T, U> = passthrough): { promise: Promise<U>; cancel: EventEmitter<void> } {
53
let subscription: Disposable;
54
const cancel = new EventEmitter<void>();
55
return {
56
promise: new Promise<U>((resolve, reject) => {
57
cancel.event(_ => reject('Cancelled'));
58
subscription = event((value: T) => {
59
try {
60
Promise.resolve(adapter(value, resolve, reject))
61
.catch(reject);
62
} catch (error) {
63
reject(error);
64
}
65
});
66
}).then(
67
(result: U) => {
68
subscription.dispose();
69
return result;
70
},
71
error => {
72
subscription.dispose();
73
throw error;
74
}
75
),
76
cancel
77
};
78
}
79
80
export function arrayEquals<T>(one: ReadonlyArray<T> | undefined, other: ReadonlyArray<T> | undefined, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
81
if (one === other) {
82
return true;
83
}
84
85
if (!one || !other) {
86
return false;
87
}
88
89
if (one.length !== other.length) {
90
return false;
91
}
92
93
for (let i = 0, len = one.length; i < len; i++) {
94
if (!itemEquals(one[i], other[i])) {
95
return false;
96
}
97
}
98
99
return true;
100
}
101
102
103
export class StopWatch {
104
105
private _startTime: number = Date.now();
106
private _stopTime: number = -1;
107
108
public stop(): void {
109
this._stopTime = Date.now();
110
}
111
112
public elapsed(): number {
113
if (this._stopTime !== -1) {
114
return this._stopTime - this._startTime;
115
}
116
return Date.now() - this._startTime;
117
}
118
}
119
120