@lvce-editor/shared-process 0.0.26 → 0.0.29
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/config/builtinCommands.json +103 -87
- package/config/defaultKeyBindings.json +23 -18
- package/config/defaultSettings.json +3 -1
- package/index.js +2 -2
- package/package.json +13 -10
- package/src/parts/Assert/Assert.js +12 -5
- package/src/parts/ChildProcess/ChildProcessWithFork.js +19 -0
- package/src/parts/ClipBoard/ClipBoard.ipc.js +3 -4
- package/src/parts/Command/Command.js +30 -17
- package/src/parts/Credentials/Credentials.ipc.js +6 -7
- package/src/parts/Developer/Developer.ipc.js +10 -17
- package/src/parts/Electron/Electron.ipc.js +15 -16
- package/src/parts/Electron/Electron.js +43 -34
- package/src/parts/ExtensionHost/ExtensionHost.ipc.js +15 -72
- package/src/parts/ExtensionHost/ExtensionHost.js +59 -138
- package/src/parts/ExtensionHostIpc/ExtensionHostIpc.js +5 -0
- package/src/parts/ExtensionHostIpc/ExtensionHostIpcWithChildProcess.js +57 -0
- package/src/parts/ExtensionHostIpc/ExtensionHostIpcWithWorker.js +38 -0
- package/src/parts/ExtensionHostRpc/ExtensionHostRpc.js +82 -0
- package/src/parts/ExtensionManagement/ExtensionManagement.ipc.js +16 -8
- package/src/parts/ExtensionManagement/ExtensionManagement.js +5 -2
- package/src/parts/{ExtensionHost/ExtensionHostColorTheme.js → ExtensionManagement/ExtensionManagementColorTheme.js} +1 -1
- package/src/parts/{ExtensionHost/ExtensionHostIconTheme.js → ExtensionManagement/ExtensionManagementIconTheme.js} +1 -1
- package/src/parts/{ExtensionHost/ExtensionHostLanguages.js → ExtensionManagement/ExtensionManagementLanguages.js} +1 -1
- package/src/parts/FileSystem/FileSystem.ipc.js +14 -15
- package/src/parts/FileSystem/FileSystem.js +56 -1
- package/src/parts/JsonRpc/JsonRpc.js +2 -2
- package/src/parts/Native/Native.ipc.js +2 -3
- package/src/parts/OutputChannel/OutputChannel.ipc.js +16 -19
- package/src/parts/ParentIpc/ParentIpc.js +93 -44
- package/src/parts/Platform/Platform.ipc.js +15 -17
- package/src/parts/Platform/Platform.js +1 -1
- package/src/parts/Preferences/Preferences.ipc.js +2 -3
- package/src/parts/Preferences/Preferences.js +0 -2
- package/src/parts/PrettyError/PrettyError.js +5 -2
- package/src/parts/Process/Process.ipc.js +3 -4
- package/src/parts/RequiresSocket/RequiresSocket.js +6 -5
- package/src/parts/Search/Search.ipc.js +2 -3
- package/src/parts/SearchFile/SearchFile.ipc.js +2 -3
- package/src/parts/Stats/Stats.js +8 -7
- package/src/parts/Terminal/Terminal.ipc.js +9 -9
- package/src/parts/Terminal/Terminal.js +1 -1
- package/src/parts/TextDocument/TextDocument.ipc.js +2 -3
- package/src/parts/Timeout/Timeout.js +7 -0
- package/src/parts/WebSocketServer/WebSocketServer.ipc.js +2 -3
- package/src/parts/Workspace/Workspace.ipc.js +3 -4
- package/src/sharedProcessMain.js +13 -4
- package/src/parts/Extension/Extension.js +0 -7
- package/src/parts/ExtensionHost/ExtensionHostBraceCompletion.js +0 -14
- package/src/parts/ExtensionHost/ExtensionHostClosingTag.js +0 -14
- package/src/parts/ExtensionHost/ExtensionHostCommand.js +0 -19
- package/src/parts/ExtensionHost/ExtensionHostCompletion.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostDefinition.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostDiagnostic.js +0 -7
- package/src/parts/ExtensionHost/ExtensionHostFileSystem.js +0 -23
- package/src/parts/ExtensionHost/ExtensionHostFormatting.js +0 -4
- package/src/parts/ExtensionHost/ExtensionHostHover.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostImplementation.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostManagement.js +0 -26
- package/src/parts/ExtensionHost/ExtensionHostOutput.js +0 -3
- package/src/parts/ExtensionHost/ExtensionHostQuickPick.js +0 -6
- package/src/parts/ExtensionHost/ExtensionHostReference.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostRename.js +0 -27
- package/src/parts/ExtensionHost/ExtensionHostSemanticTokens.js +0 -10
- package/src/parts/ExtensionHost/ExtensionHostSourceControl.js +0 -15
- package/src/parts/ExtensionHost/ExtensionHostStats.js +0 -3
- package/src/parts/ExtensionHost/ExtensionHostStatusBar.js +0 -7
- package/src/parts/ExtensionHost/ExtensionHostTabCompletion.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostTextDocument.js +0 -35
- package/src/parts/ExtensionHost/ExtensionHostTypeDefinition.js +0 -12
- package/src/parts/ExtensionHost/ExtensionHostWorkspace.js +0 -3
|
@@ -1,163 +1,84 @@
|
|
|
1
1
|
import VError from 'verror'
|
|
2
|
+
import * as Assert from '../Assert/Assert.js'
|
|
2
3
|
import * as Callback from '../Callback/Callback.js'
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
4
|
+
import * as ExtensionHostIpc from '../ExtensionHostIpc/ExtensionHostIpc.js'
|
|
5
|
+
import * as ExtensionHostRpc from '../ExtensionHostRpc/ExtensionHostRpc.js'
|
|
5
6
|
import * as JsonRpc from '../JsonRpc/JsonRpc.js'
|
|
6
|
-
import * as Platform from '../Platform/Platform.js'
|
|
7
|
-
import * as Socket from '../Socket/Socket.js'
|
|
8
|
-
import * as Assert from '../Assert/Assert.js'
|
|
9
|
-
// TODO maybe rename to extension host management for clarity
|
|
10
7
|
|
|
11
|
-
// TODO
|
|
12
|
-
const NULL_EXTENSION_HOST = {
|
|
13
|
-
dispose() {
|
|
14
|
-
throw new VError('not implemented')
|
|
15
|
-
},
|
|
16
|
-
send(message) {
|
|
17
|
-
throw new VError(
|
|
18
|
-
'extension host must be started before commands can be invoked'
|
|
19
|
-
)
|
|
20
|
-
},
|
|
21
|
-
async invoke(commandId, ...args) {
|
|
22
|
-
throw new VError(
|
|
23
|
-
'extension host must be started before commands can be invoked'
|
|
24
|
-
)
|
|
25
|
-
},
|
|
26
|
-
}
|
|
8
|
+
// TODO maybe rename to extension host management for clarity
|
|
27
9
|
|
|
28
10
|
/**
|
|
29
|
-
* @type{{
|
|
30
|
-
* extensionHost: {dispose:()=>void, invoke:(commandId, ...args)=>Promise<any>},
|
|
31
|
-
* }}
|
|
11
|
+
* @type{{extensionHosts:any }}
|
|
32
12
|
*/
|
|
33
13
|
export const state = {
|
|
34
|
-
|
|
14
|
+
extensionHosts: Object.create(null),
|
|
35
15
|
}
|
|
36
16
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
message.id,
|
|
44
|
-
new Error.OperationalError({
|
|
45
|
-
code: 'E_CALLBACK_REJECTED',
|
|
46
|
-
message: message.error.message,
|
|
47
|
-
stack: message.error.data.stack,
|
|
48
|
-
codeFrame: message.error.data.codeFrame,
|
|
49
|
-
// @ts-ignore
|
|
50
|
-
stderr: message.error.data.stderr,
|
|
51
|
-
})
|
|
52
|
-
)
|
|
53
|
-
} else {
|
|
54
|
-
Socket.send(message)
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
Socket.send(message)
|
|
58
|
-
}
|
|
17
|
+
// TODO this function is very ugly and has probably memory leaks
|
|
18
|
+
const createExtensionHost = async (socket) => {
|
|
19
|
+
Assert.object(socket)
|
|
20
|
+
const ipc = ExtensionHostIpc.create()
|
|
21
|
+
const rpc = ExtensionHostRpc.create(ipc, socket)
|
|
22
|
+
return rpc
|
|
59
23
|
}
|
|
60
24
|
|
|
61
|
-
// TODO this function is very ugly and has probably memory leaks
|
|
62
25
|
export const start = async (socket) => {
|
|
63
26
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
...process.env,
|
|
74
|
-
LOGS_DIR: Platform.getLogsDir(),
|
|
75
|
-
CONFIG_DIR: Platform.getConfigDir(),
|
|
76
|
-
},
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const handleChildProcessError = (error) => {
|
|
80
|
-
console.error(`[Extension Host] ${error}`)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const handleChildProcessExit = (exitCode) => {
|
|
84
|
-
console.info(
|
|
85
|
-
`[SharedProcess] Extension Host exited with code ${exitCode}`
|
|
86
|
-
)
|
|
87
|
-
state.extensionHost = NULL_EXTENSION_HOST
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const handleSocketClose = () => {
|
|
91
|
-
console.info('[shared process] disposing extension host')
|
|
92
|
-
childProcess.kill()
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
socket.on('close', handleSocketClose)
|
|
96
|
-
|
|
97
|
-
childProcess.on('error', handleChildProcessError)
|
|
98
|
-
|
|
99
|
-
childProcess.on('exit', handleChildProcessExit)
|
|
100
|
-
|
|
101
|
-
state.extensionHost = {
|
|
102
|
-
invoke(...args) {
|
|
103
|
-
return JsonRpc.invoke(childProcess, ...args)
|
|
104
|
-
},
|
|
105
|
-
dispose() {
|
|
106
|
-
childProcess.kill()
|
|
107
|
-
},
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
await new Promise((resolve, reject) => {
|
|
111
|
-
const handleFirstError = (error) => {
|
|
112
|
-
cleanup()
|
|
113
|
-
reject(error)
|
|
114
|
-
}
|
|
115
|
-
const handleFirstExit = (exitCode) => {
|
|
116
|
-
cleanup()
|
|
117
|
-
reject(
|
|
118
|
-
new globalThis.Error(`Extension Host exited with code ${exitCode}`)
|
|
119
|
-
)
|
|
27
|
+
const id = 1
|
|
28
|
+
console.log('start extension host', id)
|
|
29
|
+
const handleMessage = (message) => {
|
|
30
|
+
if ('result' in message) {
|
|
31
|
+
Callback.resolve(message.id, message.result)
|
|
32
|
+
} else if ('error' in message) {
|
|
33
|
+
Callback.reject(message.id, message.error)
|
|
34
|
+
} else {
|
|
35
|
+
console.error('unsupported message type')
|
|
120
36
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const handleSocketClose = () => {
|
|
127
|
-
cleanup()
|
|
128
|
-
childProcess.off('error', handleChildProcessError)
|
|
129
|
-
childProcess.off('exit', handleChildProcessExit)
|
|
130
|
-
resolve(undefined)
|
|
131
|
-
}
|
|
132
|
-
const cleanup = () => {
|
|
133
|
-
childProcess.off('error', handleFirstError)
|
|
134
|
-
childProcess.off('exit', handleFirstExit)
|
|
135
|
-
childProcess.off('message', handleFirstMessage)
|
|
136
|
-
}
|
|
137
|
-
childProcess.on('error', handleFirstError)
|
|
138
|
-
childProcess.on('exit', handleFirstExit)
|
|
139
|
-
childProcess.on('message', handleFirstMessage)
|
|
140
|
-
socket.on('close', handleSocketClose)
|
|
141
|
-
})
|
|
37
|
+
}
|
|
38
|
+
const extensionHost = await createExtensionHost(socket)
|
|
39
|
+
extensionHost.on('message', handleMessage)
|
|
40
|
+
state.extensionHosts[id] = extensionHost
|
|
41
|
+
return id
|
|
142
42
|
} catch (error) {
|
|
143
43
|
// @ts-ignore
|
|
144
44
|
throw new VError(error, 'Failed to start extension host')
|
|
145
45
|
}
|
|
146
46
|
}
|
|
147
47
|
|
|
148
|
-
export const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
48
|
+
export const send = async (socket, id, message) => {
|
|
49
|
+
Assert.number(id)
|
|
50
|
+
Assert.object(message)
|
|
51
|
+
console.log(Object.keys(state))
|
|
52
|
+
const extensionHost = state.extensionHosts[id]
|
|
53
|
+
if (!extensionHost) {
|
|
54
|
+
throw new VError(`no extension host with id ${id} found`)
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const result = await JsonRpc.invoke(
|
|
58
|
+
extensionHost,
|
|
59
|
+
message.method,
|
|
60
|
+
...message.params
|
|
61
|
+
)
|
|
62
|
+
socket.send({
|
|
63
|
+
jsonrpc: '2.0',
|
|
64
|
+
id: message.id,
|
|
65
|
+
result,
|
|
66
|
+
})
|
|
67
|
+
} catch (error) {
|
|
68
|
+
// console.log({ error })
|
|
69
|
+
socket.send({
|
|
70
|
+
jsonrpc: '2.0',
|
|
71
|
+
id: message.id,
|
|
72
|
+
error,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
156
75
|
}
|
|
157
76
|
|
|
158
|
-
export const
|
|
159
|
-
const
|
|
160
|
-
|
|
77
|
+
export const dispose = (id) => {
|
|
78
|
+
const extensionHost = state.extensionHosts[id]
|
|
79
|
+
if (!extensionHost) {
|
|
80
|
+
throw new VError(`no extension host with id ${id} found`)
|
|
161
81
|
}
|
|
162
|
-
|
|
82
|
+
extensionHost.dispose()
|
|
83
|
+
delete state.extensionHosts[id]
|
|
163
84
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as ChildProcess from '../ChildProcess/ChildProcess.js'
|
|
2
|
+
import * as Platform from '../Platform/Platform.js'
|
|
3
|
+
|
|
4
|
+
export const create = () => {
|
|
5
|
+
const extensionHostPath = Platform.getExtensionHostPath()
|
|
6
|
+
const childProcess = ChildProcess.fork(extensionHostPath, {
|
|
7
|
+
execArgv: [
|
|
8
|
+
'--experimental-json-modules',
|
|
9
|
+
'--max-old-space-size=60',
|
|
10
|
+
'--enable-source-maps',
|
|
11
|
+
],
|
|
12
|
+
env: {
|
|
13
|
+
...process.env,
|
|
14
|
+
LOGS_DIR: Platform.getLogsDir(),
|
|
15
|
+
CONFIG_DIR: Platform.getConfigDir(),
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
return {
|
|
19
|
+
on(event, listener) {
|
|
20
|
+
switch (event) {
|
|
21
|
+
case 'message':
|
|
22
|
+
childProcess.on('message', listener)
|
|
23
|
+
break
|
|
24
|
+
case 'error':
|
|
25
|
+
childProcess.on('error', listener)
|
|
26
|
+
break
|
|
27
|
+
case 'exit':
|
|
28
|
+
childProcess.on('exit', listener)
|
|
29
|
+
break
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`unsupported event type ${event}`)
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
off(event, listener) {
|
|
35
|
+
switch (event) {
|
|
36
|
+
case 'message':
|
|
37
|
+
childProcess.off('message', listener)
|
|
38
|
+
break
|
|
39
|
+
case 'error':
|
|
40
|
+
childProcess.off('error', listener)
|
|
41
|
+
break
|
|
42
|
+
case 'exit':
|
|
43
|
+
childProcess.off('exit', listener)
|
|
44
|
+
break
|
|
45
|
+
default:
|
|
46
|
+
throw new Error(`unsupported event type ${event}`)
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
send(message) {
|
|
50
|
+
childProcess.send(message)
|
|
51
|
+
},
|
|
52
|
+
dispose() {
|
|
53
|
+
childProcess.kill()
|
|
54
|
+
},
|
|
55
|
+
_process: childProcess,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Worker } from 'node:worker_threads'
|
|
2
|
+
import * as Platform from '../Platform/Platform.js'
|
|
3
|
+
|
|
4
|
+
export const create = () => {
|
|
5
|
+
const extensionHostPath = Platform.getExtensionHostPath()
|
|
6
|
+
const child = new Worker(extensionHostPath, {
|
|
7
|
+
execArgv: [
|
|
8
|
+
'--experimental-json-modules',
|
|
9
|
+
'--max-old-space-size=60',
|
|
10
|
+
'--enable-source-maps',
|
|
11
|
+
],
|
|
12
|
+
env: {
|
|
13
|
+
...process.env,
|
|
14
|
+
LOGS_DIR: Platform.getLogsDir(),
|
|
15
|
+
CONFIG_DIR: Platform.getConfigDir(),
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
return {
|
|
19
|
+
on(event, listener) {
|
|
20
|
+
switch (event) {
|
|
21
|
+
case 'message':
|
|
22
|
+
child.on('message', listener)
|
|
23
|
+
break
|
|
24
|
+
case 'error':
|
|
25
|
+
child.on('error', listener)
|
|
26
|
+
break
|
|
27
|
+
default:
|
|
28
|
+
break
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
send(message) {
|
|
32
|
+
child.postMessage(message)
|
|
33
|
+
},
|
|
34
|
+
dispose() {
|
|
35
|
+
child.terminate()
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import VError from 'verror'
|
|
2
|
+
import * as Assert from '../Assert/Assert.js'
|
|
3
|
+
import * as Timeout from '../Timeout/Timeout.js'
|
|
4
|
+
|
|
5
|
+
// TODO maybe rename to extension host management for clarity
|
|
6
|
+
|
|
7
|
+
const CONNECTION_TIMEOUT = 1000
|
|
8
|
+
|
|
9
|
+
export const create = async (ipc, socket) => {
|
|
10
|
+
Assert.object(socket)
|
|
11
|
+
|
|
12
|
+
const handleChildProcessError = (error) => {
|
|
13
|
+
console.error(`[Extension Host] ${error}`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const handleChildProcessExit = (exitCode) => {
|
|
17
|
+
console.info(`[SharedProcess] Extension Host exited with code ${exitCode}`)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const handleSocketClose = () => {
|
|
21
|
+
console.info('[shared process] disposing extension host')
|
|
22
|
+
ipc.dispose()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
socket.on('close', handleSocketClose)
|
|
26
|
+
|
|
27
|
+
ipc.on('error', handleChildProcessError)
|
|
28
|
+
|
|
29
|
+
ipc.on('exit', handleChildProcessExit)
|
|
30
|
+
|
|
31
|
+
await new Promise((resolve, reject) => {
|
|
32
|
+
const handleFirstError = (error) => {
|
|
33
|
+
cleanup()
|
|
34
|
+
reject(error)
|
|
35
|
+
}
|
|
36
|
+
const handleFirstExit = (exitCode) => {
|
|
37
|
+
cleanup()
|
|
38
|
+
reject(new VError(`Extension Host exited with code ${exitCode}`))
|
|
39
|
+
}
|
|
40
|
+
const handleFirstMessage = (message) => {
|
|
41
|
+
cleanup()
|
|
42
|
+
if (message === 'ready') {
|
|
43
|
+
resolve(undefined)
|
|
44
|
+
} else {
|
|
45
|
+
reject(new VError('Unexpected first message from extension host'))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const handleSocketClose = () => {
|
|
49
|
+
cleanup()
|
|
50
|
+
ipc.off('error', handleChildProcessError)
|
|
51
|
+
ipc.off('exit', handleChildProcessExit)
|
|
52
|
+
resolve(undefined)
|
|
53
|
+
}
|
|
54
|
+
const cleanup = () => {
|
|
55
|
+
ipc.off('error', handleFirstError)
|
|
56
|
+
ipc.off('exit', handleFirstExit)
|
|
57
|
+
ipc.off('message', handleFirstMessage)
|
|
58
|
+
clearTimeout(timeout)
|
|
59
|
+
}
|
|
60
|
+
const handleTimeout = () => {
|
|
61
|
+
cleanup()
|
|
62
|
+
reject(new VError('Extension host did not connect'))
|
|
63
|
+
}
|
|
64
|
+
const timeout = Timeout.setTimeout(handleTimeout, CONNECTION_TIMEOUT)
|
|
65
|
+
ipc.on('error', handleFirstError)
|
|
66
|
+
ipc.on('exit', handleFirstExit)
|
|
67
|
+
ipc.on('message', handleFirstMessage)
|
|
68
|
+
socket.on('close', handleSocketClose)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
on(event, listener) {
|
|
73
|
+
ipc.on(event, listener)
|
|
74
|
+
},
|
|
75
|
+
send(message) {
|
|
76
|
+
ipc.send(message)
|
|
77
|
+
},
|
|
78
|
+
dispose() {
|
|
79
|
+
ipc.dispose()
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as ExtensionHostIconTheme from '../ExtensionManagement/ExtensionManagementIconTheme.js'
|
|
2
2
|
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
3
|
+
import * as ExtensionHostColorTheme from './ExtensionManagementColorTheme.js'
|
|
4
|
+
import * as ExtensionHostLanguages from './ExtensionManagementLanguages.js'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
// prettier-ignore
|
|
7
|
+
export const Commands = {
|
|
8
|
+
'ExtensionManagement.install': ExtensionManagement.install,
|
|
9
|
+
'ExtensionManagement.uninstall': ExtensionManagement.uninstall,
|
|
10
|
+
'ExtensionManagement.enable': ExtensionManagement.enable,
|
|
11
|
+
'ExtensionManagement.disable': ExtensionManagement.disable,
|
|
12
|
+
'ExtensionManagement.getAllExtensions': ExtensionManagement.getAllExtensions,
|
|
13
|
+
'ExtensionManagement.getExtensions': ExtensionManagement.getExtensions,
|
|
14
|
+
'ExtensionHost.getColorThemeJson': ExtensionHostColorTheme.getColorThemeJson,
|
|
15
|
+
'ExtensionHost.getColorThemeNames': ExtensionHostColorTheme.getColorThemeNames,
|
|
16
|
+
'ExtensionHost.getLanguages': ExtensionHostLanguages.getLanguages,
|
|
17
|
+
'ExtensionHost.getLanguageConfiguration': ExtensionHostLanguages.getLanguageConfiguration,
|
|
18
|
+
'ExtensionHost.getIconThemeJson': ExtensionHostIconTheme.getIconTheme,
|
|
11
19
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, readdir, rename, rm } from 'node:fs/promises'
|
|
2
2
|
import { performance } from 'node:perf_hooks'
|
|
3
|
+
import path from 'node:path'
|
|
3
4
|
import isObject from 'is-object'
|
|
4
5
|
import VError from 'verror'
|
|
5
6
|
import * as Debug from '../Debug/Debug.js'
|
|
@@ -8,10 +9,12 @@ import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
|
8
9
|
import * as Path from '../Path/Path.js'
|
|
9
10
|
import * as Platform from '../Platform/Platform.js'
|
|
10
11
|
import * as Queue from '../Queue/Queue.js'
|
|
11
|
-
import path from 'node:path'
|
|
12
12
|
|
|
13
13
|
const isLanguageBasics = (extension) => {
|
|
14
|
-
|
|
14
|
+
if (extension && extension.id) {
|
|
15
|
+
return extension.id.includes('language-basics')
|
|
16
|
+
}
|
|
17
|
+
return false
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export const state = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Error from '../Error/Error.js'
|
|
2
|
-
import * as ExtensionManagement from '../ExtensionManagement/ExtensionManagement.js'
|
|
3
2
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
3
|
+
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
4
4
|
|
|
5
5
|
// TODO test this function
|
|
6
6
|
// TODO very similar with getIconTheme
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Error from '../Error/Error.js'
|
|
2
|
-
import * as ExtensionManagement from '../ExtensionManagement/ExtensionManagement.js'
|
|
3
2
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
3
|
+
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
4
4
|
|
|
5
5
|
export const getIconTheme = async (iconThemeId) => {
|
|
6
6
|
const extensions = await ExtensionManagement.getExtensions()
|
|
@@ -2,9 +2,9 @@ import { join } from 'node:path'
|
|
|
2
2
|
import { pathToFileURL } from 'node:url'
|
|
3
3
|
import VError from 'verror'
|
|
4
4
|
import * as Error from '../Error/Error.js'
|
|
5
|
-
import * as ExtensionManagement from '../ExtensionManagement/ExtensionManagement.js'
|
|
6
5
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
7
6
|
import * as Path from '../Path/Path.js'
|
|
7
|
+
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
8
8
|
|
|
9
9
|
const getExtensionLanguages = (extension) => {
|
|
10
10
|
if (!extension.languages) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as Command from '../Command/Command.js'
|
|
2
1
|
import * as FileSystem from './FileSystem.js'
|
|
3
2
|
|
|
4
3
|
// TODO ugly code here -> should be inside FileSystem.js
|
|
@@ -6,7 +5,6 @@ const fileSystemWatch = (socket, id, path) => {
|
|
|
6
5
|
// const watcher = FileSystem.watch(path, {
|
|
7
6
|
// onAll(...args) {
|
|
8
7
|
// socket.send(JSON.stringify([/* callback */ id, /* event */ args]))
|
|
9
|
-
|
|
10
8
|
// }
|
|
11
9
|
// }
|
|
12
10
|
// )
|
|
@@ -16,17 +14,18 @@ const fileSystemWatch = (socket, id, path) => {
|
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
// TODO separate ipc from code like in renderer worker
|
|
19
|
-
export const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
export const Commands = {
|
|
18
|
+
'FileSystem.copy': FileSystem.copy,
|
|
19
|
+
'FileSystem.createFile': FileSystem.createFile,
|
|
20
|
+
'FileSystem.createFolder': FileSystem.createFolder,
|
|
21
|
+
'FileSystem.ensureFile': FileSystem.ensureFile,
|
|
22
|
+
'FileSystem.getPathSeparator': FileSystem.getPathSeparator,
|
|
23
|
+
'FileSystem.getRealPath': FileSystem.getRealPath,
|
|
24
|
+
'FileSystem.mkdir': FileSystem.mkdir,
|
|
25
|
+
'FileSystem.readDirWithFileTypes': FileSystem.readDirWithFileTypes,
|
|
26
|
+
'FileSystem.readFile': FileSystem.readFile,
|
|
27
|
+
'FileSystem.remove': FileSystem.remove,
|
|
28
|
+
'FileSystem.rename': FileSystem.rename,
|
|
29
|
+
'FileSystem.stat': FileSystem.stat,
|
|
30
|
+
'FileSystem.writeFile': FileSystem.writeFile,
|
|
32
31
|
}
|
|
@@ -6,6 +6,7 @@ import * as Error from '../Error/Error.js'
|
|
|
6
6
|
import * as Path from '../Path/Path.js'
|
|
7
7
|
import * as Trash from '../Trash/Trash.js'
|
|
8
8
|
import * as Platform from '../Platform/Platform.js'
|
|
9
|
+
import VError from 'verror'
|
|
9
10
|
|
|
10
11
|
export const state = {
|
|
11
12
|
watcherMap: Object.create(null),
|
|
@@ -15,6 +16,17 @@ export const copy = async (source, target) => {
|
|
|
15
16
|
try {
|
|
16
17
|
await fs.cp(source, target, { recursive: true })
|
|
17
18
|
} catch (error) {
|
|
19
|
+
if (
|
|
20
|
+
error &&
|
|
21
|
+
error.message &&
|
|
22
|
+
error.message.startsWith(
|
|
23
|
+
'Invalid src or dest: cp returned EINVAL (src and dest cannot be the same)'
|
|
24
|
+
)
|
|
25
|
+
) {
|
|
26
|
+
throw new VError(
|
|
27
|
+
`Failed to copy "${source}" to "${target}": src and dest cannot be the same`
|
|
28
|
+
)
|
|
29
|
+
}
|
|
18
30
|
throw new Error.OperationalError({
|
|
19
31
|
cause: error,
|
|
20
32
|
code: 'E_FILE_SYSTEM_ERROR',
|
|
@@ -26,7 +38,7 @@ export const copy = async (source, target) => {
|
|
|
26
38
|
|
|
27
39
|
export const readFile = async (path) => {
|
|
28
40
|
try {
|
|
29
|
-
const content = await fs.readFile(path, '
|
|
41
|
+
const content = await fs.readFile(path, 'utf8')
|
|
30
42
|
return content
|
|
31
43
|
} catch (error) {
|
|
32
44
|
throw new Error.OperationalError({
|
|
@@ -135,6 +147,9 @@ export const exists = async (path) => {
|
|
|
135
147
|
}
|
|
136
148
|
}
|
|
137
149
|
|
|
150
|
+
/**
|
|
151
|
+
* @param {import('fs').Dirent|import('fs').StatsBase} dirent
|
|
152
|
+
*/
|
|
138
153
|
const getType = (dirent) => {
|
|
139
154
|
if (dirent.isFile()) {
|
|
140
155
|
return 'file'
|
|
@@ -142,9 +157,24 @@ const getType = (dirent) => {
|
|
|
142
157
|
if (dirent.isDirectory()) {
|
|
143
158
|
return 'directory'
|
|
144
159
|
}
|
|
160
|
+
if (dirent.isSymbolicLink()) {
|
|
161
|
+
return 'symlink'
|
|
162
|
+
}
|
|
163
|
+
if (dirent.isSocket()) {
|
|
164
|
+
return 'socket'
|
|
165
|
+
}
|
|
166
|
+
if (dirent.isBlockDevice()) {
|
|
167
|
+
return 'block-device'
|
|
168
|
+
}
|
|
169
|
+
if (dirent.isCharacterDevice()) {
|
|
170
|
+
return 'character-device'
|
|
171
|
+
}
|
|
145
172
|
return 'unknown'
|
|
146
173
|
}
|
|
147
174
|
|
|
175
|
+
/**
|
|
176
|
+
* @param {import('fs').Dirent} dirent
|
|
177
|
+
*/
|
|
148
178
|
const toPrettyDirent = (dirent) => {
|
|
149
179
|
return {
|
|
150
180
|
name: dirent.name,
|
|
@@ -212,6 +242,31 @@ export const getPathSeparator = () => {
|
|
|
212
242
|
return Platform.getPathSeparator()
|
|
213
243
|
}
|
|
214
244
|
|
|
245
|
+
export const getRealPath = async (path) => {
|
|
246
|
+
try {
|
|
247
|
+
return await fs.realpath(path)
|
|
248
|
+
} catch (error) {
|
|
249
|
+
// @ts-ignore
|
|
250
|
+
if (error && error instanceof globalThis.Error && error.code === 'ENOENT') {
|
|
251
|
+
let content
|
|
252
|
+
try {
|
|
253
|
+
content = await fs.readlink(path)
|
|
254
|
+
} catch {
|
|
255
|
+
throw new VError(error, `Failed to resolve real path for ${path}`)
|
|
256
|
+
}
|
|
257
|
+
throw new VError(`Broken symbolic link: File not found ${content}`)
|
|
258
|
+
}
|
|
259
|
+
throw new VError(error, `Failed to resolve real path for ${path}`)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export const stat = async (path) => {
|
|
264
|
+
const stats = await fs.stat(path)
|
|
265
|
+
const type = getType(stats)
|
|
266
|
+
return type
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// getRealPath('/home/simon/Documents/levivilet/lvce-editor/node_modules/.bin/abc') //?
|
|
215
270
|
// export const unwatch = (id) => {
|
|
216
271
|
// state.watchers[id].close()
|
|
217
272
|
// delete state.watchers[id]
|
|
@@ -8,11 +8,11 @@ export const send = (transport, method, ...params) => {
|
|
|
8
8
|
})
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export const invoke = (
|
|
11
|
+
export const invoke = (ipc, method, ...params) => {
|
|
12
12
|
return new Promise((resolve, reject) => {
|
|
13
13
|
// TODO use one map instead of two
|
|
14
14
|
const callbackId = Callback.register(resolve, reject)
|
|
15
|
-
|
|
15
|
+
ipc.send({
|
|
16
16
|
jsonrpc: '2.0',
|
|
17
17
|
method,
|
|
18
18
|
params,
|