@lvce-editor/shared-process 0.22.1 → 0.22.2
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 +6 -8
- package/src/parts/ExtensionHostHelperProcessIpc/ExtensionHostHelperProcessIpc.js +3 -0
- package/src/parts/ExtensionManagement/ExtensionManagement.js +48 -36
- package/src/parts/ExtensionManifests/ExtensionManifests.js +6 -3
- package/src/parts/GetUtilityProcessPortData/GetUtilityProcessPortData.js +10 -0
- package/src/parts/HandleElectronMessagePort/HandleElectronMessagePort.js +0 -1
- package/src/parts/HandleIpc/HandleIpc.js +3 -0
- package/src/parts/HandleMessagePortForExtensionHostHelperProcess/HandleMessagePortForExtensionHostHelperProcess.js +20 -4
- package/src/parts/HandleNodeMessagePort/HandleNodeMessagePort.js +0 -1
- package/src/parts/HandleWebSocket/HandleWebSocket.js +0 -1
- package/src/parts/HandleWebSocketForSharedProcess/HandleWebSocketForSharedProcess.js +6 -4
- package/src/parts/IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js +3 -0
- package/src/parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js +3 -12
- package/src/parts/IpcChildWithNodeMessagePort/IpcChildWithNodeMessagePort.js +3 -0
- package/src/parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js +17 -11
- package/src/parts/IpcParentWithElectronUtilityProcess/IpcParentWithElectronUtilityProcess.js +2 -0
- package/src/parts/Platform/Platform.js +3 -3
- package/src/parts/RequiresSocket/RequiresSocket.js +1 -0
- package/src/parts/WebSocketSerialization/WebSocketSerialization.js +7 -0
- package/src/parts/WebSocketServer/WebSocketServer.js +1 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/shared-process",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.2",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -17,23 +17,21 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@lvce-editor/assert": "^1.0
|
|
21
|
-
"@lvce-editor/extension-host": "0.22.
|
|
22
|
-
"@lvce-editor/extension-host-helper-process": "0.22.1",
|
|
20
|
+
"@lvce-editor/assert": "^1.1.0",
|
|
21
|
+
"@lvce-editor/extension-host-helper-process": "0.22.2",
|
|
23
22
|
"@lvce-editor/json-rpc": "^1.0.0",
|
|
24
23
|
"@lvce-editor/jsonc-parser": "^1.1.0",
|
|
25
|
-
"@lvce-editor/pretty-error": "^1.
|
|
26
|
-
"@lvce-editor/pty-host": "0.22.
|
|
24
|
+
"@lvce-editor/pretty-error": "^1.4.0",
|
|
25
|
+
"@lvce-editor/pty-host": "0.22.2",
|
|
27
26
|
"@lvce-editor/verror": "^1.1.2",
|
|
27
|
+
"@lvce-editor/web-socket-server": "^1.1.0",
|
|
28
28
|
"debug": "^4.3.4",
|
|
29
29
|
"execa": "^8.0.1",
|
|
30
30
|
"exit-hook": "^4.0.0",
|
|
31
31
|
"got": "^13.0.0",
|
|
32
32
|
"is-object": "^1.0.2",
|
|
33
33
|
"p-queue": "^8.0.1",
|
|
34
|
-
"parse-json": "^8.1.0",
|
|
35
34
|
"tar-fs": "^3.0.4",
|
|
36
|
-
"ws": "^8.16.0",
|
|
37
35
|
"xdg-basedir": "^5.1.0"
|
|
38
36
|
},
|
|
39
37
|
"optionalDependencies": {
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as IpcParent from '../IpcParent/IpcParent.js'
|
|
2
2
|
import * as PlatformPaths from '../PlatformPaths/PlatformPaths.js'
|
|
3
|
+
import * as Id from '../Id/Id.js'
|
|
3
4
|
|
|
4
5
|
export const create = async ({ method }) => {
|
|
5
6
|
const extensionHostHelperProcessPath = await PlatformPaths.getExtensionHostHelperProcessPath()
|
|
7
|
+
const id = Id.create()
|
|
6
8
|
const ipc = await IpcParent.create({
|
|
7
9
|
method,
|
|
8
10
|
path: extensionHostHelperProcessPath,
|
|
9
11
|
execArgv: ['--max-old-space-size=60', '--enable-source-maps'],
|
|
12
|
+
name: `Extension Host Helper Process ${id}`,
|
|
10
13
|
})
|
|
11
14
|
return ipc
|
|
12
15
|
}
|
|
@@ -31,51 +31,63 @@ export const disable = async (id) => {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export const getBuiltinExtensions = () => {
|
|
34
|
-
return ExtensionManifests.getAll(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
return ExtensionManifests.getAll(
|
|
35
|
+
[
|
|
36
|
+
{
|
|
37
|
+
type: ExtensionManifestInputType.Folder,
|
|
38
|
+
path: PlatformPaths.getBuiltinExtensionsPath(),
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
PlatformPaths.getBuiltinExtensionsPath(),
|
|
42
|
+
)
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
export const getInstalledExtensions = () => {
|
|
43
|
-
return ExtensionManifests.getAll(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
return ExtensionManifests.getAll(
|
|
47
|
+
[
|
|
48
|
+
{
|
|
49
|
+
type: ExtensionManifestInputType.Folder,
|
|
50
|
+
path: PlatformPaths.getExtensionsPath(),
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
PlatformPaths.getBuiltinExtensionsPath(),
|
|
54
|
+
)
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
export const getExtensions = () => {
|
|
52
|
-
return ExtensionManifests.getAll(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
return ExtensionManifests.getAll(
|
|
59
|
+
[
|
|
60
|
+
{
|
|
61
|
+
type: ExtensionManifestInputType.OnlyExtension,
|
|
62
|
+
path: PlatformPaths.getOnlyExtensionPath(),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: ExtensionManifestInputType.Folder,
|
|
66
|
+
path: PlatformPaths.getLinkedExtensionsPath(),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: ExtensionManifestInputType.Folder,
|
|
70
|
+
path: PlatformPaths.getExtensionsPath(),
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: ExtensionManifestInputType.Folder,
|
|
74
|
+
path: PlatformPaths.getBuiltinExtensionsPath(),
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
PlatformPaths.getBuiltinExtensionsPath(),
|
|
78
|
+
)
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
export const getDisabledExtensions = () => {
|
|
73
|
-
return ExtensionManifests.getAll(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
return ExtensionManifests.getAll(
|
|
83
|
+
[
|
|
84
|
+
{
|
|
85
|
+
type: ExtensionManifestInputType.Folder,
|
|
86
|
+
path: PlatformPaths.getDisabledExtensionsPath(),
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
PlatformPaths.getBuiltinExtensionsPath(),
|
|
90
|
+
)
|
|
79
91
|
}
|
|
80
92
|
|
|
81
93
|
export * from '../ExtensionUninstall/ExtensionUninstall.js'
|
|
@@ -21,7 +21,7 @@ const get = (input) => {
|
|
|
21
21
|
return module.getExtensionManifests(input.path)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const deduplicateExtensions = (extensions) => {
|
|
24
|
+
const deduplicateExtensions = (extensions, builtinExtensionsPath) => {
|
|
25
25
|
const seen = Object.create(null)
|
|
26
26
|
const uniqueExtensions = []
|
|
27
27
|
for (const extension of extensions) {
|
|
@@ -29,14 +29,17 @@ const deduplicateExtensions = (extensions) => {
|
|
|
29
29
|
continue
|
|
30
30
|
}
|
|
31
31
|
seen[extension.id] = true
|
|
32
|
+
if (extension.path.startsWith(builtinExtensionsPath)) {
|
|
33
|
+
extension.builtin = true
|
|
34
|
+
}
|
|
32
35
|
uniqueExtensions.push(extension)
|
|
33
36
|
}
|
|
34
37
|
return uniqueExtensions
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
export const getAll = async (inputs) => {
|
|
40
|
+
export const getAll = async (inputs, builtinExtensionsPath) => {
|
|
38
41
|
const manifests = await Promise.all(inputs.map(get))
|
|
39
42
|
const flatManifests = manifests.flat(1)
|
|
40
|
-
const uniqueExtensions = deduplicateExtensions(flatManifests)
|
|
43
|
+
const uniqueExtensions = deduplicateExtensions(flatManifests, builtinExtensionsPath)
|
|
41
44
|
return uniqueExtensions
|
|
42
45
|
}
|
|
@@ -19,4 +19,7 @@ export const handleIpc = (ipc) => {
|
|
|
19
19
|
return JsonRpc.handleJsonRpcMessage(ipc, message, Command.execute, Callback.resolve, preparePrettyError, logError, RequiresSocket.requiresSocket)
|
|
20
20
|
}
|
|
21
21
|
ipc.on('message', handleMessage)
|
|
22
|
+
if (ipc.start) {
|
|
23
|
+
ipc.start()
|
|
24
|
+
}
|
|
22
25
|
}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import * as Assert from '../Assert/Assert.js'
|
|
2
|
+
import * as ExtensionHostHelperProcessIpc from '../ExtensionHostHelperProcessIpc/ExtensionHostHelperProcessIpc.js'
|
|
3
|
+
import * as HandleIpc from '../HandleIpc/HandleIpc.js'
|
|
4
|
+
import * as IpcParentType from '../IpcParentType/IpcParentType.js'
|
|
5
|
+
import * as JsonRpc from '../JsonRpc/JsonRpc.js'
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
// TODO connect this ipc to the renderer worker ipc
|
|
8
|
+
// when renderer worker ipc closes, dispose all
|
|
9
|
+
// matching extension host helper processes
|
|
10
|
+
// unless the app is exiting, in which case the child processes
|
|
11
|
+
// would get cleaned up automatically
|
|
12
|
+
export const handleMessagePortForExtensionHostHelperProcess = async (rendererWorkerIpc, port) => {
|
|
4
13
|
Assert.object(port)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
const ipc = await ExtensionHostHelperProcessIpc.create({
|
|
15
|
+
method: IpcParentType.ElectronUtilityProcess,
|
|
16
|
+
})
|
|
17
|
+
HandleIpc.handleIpc(ipc)
|
|
18
|
+
await JsonRpc.invokeAndTransfer(ipc, [port], 'HandleElectronMessagePort.handleElectronMessagePort')
|
|
19
|
+
const cleanup = () => {
|
|
20
|
+
ipc.dispose()
|
|
21
|
+
rendererWorkerIpc.off('close', cleanup)
|
|
22
|
+
}
|
|
23
|
+
rendererWorkerIpc.on('close', cleanup)
|
|
8
24
|
}
|
|
@@ -18,7 +18,6 @@ export const handleWebSocket = async (message, handle) => {
|
|
|
18
18
|
handle.pause()
|
|
19
19
|
const module = await HandleWebSocketModule.load(protocol)
|
|
20
20
|
await module.handleWebSocket(message, handle, protocol)
|
|
21
|
-
handle.resume()
|
|
22
21
|
} catch (error) {
|
|
23
22
|
DestroyWebSocket.destroySocket(handle)
|
|
24
23
|
throw new VError(error, `Failed to connect to websocket`)
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import * as Assert from '../Assert/Assert.js'
|
|
1
2
|
import * as HandleIpc from '../HandleIpc/HandleIpc.js'
|
|
2
3
|
import * as HandleSocketError from '../HandleSocketError/HandleSocketError.js'
|
|
3
4
|
import * as IpcChild from '../IpcChild/IpcChild.js'
|
|
4
5
|
import * as IpcChildType from '../IpcChildType/IpcChildType.js'
|
|
5
|
-
import * as WebSocketServer from '../WebSocketServer/WebSocketServer.js'
|
|
6
6
|
|
|
7
|
-
export const handleWebSocket = async (
|
|
7
|
+
export const handleWebSocket = async (request, handle) => {
|
|
8
|
+
Assert.object(request)
|
|
9
|
+
Assert.object(handle)
|
|
8
10
|
handle.on('error', HandleSocketError.handleSocketError)
|
|
9
|
-
const webSocket = await WebSocketServer.handleUpgrade(message, handle)
|
|
10
11
|
const ipc = await IpcChild.listen({
|
|
11
12
|
method: IpcChildType.WebSocket,
|
|
12
|
-
|
|
13
|
+
request,
|
|
14
|
+
handle,
|
|
13
15
|
})
|
|
14
16
|
HandleIpc.handleIpc(ipc)
|
|
15
17
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as GetUtilityProcessPortData from '../GetUtilityProcessPortData/GetUtilityProcessPortData.js'
|
|
2
|
+
|
|
1
3
|
export const listen = () => {
|
|
2
4
|
// @ts-ignore
|
|
3
5
|
const { parentPort } = process
|
|
@@ -11,24 +13,13 @@ export const signal = (parentPort) => {
|
|
|
11
13
|
parentPort.postMessage('ready')
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
const getActualData = (event) => {
|
|
15
|
-
const { data, ports } = event
|
|
16
|
-
if (ports.length === 0) {
|
|
17
|
-
return data
|
|
18
|
-
}
|
|
19
|
-
return {
|
|
20
|
-
...data,
|
|
21
|
-
params: [...ports, ...data.params],
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
16
|
export const wrap = (parentPort) => {
|
|
26
17
|
return {
|
|
27
18
|
parentPort,
|
|
28
19
|
on(event, listener) {
|
|
29
20
|
if (event === 'message') {
|
|
30
21
|
const wrappedListener = (event) => {
|
|
31
|
-
const actualData =
|
|
22
|
+
const actualData = GetUtilityProcessPortData.getUtilityProcessPortData(event)
|
|
32
23
|
listener(actualData)
|
|
33
24
|
}
|
|
34
25
|
this.parentPort.on(event, wrappedListener)
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import * as GetFirstWebSocketEvent from '../GetFirstWebSocketEvent/GetFirstWebSocketEvent.js'
|
|
2
|
+
import { IpcError } from '../IpcError/IpcError.js'
|
|
2
3
|
import * as IsWebSocketOpen from '../IsWebSocketOpen/IsWebSocketOpen.js'
|
|
4
|
+
import * as WebSocketSerialization from '../WebSocketSerialization/WebSocketSerialization.js'
|
|
5
|
+
import * as WebSocketServer from '../WebSocketServer/WebSocketServer.js'
|
|
3
6
|
|
|
4
|
-
export const listen = async ({
|
|
7
|
+
export const listen = async ({ request, handle }) => {
|
|
8
|
+
if (!request) {
|
|
9
|
+
throw new IpcError('request must be defined')
|
|
10
|
+
}
|
|
11
|
+
if (!handle) {
|
|
12
|
+
throw new IpcError('handle must be defined')
|
|
13
|
+
}
|
|
14
|
+
const webSocket = await WebSocketServer.handleUpgrade(request, handle)
|
|
15
|
+
webSocket.pause()
|
|
5
16
|
if (!IsWebSocketOpen.isWebSocketOpen(webSocket)) {
|
|
6
17
|
const { type, event } = await GetFirstWebSocketEvent.getFirstWebSocketEvent(webSocket)
|
|
7
18
|
console.log({ type, event })
|
|
@@ -9,11 +20,6 @@ export const listen = async ({ webSocket }) => {
|
|
|
9
20
|
return webSocket
|
|
10
21
|
}
|
|
11
22
|
|
|
12
|
-
const getActualData = (message) => {
|
|
13
|
-
const data = JSON.parse(message.toString())
|
|
14
|
-
return data
|
|
15
|
-
}
|
|
16
|
-
|
|
17
23
|
export const wrap = (webSocket) => {
|
|
18
24
|
return {
|
|
19
25
|
webSocket,
|
|
@@ -25,14 +31,11 @@ export const wrap = (webSocket) => {
|
|
|
25
31
|
switch (event) {
|
|
26
32
|
case 'message':
|
|
27
33
|
const wrappedListener = (message) => {
|
|
28
|
-
const data =
|
|
34
|
+
const data = WebSocketSerialization.deserialize(message)
|
|
29
35
|
listener(data)
|
|
30
36
|
}
|
|
31
37
|
webSocket.on('message', wrappedListener)
|
|
32
38
|
break
|
|
33
|
-
case 'close':
|
|
34
|
-
webSocket.on('close', listener)
|
|
35
|
-
break
|
|
36
39
|
default:
|
|
37
40
|
throw new Error('unknown event listener type')
|
|
38
41
|
}
|
|
@@ -41,11 +44,14 @@ export const wrap = (webSocket) => {
|
|
|
41
44
|
this.webSocket.off(event, listener)
|
|
42
45
|
},
|
|
43
46
|
send(message) {
|
|
44
|
-
const stringifiedMessage =
|
|
47
|
+
const stringifiedMessage = WebSocketSerialization.serialize(message)
|
|
45
48
|
this.webSocket.send(stringifiedMessage)
|
|
46
49
|
},
|
|
47
50
|
dispose() {
|
|
48
51
|
this.webSocket.close()
|
|
49
52
|
},
|
|
53
|
+
start() {
|
|
54
|
+
this.webSocket.resume()
|
|
55
|
+
},
|
|
50
56
|
}
|
|
51
57
|
}
|
package/src/parts/IpcParentWithElectronUtilityProcess/IpcParentWithElectronUtilityProcess.js
CHANGED
|
@@ -13,6 +13,7 @@ export const create = async (options) => {
|
|
|
13
13
|
})
|
|
14
14
|
// TODO use uuid instead of name
|
|
15
15
|
const port = await TemporaryMessagePort.create(options.name)
|
|
16
|
+
port.name = options.name
|
|
16
17
|
return port
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -43,6 +44,7 @@ export const wrap = (port) => {
|
|
|
43
44
|
off(event, listener) {},
|
|
44
45
|
dispose() {
|
|
45
46
|
this.port.close()
|
|
47
|
+
ParentIpc.invoke('TemporaryMessagePort.dispose', this.port.name)
|
|
46
48
|
},
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -61,11 +61,11 @@ export const getSetupName = () => {
|
|
|
61
61
|
return 'Lvce-Setup'
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export const version = '0.22.
|
|
64
|
+
export const version = '0.22.2'
|
|
65
65
|
|
|
66
|
-
export const commit = '
|
|
66
|
+
export const commit = 'c239d9c'
|
|
67
67
|
|
|
68
|
-
export const date = '2024-01-
|
|
68
|
+
export const date = '2024-01-06T23:18:20.000Z'
|
|
69
69
|
|
|
70
70
|
export const getVersion = () => {
|
|
71
71
|
return version
|
|
@@ -10,6 +10,7 @@ const METHODS_THAT_REQUIRE_SOCKET = new Set([
|
|
|
10
10
|
'IncrementalTextSearch.start',
|
|
11
11
|
'ElectronApplicationMenu.setItems',
|
|
12
12
|
'GetWindowId.getWindowId',
|
|
13
|
+
'HandleMessagePortForExtensionHostHelperProcess.handleMessagePortForExtensionHostHelperProcess',
|
|
13
14
|
])
|
|
14
15
|
|
|
15
16
|
export const requiresSocket = (method) => {
|
|
@@ -1,30 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import * as _ws from 'ws'
|
|
3
|
-
import * as IsSocket from '../IsSocket/IsSocket.js'
|
|
4
|
-
import * as Promises from '../Promises/Promises.js'
|
|
5
|
-
|
|
6
|
-
// workaround for jest or node bug
|
|
7
|
-
const WebSocketServer = _ws.WebSocketServer
|
|
8
|
-
? _ws.WebSocketServer
|
|
9
|
-
: // @ts-ignore
|
|
10
|
-
_ws.default.WebSocketServer
|
|
11
|
-
|
|
12
|
-
const webSocketServer = new WebSocketServer({
|
|
13
|
-
noServer: true,
|
|
14
|
-
|
|
15
|
-
// TODO not sure if ws compress is working at all
|
|
16
|
-
// perMessageDeflate: true
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
export const handleUpgrade = async (request, socket) => {
|
|
20
|
-
if (!IsSocket.isSocket(socket)) {
|
|
21
|
-
throw new TypeError(`socket must be of type Socket`)
|
|
22
|
-
}
|
|
23
|
-
const { resolve, promise } = Promises.withResolvers()
|
|
24
|
-
const upgradeCallback = (ws) => {
|
|
25
|
-
resolve(ws)
|
|
26
|
-
}
|
|
27
|
-
webSocketServer.handleUpgrade(request, socket, Buffer.alloc(0), upgradeCallback)
|
|
28
|
-
const webSocket = await promise
|
|
29
|
-
return webSocket
|
|
30
|
-
}
|
|
1
|
+
export * from '@lvce-editor/web-socket-server'
|