@eclipse-glsp/server 2.6.0 → 2.7.0-next.7

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 (87) hide show
  1. package/lib/browser/di/app-module.d.ts +1 -1
  2. package/lib/browser/di/app-module.d.ts.map +1 -1
  3. package/lib/browser/di/app-module.js +5 -1
  4. package/lib/browser/di/app-module.js.map +1 -1
  5. package/lib/browser/di/browser-action-dispatch-scope.d.ts +39 -0
  6. package/lib/browser/di/browser-action-dispatch-scope.d.ts.map +1 -0
  7. package/lib/browser/di/browser-action-dispatch-scope.js +77 -0
  8. package/lib/browser/di/browser-action-dispatch-scope.js.map +1 -0
  9. package/lib/browser/index.d.ts +2 -1
  10. package/lib/browser/index.d.ts.map +1 -1
  11. package/lib/browser/index.js +2 -1
  12. package/lib/browser/index.js.map +1 -1
  13. package/lib/common/actions/action-dispatcher.d.ts +107 -5
  14. package/lib/common/actions/action-dispatcher.d.ts.map +1 -1
  15. package/lib/common/actions/action-dispatcher.js +199 -26
  16. package/lib/common/actions/action-dispatcher.js.map +1 -1
  17. package/lib/common/actions/client-action-handler.d.ts +1 -1
  18. package/lib/common/actions/client-action-handler.js +2 -2
  19. package/lib/common/actions/client-action-handler.js.map +1 -1
  20. package/lib/common/actions/global-action-provider.js +1 -2
  21. package/lib/common/actions/global-action-provider.js.map +1 -1
  22. package/lib/common/di/service-identifiers.d.ts +1 -1
  23. package/lib/common/features/clipboard/request-clipboard-data-action-handler.d.ts +1 -1
  24. package/lib/common/features/clipboard/request-clipboard-data-action-handler.js +1 -2
  25. package/lib/common/features/clipboard/request-clipboard-data-action-handler.js.map +1 -1
  26. package/lib/common/features/layout/computed-bounds-action-handler.d.ts +1 -1
  27. package/lib/common/features/model/model-submission-handler.d.ts +1 -1
  28. package/lib/common/features/model/model-submission-handler.js +1 -1
  29. package/lib/common/features/model/request-model-action-handler.d.ts +1 -1
  30. package/lib/common/features/model/request-model-action-handler.js +1 -1
  31. package/lib/common/features/progress/progress-service.js +1 -1
  32. package/lib/common/index.d.ts +2 -1
  33. package/lib/common/index.d.ts.map +1 -1
  34. package/lib/common/index.js +2 -1
  35. package/lib/common/index.js.map +1 -1
  36. package/lib/common/protocol/glsp-server.d.ts +4 -2
  37. package/lib/common/protocol/glsp-server.d.ts.map +1 -1
  38. package/lib/common/protocol/glsp-server.js +35 -4
  39. package/lib/common/protocol/glsp-server.js.map +1 -1
  40. package/lib/common/utils/action-queue.d.ts +58 -0
  41. package/lib/common/utils/action-queue.d.ts.map +1 -0
  42. package/lib/common/utils/action-queue.js +99 -0
  43. package/lib/common/utils/action-queue.js.map +1 -0
  44. package/lib/common/utils/promise-queue.d.ts +5 -1
  45. package/lib/common/utils/promise-queue.d.ts.map +1 -1
  46. package/lib/common/utils/promise-queue.js +5 -1
  47. package/lib/common/utils/promise-queue.js.map +1 -1
  48. package/lib/node/di/app-module.d.ts +1 -1
  49. package/lib/node/di/app-module.d.ts.map +1 -1
  50. package/lib/node/di/app-module.js +2 -0
  51. package/lib/node/di/app-module.js.map +1 -1
  52. package/lib/node/di/node-action-dispatch-scope.d.ts +26 -0
  53. package/lib/node/di/node-action-dispatch-scope.d.ts.map +1 -0
  54. package/lib/node/di/node-action-dispatch-scope.js +45 -0
  55. package/lib/node/di/node-action-dispatch-scope.js.map +1 -0
  56. package/lib/node/index.d.ts +2 -1
  57. package/lib/node/index.d.ts.map +1 -1
  58. package/lib/node/index.js +2 -1
  59. package/lib/node/index.js.map +1 -1
  60. package/package.json +5 -5
  61. package/src/browser/di/app-module.ts +6 -2
  62. package/src/browser/di/browser-action-dispatch-scope.spec.ts +75 -0
  63. package/src/browser/di/browser-action-dispatch-scope.ts +67 -0
  64. package/src/browser/index.ts +2 -1
  65. package/src/common/actions/action-dispatcher.ts +292 -25
  66. package/src/common/actions/client-action-handler.ts +2 -2
  67. package/src/common/actions/global-action-provider.ts +2 -2
  68. package/src/common/command/recording-command.spec.ts +1 -2
  69. package/src/common/di/service-identifiers.ts +1 -1
  70. package/src/common/features/clipboard/request-clipboard-data-action-handler.ts +2 -2
  71. package/src/common/features/contextactions/context-actions-provider-registry.spec.ts +2 -2
  72. package/src/common/features/layout/computed-bounds-action-handler.ts +1 -1
  73. package/src/common/features/model/model-submission-handler.ts +1 -1
  74. package/src/common/features/model/request-model-action-handler.ts +1 -1
  75. package/src/common/features/progress/progress-service.ts +1 -1
  76. package/src/common/index.ts +2 -1
  77. package/src/common/protocol/glsp-server.ts +41 -2
  78. package/src/common/test/mock-util.ts +17 -3
  79. package/src/common/utils/action-queue.spec.ts +133 -0
  80. package/src/common/utils/action-queue.ts +107 -0
  81. package/src/common/utils/promise-queue.spec.ts +6 -2
  82. package/src/common/utils/promise-queue.ts +5 -1
  83. package/src/node/actions/action-dispatcher.spec.ts +656 -0
  84. package/src/node/di/app-module.ts +4 -2
  85. package/src/node/di/node-action-dispatch-scope.ts +35 -0
  86. package/src/node/index.ts +2 -1
  87. package/src/common/actions/action-dispatcher.spec.ts +0 -291
@@ -0,0 +1,35 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 EclipseSource 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
+ import { AsyncLocalStorage } from 'async_hooks';
18
+ import { injectable } from 'inversify';
19
+ import { ActionDispatchScope } from '../../common/actions/action-dispatcher';
20
+
21
+ /**
22
+ * Node.js {@link ActionDispatchScope} backed by native `AsyncLocalStorage`.
23
+ */
24
+ @injectable()
25
+ export class NodeActionDispatchScope implements ActionDispatchScope {
26
+ protected storage = new AsyncLocalStorage<boolean>();
27
+
28
+ enter<R>(callback: () => R): R {
29
+ return this.storage.run(true, callback);
30
+ }
31
+
32
+ isReentrant(): boolean {
33
+ return this.storage.getStore() === true;
34
+ }
35
+ }
package/src/node/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /********************************************************************************
2
- * Copyright (c) 2022-2024 EclipseSource and others.
2
+ * Copyright (c) 2022-2026 EclipseSource and others.
3
3
  *
4
4
  * This program and the accompanying materials are made available under the
5
5
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -15,6 +15,7 @@
15
15
  ********************************************************************************/
16
16
  export * from './abstract-json-model-storage';
17
17
  export * from './di/app-module';
18
+ export * from './di/node-action-dispatch-scope';
18
19
  export * from './di/winston-logger';
19
20
  export * from './gmodel/gmodel-storage';
20
21
  export * from './launch/cli-parser';
@@ -1,291 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2022-2023 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
- import { Action, UpdateModelAction } from '@eclipse-glsp/protocol';
17
- import { expect } from 'chai';
18
- import { Container, ContainerModule } from 'inversify';
19
- import * as sinon from 'sinon';
20
- import { ClientActionKinds, ClientId } from '../di/service-identifiers';
21
- import { ClientSessionManager } from '../session/client-session-manager';
22
- import * as mock from '../test/mock-util';
23
- import { Logger } from '../utils/logger';
24
- import { DefaultActionDispatcher } from './action-dispatcher';
25
- import { ActionHandler } from './action-handler';
26
- import { ActionHandlerRegistry } from './action-handler-registry';
27
- import { ClientActionForwarder } from './client-action-handler';
28
-
29
- function waitSync(timeInMillis: number): void {
30
- const start = Date.now();
31
- let now = start;
32
- while (now - start < timeInMillis) {
33
- now = Date.now();
34
- }
35
- }
36
-
37
- describe('test DefaultActionDispatcher', () => {
38
- const container = new Container();
39
- const clientId = 'myClientId';
40
- const actionHandlerRegistry = new ActionHandlerRegistry();
41
- let registry_get_stub: sinon.SinonStub<[string], ActionHandler[]>;
42
- const sandbox = sinon.createSandbox();
43
-
44
- container.load(
45
- new ContainerModule(bind => {
46
- bind(Logger).toConstantValue(new mock.StubLogger());
47
- bind(ClientSessionManager).toConstantValue(new mock.StubClientSessionManager());
48
- bind(ClientId).toConstantValue(clientId);
49
- bind(ActionHandlerRegistry).toConstantValue(actionHandlerRegistry);
50
- bind(ClientActionKinds).toConstantValue(['response', 'response1', 'response2']);
51
- bind(ClientActionForwarder).toConstantValue(sinon.createStubInstance(ClientActionForwarder));
52
- })
53
- );
54
- const actionDispatcher = container.resolve(DefaultActionDispatcher);
55
-
56
- beforeEach(() => {
57
- registry_get_stub = sandbox.stub(actionHandlerRegistry, 'get');
58
- });
59
-
60
- afterEach(() => {
61
- sandbox.restore();
62
- });
63
-
64
- describe('test with one-way actions (no response actions)', () => {
65
- it('dispatch- unhandled action', async () => {
66
- mock.expectToThrowAsync(() => actionDispatcher.dispatch({ kind: 'unhandled' }));
67
- });
68
-
69
- it('dispatch - one action', async () => {
70
- // Mock setup
71
- const action = 'action';
72
- const handler = new mock.StubActionHandler([action]);
73
- const getHandler = (kind: string): ActionHandler[] => (kind === action ? [handler] : []);
74
- registry_get_stub.callsFake(getHandler);
75
- const spy_handler_execute = sinon.spy(handler, 'execute');
76
- // Test execution
77
- await actionDispatcher.dispatch({ kind: action });
78
- expect(spy_handler_execute.calledOnce).true;
79
- });
80
-
81
- describe('test multi dispatch with single-handled actions', () => {
82
- // Mock Setup
83
- const action1 = 'a1';
84
- const action2 = 'a2';
85
- const action3 = 'a3';
86
-
87
- const handler1 = new mock.StubActionHandler([action1]);
88
- const handler2 = new mock.StubActionHandler([action2]);
89
- const handler3 = new mock.StubActionHandler([action3]);
90
-
91
- const spy_handler1_execute = sinon.stub(handler1, 'execute').returns([]);
92
- const spy_handler2_execute = sinon.stub(handler2, 'execute').returns([]);
93
- const spy_handler3_execute = sinon.stub(handler3, 'execute').returns([]);
94
- const handlerMockImpl = (kind: string): ActionHandler[] => {
95
- switch (kind) {
96
- case action1:
97
- return [handler1];
98
- case action2:
99
- return [handler2];
100
- case action3:
101
- return [handler3];
102
- default:
103
- return [];
104
- }
105
- };
106
-
107
- it('dispatch - multiple actions', async () => {
108
- // Mock setup
109
- registry_get_stub.callsFake(handlerMockImpl);
110
- // Test execution
111
- actionDispatcher.dispatch({ kind: action1 });
112
- actionDispatcher.dispatch({ kind: action2 });
113
- await actionDispatcher.dispatch({ kind: action3 });
114
- // Check if all handlers have been called
115
- expect(spy_handler1_execute.called).true;
116
- expect(spy_handler2_execute.called).true;
117
- expect(spy_handler3_execute.called).true;
118
- // Check if all handlers have been called in the right order
119
- sinon.assert.callOrder(spy_handler1_execute, spy_handler2_execute, spy_handler3_execute);
120
- });
121
-
122
- it('dispatchAll- multiple actions', async () => {
123
- // Mock setup
124
- registry_get_stub.callsFake(handlerMockImpl);
125
- // Test execution
126
- await actionDispatcher.dispatchAll([{ kind: action1 }, { kind: action2 }, { kind: action3 }]);
127
- // Check if all handlers have been called
128
- expect(spy_handler1_execute.calledOnce);
129
- expect(spy_handler2_execute.calledOnce);
130
- expect(spy_handler3_execute.calledOnce);
131
- // Check if all handlers have been called in the right order
132
- sinon.assert.callOrder(spy_handler1_execute, spy_handler2_execute, spy_handler3_execute);
133
- });
134
-
135
- it('dispatch - multiple actions (racing execution times)', async () => {
136
- // Mock setup
137
- registry_get_stub.callsFake(handlerMockImpl);
138
- spy_handler1_execute.callsFake((_action: Action) => {
139
- waitSync(500);
140
- return [];
141
- });
142
- spy_handler2_execute.callsFake((_action: Action) => {
143
- waitSync(200);
144
- return [];
145
- });
146
- spy_handler3_execute.callsFake((_action: Action) => {
147
- waitSync(100);
148
- return [];
149
- });
150
- // Test execution
151
- actionDispatcher.dispatch({ kind: action1 });
152
- actionDispatcher.dispatch({ kind: action2 });
153
- await actionDispatcher.dispatch({ kind: action3 });
154
- // Check if all handlers have been called
155
- expect(spy_handler1_execute.calledOnce);
156
- expect(spy_handler2_execute.calledOnce);
157
- expect(spy_handler3_execute.calledOnce);
158
- // Check if all handlers have been called in the right order
159
- sinon.assert.callOrder(spy_handler1_execute, spy_handler2_execute, spy_handler3_execute);
160
- });
161
- });
162
-
163
- it('dispatch- one action & multiple handlers', async () => {
164
- // Mock setup
165
- const action1 = 'a1';
166
-
167
- const handler1 = new mock.StubActionHandler([action1]);
168
- const handler2 = new mock.StubActionHandler([action1]);
169
-
170
- registry_get_stub.callsFake((kind: string) => (kind === action1 ? [handler1, handler2] : []));
171
- const spy_handler1_execute = sinon.spy(handler1, 'execute');
172
- const spy_handler2_execute = sinon.spy(handler2, 'execute');
173
- // Test execution
174
- await actionDispatcher.dispatch({ kind: action1 });
175
- expect(spy_handler1_execute.calledOnce);
176
- expect(spy_handler2_execute.calledOnce);
177
- sinon.assert.callOrder(spy_handler1_execute, spy_handler2_execute);
178
- });
179
- });
180
-
181
- describe('test with handler response actions ', () => {
182
- it('dispatch - one action & one handler response action', async () => {
183
- // Mock setup
184
- const request = 'request';
185
- const response = 'response';
186
-
187
- const requestHandler = new mock.StubActionHandler([request]);
188
- const responseHandler = new mock.StubActionHandler([response]);
189
-
190
- const spy_requestHandler_execute = sinon.stub(requestHandler, 'execute').returns([{ kind: response }]);
191
- const spy_responseHandler_execute = sinon.spy(responseHandler, 'execute');
192
- registry_get_stub.callsFake((kind: string) => {
193
- switch (kind) {
194
- case request:
195
- return [requestHandler];
196
- case response:
197
- return [responseHandler];
198
- default:
199
- return [];
200
- }
201
- });
202
- // Test execution
203
- await actionDispatcher.dispatch({ kind: request });
204
- // Add a delay so that the action dispatcher has time to dispatch the handler response
205
- await mock.delay(200);
206
- // Check if all handlers have been called
207
- expect(spy_requestHandler_execute.calledOnce);
208
- expect(spy_responseHandler_execute.calledOnce);
209
- });
210
-
211
- it('dispatch - multiple actions & multiple response', async () => {
212
- // Mock setup
213
- const request1 = 'request1';
214
- const request2 = 'request2';
215
- const response1 = 'response1';
216
- const response2 = 'response2';
217
-
218
- const responseHandler1 = new mock.StubActionHandler([response1]);
219
- const responseHandler2 = new mock.StubActionHandler([response2]);
220
- const requestHandler1 = new mock.StubActionHandler([request1]);
221
- const requestHandler2 = new mock.StubActionHandler([request2]);
222
-
223
- const spy_requestHandler1_execute = sinon.stub(requestHandler1, 'execute').returns([{ kind: response1 }, { kind: response2 }]);
224
- const spy_requestHandler2_execute = sinon.stub(requestHandler2, 'execute').returns([{ kind: response2 }]);
225
- const spy_responseHandler1_execute = sinon.spy(responseHandler1, 'execute');
226
- const spy_responseHandler2_execute = sinon.spy(responseHandler2, 'execute');
227
- registry_get_stub.callsFake((kind: string) => {
228
- switch (kind) {
229
- case request1:
230
- return [requestHandler1];
231
- case request2:
232
- return [requestHandler2];
233
- case response1:
234
- return [responseHandler1, responseHandler2];
235
- case response2:
236
- return [responseHandler2];
237
- default:
238
- return [];
239
- }
240
- });
241
- // Test execution
242
- actionDispatcher.dispatch({ kind: request1 });
243
- await actionDispatcher.dispatch({ kind: request2 });
244
-
245
- // Add a delay so that the action dispatcher has time to dispatch the handler response
246
- await mock.delay(100);
247
- // Check if all handlers have been called correctly
248
- expect(spy_requestHandler1_execute.calledOnce);
249
- expect(spy_requestHandler2_execute.calledOnce);
250
- expect(spy_responseHandler1_execute.calledOnce);
251
- expect(spy_responseHandler2_execute.calledThrice);
252
- // Check if all handlers have been called in the right order
253
- sinon.assert.callOrder(spy_requestHandler1_execute, spy_requestHandler2_execute);
254
- sinon.assert.callOrder(spy_responseHandler1_execute, spy_responseHandler2_execute);
255
- });
256
- });
257
-
258
- describe('test dispatch after next update', () => {
259
- it('dispatchAfterNextUpdate', async () => {
260
- // Mock setup
261
- const updateModelAction = UpdateModelAction.create({ id: 'newRoot', type: 'myType' });
262
- const intermediateAction = 'intermediate';
263
- const postUpdateAction = 'postUpdate';
264
- const handler = new mock.StubActionHandler([updateModelAction.kind, intermediateAction]);
265
- const postUpdateHandler = new mock.StubActionHandler([postUpdateAction]);
266
-
267
- const getHandler = (kind: string): ActionHandler[] => {
268
- if (kind === updateModelAction.kind || kind === intermediateAction) {
269
- return [handler];
270
- } else if (kind === postUpdateAction) {
271
- return [postUpdateHandler];
272
- }
273
-
274
- return [];
275
- };
276
- registry_get_stub.callsFake(getHandler);
277
- const spy_postUpdateHandler_execute = sinon.spy(postUpdateHandler, 'execute');
278
-
279
- // Test execution
280
- actionDispatcher.dispatchAfterNextUpdate({ kind: postUpdateAction });
281
- expect(spy_postUpdateHandler_execute.called).to.be.false;
282
- await actionDispatcher.dispatch({ kind: intermediateAction });
283
- expect(spy_postUpdateHandler_execute.called).to.be.false;
284
- await actionDispatcher.dispatch(updateModelAction);
285
- expect(spy_postUpdateHandler_execute.calledOnce);
286
- // Check that action does not get dispatched again
287
- await actionDispatcher.dispatch(updateModelAction);
288
- expect(spy_postUpdateHandler_execute.calledOnce);
289
- });
290
- });
291
- });