@lvce-editor/shared-process 0.84.18 → 0.85.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.84.18",
3
+ "version": "0.85.1",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -19,13 +19,13 @@
19
19
  "dependencies": {
20
20
  "@lvce-editor/assert": "1.6.0",
21
21
  "@lvce-editor/auth-process": "1.6.0",
22
- "@lvce-editor/extension-host-helper-process": "0.84.18",
22
+ "@lvce-editor/extension-host-helper-process": "0.85.1",
23
23
  "@lvce-editor/ipc": "16.1.0",
24
24
  "@lvce-editor/json-rpc": "8.1.0",
25
25
  "@lvce-editor/jsonc-parser": "1.5.0",
26
26
  "@lvce-editor/pretty-error": "2.0.0",
27
- "@lvce-editor/process-explorer": "3.7.0",
28
- "@lvce-editor/rpc-registry": "9.30.0",
27
+ "@lvce-editor/process-explorer": "3.8.0",
28
+ "@lvce-editor/rpc-registry": "9.31.0",
29
29
  "@lvce-editor/verror": "1.7.0",
30
30
  "is-object": "^1.0.2",
31
31
  "xdg-basedir": "^5.1.0"
@@ -2,6 +2,6 @@ import { join } from 'path';
2
2
  import { fileURLToPath } from 'url';
3
3
  export const getBuiltinExtensionsPath = () => {
4
4
  const staticServerPath = fileURLToPath(import.meta.resolve('@lvce-editor/static-server'));
5
- const builtinExtensionsPath = join(staticServerPath, '..', '..', 'static', 'dfd5b2f', 'extensions');
5
+ const builtinExtensionsPath = join(staticServerPath, '..', '..', 'static', '6f0f9b3', 'extensions');
6
6
  return builtinExtensionsPath;
7
7
  };
@@ -3,8 +3,10 @@ import * as Assert from '../Assert/Assert.js';
3
3
  import * as HandleIncomingIpcMessagePort from '../HandleIncomingIpcMessagePort/HandleIncomingIpcMessagePort.js';
4
4
  import * as HandleIncomingIpcWebSocket from '../HandleIncomingIpcWebSocket/HandleIncomingIpcWebSocket.js';
5
5
  import * as HandleIpcModule from '../HandleIpcModule/HandleIpcModule.js';
6
+ import * as IpcId from '../IpcId/IpcId.js';
6
7
  import * as IsMessagePortMain from '../IsMessagePortMain/IsMessagePortMain.js';
7
8
  import * as IsSocket from '../IsSocket/IsSocket.js';
9
+ import * as ProcessExplorer from '../ProcessExplorer/ProcessExplorer.js';
8
10
  const strinfyHandle = (handle) => {
9
11
  if (!handle) {
10
12
  return `${handle}`;
@@ -28,5 +30,13 @@ export const handleIncomingIpc = async (ipcId, handle, message) => {
28
30
  Assert.number(ipcId);
29
31
  const module = HandleIpcModule.getModule(ipcId);
30
32
  const { target, response } = await getIpcAndResponse(module, handle, message);
31
- await ApplyIncomingIpcResponse.applyIncomingIpcResponse(target, response, ipcId);
33
+ try {
34
+ await ApplyIncomingIpcResponse.applyIncomingIpcResponse(target, response, ipcId);
35
+ }
36
+ catch (error) {
37
+ if (ipcId === IpcId.ProcessExplorer) {
38
+ ProcessExplorer.decreaseRefCount();
39
+ }
40
+ throw error;
41
+ }
32
42
  };
@@ -1,6 +1,6 @@
1
1
  export const handleIncomingIpcMessagePort = async (module, handle, message) => {
2
- const target = await module.targetMessagePort(handle, message);
3
2
  const response = module.upgradeMessagePort(handle, message);
3
+ const target = await module.targetMessagePort(handle, message);
4
4
  return {
5
5
  target,
6
6
  response,
@@ -1,6 +1,6 @@
1
1
  export const handleIncomingIpcWebSocket = async (module, handle, message) => {
2
- const target = await module.targetWebSocket(handle, message);
3
2
  const response = module.upgradeWebSocket(handle, message);
3
+ const target = await module.targetWebSocket(handle, message);
4
4
  return {
5
5
  target,
6
6
  response,
@@ -1,10 +1,10 @@
1
1
  import * as ProcessExplorer from '../ProcessExplorer/ProcessExplorer.js';
2
2
  import * as Assert from '../Assert/Assert.js';
3
3
  export const targetMessagePort = () => {
4
- return ProcessExplorer.getOrCreate();
4
+ return ProcessExplorer.acquire();
5
5
  };
6
6
  export const targetWebSocket = () => {
7
- return ProcessExplorer.getOrCreate();
7
+ return ProcessExplorer.acquire();
8
8
  };
9
9
  export const upgradeMessagePort = (port) => {
10
10
  Assert.object(port);
@@ -2,11 +2,17 @@ import * as Assert from '../Assert/Assert.js';
2
2
  import * as DestroyWebSocket from '../DestroySocket/DestroySocket.js';
3
3
  import * as HandleWebSocketModule from '../HandleWebSocketModule/HandleWebSocketModule.js';
4
4
  import * as GetTypeFromUrl from '../GetTypeFromUrl/GetTypeFromUrl.js';
5
+ import * as IsAllowedWebSocketOrigin from '../IsAllowedWebSocketOrigin/IsAllowedWebSocketOrigin.js';
6
+ import * as RejectWebSocket from '../RejectWebSocket/RejectWebSocket.js';
5
7
  import { VError } from '../VError/VError.js';
6
8
  export const handleWebSocket = async (handle, message) => {
7
9
  try {
8
10
  Assert.object(handle);
9
11
  Assert.object(message);
12
+ if (!IsAllowedWebSocketOrigin.isAllowedWebSocketOrigin(message)) {
13
+ RejectWebSocket.rejectWebSocket(handle);
14
+ return;
15
+ }
10
16
  const { url } = message;
11
17
  const type = GetTypeFromUrl.getTypeFromUrl(url);
12
18
  handle.pause();
@@ -1,5 +1,6 @@
1
1
  export const NotFound = 404;
2
2
  export const Ok = 200;
3
+ export const Forbidden = 403;
3
4
  export const ServerError = 500;
4
5
  export const NotModifed = 304;
5
6
  export const MultipleChoices = 300;
@@ -0,0 +1,43 @@
1
+ const getHeaderValue = (headers, name) => {
2
+ const lowerCaseName = name.toLowerCase();
3
+ for (const [key, value] of Object.entries(headers || {})) {
4
+ if (key.toLowerCase() === lowerCaseName) {
5
+ return value;
6
+ }
7
+ }
8
+ return '';
9
+ };
10
+ const normalizeHeaderValue = (value) => {
11
+ if (Array.isArray(value)) {
12
+ return value.join(',');
13
+ }
14
+ if (typeof value !== 'string') {
15
+ return '';
16
+ }
17
+ return value;
18
+ };
19
+ const getAllowedHosts = (headers) => {
20
+ const host = normalizeHeaderValue(getHeaderValue(headers, 'host'));
21
+ const forwardedHost = normalizeHeaderValue(getHeaderValue(headers, 'x-forwarded-host'));
22
+ const hosts = [host, ...forwardedHost.split(',')];
23
+ return hosts.map((host) => host.trim().toLowerCase()).filter(Boolean);
24
+ };
25
+ export const isAllowedWebSocketOrigin = (request) => {
26
+ const { headers } = request;
27
+ const origin = normalizeHeaderValue(getHeaderValue(headers, 'origin'));
28
+ if (!origin) {
29
+ return false;
30
+ }
31
+ try {
32
+ const url = new URL(origin);
33
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
34
+ return false;
35
+ }
36
+ const originHost = url.host.toLowerCase();
37
+ const allowedHosts = getAllowedHosts(headers);
38
+ return allowedHosts.includes(originHost);
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ };
@@ -95,6 +95,8 @@ export const load = (moduleId) => {
95
95
  return import('../Preferences/Preferences.ipc.js');
96
96
  case ModuleId.Process:
97
97
  return import('../Process/Process.ipc.js');
98
+ case ModuleId.ProcessExplorer:
99
+ return import('../ProcessExplorer/ProcessExplorer.ipc.js');
98
100
  case ModuleId.ProcessId:
99
101
  return import('../ProcessId/ProcessId.ipc.js');
100
102
  case ModuleId.RebuildNodePty:
@@ -10,6 +10,7 @@ export const Preferences = 9;
10
10
  export const RecentlyOpened = 10;
11
11
  export const GetWindowId = 377;
12
12
  export const ElectronWindowProcessExplorer = 12;
13
+ export const ProcessExplorer = 13;
13
14
  export const Terminal = 14;
14
15
  export const TextDocument = 15;
15
16
  export const Workspace = 17;
@@ -234,6 +234,8 @@ export const getModuleId = (commandId) => {
234
234
  case 'ProcessId.getMainProcessId':
235
235
  case 'ProcessId.getSharedProcessId':
236
236
  return ModuleId.ProcessId;
237
+ case 'ProcessExplorer.decreaseRefCount':
238
+ return ModuleId.ProcessExplorer;
237
239
  case 'RebuildNodePty.rebuildNodePty':
238
240
  return ModuleId.RebuildNodePty;
239
241
  case 'RecentlyOpened.addPath':
@@ -41,9 +41,9 @@ export const getAppImageName = () => {
41
41
  export const getSetupName = () => {
42
42
  return 'Lvce-Setup';
43
43
  };
44
- export const version = '0.84.18';
45
- export const commit = 'dfd5b2f';
46
- export const date = '2026-07-04T15:14:46.000Z';
44
+ export const version = '0.85.1';
45
+ export const commit = '6f0f9b3';
46
+ export const date = '2026-07-08T07:37:58.000Z';
47
47
  export const getVersion = () => {
48
48
  return version;
49
49
  };
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
2
  import * as Root from '../Root/Root.js';
3
3
  export const getPreloadUrl = () => {
4
- return join(Root.root, 'static', 'dfd5b2f', 'packages', 'preload', 'dist', 'index.js');
4
+ return join(Root.root, 'static', '6f0f9b3', 'packages', 'preload', 'dist', 'index.js');
5
5
  };
@@ -0,0 +1,5 @@
1
+ import * as ProcessExplorer from './ProcessExplorer.js';
2
+ export const name = 'ProcessExplorer';
3
+ export const Commands = {
4
+ decreaseRefCount: ProcessExplorer.decreaseRefCount,
5
+ };
@@ -4,6 +4,7 @@ export const state = {
4
4
  * @type {any}
5
5
  */
6
6
  ipc: undefined,
7
+ refCount: 0,
7
8
  };
8
9
  export const getOrCreate = async () => {
9
10
  if (!state.ipc) {
@@ -11,3 +12,37 @@ export const getOrCreate = async () => {
11
12
  }
12
13
  return state.ipc;
13
14
  };
15
+ export const acquire = async () => {
16
+ state.refCount++;
17
+ try {
18
+ return await getOrCreate();
19
+ }
20
+ catch (error) {
21
+ decreaseRefCount();
22
+ throw error;
23
+ }
24
+ };
25
+ const disposeLater = (ipcPromise) => {
26
+ setTimeout(async () => {
27
+ try {
28
+ const ipc = await ipcPromise;
29
+ await ipc.dispose();
30
+ }
31
+ catch {
32
+ // ignore disposal errors
33
+ }
34
+ }, 0);
35
+ };
36
+ export const decreaseRefCount = () => {
37
+ if (state.refCount > 0) {
38
+ state.refCount--;
39
+ }
40
+ if (state.refCount === 0) {
41
+ const { ipc } = state;
42
+ state.ipc = undefined;
43
+ if (ipc) {
44
+ disposeLater(ipc);
45
+ }
46
+ }
47
+ return state.refCount;
48
+ };
@@ -0,0 +1,10 @@
1
+ import * as DestroySocket from '../DestroySocket/DestroySocket.js';
2
+ import * as HttpStatusCode from '../HttpStatusCode/HttpStatusCode.js';
3
+ export const rejectWebSocket = (socket) => {
4
+ socket.write(`HTTP/1.1 ${HttpStatusCode.Forbidden} Forbidden\r\nConnection: close\r\nContent-Length: 0\r\n\r\n`);
5
+ if (typeof socket.end === 'function') {
6
+ socket.end();
7
+ return;
8
+ }
9
+ DestroySocket.destroySocket(socket);
10
+ };