@theia/plugin-ext 1.33.0-next.2 → 1.33.0-next.24

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 (153) hide show
  1. package/lib/common/index.js +2 -0
  2. package/lib/common/index.js.map +1 -1
  3. package/lib/common/plugin-api-rpc-model.d.ts +78 -0
  4. package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
  5. package/lib/common/plugin-api-rpc-model.js +17 -1
  6. package/lib/common/plugin-api-rpc-model.js.map +1 -1
  7. package/lib/common/plugin-api-rpc.d.ts +20 -7
  8. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  9. package/lib/common/plugin-api-rpc.js +0 -2
  10. package/lib/common/plugin-api-rpc.js.map +1 -1
  11. package/lib/common/plugin-protocol.d.ts +4 -4
  12. package/lib/common/plugin-protocol.d.ts.map +1 -1
  13. package/lib/common/proxy-handler.d.ts +66 -0
  14. package/lib/common/proxy-handler.d.ts.map +1 -0
  15. package/lib/common/proxy-handler.js +98 -0
  16. package/lib/common/proxy-handler.js.map +1 -0
  17. package/lib/common/reference-map.d.ts +8 -0
  18. package/lib/common/reference-map.d.ts.map +1 -0
  19. package/lib/common/reference-map.js +40 -0
  20. package/lib/common/reference-map.js.map +1 -0
  21. package/lib/common/rpc-protocol.d.ts +25 -51
  22. package/lib/common/rpc-protocol.d.ts.map +1 -1
  23. package/lib/common/rpc-protocol.js +126 -323
  24. package/lib/common/rpc-protocol.js.map +1 -1
  25. package/lib/hosted/browser/hosted-plugin-watcher.d.ts +1 -1
  26. package/lib/hosted/browser/hosted-plugin-watcher.d.ts.map +1 -1
  27. package/lib/hosted/browser/hosted-plugin-watcher.js.map +1 -1
  28. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  29. package/lib/hosted/browser/hosted-plugin.js +13 -8
  30. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  31. package/lib/hosted/browser/plugin-worker.d.ts.map +1 -1
  32. package/lib/hosted/browser/plugin-worker.js +14 -9
  33. package/lib/hosted/browser/plugin-worker.js.map +1 -1
  34. package/lib/hosted/browser/worker/worker-main.d.ts +1 -1
  35. package/lib/hosted/browser/worker/worker-main.d.ts.map +1 -1
  36. package/lib/hosted/browser/worker/worker-main.js +23 -22
  37. package/lib/hosted/browser/worker/worker-main.js.map +1 -1
  38. package/lib/hosted/node/hosted-plugin-process.d.ts +5 -4
  39. package/lib/hosted/node/hosted-plugin-process.d.ts.map +1 -1
  40. package/lib/hosted/node/hosted-plugin-process.js +20 -13
  41. package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
  42. package/lib/hosted/node/hosted-plugin-protocol.d.ts +22 -0
  43. package/lib/hosted/node/hosted-plugin-protocol.d.ts.map +1 -0
  44. package/lib/hosted/node/hosted-plugin-protocol.js +37 -0
  45. package/lib/hosted/node/hosted-plugin-protocol.js.map +1 -0
  46. package/lib/hosted/node/hosted-plugin.d.ts +1 -1
  47. package/lib/hosted/node/hosted-plugin.d.ts.map +1 -1
  48. package/lib/hosted/node/hosted-plugin.js.map +1 -1
  49. package/lib/hosted/node/plugin-host.d.ts +1 -1
  50. package/lib/hosted/node/plugin-host.d.ts.map +1 -1
  51. package/lib/hosted/node/plugin-host.js +10 -21
  52. package/lib/hosted/node/plugin-host.js.map +1 -1
  53. package/lib/hosted/node/plugin-service.d.ts +1 -1
  54. package/lib/hosted/node/plugin-service.d.ts.map +1 -1
  55. package/lib/hosted/node/plugin-service.js.map +1 -1
  56. package/lib/main/browser/custom-editors/custom-editors-main.d.ts.map +1 -1
  57. package/lib/main/browser/custom-editors/custom-editors-main.js +2 -2
  58. package/lib/main/browser/custom-editors/custom-editors-main.js.map +1 -1
  59. package/lib/main/browser/file-system-main-impl.d.ts +1 -0
  60. package/lib/main/browser/file-system-main-impl.d.ts.map +1 -1
  61. package/lib/main/browser/file-system-main-impl.js +9 -2
  62. package/lib/main/browser/file-system-main-impl.js.map +1 -1
  63. package/lib/main/browser/languages-main.d.ts +1 -0
  64. package/lib/main/browser/languages-main.d.ts.map +1 -1
  65. package/lib/main/browser/languages-main.js +10 -0
  66. package/lib/main/browser/languages-main.js.map +1 -1
  67. package/lib/main/browser/main-context.d.ts.map +1 -1
  68. package/lib/main/browser/main-context.js +0 -3
  69. package/lib/main/browser/main-context.js.map +1 -1
  70. package/lib/main/browser/tasks-main.d.ts.map +1 -1
  71. package/lib/main/browser/tasks-main.js +13 -9
  72. package/lib/main/browser/tasks-main.js.map +1 -1
  73. package/lib/main/browser/terminal-main.d.ts +1 -1
  74. package/lib/main/browser/terminal-main.d.ts.map +1 -1
  75. package/lib/main/browser/terminal-main.js +2 -2
  76. package/lib/main/browser/terminal-main.js.map +1 -1
  77. package/lib/main/browser/webview/webview.d.ts +1 -0
  78. package/lib/main/browser/webview/webview.d.ts.map +1 -1
  79. package/lib/main/browser/webview/webview.js.map +1 -1
  80. package/lib/main/browser/webviews-main.d.ts.map +1 -1
  81. package/lib/main/browser/webviews-main.js +6 -6
  82. package/lib/main/browser/webviews-main.js.map +1 -1
  83. package/lib/plugin/debug/debug-ext.d.ts +2 -1
  84. package/lib/plugin/debug/debug-ext.d.ts.map +1 -1
  85. package/lib/plugin/debug/debug-ext.js +10 -1
  86. package/lib/plugin/debug/debug-ext.js.map +1 -1
  87. package/lib/plugin/debug/plugin-debug-adapter-session.d.ts +6 -5
  88. package/lib/plugin/debug/plugin-debug-adapter-session.d.ts.map +1 -1
  89. package/lib/plugin/debug/plugin-debug-adapter-session.js +18 -4
  90. package/lib/plugin/debug/plugin-debug-adapter-session.js.map +1 -1
  91. package/lib/plugin/file-system-ext-impl.d.ts +2 -0
  92. package/lib/plugin/file-system-ext-impl.d.ts.map +1 -1
  93. package/lib/plugin/file-system-ext-impl.js +22 -5
  94. package/lib/plugin/file-system-ext-impl.js.map +1 -1
  95. package/lib/plugin/languages/inline-completion.d.ts +21 -0
  96. package/lib/plugin/languages/inline-completion.d.ts.map +1 -0
  97. package/lib/plugin/languages/inline-completion.js +94 -0
  98. package/lib/plugin/languages/inline-completion.js.map +1 -0
  99. package/lib/plugin/languages.d.ts +5 -2
  100. package/lib/plugin/languages.d.ts.map +1 -1
  101. package/lib/plugin/languages.js +16 -1
  102. package/lib/plugin/languages.js.map +1 -1
  103. package/lib/plugin/plugin-context.d.ts.map +1 -1
  104. package/lib/plugin/plugin-context.js +107 -3
  105. package/lib/plugin/plugin-context.js.map +1 -1
  106. package/lib/plugin/theming.d.ts.map +1 -1
  107. package/lib/plugin/theming.js +3 -0
  108. package/lib/plugin/theming.js.map +1 -1
  109. package/lib/plugin/type-converters.d.ts.map +1 -1
  110. package/lib/plugin/type-converters.js +6 -14
  111. package/lib/plugin/type-converters.js.map +1 -1
  112. package/lib/plugin/type-converters.spec.js +5 -4
  113. package/lib/plugin/type-converters.spec.js.map +1 -1
  114. package/lib/plugin/types-impl.d.ts +149 -9
  115. package/lib/plugin/types-impl.d.ts.map +1 -1
  116. package/lib/plugin/types-impl.js +205 -32
  117. package/lib/plugin/types-impl.js.map +1 -1
  118. package/package.json +25 -25
  119. package/src/common/index.ts +4 -0
  120. package/src/common/plugin-api-rpc-model.ts +96 -0
  121. package/src/common/plugin-api-rpc.ts +25 -7
  122. package/src/common/plugin-protocol.ts +4 -4
  123. package/src/common/proxy-handler.ts +126 -0
  124. package/src/common/reference-map.ts +38 -0
  125. package/src/common/rpc-protocol.ts +128 -401
  126. package/src/hosted/browser/hosted-plugin-watcher.ts +4 -3
  127. package/src/hosted/browser/hosted-plugin.ts +17 -8
  128. package/src/hosted/browser/plugin-worker.ts +16 -10
  129. package/src/hosted/browser/worker/worker-main.ts +25 -26
  130. package/src/hosted/node/hosted-plugin-process.ts +25 -16
  131. package/src/hosted/node/hosted-plugin-protocol.ts +49 -0
  132. package/src/hosted/node/hosted-plugin.ts +1 -1
  133. package/src/hosted/node/plugin-host.ts +11 -22
  134. package/src/hosted/node/plugin-service.ts +1 -1
  135. package/src/main/browser/custom-editors/custom-editors-main.ts +2 -1
  136. package/src/main/browser/file-system-main-impl.ts +12 -3
  137. package/src/main/browser/languages-main.ts +18 -1
  138. package/src/main/browser/main-context.ts +0 -4
  139. package/src/main/browser/tasks-main.ts +13 -9
  140. package/src/main/browser/terminal-main.ts +2 -2
  141. package/src/main/browser/webview/pre/main.js +8 -1
  142. package/src/main/browser/webview/webview.ts +1 -0
  143. package/src/main/browser/webviews-main.ts +6 -3
  144. package/src/plugin/debug/debug-ext.ts +11 -2
  145. package/src/plugin/debug/plugin-debug-adapter-session.ts +17 -9
  146. package/src/plugin/file-system-ext-impl.ts +21 -5
  147. package/src/plugin/languages/inline-completion.ts +126 -0
  148. package/src/plugin/languages.ts +30 -3
  149. package/src/plugin/plugin-context.ts +142 -4
  150. package/src/plugin/theming.ts +3 -0
  151. package/src/plugin/type-converters.spec.ts +5 -4
  152. package/src/plugin/type-converters.ts +10 -12
  153. package/src/plugin/types-impl.ts +253 -27
@@ -13,8 +13,9 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
+ import { BasicChannel } from '@theia/core/lib/common/message-rpc/channel';
17
+ import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '@theia/core/lib/common/message-rpc/uint8-array-message-buffer';
16
18
  import { injectable } from '@theia/core/shared/inversify';
17
- import { Emitter } from '@theia/core/lib/common/event';
18
19
  import { RPCProtocol, RPCProtocolImpl } from '../../common/rpc-protocol';
19
20
 
20
21
  @injectable()
@@ -25,22 +26,27 @@ export class PluginWorker {
25
26
  public readonly rpc: RPCProtocol;
26
27
 
27
28
  constructor() {
28
- const emitter = new Emitter<string>();
29
-
30
29
  this.worker = new Worker(new URL('./worker/worker-main',
31
30
  // @ts-expect-error (TS1343)
32
31
  // We compile to CommonJS but `import.meta` is still available in the browser
33
32
  import.meta.url));
34
33
 
35
- this.worker.onmessage = m => emitter.fire(m.data);
36
- this.worker.onerror = e => console.error(e);
34
+ const channel = new BasicChannel(() => {
35
+ const writer = new Uint8ArrayWriteBuffer();
36
+ writer.onCommit(buffer => {
37
+ this.worker.postMessage(buffer);
38
+ });
39
+ return writer;
40
+ });
41
+
42
+ this.rpc = new RPCProtocolImpl(channel);
37
43
 
38
- this.rpc = new RPCProtocolImpl({
39
- onMessage: emitter.event,
40
- send: (m: string) => {
41
- this.worker.postMessage(m);
42
- }
44
+ // eslint-disable-next-line arrow-body-style
45
+ this.worker.onmessage = buffer => channel.onMessageEmitter.fire(() => {
46
+ return new Uint8ArrayReadBuffer(buffer.data);
43
47
  });
48
+
49
+ this.worker.onerror = e => channel.onErrorEmitter.fire(e);
44
50
  }
45
51
 
46
52
  }
@@ -13,28 +13,29 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
-
17
- import { Emitter } from '@theia/core/lib/common/event';
18
- import { RPCProtocolImpl } from '../../../common/rpc-protocol';
19
- import { PluginManagerExtImpl } from '../../../plugin/plugin-manager';
20
- import { MAIN_RPC_CONTEXT, Plugin, emptyPlugin, TerminalServiceExt } from '../../../common/plugin-api-rpc';
21
- import { createAPIFactory } from '../../../plugin/plugin-context';
22
- import { getPluginId, PluginMetadata } from '../../../common/plugin-protocol';
16
+ // eslint-disable-next-line import/no-extraneous-dependencies
17
+ import 'reflect-metadata';
18
+ import { BasicChannel } from '@theia/core/lib/common/message-rpc/channel';
19
+ import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '@theia/core/lib/common/message-rpc/uint8-array-message-buffer';
23
20
  import * as theia from '@theia/plugin';
24
- import { PreferenceRegistryExtImpl } from '../../../plugin/preference-registry';
21
+ import { emptyPlugin, MAIN_RPC_CONTEXT, Plugin, TerminalServiceExt } from '../../../common/plugin-api-rpc';
25
22
  import { ExtPluginApi } from '../../../common/plugin-ext-api-contribution';
26
- import { createDebugExtStub } from './debug-stub';
23
+ import { getPluginId, PluginMetadata } from '../../../common/plugin-protocol';
24
+ import { RPCProtocolImpl } from '../../../common/rpc-protocol';
25
+ import { ClipboardExt } from '../../../plugin/clipboard-ext';
27
26
  import { EditorsAndDocumentsExtImpl } from '../../../plugin/editors-and-documents';
28
- import { WorkspaceExtImpl } from '../../../plugin/workspace';
29
27
  import { MessageRegistryExt } from '../../../plugin/message-registry';
30
- import { WorkerEnvExtImpl } from './worker-env-ext';
31
- import { ClipboardExt } from '../../../plugin/clipboard-ext';
28
+ import { createAPIFactory } from '../../../plugin/plugin-context';
29
+ import { PluginManagerExtImpl } from '../../../plugin/plugin-manager';
32
30
  import { KeyValueStorageProxy } from '../../../plugin/plugin-storage';
31
+ import { PreferenceRegistryExtImpl } from '../../../plugin/preference-registry';
32
+ import { SecretsExtImpl } from '../../../plugin/secrets-ext';
33
+ import { TerminalServiceExtImpl } from '../../../plugin/terminal-ext';
33
34
  import { WebviewsExtImpl } from '../../../plugin/webviews';
35
+ import { WorkspaceExtImpl } from '../../../plugin/workspace';
36
+ import { createDebugExtStub } from './debug-stub';
34
37
  import { loadManifest } from './plugin-manifest-loader';
35
- import { TerminalServiceExtImpl } from '../../../plugin/terminal-ext';
36
- import { reviver } from '../../../plugin/types-impl';
37
- import { SecretsExtImpl } from '../../../plugin/secrets-ext';
38
+ import { WorkerEnvExtImpl } from './worker-env-ext';
38
39
 
39
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
41
  const ctx = self as any;
@@ -42,22 +43,20 @@ const ctx = self as any;
42
43
  const pluginsApiImpl = new Map<string, typeof theia>();
43
44
  const pluginsModulesNames = new Map<string, Plugin>();
44
45
 
45
- const emitter = new Emitter<string>();
46
- const rpc = new RPCProtocolImpl({
47
- onMessage: emitter.event,
48
- send: (m: string) => {
49
- ctx.postMessage(m);
50
- },
51
- },
52
- {
53
- reviver: reviver
46
+ const channel = new BasicChannel(() => {
47
+ const writeBuffer = new Uint8ArrayWriteBuffer();
48
+ writeBuffer.onCommit(buffer => {
49
+ ctx.postMessage(buffer);
50
+ });
51
+ return writeBuffer;
54
52
  });
55
-
56
53
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
54
  addEventListener('message', (message: any) => {
58
- emitter.fire(message.data);
55
+ channel.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(message.data));
59
56
  });
60
57
 
58
+ const rpc = new RPCProtocolImpl(channel);
59
+
61
60
  const scripts = new Set<string>();
62
61
 
63
62
  function initialize(contextPath: string, pluginMetadata: PluginMetadata): void {
@@ -14,16 +14,18 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import * as cp from 'child_process';
18
- import { injectable, inject, named } from '@theia/core/shared/inversify';
19
- import { ILogger, ConnectionErrorHandler, ContributionProvider, MessageService } from '@theia/core/lib/common';
17
+ import { ConnectionErrorHandler, ContributionProvider, ILogger, MessageService } from '@theia/core/lib/common';
18
+ import { Deferred } from '@theia/core/lib/common/promise-util';
20
19
  import { createIpcEnv } from '@theia/core/lib/node/messaging/ipc-protocol';
21
- import { HostedPluginClient, ServerPluginRunner, PluginHostEnvironmentVariable, DeployedPlugin, PLUGIN_HOST_BACKEND, PluginIdentifiers } from '../../common/plugin-protocol';
22
- import { MessageType } from '../../common/rpc-protocol';
20
+ import { inject, injectable, named } from '@theia/core/shared/inversify';
21
+ import * as cp from 'child_process';
23
22
  import { HostedPluginCliContribution } from './hosted-plugin-cli-contribution';
24
- import * as psTree from 'ps-tree';
25
- import { Deferred } from '@theia/core/lib/common/promise-util';
26
23
  import { HostedPluginLocalizationService } from './hosted-plugin-localization-service';
24
+ import { ProcessTerminatedMessage, ProcessTerminateMessage } from './hosted-plugin-protocol';
25
+ import { BinaryMessagePipe } from '@theia/core/lib/node/messaging/binary-message-pipe';
26
+ import { DeployedPlugin, HostedPluginClient, PluginHostEnvironmentVariable, PluginIdentifiers, PLUGIN_HOST_BACKEND, ServerPluginRunner } from '../../common/plugin-protocol';
27
+ import psTree = require('ps-tree');
28
+ import { Duplex } from 'stream';
27
29
 
28
30
  export interface IPCConnectionOptions {
29
31
  readonly serverName: string;
@@ -60,6 +62,7 @@ export class HostedPluginProcess implements ServerPluginRunner {
60
62
  protected readonly localizationService: HostedPluginLocalizationService;
61
63
 
62
64
  private childProcess: cp.ChildProcess | undefined;
65
+ private messagePipe?: BinaryMessagePipe;
63
66
  private client: HostedPluginClient;
64
67
 
65
68
  private terminatingPluginServer = false;
@@ -82,14 +85,14 @@ export class HostedPluginProcess implements ServerPluginRunner {
82
85
  }
83
86
 
84
87
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
- public acceptMessage(pluginHostId: string, message: string): boolean {
88
+ public acceptMessage(pluginHostId: string, message: Uint8Array): boolean {
86
89
  return pluginHostId === 'main';
87
90
  }
88
91
 
89
92
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
- public onMessage(pluginHostId: string, jsonMessage: string): void {
91
- if (this.childProcess) {
92
- this.childProcess.send(jsonMessage);
93
+ public onMessage(pluginHostId: string, message: Uint8Array): void {
94
+ if (this.messagePipe) {
95
+ this.messagePipe.send(message);
93
96
  }
94
97
  }
95
98
 
@@ -106,12 +109,12 @@ export class HostedPluginProcess implements ServerPluginRunner {
106
109
  const waitForTerminated = new Deferred<void>();
107
110
  cp.on('message', message => {
108
111
  const msg = JSON.parse(message as string);
109
- if ('type' in msg && msg.type === MessageType.Terminated) {
112
+ if (ProcessTerminatedMessage.is(msg)) {
110
113
  waitForTerminated.resolve();
111
114
  }
112
115
  });
113
116
  const stopTimeout = this.cli.pluginHostStopTimeout;
114
- cp.send(JSON.stringify({ type: MessageType.Terminate, stopTimeout }));
117
+ cp.send(JSON.stringify({ type: ProcessTerminateMessage.TYPE, stopTimeout }));
115
118
 
116
119
  const terminateTimeout = this.cli.pluginHostTerminateTimeout;
117
120
  if (terminateTimeout) {
@@ -156,9 +159,11 @@ export class HostedPluginProcess implements ServerPluginRunner {
156
159
  logger: this.logger,
157
160
  args: []
158
161
  });
159
- this.childProcess.on('message', message => {
162
+
163
+ this.messagePipe = new BinaryMessagePipe(this.childProcess.stdio[4] as Duplex);
164
+ this.messagePipe.onMessage(buffer => {
160
165
  if (this.client) {
161
- this.client.postMessage(PLUGIN_HOST_BACKEND, message as string);
166
+ this.client.postMessage(PLUGIN_HOST_BACKEND, buffer);
162
167
  }
163
168
  });
164
169
  }
@@ -184,7 +189,11 @@ export class HostedPluginProcess implements ServerPluginRunner {
184
189
  silent: true,
185
190
  env: env,
186
191
  execArgv: [],
187
- stdio: ['pipe', 'pipe', 'pipe', 'ipc']
192
+ // 5th element MUST be 'overlapped' for it to work properly on Windows.
193
+ // 'overlapped' works just like 'pipe' on non-Windows platforms.
194
+ // See: https://nodejs.org/docs/latest-v14.x/api/child_process.html#child_process_options_stdio
195
+ // Note: For some reason `@types/node` does not know about 'overlapped'.
196
+ stdio: ['pipe', 'pipe', 'pipe', 'ipc', 'overlapped' as 'pipe']
188
197
  };
189
198
  const inspectArgPrefix = `--${options.serverName}-inspect`;
190
199
  const inspectArg = process.argv.find(v => v.startsWith(inspectArgPrefix));
@@ -0,0 +1,49 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2022 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ // Custom message protocol between `HostedPluginProcess` and its `PluginHost` child process.
18
+
19
+ /**
20
+ * Sent to initiate termination of the counterpart process.
21
+ */
22
+ export interface ProcessTerminateMessage {
23
+ type: typeof ProcessTerminateMessage.TYPE,
24
+ stopTimeout?: number
25
+ }
26
+
27
+ export namespace ProcessTerminateMessage {
28
+ export const TYPE = 0;
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ export function is(object: any): object is ProcessTerminateMessage {
31
+ return typeof object === 'object' && object.type === TYPE;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Sent to inform the counter part process that the process termination has been completed.
37
+ */
38
+ export interface ProcessTerminatedMessage {
39
+ type: typeof ProcessTerminateMessage.TYPE,
40
+ }
41
+
42
+ export namespace ProcessTerminatedMessage {
43
+ export const TYPE = 1;
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ export function is(object: any): object is ProcessTerminateMessage {
46
+ return typeof object === 'object' && object.type === TYPE;
47
+ }
48
+ }
49
+
@@ -71,7 +71,7 @@ export class HostedPluginSupport {
71
71
  }
72
72
  }
73
73
 
74
- onMessage(pluginHostId: string, message: string): void {
74
+ onMessage(pluginHostId: string, message: Uint8Array): void {
75
75
  // need to perform routing
76
76
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
77
  if (this.pluginRunners.length > 0) {
@@ -13,11 +13,12 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
-
17
- import { Emitter } from '@theia/core/lib/common/event';
18
- import { RPCProtocolImpl, MessageType, ConnectionClosedError } from '../../common/rpc-protocol';
16
+ // eslint-disable-next-line import/no-extraneous-dependencies
17
+ import 'reflect-metadata';
18
+ import { ConnectionClosedError, RPCProtocolImpl } from '../../common/rpc-protocol';
19
+ import { ProcessTerminatedMessage, ProcessTerminateMessage } from './hosted-plugin-protocol';
19
20
  import { PluginHostRPC } from './plugin-host-rpc';
20
- import { reviver } from '../../plugin/types-impl';
21
+ import { IPCChannel } from '@theia/core/lib/node';
21
22
 
22
23
  console.log('PLUGIN_HOST(' + process.pid + ') starting instance');
23
24
 
@@ -74,18 +75,8 @@ process.on('rejectionHandled', (promise: Promise<any>) => {
74
75
  });
75
76
 
76
77
  let terminating = false;
77
- const emitter = new Emitter<string>();
78
- const rpc = new RPCProtocolImpl({
79
- onMessage: emitter.event,
80
- send: (m: string) => {
81
- if (process.send && !terminating) {
82
- process.send(m);
83
- }
84
- }
85
- },
86
- {
87
- reviver: reviver
88
- });
78
+ const channel = new IPCChannel();
79
+ const rpc = new RPCProtocolImpl(channel);
89
80
 
90
81
  process.on('message', async (message: string) => {
91
82
  if (terminating) {
@@ -93,10 +84,9 @@ process.on('message', async (message: string) => {
93
84
  }
94
85
  try {
95
86
  const msg = JSON.parse(message);
96
- if ('type' in msg && msg.type === MessageType.Terminate) {
87
+ if (ProcessTerminateMessage.is(msg)) {
97
88
  terminating = true;
98
- emitter.dispose();
99
- if ('stopTimeout' in msg && typeof msg.stopTimeout === 'number' && msg.stopTimeout) {
89
+ if (msg.stopTimeout) {
100
90
  await Promise.race([
101
91
  pluginHostRPC.terminate(),
102
92
  new Promise(resolve => setTimeout(resolve, msg.stopTimeout))
@@ -106,10 +96,9 @@ process.on('message', async (message: string) => {
106
96
  }
107
97
  rpc.dispose();
108
98
  if (process.send) {
109
- process.send(JSON.stringify({ type: MessageType.Terminated }));
99
+ process.send(JSON.stringify({ type: ProcessTerminatedMessage.TYPE }));
110
100
  }
111
- } else {
112
- emitter.fire(message);
101
+
113
102
  }
114
103
  } catch (e) {
115
104
  console.error(e);
@@ -164,7 +164,7 @@ export class HostedPluginServerImpl implements HostedPluginServer {
164
164
  return Promise.all(plugins.map(plugin => this.localizationService.localizePlugin(plugin)));
165
165
  }
166
166
 
167
- onMessage(pluginHostId: string, message: string): Promise<void> {
167
+ onMessage(pluginHostId: string, message: Uint8Array): Promise<void> {
168
168
  this.hostedPlugin.onMessage(pluginHostId, message);
169
169
  return Promise.resolve();
170
170
  }
@@ -223,11 +223,12 @@ export class CustomEditorsMainImpl implements CustomEditorsMain, Disposable {
223
223
  const view = await this.widgetManager.getOrCreateWidget<CustomEditorWidget>(CustomEditorWidget.FACTORY_ID, <WebviewWidgetIdentifier>{ id: panelId });
224
224
  this.webviewsMain.hookWebview(view);
225
225
  view.title.label = title;
226
- const { enableFindWidget, retainContextWhenHidden, enableScripts, localResourceRoots, ...contentOptions } = options;
226
+ const { enableFindWidget, retainContextWhenHidden, enableScripts, enableForms, localResourceRoots, ...contentOptions } = options;
227
227
  view.viewColumn = ViewColumn.One; // behaviour might be overridden later using widgetOpenerOptions (if available)
228
228
  view.options = { enableFindWidget, retainContextWhenHidden };
229
229
  view.setContentOptions({
230
230
  allowScripts: enableScripts,
231
+ allowForms: enableForms,
231
232
  localResourceRoots: localResourceRoots && localResourceRoots.map(root => root.toString()),
232
233
  ...contentOptions,
233
234
  ...view.contentOptions
@@ -27,7 +27,7 @@ import { URI } from '@theia/core/shared/vscode-uri';
27
27
  import { interfaces } from '@theia/core/shared/inversify';
28
28
  import CoreURI from '@theia/core/lib/common/uri';
29
29
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
30
- import { Disposable } from '@theia/core/lib/common/disposable';
30
+ import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
31
31
  import { Event, Emitter } from '@theia/core/lib/common/event';
32
32
  import { MAIN_RPC_CONTEXT, FileSystemMain, FileSystemExt, IFileChangeDto } from '../../common/plugin-api-rpc';
33
33
  import { RPCProtocol } from '../../common/rpc-protocol';
@@ -46,15 +46,24 @@ export class FileSystemMainImpl implements FileSystemMain, Disposable {
46
46
  private readonly _proxy: FileSystemExt;
47
47
  private readonly _fileProvider = new Map<number, RemoteFileSystemProvider>();
48
48
  private readonly _fileService: FileService;
49
+ private readonly _disposables = new DisposableCollection();
49
50
 
50
51
  constructor(rpc: RPCProtocol, container: interfaces.Container) {
51
52
  this._proxy = rpc.getProxy(MAIN_RPC_CONTEXT.FILE_SYSTEM_EXT);
52
53
  this._fileService = container.get(FileService);
54
+
55
+ for (const { scheme, capabilities } of this._fileService.listCapabilities()) {
56
+ this._proxy.$acceptProviderInfos(scheme, capabilities);
57
+ }
58
+
59
+ this._disposables.push(this._fileService.onDidChangeFileSystemProviderRegistrations(e => this._proxy.$acceptProviderInfos(e.scheme, e.provider?.capabilities)));
60
+ this._disposables.push(this._fileService.onDidChangeFileSystemProviderCapabilities(e => this._proxy.$acceptProviderInfos(e.scheme, e.provider.capabilities)));
61
+ this._disposables.push(Disposable.create(() => this._fileProvider.forEach(value => value.dispose())));
62
+ this._disposables.push(Disposable.create(() => this._fileProvider.clear()));
53
63
  }
54
64
 
55
65
  dispose(): void {
56
- this._fileProvider.forEach(value => value.dispose());
57
- this._fileProvider.clear();
66
+ this._disposables.dispose();
58
67
  }
59
68
 
60
69
  $registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void {
@@ -34,7 +34,8 @@ import {
34
34
  WorkspaceTextEditDto,
35
35
  PluginInfo,
36
36
  LanguageStatus as LanguageStatusDTO,
37
- InlayHintDto
37
+ InlayHintDto,
38
+ IdentifiableInlineCompletions
38
39
  } from '../../common/plugin-api-rpc';
39
40
  import { injectable, inject } from '@theia/core/shared/inversify';
40
41
  import {
@@ -868,6 +869,22 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
868
869
  }
869
870
  }
870
871
 
872
+ $registerInlineCompletionsSupport(handle: number, selector: SerializedDocumentFilter[]): void {
873
+ const languageSelector = this.toLanguageSelector(selector);
874
+ const provider: monaco.languages.InlineCompletionsProvider<IdentifiableInlineCompletions> = {
875
+ provideInlineCompletions: async (
876
+ model: monaco.editor.ITextModel,
877
+ position: monaco.Position,
878
+ context: monaco.languages.InlineCompletionContext,
879
+ token: CancellationToken
880
+ ): Promise<IdentifiableInlineCompletions | undefined> => this.proxy.$provideInlineCompletions(handle, model.uri, position, context, token),
881
+ freeInlineCompletions: (completions: IdentifiableInlineCompletions): void => {
882
+ this.proxy.$freeInlineCompletionsList(handle, completions.pid);
883
+ }
884
+ };
885
+ this.register(handle, (monaco.languages.registerInlineCompletionsProvider as RegistrationFunction<monaco.languages.InlineCompletionsProvider>)(languageSelector, provider));
886
+ }
887
+
871
888
  $registerQuickFixProvider(
872
889
  handle: number,
873
890
  pluginInfo: PluginInfo,
@@ -56,7 +56,6 @@ import { CustomEditorsMainImpl } from './custom-editors/custom-editors-main';
56
56
  import { SecretsMainImpl } from './secrets-main';
57
57
  import { WebviewViewsMainImpl } from './webview-views/webview-views-main';
58
58
  import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
59
- import { NotificationExtImpl } from '../../plugin/notification';
60
59
  import { UntitledResourceResolver } from '@theia/core/lib/common/resource';
61
60
  import { ThemeService } from '@theia/core/lib/browser/theming';
62
61
 
@@ -110,9 +109,6 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
110
109
  const notificationMain = new NotificationMainImpl(rpc, container);
111
110
  rpc.set(PLUGIN_RPC_CONTEXT.NOTIFICATION_MAIN, notificationMain);
112
111
 
113
- const notificationExt = new NotificationExtImpl(rpc);
114
- rpc.set(MAIN_RPC_CONTEXT.NOTIFICATION_EXT, notificationExt);
115
-
116
112
  const terminalMain = new TerminalServiceMainImpl(rpc, container);
117
113
  rpc.set(PLUGIN_RPC_CONTEXT.TERMINAL_MAIN, terminalMain);
118
114
 
@@ -26,7 +26,7 @@ import { RPCProtocol } from '../../common/rpc-protocol';
26
26
  import { Disposable, DisposableCollection } from '@theia/core/lib/common';
27
27
  import { TaskProviderRegistry, TaskResolverRegistry, TaskProvider, TaskResolver } from '@theia/task/lib/browser/task-contribution';
28
28
  import { interfaces } from '@theia/core/shared/inversify';
29
- import { TaskInfo, TaskExitedEvent, TaskConfiguration, TaskCustomization, TaskOutputPresentation, RevealKind, PanelKind } from '@theia/task/lib/common/task-protocol';
29
+ import { TaskInfo, TaskExitedEvent, TaskConfiguration, TaskOutputPresentation, RevealKind, PanelKind } from '@theia/task/lib/common/task-protocol';
30
30
  import { TaskWatcher } from '@theia/task/lib/common/task-watcher';
31
31
  import { TaskService } from '@theia/task/lib/browser/task-service';
32
32
  import { TaskDefinitionRegistry } from '@theia/task/lib/browser';
@@ -207,8 +207,11 @@ export class TasksMainImpl implements TasksMain, Disposable {
207
207
  if (presentation) {
208
208
  partialConfig.presentation = this.convertTaskPresentation(presentation);
209
209
  }
210
- if (group === 'build' || group === 'test') {
211
- partialConfig.group = group;
210
+ if (group) {
211
+ partialConfig.group = {
212
+ kind: group.kind,
213
+ isDefault: group.isDefault
214
+ };
212
215
  }
213
216
  return {
214
217
  ...common,
@@ -225,12 +228,13 @@ export class TasksMainImpl implements TasksMain, Disposable {
225
228
  if (presentation) {
226
229
  partialDto.presentation = this.convertTaskPresentation(presentation);
227
230
  }
228
- if (group) {
229
- if (TaskCustomization.isBuildTask(task)) {
230
- partialDto.group = 'build';
231
- } else if (TaskCustomization.isTestTask(task)) {
232
- partialDto.group = 'test';
233
- }
231
+ if (group === 'build' || group === 'test') {
232
+ partialDto.group = {
233
+ kind: group,
234
+ isDefault: false
235
+ };
236
+ } else if (typeof group === 'object') {
237
+ partialDto.group = group;
234
238
  }
235
239
  return {
236
240
  ...common,
@@ -260,11 +260,11 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
260
260
  }
261
261
  }
262
262
 
263
- async provideLinks(line: string, terminal: TerminalWidget, cancelationToken?: CancellationToken | undefined): Promise<TerminalLink[]> {
263
+ async provideLinks(line: string, terminal: TerminalWidget, cancellationToken?: CancellationToken | undefined): Promise<TerminalLink[]> {
264
264
  if (this.terminalLinkProviders.length < 1) {
265
265
  return [];
266
266
  }
267
- const links = await this.extProxy.$provideTerminalLinks(line, terminal.id, cancelationToken ?? CancellationToken.None);
267
+ const links = await this.extProxy.$provideTerminalLinks(line, terminal.id, cancellationToken ?? CancellationToken.None);
268
268
  return links.map(link => ({ ...link, handle: () => this.extProxy.$handleTerminalLink(link) }));
269
269
  }
270
270
 
@@ -479,7 +479,14 @@
479
479
  const newFrame = document.createElement('iframe');
480
480
  newFrame.setAttribute('id', 'pending-frame');
481
481
  newFrame.setAttribute('frameborder', '0');
482
- newFrame.setAttribute('sandbox', options.allowScripts ? 'allow-scripts allow-forms allow-same-origin allow-downloads' : 'allow-same-origin');
482
+ const sandboxOptions = ['allow-same-origin'];
483
+ if (options.allowScripts) {
484
+ sandboxOptions.push('allow-scripts', 'allow-downloads');
485
+ }
486
+ if (options.allowForms ?? options.allowScripts) {
487
+ sandboxOptions.push('allow-forms');
488
+ }
489
+ newFrame.setAttribute('sandbox', sandboxOptions.join(' '));
483
490
  if (host.fakeLoad) {
484
491
  // We should just be able to use srcdoc, but I wasn't
485
492
  // seeing the service worker applying properly.
@@ -73,6 +73,7 @@ export const enum WebviewMessageChannels {
73
73
 
74
74
  export interface WebviewContentOptions {
75
75
  readonly allowScripts?: boolean;
76
+ readonly allowForms?: boolean;
76
77
  readonly localResourceRoots?: ReadonlyArray<string>;
77
78
  readonly portMapping?: ReadonlyArray<WebviewPortMapping>;
78
79
  readonly enableCommandUris?: boolean;
@@ -67,10 +67,11 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable {
67
67
  this.hookWebview(view);
68
68
  view.viewType = viewType;
69
69
  view.title.label = title;
70
- const { enableFindWidget, retainContextWhenHidden, enableScripts, localResourceRoots, ...contentOptions } = options;
70
+ const { enableFindWidget, retainContextWhenHidden, enableScripts, enableForms, localResourceRoots, ...contentOptions } = options;
71
71
  view.options = { enableFindWidget, retainContextWhenHidden };
72
72
  view.setContentOptions({
73
73
  allowScripts: enableScripts,
74
+ allowForms: enableForms,
74
75
  localResourceRoots: localResourceRoots && localResourceRoots.map(root => root.toString()),
75
76
  ...contentOptions
76
77
  });
@@ -171,9 +172,10 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable {
171
172
 
172
173
  async $setOptions(handle: string, options: WebviewOptions): Promise<void> {
173
174
  const webview = await this.getWebview(handle);
174
- const { enableScripts, localResourceRoots, ...contentOptions } = options;
175
+ const { enableScripts, enableForms, localResourceRoots, ...contentOptions } = options;
175
176
  webview.setContentOptions({
176
177
  allowScripts: enableScripts,
178
+ allowForms: enableForms,
177
179
  localResourceRoots: localResourceRoots && localResourceRoots.map(root => root.toString()),
178
180
  ...contentOptions
179
181
  });
@@ -210,10 +212,11 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable {
210
212
  }
211
213
 
212
214
  const options = widget.options;
213
- const { allowScripts, localResourceRoots, ...contentOptions } = widget.contentOptions;
215
+ const { allowScripts, allowForms, localResourceRoots, ...contentOptions } = widget.contentOptions;
214
216
  this.updateViewState(widget);
215
217
  await this.proxy.$deserializeWebviewPanel(handle, widget.viewType, title, state, widget.viewState, {
216
218
  enableScripts: allowScripts,
219
+ enableForms: allowForms,
217
220
  localResourceRoots: localResourceRoots && localResourceRoots.map(root => URI.parse(root)),
218
221
  ...contentOptions,
219
222
  ...options
@@ -32,6 +32,7 @@ import { DebugAdapter } from '@theia/debug/lib/common/debug-model';
32
32
  import { PluginDebugAdapterCreator } from './plugin-debug-adapter-creator';
33
33
  import { NodeDebugAdapterCreator } from '../node/debug/plugin-node-debug-adapter-creator';
34
34
  import { DebugProtocol } from '@vscode/debugprotocol';
35
+ import { DebugConfiguration } from '@theia/debug/lib/common/debug-configuration';
35
36
 
36
37
  interface ConfigurationProviderRecord {
37
38
  handle: number;
@@ -171,7 +172,13 @@ export class DebugExtImpl implements DebugExt {
171
172
  }
172
173
 
173
174
  startDebugging(folder: theia.WorkspaceFolder | undefined, nameOrConfiguration: string | theia.DebugConfiguration, options: theia.DebugSessionOptions): PromiseLike<boolean> {
174
- return this.proxy.$startDebugging(folder, nameOrConfiguration, options);
175
+ return this.proxy.$startDebugging(folder, nameOrConfiguration, {
176
+ parentSessionId: options.parentSession?.id,
177
+ compact: options.compact,
178
+ consoleMode: options.consoleMode,
179
+ lifecycleManagedByParent: options.lifecycleManagedByParent,
180
+ noDebug: options.noDebug
181
+ });
175
182
  }
176
183
 
177
184
  stopDebugging(session?: theia.DebugSession): PromiseLike<void> {
@@ -313,13 +320,15 @@ export class DebugExtImpl implements DebugExt {
313
320
  return undefined;
314
321
  }
315
322
 
316
- async $createDebugSession(debugConfiguration: theia.DebugConfiguration, workspaceFolderUri: string | undefined): Promise<string> {
323
+ async $createDebugSession(debugConfiguration: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<string> {
317
324
  const sessionId = uuid.v4();
318
325
 
326
+ const parentSession = debugConfiguration.parentSessionId ? this.sessions.get(debugConfiguration.parentSessionId) : undefined;
319
327
  const theiaSession: theia.DebugSession = {
320
328
  id: sessionId,
321
329
  type: debugConfiguration.type,
322
330
  name: debugConfiguration.name,
331
+ parentSession: parentSession,
323
332
  workspaceFolder: this.toWorkspaceFolder(workspaceFolderUri),
324
333
  configuration: debugConfiguration,
325
334
  customRequest: async (command: string, args?: any) => {