@theia/core 1.73.0-next.20 → 1.73.0-next.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/lib/browser/authentication-service.d.ts +2 -0
  2. package/lib/browser/authentication-service.d.ts.map +1 -1
  3. package/lib/browser/authentication-service.js +8 -2
  4. package/lib/browser/authentication-service.js.map +1 -1
  5. package/lib/browser/catalog.json +36 -8
  6. package/lib/browser/frontend-application.d.ts +2 -0
  7. package/lib/browser/frontend-application.d.ts.map +1 -1
  8. package/lib/browser/frontend-application.js +15 -9
  9. package/lib/browser/frontend-application.js.map +1 -1
  10. package/lib/browser/json-schema-store.d.ts +2 -0
  11. package/lib/browser/json-schema-store.d.ts.map +1 -1
  12. package/lib/browser/json-schema-store.js +8 -2
  13. package/lib/browser/json-schema-store.js.map +1 -1
  14. package/lib/browser/keybinding.js +2 -1
  15. package/lib/browser/keybinding.js.map +1 -1
  16. package/lib/browser/preferences/frontend-config-preference-contributions.d.ts +2 -0
  17. package/lib/browser/preferences/frontend-config-preference-contributions.d.ts.map +1 -1
  18. package/lib/browser/preferences/frontend-config-preference-contributions.js +7 -1
  19. package/lib/browser/preferences/frontend-config-preference-contributions.js.map +1 -1
  20. package/lib/browser/preferences/preference-schema-provider.spec.js +3 -0
  21. package/lib/browser/preferences/preference-schema-provider.spec.js.map +1 -1
  22. package/lib/browser/preferences/preference-validation-service.d.ts +2 -0
  23. package/lib/browser/preferences/preference-validation-service.d.ts.map +1 -1
  24. package/lib/browser/preferences/preference-validation-service.js +11 -5
  25. package/lib/browser/preferences/preference-validation-service.js.map +1 -1
  26. package/lib/browser/preferences/preference-validation-service.spec.js +2 -0
  27. package/lib/browser/preferences/preference-validation-service.spec.js.map +1 -1
  28. package/lib/browser/secondary-window-handler.d.ts +2 -0
  29. package/lib/browser/secondary-window-handler.d.ts.map +1 -1
  30. package/lib/browser/secondary-window-handler.js +12 -6
  31. package/lib/browser/secondary-window-handler.js.map +1 -1
  32. package/lib/browser/shell/application-shell.d.ts +2 -0
  33. package/lib/browser/shell/application-shell.d.ts.map +1 -1
  34. package/lib/browser/shell/application-shell.js +9 -3
  35. package/lib/browser/shell/application-shell.js.map +1 -1
  36. package/lib/browser/tree/tree-container.spec.js +4 -0
  37. package/lib/browser/tree/tree-container.spec.js.map +1 -1
  38. package/lib/browser/tree/tree.d.ts +2 -0
  39. package/lib/browser/tree/tree.d.ts.map +1 -1
  40. package/lib/browser/tree/tree.js +7 -1
  41. package/lib/browser/tree/tree.js.map +1 -1
  42. package/lib/browser/window/default-window-service.d.ts +2 -1
  43. package/lib/browser/window/default-window-service.d.ts.map +1 -1
  44. package/lib/browser/window/default-window-service.js +10 -5
  45. package/lib/browser/window/default-window-service.js.map +1 -1
  46. package/lib/browser/window/default-window-service.spec.js +2 -0
  47. package/lib/browser/window/default-window-service.spec.js.map +1 -1
  48. package/lib/browser-only/messaging/frontend-only-service-connection-provider.d.ts +2 -0
  49. package/lib/browser-only/messaging/frontend-only-service-connection-provider.d.ts.map +1 -1
  50. package/lib/browser-only/messaging/frontend-only-service-connection-provider.js +8 -2
  51. package/lib/browser-only/messaging/frontend-only-service-connection-provider.js.map +1 -1
  52. package/lib/common/command.d.ts +2 -0
  53. package/lib/common/command.d.ts.map +1 -1
  54. package/lib/common/command.js +10 -4
  55. package/lib/common/command.js.map +1 -1
  56. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  57. package/lib/electron-main/electron-main-application.js +4 -2
  58. package/lib/electron-main/electron-main-application.js.map +1 -1
  59. package/lib/electron-node/request/electron-backend-request-service.d.ts +2 -0
  60. package/lib/electron-node/request/electron-backend-request-service.d.ts.map +1 -1
  61. package/lib/electron-node/request/electron-backend-request-service.js +7 -1
  62. package/lib/electron-node/request/electron-backend-request-service.js.map +1 -1
  63. package/lib/electron-node/token/electron-token-backend-contribution.d.ts +2 -0
  64. package/lib/electron-node/token/electron-token-backend-contribution.d.ts.map +1 -1
  65. package/lib/electron-node/token/electron-token-backend-contribution.js +7 -1
  66. package/lib/electron-node/token/electron-token-backend-contribution.js.map +1 -1
  67. package/lib/electron-node/token/electron-token-validator.d.ts +2 -0
  68. package/lib/electron-node/token/electron-token-validator.d.ts.map +1 -1
  69. package/lib/electron-node/token/electron-token-validator.js +7 -1
  70. package/lib/electron-node/token/electron-token-validator.js.map +1 -1
  71. package/lib/node/backend-application.d.ts +2 -0
  72. package/lib/node/backend-application.d.ts.map +1 -1
  73. package/lib/node/backend-application.js +17 -11
  74. package/lib/node/backend-application.js.map +1 -1
  75. package/lib/node/backend-application.spec.js +3 -2
  76. package/lib/node/backend-application.spec.js.map +1 -1
  77. package/lib/node/messaging/default-messaging-service.d.ts +2 -0
  78. package/lib/node/messaging/default-messaging-service.d.ts.map +1 -1
  79. package/lib/node/messaging/default-messaging-service.js +8 -2
  80. package/lib/node/messaging/default-messaging-service.js.map +1 -1
  81. package/lib/node/messaging/test/default-messaging-service.spec.js +2 -0
  82. package/lib/node/messaging/test/default-messaging-service.spec.js.map +1 -1
  83. package/lib/node/messaging/websocket-endpoint.d.ts +2 -0
  84. package/lib/node/messaging/websocket-endpoint.d.ts.map +1 -1
  85. package/lib/node/messaging/websocket-endpoint.js +7 -1
  86. package/lib/node/messaging/websocket-endpoint.js.map +1 -1
  87. package/lib/node/process-utils.d.ts +2 -0
  88. package/lib/node/process-utils.d.ts.map +1 -1
  89. package/lib/node/process-utils.js +8 -2
  90. package/lib/node/process-utils.js.map +1 -1
  91. package/lib/node/process-utils.spec.js +11 -9
  92. package/lib/node/process-utils.spec.js.map +1 -1
  93. package/package.json +4 -4
  94. package/src/browser/authentication-service.ts +6 -3
  95. package/src/browser/frontend-application.ts +13 -9
  96. package/src/browser/json-schema-store.ts +6 -2
  97. package/src/browser/keybinding.ts +2 -2
  98. package/src/browser/preferences/frontend-config-preference-contributions.ts +7 -2
  99. package/src/browser/preferences/preference-schema-provider.spec.ts +5 -0
  100. package/src/browser/preferences/preference-validation-service.spec.ts +3 -1
  101. package/src/browser/preferences/preference-validation-service.ts +9 -6
  102. package/src/browser/secondary-window-handler.ts +11 -7
  103. package/src/browser/shell/application-shell.ts +8 -4
  104. package/src/browser/tree/tree-container.spec.ts +6 -0
  105. package/src/browser/tree/tree.ts +6 -2
  106. package/src/browser/window/default-window-service.spec.ts +3 -1
  107. package/src/browser/window/default-window-service.ts +9 -6
  108. package/src/browser-only/messaging/frontend-only-service-connection-provider.ts +8 -3
  109. package/src/common/command.ts +8 -4
  110. package/src/electron-main/electron-main-application.ts +4 -2
  111. package/src/electron-node/request/electron-backend-request-service.ts +6 -2
  112. package/src/electron-node/token/electron-token-backend-contribution.ts +6 -2
  113. package/src/electron-node/token/electron-token-validator.ts +6 -2
  114. package/src/node/backend-application.spec.ts +3 -3
  115. package/src/node/backend-application.ts +15 -11
  116. package/src/node/messaging/default-messaging-service.ts +6 -2
  117. package/src/node/messaging/test/default-messaging-service.spec.ts +3 -1
  118. package/src/node/messaging/websocket-endpoint.ts +6 -2
  119. package/src/node/process-utils.spec.ts +12 -9
  120. package/src/node/process-utils.ts +7 -3
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { inject, injectable, named } from 'inversify';
18
- import { Event, Emitter } from '../../common';
18
+ import { Event, Emitter, ILogger } from '../../common';
19
19
  import { CorePreferences } from '../../common/core-preferences';
20
20
  import { ContributionProvider } from '../../common/contribution-provider';
21
21
  import { FrontendApplicationContribution, OnWillStopAction } from '../frontend-application-contribution';
@@ -43,6 +43,9 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
43
43
  @named(FrontendApplicationContribution)
44
44
  protected readonly contributions: ContributionProvider<FrontendApplicationContribution>;
45
45
 
46
+ @inject(ILogger) @named('core:DefaultWindowService')
47
+ protected readonly logger: ILogger;
48
+
46
49
  onStart(app: FrontendApplication): void {
47
50
  this.frontendApplication = app;
48
51
  this.registerUnloadListeners();
@@ -114,7 +117,7 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
114
117
  return true;
115
118
  }
116
119
  const preparedValues = await Promise.all(vetoes.map(e => e.prepare?.(stopReason)));
117
- console.debug('Shutdown prevented by', vetoes.map(({ reason }) => reason).join(', '));
120
+ this.logger.debug('Shutdown prevented by', vetoes.map(({ reason }) => reason).join(', '));
118
121
  for (let i = 0; i < vetoes.length; i++) {
119
122
  try {
120
123
  const result = await vetoes[i].action(preparedValues[i], stopReason);
@@ -122,10 +125,10 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
122
125
  return false;
123
126
  }
124
127
  } catch (e) {
125
- console.error(e);
128
+ this.logger.error(e);
126
129
  }
127
130
  }
128
- console.debug('OnWillStop actions resolved; allowing shutdown');
131
+ this.logger.debug('OnWillStop actions resolved; allowing shutdown');
129
132
  this.allowVetoes = false;
130
133
  return true;
131
134
  }
@@ -145,10 +148,10 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
145
148
  const vetoes = this.collectContributionUnloadVetoes();
146
149
  if (vetoes.length) {
147
150
  // In the browser, we don't call the functions because this has to finish in a single tick, so we treat any desired action as a veto.
148
- console.debug('Shutdown prevented by', vetoes.map(({ reason }) => reason).join(', '));
151
+ this.logger.debug('Shutdown prevented by', vetoes.map(({ reason }) => reason).join(', '));
149
152
  return this.preventUnload(event);
150
153
  }
151
- console.debug('Shutdown will proceed.');
154
+ this.logger.debug('Shutdown will proceed.');
152
155
  }
153
156
 
154
157
  /**
@@ -14,8 +14,9 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
  import { Event, RpcProxy, Channel, RpcProxyFactory, Emitter } from '../../common';
17
- import { injectable } from 'inversify';
17
+ import { injectable, inject, named } from 'inversify';
18
18
  import { ServiceConnectionProvider } from '../../browser/messaging/service-connection-provider';
19
+ import { ILogger } from '../../common/logger';
19
20
  import { ConnectionSource } from '../../browser/messaging/connection-source';
20
21
 
21
22
  @injectable()
@@ -25,15 +26,19 @@ export class FrontendOnlyConnectionSource implements ConnectionSource {
25
26
 
26
27
  @injectable()
27
28
  export class FrontendOnlyServiceConnectionProvider extends ServiceConnectionProvider {
29
+
30
+ @inject(ILogger) @named('core:FrontendOnlyServiceConnectionProvider')
31
+ protected readonly logger: ILogger;
32
+
28
33
  onSocketDidOpen = Event.None;
29
34
  onSocketDidClose = Event.None;
30
35
  onIncomingMessageActivity = Event.None;
31
36
  override createProxy<T extends object>(path: unknown, target?: unknown): RpcProxy<T> {
32
- console.debug(`[Frontend-Only Fallback] Created proxy connection for ${path}`);
37
+ this.logger.debug(`[Frontend-Only Fallback] Created proxy connection for ${path}`);
33
38
  const factory = target instanceof RpcProxyFactory ? target : new RpcProxyFactory<T>(target);
34
39
  return factory.createProxy();
35
40
  }
36
41
  override listen(path: string, handler: ServiceConnectionProvider.ConnectionHandler, reconnect: boolean): void {
37
- console.debug('[Frontend-Only Fallback] Listen to websocket connection requested');
42
+ this.logger.debug('[Frontend-Only Fallback] Listen to websocket connection requested');
38
43
  }
39
44
  }
@@ -21,6 +21,7 @@ import { ContributionProvider } from './contribution-provider';
21
21
  import { nls } from './nls';
22
22
  import debounce = require('p-debounce');
23
23
  import { isObject } from './types';
24
+ import { ILogger } from './logger';
24
25
 
25
26
  /**
26
27
  * A command is a unique identifier of a function
@@ -190,6 +191,9 @@ export interface CommandService {
190
191
  @injectable()
191
192
  export class CommandRegistry implements CommandService {
192
193
 
194
+ @inject(ILogger) @named('core:CommandRegistry')
195
+ protected readonly logger: ILogger;
196
+
193
197
  protected readonly _commands: { [id: string]: Command } = {};
194
198
  protected readonly _handlers: { [id: string]: CommandHandler[] } = {};
195
199
 
@@ -232,7 +236,7 @@ export class CommandRegistry implements CommandService {
232
236
  */
233
237
  registerCommand(command: Command, handler?: CommandHandler): Disposable {
234
238
  if (this._commands[command.id]) {
235
- console.warn(`A command ${command.id} is already registered.`);
239
+ this.logger.warn(`A command ${command.id} is already registered.`);
236
240
  return Disposable.NULL;
237
241
  }
238
242
  const toDispose = new DisposableCollection(this.doRegisterCommand(command));
@@ -363,7 +367,7 @@ export class CommandRegistry implements CommandService {
363
367
  return handler;
364
368
  }
365
369
  } catch (error) {
366
- console.error(error);
370
+ this.logger.error(error);
367
371
  }
368
372
  }
369
373
  }
@@ -383,7 +387,7 @@ export class CommandRegistry implements CommandService {
383
387
  return handler;
384
388
  }
385
389
  } catch (error) {
386
- console.error(error);
390
+ this.logger.error(error);
387
391
  }
388
392
  }
389
393
  }
@@ -403,7 +407,7 @@ export class CommandRegistry implements CommandService {
403
407
  return handler;
404
408
  }
405
409
  } catch (error) {
406
- console.error(error);
410
+ this.logger.error(error);
407
411
  }
408
412
  }
409
413
  }
@@ -394,6 +394,8 @@ export class ElectronMainApplication {
394
394
  const cancelTokenSource = new CancellationTokenSource();
395
395
  const minTime = timeout(splashScreenOptions.minDuration ?? 0, cancelTokenSource.token);
396
396
  const maxTime = timeout(splashScreenOptions.maxDuration ?? 30000, cancelTokenSource.token);
397
+ // Swallow rejections that occur when the cancellation token is cancelled after one of the timers wins.
398
+ const ignoreCancellation = () => { /* timer was cancelled, intentionally ignored */ };
397
399
 
398
400
  const showWindowAndCloseSplashScreen = () => {
399
401
  cancelTokenSource.cancel();
@@ -404,10 +406,10 @@ export class ElectronMainApplication {
404
406
  };
405
407
  TheiaRendererAPI.onApplicationStateChanged(mainWindow.webContents, state => {
406
408
  if (state === 'ready') {
407
- minTime.then(() => showWindowAndCloseSplashScreen());
409
+ minTime.then(() => showWindowAndCloseSplashScreen(), ignoreCancellation);
408
410
  }
409
411
  });
410
- maxTime.then(() => showWindowAndCloseSplashScreen());
412
+ maxTime.then(() => showWindowAndCloseSplashScreen(), ignoreCancellation);
411
413
  return splashScreenWindow;
412
414
  }
413
415
 
@@ -14,15 +14,19 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
 
17
- import { decorate, injectable } from 'inversify';
17
+ import { decorate, injectable, inject, named } from 'inversify';
18
18
  import { NodeRequestOptions, NodeRequestService } from '@theia/request/lib/node-request-service';
19
19
  import { ElectronSecurityToken } from '../../electron-common/electron-token';
20
+ import { ILogger } from '../../common';
20
21
 
21
22
  decorate(injectable(), NodeRequestService);
22
23
 
23
24
  @injectable()
24
25
  export class ElectronBackendRequestService extends NodeRequestService {
25
26
 
27
+ @inject(ILogger) @named('core:ElectronBackendRequestService')
28
+ protected readonly logger: ILogger;
29
+
26
30
  override async getProxyUrl(url: string): Promise<string | undefined> {
27
31
  if (this.proxyUrl) {
28
32
  return this.proxyUrl;
@@ -34,7 +38,7 @@ export class ElectronBackendRequestService extends NodeRequestService {
34
38
  return this.buildProxyUrl(url, proxyHost);
35
39
  }
36
40
  } catch (e) {
37
- console.error('Could not resolve electron proxy.', e);
41
+ this.logger.error('Could not resolve electron proxy.', e);
38
42
  }
39
43
  return super.getProxyUrl(url);
40
44
  }
@@ -15,9 +15,10 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import express = require('express');
18
- import { injectable, inject } from 'inversify';
18
+ import { injectable, inject, named } from 'inversify';
19
19
  import { BackendApplicationContribution } from '../../node';
20
20
  import { ElectronTokenValidator } from './electron-token-validator';
21
+ import { ILogger } from '../../common/logger';
21
22
 
22
23
  /**
23
24
  * This component contributes an Express middleware that will refuse all
@@ -26,6 +27,9 @@ import { ElectronTokenValidator } from './electron-token-validator';
26
27
  @injectable()
27
28
  export class ElectronTokenBackendContribution implements BackendApplicationContribution {
28
29
 
30
+ @inject(ILogger) @named('core:ElectronTokenBackendContribution')
31
+ protected readonly logger: ILogger;
32
+
29
33
  @inject(ElectronTokenValidator)
30
34
  protected readonly tokenValidator: ElectronTokenValidator;
31
35
 
@@ -40,7 +44,7 @@ export class ElectronTokenBackendContribution implements BackendApplicationContr
40
44
  if (this.tokenValidator.allowRequest(req)) {
41
45
  next();
42
46
  } else {
43
- console.error(`refused an http request: ${req.connection.remoteAddress}`);
47
+ this.logger.error(`refused an http request: ${req.connection.remoteAddress}`);
44
48
  res.sendStatus(403);
45
49
  }
46
50
  }
@@ -17,10 +17,11 @@
17
17
  import * as http from 'http';
18
18
  import * as cookie from 'cookie';
19
19
  import * as crypto from 'crypto';
20
- import { injectable, postConstruct } from 'inversify';
20
+ import { injectable, postConstruct, inject, named } from 'inversify';
21
21
  import { isObject, isString, MaybePromise } from '../../common';
22
22
  import { ElectronSecurityToken } from '../../electron-common/electron-token';
23
23
  import { WsRequestValidatorContribution } from '../../node/ws-request-validators';
24
+ import { ILogger } from '../../common/logger';
24
25
 
25
26
  /**
26
27
  * On Electron, we want to make sure that only Electron's browser-windows access the backend services.
@@ -28,6 +29,9 @@ import { WsRequestValidatorContribution } from '../../node/ws-request-validators
28
29
  @injectable()
29
30
  export class ElectronTokenValidator implements WsRequestValidatorContribution {
30
31
 
32
+ @inject(ILogger) @named('core:ElectronTokenValidator')
33
+ protected readonly logger: ILogger;
34
+
31
35
  protected electronSecurityToken?: ElectronSecurityToken;
32
36
 
33
37
  @postConstruct()
@@ -70,7 +74,7 @@ export class ElectronTokenValidator implements WsRequestValidatorContribution {
70
74
  const expected = Buffer.from(this.electronSecurityToken!.value, 'utf8');
71
75
  return received.byteLength === expected.byteLength && crypto.timingSafeEqual(received, expected);
72
76
  } catch (error) {
73
- console.error(error);
77
+ this.logger.error(error);
74
78
  }
75
79
  }
76
80
  return false;
@@ -19,7 +19,6 @@ import * as sinon from 'sinon';
19
19
  import { Container, ContainerModule, injectable, preDestroy } from 'inversify';
20
20
  import { bindContributionProvider, ILogger, Stopwatch } from '../common';
21
21
  import { Deferred } from '../common/promise-util';
22
- import { MockLogger } from '../common/test/mock-logger';
23
22
  import { NodeStopwatch } from './performance/node-stopwatch';
24
23
  import { ProcessUtils } from './process-utils';
25
24
  import {
@@ -29,6 +28,7 @@ import {
29
28
  RootContainer
30
29
  } from './backend-application';
31
30
  import { CliContribution } from './cli';
31
+ import { MockLogger } from '../common/test/mock-logger';
32
32
 
33
33
  /**
34
34
  * Test subclass that exposes the protected `gracefulShutdown` for direct testing.
@@ -82,7 +82,6 @@ describe('BackendApplication', () => {
82
82
  const container = new Container();
83
83
 
84
84
  container.bind(RootContainer).toConstantValue(container);
85
-
86
85
  container.bind(ILogger).to(MockLogger).inSingletonScope();
87
86
  container.bind(Stopwatch).to(NodeStopwatch).inSingletonScope();
88
87
  container.bind(ProcessUtils).toSelf().inSingletonScope();
@@ -242,7 +241,8 @@ describe('BackendApplication', () => {
242
241
  container.bind(BackendApplicationContribution).toConstantValue({
243
242
  onStop: () => { secondRan = true; }
244
243
  });
245
- const errorStub = sandbox.stub(console, 'error');
244
+ const mockLogger = container.get(ILogger) as ILogger;
245
+ const errorStub = sandbox.stub(mockLogger, 'error');
246
246
 
247
247
  const app = container.get(TestBackendApplication);
248
248
  await app.invokeGracefulShutdown();
@@ -28,6 +28,7 @@ import { Deferred, timeoutReject } from '../common/promise-util';
28
28
  import { environment } from '../common/index';
29
29
  import { AddressInfo } from 'net';
30
30
  import { ProcessUtils } from './process-utils';
31
+ import { ILogger } from '../common/logger';
31
32
 
32
33
  /**
33
34
  * The path to the application project directory. This is the directory where the application code is located.
@@ -180,6 +181,9 @@ export class BackendApplication {
180
181
  @inject(Stopwatch)
181
182
  protected readonly stopwatch: Stopwatch;
182
183
 
184
+ @inject(ILogger) @named('core:BackendApplication')
185
+ protected readonly logger: ILogger;
186
+
183
187
  @inject(RootContainer)
184
188
  protected readonly rootContainer: interfaces.Container;
185
189
 
@@ -201,7 +205,7 @@ export class BackendApplication {
201
205
  // Workaround for Electron not installing a handler to ignore SIGPIPE error
202
206
  // (https://github.com/electron/electron/issues/13254)
203
207
  process.on('SIGPIPE', () => {
204
- console.error(new Error('Unexpected SIGPIPE'));
208
+ this.logger.error(new Error('Unexpected SIGPIPE'));
205
209
  });
206
210
 
207
211
  // Handles normal process termination.
@@ -221,7 +225,7 @@ export class BackendApplication {
221
225
  await this.measureContribution(contribution, 'initialize',
222
226
  () => contribution.initialize!());
223
227
  } catch (error) {
224
- console.error('Could not initialize contribution', error);
228
+ this.logger.error('Could not initialize contribution', error);
225
229
  }
226
230
  }
227
231
  }));
@@ -258,11 +262,11 @@ export class BackendApplication {
258
262
  await this.measureContribution(contribution, 'configure',
259
263
  () => contribution.configure!(this.app));
260
264
  } catch (error) {
261
- console.error('Could not configure contribution', error);
265
+ this.logger.error('Could not configure contribution', error);
262
266
  }
263
267
  }
264
268
  }));
265
- console.info('configured all backend app contributions');
269
+ this.logger.info('configured all backend app contributions');
266
270
  }
267
271
 
268
272
  use(...handlers: express.Handler[]): void {
@@ -297,14 +301,14 @@ export class BackendApplication {
297
301
  try {
298
302
  key = await fs.readFile(this.cliParams.certkey as string);
299
303
  } catch (err) {
300
- console.error("Can't read certificate key");
304
+ this.logger.error("Can't read certificate key");
301
305
  throw err;
302
306
  }
303
307
 
304
308
  try {
305
309
  cert = await fs.readFile(this.cliParams.cert as string);
306
310
  } catch (err) {
307
- console.error("Can't read certificate");
311
+ this.logger.error("Can't read certificate");
308
312
  throw err;
309
313
  }
310
314
  server = https.createServer({ key, cert }, this.app);
@@ -323,7 +327,7 @@ export class BackendApplication {
323
327
  // address should be defined at this point
324
328
  const address = server.address()!;
325
329
  const url = typeof address === 'string' ? address : this.getHttpUrl(address, this.cliParams.ssl);
326
- console.info(`Theia app listening on ${url}.`);
330
+ this.logger.info(`Theia app listening on ${url}.`);
327
331
  deferred.resolve(server);
328
332
  });
329
333
 
@@ -336,7 +340,7 @@ export class BackendApplication {
336
340
  await this.measureContribution(contribution, 'onStart',
337
341
  () => contribution.onStart!(server));
338
342
  } catch (error) {
339
- console.error('Could not start contribution', error);
343
+ this.logger.error('Could not start contribution', error);
340
344
  }
341
345
  }
342
346
  }
@@ -415,7 +419,7 @@ export class BackendApplication {
415
419
  try {
416
420
  await contrib.onStop(this.app);
417
421
  } catch (error) {
418
- console.error('Could not stop contribution', error);
422
+ this.logger.error('Could not stop contribution', error);
419
423
  }
420
424
  }
421
425
  }));
@@ -466,9 +470,9 @@ export class BackendApplication {
466
470
 
467
471
  protected handleUncaughtError(error: Error): void {
468
472
  if (error) {
469
- console.error('Uncaught Exception: ', error.toString());
473
+ this.logger.error('Uncaught Exception: ', error.toString());
470
474
  if (error.stack) {
471
- console.error(error.stack);
475
+ this.logger.error(error.stack);
472
476
  }
473
477
  }
474
478
  }
@@ -22,6 +22,7 @@ import Route = require('route-parser');
22
22
  import { Channel, ChannelMultiplexer } from '../../common/message-rpc/channel';
23
23
  import { FrontendConnectionService } from './frontend-connection-service';
24
24
  import { BackendApplicationContribution } from '../backend-application';
25
+ import { ILogger } from '../../common/logger';
25
26
 
26
27
  export const MessagingContainer = Symbol('MessagingContainer');
27
28
  export const MainChannel = Symbol('MainChannel');
@@ -37,6 +38,9 @@ export class DefaultMessagingService implements MessagingService, BackendApplica
37
38
  @inject(ContributionProvider) @named(ConnectionContainerModule)
38
39
  protected readonly connectionModules: ContributionProvider<interfaces.ContainerModule>;
39
40
 
41
+ @inject(ILogger) @named('core:DefaultMessagingService')
42
+ protected readonly logger: ILogger;
43
+
40
44
  @inject(ContributionProvider) @named(MessagingService.Contribution)
41
45
  protected readonly contributions: ContributionProvider<MessagingService.Contribution>;
42
46
 
@@ -62,8 +66,8 @@ export class DefaultMessagingService implements MessagingService, BackendApplica
62
66
  const channelHandlers = this.getConnectionChannelHandlers(channel);
63
67
  multiplexer.onDidOpenChannel(event => {
64
68
  if (channelHandlers.route(event.id, event.channel)) {
65
- console.debug(`Opening channel for service path '${event.id}'.`);
66
- event.channel.onClose(() => console.info(`Closing channel on service path '${event.id}'.`));
69
+ this.logger.debug(`Opening channel for service path '${event.id}'.`);
70
+ event.channel.onClose(() => this.logger.info(`Closing channel on service path '${event.id}'.`));
67
71
  }
68
72
  });
69
73
  }
@@ -16,13 +16,14 @@
16
16
 
17
17
  import { expect } from 'chai';
18
18
  import { Container, injectable, preDestroy } from 'inversify';
19
- import { ConnectionHandler, bindContributionProvider, servicesPath } from '../../../common';
19
+ import { ConnectionHandler, bindContributionProvider, servicesPath, ILogger } from '../../../common';
20
20
  import { BasicChannel, Channel } from '../../../common/message-rpc/channel';
21
21
  import { Uint8ArrayWriteBuffer } from '../../../common/message-rpc/uint8-array-message-buffer';
22
22
  import { ConnectionContainerModule } from '../connection-container-module';
23
23
  import { DefaultMessagingService, MessagingContainer } from '../default-messaging-service';
24
24
  import { FrontendConnectionService } from '../frontend-connection-service';
25
25
  import { MessagingService } from '../messaging-service';
26
+ import { MockLogger } from '../../../common/test/mock-logger';
26
27
 
27
28
  describe('DefaultMessagingService', () => {
28
29
 
@@ -63,6 +64,7 @@ describe('DefaultMessagingService', () => {
63
64
  }
64
65
  };
65
66
  container.bind(FrontendConnectionService).toConstantValue(frontendConnectionService);
67
+ container.bind(ILogger).to(MockLogger).inSingletonScope();
66
68
 
67
69
  const messagingService = container.get(DefaultMessagingService);
68
70
  messagingService.initialize();
@@ -16,12 +16,13 @@
16
16
  import { MessagingService } from './messaging-service';
17
17
  import * as http from 'http';
18
18
  import * as https from 'https';
19
- import { inject, injectable } from 'inversify';
19
+ import { inject, injectable, named } from 'inversify';
20
20
  import { Server, Socket } from 'socket.io';
21
21
  import { WsRequestValidator } from '../ws-request-validators';
22
22
  import { MessagingListener } from './messaging-listeners';
23
23
  import { ConnectionHandlers } from './default-messaging-service';
24
24
  import { BackendApplicationContribution } from '../backend-application';
25
+ import { ILogger } from '../../common/logger';
25
26
 
26
27
  @injectable()
27
28
  export class WebsocketEndpoint implements BackendApplicationContribution {
@@ -31,6 +32,9 @@ export class WebsocketEndpoint implements BackendApplicationContribution {
31
32
  @inject(MessagingListener)
32
33
  protected readonly messagingListener: MessagingListener;
33
34
 
35
+ @inject(ILogger) @named('core:WebsocketEndpoint')
36
+ protected readonly logger: ILogger;
37
+
34
38
  protected checkAliveTimeout = 30000; // 30 seconds
35
39
  protected maxHttpBufferSize = 1e8; // 100 MB
36
40
 
@@ -72,7 +76,7 @@ export class WebsocketEndpoint implements BackendApplicationContribution {
72
76
  protected async handleConnection(socket: Socket): Promise<void> {
73
77
  const pathname = socket.nsp.name;
74
78
  if (pathname && !this.wsHandlers.route(pathname, socket)) {
75
- console.error('Cannot find a ws handler for the path: ' + pathname);
79
+ this.logger.error('Cannot find a ws handler for the path: ' + pathname);
76
80
  }
77
81
  }
78
82
  }
@@ -15,8 +15,11 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { expect } from 'chai';
18
+ import * as sinon from 'sinon';
18
19
  import { Container } from 'inversify';
19
20
  import { ProcessUtils } from './process-utils';
21
+ import { ILogger } from '../common';
22
+ import { MockLogger } from '../common/test/mock-logger';
20
23
 
21
24
  /** PPID, PID */
22
25
  const mockPsOutput = `\
@@ -36,6 +39,8 @@ describe('ProcessUtils', () => {
36
39
  beforeEach(() => {
37
40
  const container = new Container();
38
41
  container.bind(ProcessUtils).toSelf().inSingletonScope();
42
+ container.bind(ILogger).to(MockLogger).inSingletonScope();
43
+
39
44
  coreProcessManager = container.get(ProcessUtils);
40
45
  });
41
46
 
@@ -48,8 +53,7 @@ describe('ProcessUtils', () => {
48
53
 
49
54
  describe('#unixTerminateProcessTree', () => {
50
55
  let originalKill: typeof process.kill;
51
- let originalConsoleError: typeof console.error;
52
- let loggedErrors: unknown[];
56
+ let errorStub: sinon.SinonStub;
53
57
 
54
58
  function throwingKill(code: string): typeof process.kill {
55
59
  return (() => {
@@ -61,9 +65,8 @@ describe('ProcessUtils', () => {
61
65
 
62
66
  beforeEach(() => {
63
67
  originalKill = process.kill;
64
- originalConsoleError = console.error;
65
- loggedErrors = [];
66
- console.error = (...args: unknown[]) => { loggedErrors.push(args); };
68
+ const mockLogger = (coreProcessManager as unknown as { logger: ILogger }).logger;
69
+ errorStub = sinon.stub(mockLogger, 'error');
67
70
  // One child plus the parent; report the parent as its own group leader so the `kill(-ppid)` branch runs too.
68
71
  coreProcessManager['unixGetChildrenRecursive'] = () => new Set([424242]);
69
72
  coreProcessManager['unixGetPGID'] = (pid: number) => pid;
@@ -71,26 +74,26 @@ describe('ProcessUtils', () => {
71
74
 
72
75
  afterEach(() => {
73
76
  process.kill = originalKill;
74
- console.error = originalConsoleError;
77
+ sinon.restore();
75
78
  });
76
79
 
77
80
  it('does not throw or log when processes in the tree are already gone (ESRCH)', () => {
78
81
  process.kill = throwingKill('ESRCH');
79
82
  expect(() => coreProcessManager['unixTerminateProcessTree'](424243)).to.not.throw();
80
- expect(loggedErrors).to.be.empty;
83
+ expect(errorStub.called).to.be.false;
81
84
  });
82
85
 
83
86
  it('logs unexpected kill errors (e.g. EPERM) without throwing', () => {
84
87
  process.kill = throwingKill('EPERM');
85
88
  expect(() => coreProcessManager['unixTerminateProcessTree'](424243)).to.not.throw();
86
- expect(loggedErrors).to.not.be.empty;
89
+ expect(errorStub.called).to.be.true;
87
90
  });
88
91
 
89
92
  it('does not throw when a kill rejects with a value that has no code (e.g. undefined)', () => {
90
93
  const thrown: unknown = undefined;
91
94
  process.kill = (() => { throw thrown; }) as typeof process.kill;
92
95
  expect(() => coreProcessManager['unixTerminateProcessTree'](424243)).to.not.throw();
93
- expect(loggedErrors).to.not.be.empty;
96
+ expect(errorStub.called).to.be.true;
94
97
  });
95
98
  });
96
99
  });
@@ -15,7 +15,8 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import * as cp from 'child_process';
18
- import { injectable } from 'inversify';
18
+ import { injectable, inject, named } from 'inversify';
19
+ import { ILogger } from '../common/logger';
19
20
 
20
21
  /**
21
22
  * `@theia/core` service with some process-related utilities.
@@ -23,6 +24,9 @@ import { injectable } from 'inversify';
23
24
  @injectable()
24
25
  export class ProcessUtils {
25
26
 
27
+ @inject(ILogger) @named('core:ProcessUtils')
28
+ protected readonly logger: ILogger;
29
+
26
30
  terminateProcessTree(ppid: number): void {
27
31
  if (process.platform === 'win32') {
28
32
  this.winTerminateProcessTree(ppid);
@@ -39,7 +43,7 @@ export class ProcessUtils {
39
43
  // taskkill may exit with a non-zero code when some child processes have already exited.
40
44
  // This is expected during shutdown — log but don't throw.
41
45
  if (result.status !== 0) {
42
- console.warn(`taskkill.exe exited with ${result.status} for PID ${ppid}. Output:\n${JSON.stringify(result.output)}`);
46
+ this.logger.warn(`taskkill.exe exited with ${result.status} for PID ${ppid}. Output:\n${JSON.stringify(result.output)}`);
43
47
  }
44
48
  }
45
49
 
@@ -66,7 +70,7 @@ export class ProcessUtils {
66
70
  // ESRCH means the process is already gone, which is the goal here. Log
67
71
  // anything else but keep going so the rest of the tree is still killed.
68
72
  if ((error as NodeJS.ErrnoException | undefined)?.code !== 'ESRCH') {
69
- console.error(`[${pid}] failed to kill`, error);
73
+ this.logger.error(`[${pid}] failed to kill`, error);
70
74
  }
71
75
  }
72
76
  }