1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CancellationToken } from 'vs/base/common/cancellation';
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ILifecycleService = createDecorator<ILifecycleService>('lifecycleService');
/**
* An event that is send out when the window is about to close. Clients have a chance to veto
* the closing by either calling veto with a boolean "true" directly or with a promise that
* resolves to a boolean. Returning a promise is useful in cases of long running operations
* on shutdown.
*
* Note: It is absolutely important to avoid long running promises if possible. Please try hard
* to return a boolean directly. Returning a promise has quite an impact on the shutdown sequence!
*/
export interface BeforeShutdownEvent {
/**
* The reason why the application will be shutting down.
*/
readonly reason: ShutdownReason;
/**
* Allows to veto the shutdown. The veto can be a long running operation but it
* will block the application from closing.
*
* @param id to identify the veto operation in case it takes very long or never
* completes.
*/
veto(value: boolean | Promise<boolean>, id: string): void;
}
export interface InternalBeforeShutdownEvent extends BeforeShutdownEvent {
/**
* Allows to set a veto operation to run after all other
* vetos have been handled from the `BeforeShutdownEvent`
*
* This method is hidden from the API because it is intended
* to be only used once internally.
*/
finalVeto(vetoFn: () => boolean | Promise<boolean>, id: string): void;
}
/**
* An event that signals an error happened during `onBeforeShutdown` veto handling.
* In this case the shutdown operation will not proceed because this is an unexpected
* condition that is treated like a veto.
*/
export interface BeforeShutdownErrorEvent {
/**
* The reason why the application is shutting down.
*/
readonly reason: ShutdownReason;
/**
* The error that happened during shutdown handling.
*/
readonly error: Error;
}
export interface IWillShutdownEventJoiner {
id: string;
label: string;
}
/**
* An event that is send out when the window closes. Clients have a chance to join the closing
* by providing a promise from the join method. Returning a promise is useful in cases of long
* running operations on shutdown.
*
* Note: It is absolutely important to avoid long running promises if possible. Please try hard
* to return a boolean directly. Returning a promise has quite an impact on the shutdown sequence!
*/
export interface WillShutdownEvent {
/**
* The reason why the application is shutting down.
*/
readonly reason: ShutdownReason;
/**
* A token that will signal cancellation when the
* shutdown was forced by the user.
*/
readonly token: CancellationToken;
/**
* Allows to join the shutdown. The promise can be a long running operation but it
* will block the application from closing.
*
* @param joiner to identify the join operation in case it takes very long or never
* completes.
*/
join(promise: Promise<void>, joiner: IWillShutdownEventJoiner): void;
/**
* Allows to access the joiners that have not finished joining this event.
*/
joiners(): IWillShutdownEventJoiner[];
/**
* Allows to enforce the shutdown, even when there are
* pending `join` operations to complete.
*/
force(): void;
}
export const enum ShutdownReason {
/**
* The window is closed.
*/
CLOSE = 1,
/**
* The window closes because the application quits.
*/
QUIT,
/**
* The window is reloaded.
*/
RELOAD,
/**
* The window is loaded into a different workspace context.
*/
LOAD
}
export const enum StartupKind {
NewWindow = 1,
ReloadedWindow = 3,
ReopenedWindow = 4
}
export function StartupKindToString(startupKind: StartupKind): string {
switch (startupKind) {
case StartupKind.NewWindow: return 'NewWindow';
case StartupKind.ReloadedWindow: return 'ReloadedWindow';
case StartupKind.ReopenedWindow: return 'ReopenedWindow';
}
}
export const enum LifecyclePhase {
/**
* The first phase signals that we are about to startup getting ready.
*
* Note: doing work in this phase blocks an editor from showing to
* the user, so please rather consider to use `Restored` phase.
*/
Starting = 1,
/**
* Services are ready and the window is about to restore its UI state.
*
* Note: doing work in this phase blocks an editor from showing to
* the user, so please rather consider to use `Restored` phase.
*/
Ready = 2,
/**
* Views, panels and editors have restored. Editors are given a bit of
* time to restore their contents.
*/
Restored = 3,
/**
* The last phase after views, panels and editors have restored and
* some time has passed (2-5 seconds).
*/
Eventually = 4
}
export function LifecyclePhaseToString(phase: LifecyclePhase): string {
switch (phase) {
case LifecyclePhase.Starting: return 'Starting';
case LifecyclePhase.Ready: return 'Ready';
case LifecyclePhase.Restored: return 'Restored';
case LifecyclePhase.Eventually: return 'Eventually';
}
}
/**
* A lifecycle service informs about lifecycle events of the
* application, such as shutdown.
*/
export interface ILifecycleService {
readonly _serviceBrand: undefined;
/**
* Value indicates how this window got loaded.
*/
readonly startupKind: StartupKind;
/**
* A flag indicating in what phase of the lifecycle we currently are.
*/
phase: LifecyclePhase;
/**
* Fired before shutdown happens. Allows listeners to veto against the
* shutdown to prevent it from happening.
*
* The event carries a shutdown reason that indicates how the shutdown was triggered.
*/
readonly onBeforeShutdown: Event<BeforeShutdownEvent>;
/**
* Fired when the shutdown was prevented by a component giving veto.
*/
readonly onShutdownVeto: Event<void>;
/**
* Fired when an error happened during `onBeforeShutdown` veto handling.
* In this case the shutdown operation will not proceed because this is
* an unexpected condition that is treated like a veto.
*
* The event carries a shutdown reason that indicates how the shutdown was triggered.
*/
readonly onBeforeShutdownError: Event<BeforeShutdownErrorEvent>;
/**
* Fired when no client is preventing the shutdown from happening (from `onBeforeShutdown`).
*
* This event can be joined with a long running operation via `WillShutdownEvent#join()` to
* handle long running shutdown operations.
*
* The event carries a shutdown reason that indicates how the shutdown was triggered.
*/
readonly onWillShutdown: Event<WillShutdownEvent>;
/**
* Fired when the shutdown is about to happen after long running shutdown operations
* have finished (from `onWillShutdown`).
*
* This event should be used to dispose resources.
*/
readonly onDidShutdown: Event<void>;
/**
* Returns a promise that resolves when a certain lifecycle phase
* has started.
*/
when(phase: LifecyclePhase): Promise<void>;
/**
* Triggers a shutdown of the workbench. Depending on native or web, this can have
* different implementations and behaviour.
*
* **Note:** this should normally not be called. See related methods in `IHostService`
* and `INativeHostService` to close a window or quit the application.
*/
shutdown(): Promise<void>;
}
export const NullLifecycleService: ILifecycleService = {
_serviceBrand: undefined,
onBeforeShutdown: Event.None,
onBeforeShutdownError: Event.None,
onShutdownVeto: Event.None,
onWillShutdown: Event.None,
onDidShutdown: Event.None,
phase: LifecyclePhase.Restored,
startupKind: StartupKind.NewWindow,
async when() { },
async shutdown() { }
};
|