@lvce-editor/shared-process 0.16.18 → 0.16.19
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/extensions/builtin.language-basics-javascript/src/tokenizeJavaScript.js +5 -0
- package/extensions/builtin.language-basics-less/src/tokenizeLess.js +17 -1
- package/package.json +4 -4
- package/src/parts/ElectronContextMenu/ElectronContextMenu.ipc.js +7 -0
- package/src/parts/ElectronContextMenu/ElectronContextMenu.js +5 -0
- package/src/parts/ElectronProcess/ElectronProcess.ipc.js +8 -0
- package/src/parts/ElectronProcess/ElectronProcess.js +9 -0
- package/src/parts/ElectronSafeStorage/ElectronSafeStorage.ipc.js +9 -0
- package/src/parts/ElectronSafeStorage/ElectronSafeStorage.js +13 -0
- package/src/parts/ExtensionManifest/ExtensionManifest.js +2 -1
- package/src/parts/ExtensionManifests/ExtensionManifestsFromFolder.js +2 -4
- package/src/parts/ExtensionManifests/ExtensionManifestsFromLinkedExtensionsFolder.js +2 -4
- package/src/parts/FileSystem/FileSystem.js +9 -4
- package/src/parts/GetAccurateMemoryUsage/GetAccurateMemoryUsage.js +30 -23
- package/src/parts/GetElectronRebuildPath/GetElectronRebuildPath.js +2 -2
- package/src/parts/GetFirstEvent/GetFirstEvent.js +22 -0
- package/src/parts/GetFirstNodeWorkerEvent/GetFirstNodeWorkerEvent.js +5 -16
- package/src/parts/GetFirstWebSocketEvent/GetFirstWebSocketEvent.js +3 -3
- package/src/parts/GetHttpErrorMessage/GetHttpErrorMessage.js +28 -0
- package/src/parts/GetLatestReleaseVersion/GetLatestReleaseVersion.js +2 -28
- package/src/parts/GetTerminalProcessPath/GetTerminalProcessPath.js +6 -0
- package/src/parts/IpcParentType/IpcParentType.js +1 -0
- package/src/parts/IpcParentWithElectronUtilityProcess/IpcParentWithElectronUtilityProcess.js +12 -0
- package/src/parts/IsEsrchError/IsEsrchError.js +5 -0
- package/src/parts/IsWindows/IsWindows.js +1 -0
- package/src/parts/ListProcessGetName/ListProcessGetName.js +3 -0
- package/src/parts/Module/Module.js +10 -2
- package/src/parts/ModuleId/ModuleId.js +5 -0
- package/src/parts/ModuleMap/ModuleMap.js +18 -0
- package/src/parts/PassThroughElectronMessageForTerminalProcess/PassThroughElectronMessageForTerminalProcess.js +29 -0
- package/src/parts/PassThroughElectronMessagePort/PassThroughElectronMessagePort.ipc.js +7 -0
- package/src/parts/PassThroughElectronMessagePort/PassThroughElectronMessagePort.js +4 -0
- package/src/parts/PassThroughElectronMessagePortModule/PassThroughElectronMessagePortModule.js +8 -0
- package/src/parts/Platform/Platform.ipc.js +1 -1
- package/src/parts/Platform/Platform.js +3 -3
- package/src/parts/Preferences/Preferences.js +2 -1
- package/src/parts/Process/Process.js +4 -0
- package/src/parts/PtyHost/PtyHost.js +17 -12
- package/src/parts/RebuildForElectron/RebuildForElectron.js +19 -0
- package/src/parts/RebuildForNode/RebuildForNode.js +17 -0
- package/src/parts/RebuildNodePty/RebuildNodePty.js +5 -38
- package/src/parts/RecentlyOpened/RecentlyOpened.js +3 -2
- package/src/parts/Terminal/Terminal.js +5 -3
- package/src/parts/WaitForProcessToExit/WaitForProcessToExit.js +4 -24
- package/src/parts/WebSocketReadyState/WebSocketReadyState.js +5 -0
- package/src/parts/Window/ElectronWindow.ipc.js +12 -0
- package/src/parts/Window/ElectronWindow.js +32 -0
|
@@ -143,6 +143,8 @@ const RE_REGEX =
|
|
|
143
143
|
|
|
144
144
|
const RE_VARIABLE_NAME_SPECIAL = /\p{L}/u
|
|
145
145
|
const RE_VARIABLE_NAME_SPECIAL_2 = /./u
|
|
146
|
+
const RE_BUILTIN_CLASS =
|
|
147
|
+
/^(?:Array|Object|Promise|ArrayBuffer|URL|URLSearchParams|WebSocket|FileSystemHandle|Function|StorageEvent|MessageEvent|MessageChannel|Int32Array|Boolean|String|Error|Set|RegExp|Map|WeakMap|RangeError|Date|Headers|Response|Request|Buffer|MessagePort|FileHandle|X509Certificate|Blob|HTMLElement)\b/
|
|
146
148
|
|
|
147
149
|
export const initialLineState = {
|
|
148
150
|
state: State.TopLevelContent,
|
|
@@ -251,6 +253,9 @@ export const tokenizeLine = (line, lineState) => {
|
|
|
251
253
|
} else if ((next = part.match(RE_FUNCTION_CALL_NAME))) {
|
|
252
254
|
token = TokenType.FunctionName
|
|
253
255
|
state = State.TopLevelContent
|
|
256
|
+
} else if ((next = part.match(RE_BUILTIN_CLASS))) {
|
|
257
|
+
token = TokenType.Class
|
|
258
|
+
state = State.TopLevelContent
|
|
254
259
|
} else if ((next = part.match(RE_VARIABLE_NAME))) {
|
|
255
260
|
token = TokenType.VariableName
|
|
256
261
|
state = State.TopLevelContent
|
|
@@ -125,6 +125,8 @@ const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^']+/
|
|
|
125
125
|
const RE_SINGLE_QUOTE = /^'/
|
|
126
126
|
const RE_ANYTHING_BUT_CURLY = /^[^\{\}]+/s
|
|
127
127
|
const RE_LINE_COMMENT = /\/\/.*/
|
|
128
|
+
const RE_NESTED_SELECTOR = /^[\w\.\-\s]+(?=\s*(?:\{|,))/
|
|
129
|
+
const RE_AMPERSAND = /^\&/
|
|
128
130
|
|
|
129
131
|
/**
|
|
130
132
|
* @param {string} line
|
|
@@ -205,9 +207,13 @@ export const tokenizeLine = (line, lineState) => {
|
|
|
205
207
|
if ((next = part.match(RE_WHITESPACE))) {
|
|
206
208
|
token = TokenType.Whitespace
|
|
207
209
|
state = State.AfterSelector
|
|
210
|
+
} else if ((next = part.match(RE_AMPERSAND))) {
|
|
211
|
+
token = TokenType.Punctuation
|
|
212
|
+
state = State.AfterSelector
|
|
208
213
|
} else if ((next = part.match(RE_CURLY_OPEN))) {
|
|
209
214
|
token = TokenType.CurlyOpen
|
|
210
215
|
state = State.InsideSelector
|
|
216
|
+
stack.push(State.InsideSelector)
|
|
211
217
|
} else if ((next = part.match(RE_SELECTOR_CLASS))) {
|
|
212
218
|
token = TokenType.CssSelectorClass
|
|
213
219
|
state = State.AfterSelector
|
|
@@ -297,6 +303,16 @@ export const tokenizeLine = (line, lineState) => {
|
|
|
297
303
|
if ((next = part.match(RE_WHITESPACE))) {
|
|
298
304
|
token = TokenType.Whitespace
|
|
299
305
|
state = State.InsideSelector
|
|
306
|
+
} else if ((next = part.match(RE_AMPERSAND))) {
|
|
307
|
+
token = TokenType.Punctuation
|
|
308
|
+
state = State.InsideSelector
|
|
309
|
+
} else if ((next = part.match(RE_NESTED_SELECTOR))) {
|
|
310
|
+
if (next[0].startsWith('.')) {
|
|
311
|
+
token = TokenType.CssSelectorClass
|
|
312
|
+
} else {
|
|
313
|
+
token = TokenType.CssSelector
|
|
314
|
+
}
|
|
315
|
+
state = State.AfterSelector
|
|
300
316
|
} else if ((next = part.match(RE_PROPERTY_NAME))) {
|
|
301
317
|
token = TokenType.CssPropertyName
|
|
302
318
|
state = State.AfterPropertyName
|
|
@@ -318,7 +334,7 @@ export const tokenizeLine = (line, lineState) => {
|
|
|
318
334
|
state = State.InsideSelector
|
|
319
335
|
} else if ((next = part.match(RE_CURLY_CLOSE))) {
|
|
320
336
|
token = TokenType.CurlyClose
|
|
321
|
-
state = State.TopLevelContent
|
|
337
|
+
state = stack.pop() || State.TopLevelContent
|
|
322
338
|
} else {
|
|
323
339
|
throw new Error('no')
|
|
324
340
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/shared-process",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.19",
|
|
4
4
|
"description": "Utility package for @lvce-editor/server",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@babel/code-frame": "^7.22.5",
|
|
20
|
-
"@lvce-editor/extension-host": "0.16.
|
|
21
|
-
"@lvce-editor/extension-host-helper-process": "0.16.
|
|
22
|
-
"@lvce-editor/pty-host": "0.16.
|
|
20
|
+
"@lvce-editor/extension-host": "0.16.19",
|
|
21
|
+
"@lvce-editor/extension-host-helper-process": "0.16.19",
|
|
22
|
+
"@lvce-editor/pty-host": "0.16.19",
|
|
23
23
|
"debug": "^4.3.4",
|
|
24
24
|
"execa": "^7.1.1",
|
|
25
25
|
"exit-hook": "^3.2.0",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as ElectronSafeStorage from './ElectronSafeStorage.js'
|
|
2
|
+
|
|
3
|
+
export const name = 'ElectronSafeStorage'
|
|
4
|
+
|
|
5
|
+
export const Commands = {
|
|
6
|
+
decryptString: ElectronSafeStorage.decryptString,
|
|
7
|
+
encryptString: ElectronSafeStorage.encryptString,
|
|
8
|
+
isEncryptionAvailable: ElectronSafeStorage.isEncryptionAvailable,
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as ParentIpc from '../ParentIpc/ParentIpc.js'
|
|
2
|
+
|
|
3
|
+
export const isEncryptionAvailable = () => {
|
|
4
|
+
return ParentIpc.invoke('ElectronSafeStorage.isEncryptionAvailable')
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const encryptString = (plainText) => {
|
|
8
|
+
return ParentIpc.invoke('ElectronSafeStorage.encryptString', plainText)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const decryptString = (encrypted) => {
|
|
12
|
+
return ParentIpc.invoke('ElectronSafeStorage.decryptString', encrypted)
|
|
13
|
+
}
|
|
@@ -3,6 +3,7 @@ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
|
3
3
|
import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
|
|
4
4
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
5
5
|
import * as Path from '../Path/Path.js'
|
|
6
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
6
7
|
import { VError } from '../VError/VError.js'
|
|
7
8
|
|
|
8
9
|
const RE_EXTENSION_FRAGMENT = /.+(\/|\\)(.+)$/
|
|
@@ -32,7 +33,7 @@ export const get = async (path) => {
|
|
|
32
33
|
} catch (error) {
|
|
33
34
|
const id = inferExtensionId(path)
|
|
34
35
|
const enhancedError = new VError(error, `Failed to load extension manifest for ${id}`)
|
|
35
|
-
if (error
|
|
36
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
36
37
|
try {
|
|
37
38
|
const monoRepoPath = Path.join(path, `packages`, 'extension', 'extension.json')
|
|
38
39
|
const json = await ReadJson.readJson(monoRepoPath)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
2
1
|
import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
|
|
3
2
|
import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
3
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
4
4
|
import * as ToAbsolutePaths from '../ToAbsolutePaths/ToAbsolutePaths.js'
|
|
5
5
|
import { VError } from '../VError/VError.js'
|
|
6
6
|
|
|
@@ -14,9 +14,7 @@ export const getExtensionManifests = async (path) => {
|
|
|
14
14
|
const manifests = await Promise.all(absolutePaths.map(ExtensionManifest.get))
|
|
15
15
|
return manifests
|
|
16
16
|
} catch (error) {
|
|
17
|
-
|
|
18
|
-
// @ts-ignore
|
|
19
|
-
if (error.code === ErrorCodes.ENOENT) {
|
|
17
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
20
18
|
return []
|
|
21
19
|
}
|
|
22
20
|
throw new VError(error, 'Failed to get extension manifests')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readlink } from 'fs/promises'
|
|
2
|
-
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
3
2
|
import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
|
|
4
3
|
import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
|
|
5
4
|
import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
5
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
6
6
|
import * as ToAbsolutePaths from '../ToAbsolutePaths/ToAbsolutePaths.js'
|
|
7
7
|
import { VError } from '../VError/VError.js'
|
|
8
8
|
|
|
@@ -46,9 +46,7 @@ export const getExtensionManifests = async (path) => {
|
|
|
46
46
|
const merged = mergeWithSymLinks(manifests, symlinks)
|
|
47
47
|
return merged
|
|
48
48
|
} catch (error) {
|
|
49
|
-
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
if (error.code === ErrorCodes.ENOENT) {
|
|
49
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
52
50
|
return []
|
|
53
51
|
}
|
|
54
52
|
throw new VError(error, 'Failed to get extension manifests')
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// TODO lazyload chokidar and trash (but doesn't work currently because of bug with jest)
|
|
2
2
|
import * as fs from 'node:fs/promises'
|
|
3
3
|
import * as os from 'node:os'
|
|
4
|
+
import * as Assert from '../Assert/Assert.js'
|
|
4
5
|
import * as EncodingType from '../EncodingType/EncodingType.js'
|
|
5
|
-
import { FileNotFoundError } from '../FileNotFoundError/FileNotFoundError.js'
|
|
6
6
|
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
7
|
+
import { FileNotFoundError } from '../FileNotFoundError/FileNotFoundError.js'
|
|
7
8
|
import * as GetDirentType from '../GetDirentType/GetDirentType.js'
|
|
9
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
8
10
|
import * as Path from '../Path/Path.js'
|
|
9
11
|
import * as Platform from '../Platform/Platform.js'
|
|
10
12
|
import * as Trash from '../Trash/Trash.js'
|
|
@@ -36,6 +38,7 @@ export const copy = async (source, target) => {
|
|
|
36
38
|
export const readFile = async (path, encoding = EncodingType.Utf8) => {
|
|
37
39
|
// console.info('[shared-process] read file', path)
|
|
38
40
|
try {
|
|
41
|
+
Assert.string(path)
|
|
39
42
|
// const start = performance.now()
|
|
40
43
|
// console.time(`read ${path}`)
|
|
41
44
|
const content = await fs.readFile(path, encoding)
|
|
@@ -44,7 +47,7 @@ export const readFile = async (path, encoding = EncodingType.Utf8) => {
|
|
|
44
47
|
// console.timeEnd(`read ${path}`)
|
|
45
48
|
return content
|
|
46
49
|
} catch (error) {
|
|
47
|
-
if (error
|
|
50
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
48
51
|
throw new FileNotFoundError(path)
|
|
49
52
|
}
|
|
50
53
|
throw new VError(error, `Failed to read file "${path}"`)
|
|
@@ -59,11 +62,13 @@ export const readFile = async (path, encoding = EncodingType.Utf8) => {
|
|
|
59
62
|
*/
|
|
60
63
|
export const writeFile = async (path, content, encoding = EncodingType.Utf8) => {
|
|
61
64
|
try {
|
|
65
|
+
Assert.string(path)
|
|
66
|
+
Assert.string(content)
|
|
62
67
|
// queue would be more correct for concurrent writes but also slower
|
|
63
68
|
// Queue.add(`writeFile/${path}`, () =>
|
|
64
69
|
await fs.writeFile(path, content, encoding)
|
|
65
70
|
} catch (error) {
|
|
66
|
-
if (error
|
|
71
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
67
72
|
throw new FileNotFoundError(path)
|
|
68
73
|
}
|
|
69
74
|
throw new VError(error, `Failed to write to file "${path}"`)
|
|
@@ -169,7 +174,7 @@ export const readDir = async (path) => {
|
|
|
169
174
|
const dirents = await fs.readdir(path)
|
|
170
175
|
return dirents
|
|
171
176
|
} catch (error) {
|
|
172
|
-
if (error
|
|
177
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
173
178
|
throw new FileNotFoundError(path)
|
|
174
179
|
}
|
|
175
180
|
throw new VError(error, `Failed to read directory "${path}"`)
|
|
@@ -3,34 +3,41 @@ import { join } from 'node:path'
|
|
|
3
3
|
import * as Assert from '../Assert/Assert.js'
|
|
4
4
|
import * as Character from '../Character/Character.js'
|
|
5
5
|
import * as EncodingType from '../EncodingType/EncodingType.js'
|
|
6
|
-
import * as
|
|
6
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
7
|
+
import * as IsEsrchError from '../IsEsrchError/IsEsrchError.js'
|
|
7
8
|
import { VError } from '../VError/VError.js'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
Assert.number(pid)
|
|
10
|
+
const getContent = async (pid) => {
|
|
11
11
|
try {
|
|
12
12
|
const filePath = join('/proc', `${pid}`, 'statm')
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
const content = await readFile(filePath, EncodingType.Utf8)
|
|
14
|
+
return content
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (IsEnoentError.isEnoentError(error) || IsEsrchError.isEsrchError(error)) {
|
|
17
|
+
return ''
|
|
18
|
+
}
|
|
19
|
+
throw error
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const parseMemory = (content) => {
|
|
24
|
+
const trimmedContent = content.trim()
|
|
25
|
+
const numberBlocks = trimmedContent.split(Character.Space)
|
|
26
|
+
const pageSize = 4096
|
|
27
|
+
const rss = Number.parseInt(numberBlocks[1]) * pageSize
|
|
28
|
+
const shared = Number.parseInt(numberBlocks[2]) * pageSize
|
|
29
|
+
const memory = rss - shared
|
|
30
|
+
return memory
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const getAccurateMemoryUsage = async (pid) => {
|
|
34
|
+
try {
|
|
35
|
+
Assert.number(pid)
|
|
36
|
+
const content = await getContent(pid)
|
|
37
|
+
if (!content) {
|
|
38
|
+
return -1
|
|
27
39
|
}
|
|
28
|
-
const
|
|
29
|
-
const numberBlocks = trimmedContent.split(Character.Space)
|
|
30
|
-
const pageSize = 4096
|
|
31
|
-
const rss = Number.parseInt(numberBlocks[1]) * pageSize
|
|
32
|
-
const shared = Number.parseInt(numberBlocks[2]) * pageSize
|
|
33
|
-
const memory = rss - shared
|
|
40
|
+
const memory = parseMemory(content)
|
|
34
41
|
return memory
|
|
35
42
|
} catch (error) {
|
|
36
43
|
throw new VError(error, 'Failed to get accurate memory usage')
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as IsWindows from '../IsWindows/IsWindows.js'
|
|
2
2
|
import * as Path from '../Path/Path.js'
|
|
3
3
|
import * as Root from '../Root/Root.js'
|
|
4
4
|
|
|
5
5
|
export const getElectronRebuildPath = () => {
|
|
6
|
-
if (
|
|
6
|
+
if (IsWindows.isWindows) {
|
|
7
7
|
return Path.join(Root.root, 'packages', 'main-process', 'node_modules', '.bin', 'electron-rebuild.cmd')
|
|
8
8
|
}
|
|
9
9
|
return Path.join(Root.root, 'packages', 'main-process', 'node_modules', '.bin', 'electron-rebuild')
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const getFirstEvent = async (eventEmitter, eventMap) => {
|
|
2
|
+
const { type, event } = await new Promise((resolve, reject) => {
|
|
3
|
+
const listenerMap = Object.create(null)
|
|
4
|
+
const cleanup = (value) => {
|
|
5
|
+
for (const event of Object.keys(eventMap)) {
|
|
6
|
+
eventEmitter.off(event, listenerMap[event])
|
|
7
|
+
}
|
|
8
|
+
resolve(value)
|
|
9
|
+
}
|
|
10
|
+
for (const [event, type] of Object.entries(eventMap)) {
|
|
11
|
+
const listener = (event) => {
|
|
12
|
+
cleanup({
|
|
13
|
+
type,
|
|
14
|
+
event,
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
eventEmitter.on(event, listener)
|
|
18
|
+
listenerMap[event] = listener
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
return { type, event }
|
|
22
|
+
}
|
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
2
|
+
import * as GetFirstEvent from '../GetFirstEvent/GetFirstEvent.js'
|
|
2
3
|
|
|
3
|
-
export const getFirstNodeWorkerEvent =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
worker.off('error', handleError)
|
|
8
|
-
resolve(value)
|
|
9
|
-
}
|
|
10
|
-
const handleExit = (event) => {
|
|
11
|
-
cleanup({ type: FirstNodeWorkerEventType.Exit, event })
|
|
12
|
-
}
|
|
13
|
-
const handleError = (event) => {
|
|
14
|
-
cleanup({ type: FirstNodeWorkerEventType.Error, event })
|
|
15
|
-
}
|
|
16
|
-
worker.on('exit', handleExit)
|
|
17
|
-
worker.on('error', handleError)
|
|
4
|
+
export const getFirstNodeWorkerEvent = (worker) => {
|
|
5
|
+
return GetFirstEvent.getFirstEvent(worker, {
|
|
6
|
+
exit: FirstNodeWorkerEventType.Exit,
|
|
7
|
+
error: FirstNodeWorkerEventType.Error,
|
|
18
8
|
})
|
|
19
|
-
return { type, event }
|
|
20
9
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as FirstWebSocketEventType from '../FirstWebSocketEventType/FirstWebSocketEventType.js'
|
|
2
|
-
import
|
|
2
|
+
import * as WebSocketReadyState from '../WebSocketReadyState/WebSocketReadyState.js'
|
|
3
3
|
|
|
4
4
|
export const getFirstWebSocketEvent = async (webSocket) => {
|
|
5
5
|
switch (webSocket.readyState) {
|
|
6
|
-
case
|
|
6
|
+
case WebSocketReadyState.Open:
|
|
7
7
|
return {
|
|
8
8
|
type: FirstWebSocketEventType.Open,
|
|
9
9
|
event: undefined,
|
|
10
10
|
}
|
|
11
|
-
case
|
|
11
|
+
case WebSocketReadyState.Closed:
|
|
12
12
|
return {
|
|
13
13
|
type: FirstWebSocketEventType.Close,
|
|
14
14
|
event: undefined,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HTTPError } from 'got'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {HTTPError} error
|
|
6
|
+
*/
|
|
7
|
+
export const getHttpErrorMessage = (error) => {
|
|
8
|
+
try {
|
|
9
|
+
const body = error.response.body
|
|
10
|
+
if (error.response.url.includes('api.github.com') && typeof body === 'string') {
|
|
11
|
+
const json = JSON.parse(body)
|
|
12
|
+
if (json.message) {
|
|
13
|
+
const message = json.message
|
|
14
|
+
if (message.includes('rate limit exceeded')) {
|
|
15
|
+
const reset = error.response.headers['x-ratelimit-reset']
|
|
16
|
+
const limit = error.response.headers['x-ratelimit-limit']
|
|
17
|
+
if (reset && typeof reset === 'string' && typeof limit === 'string') {
|
|
18
|
+
const resetDate = new Date(parseInt(reset) * 1000)
|
|
19
|
+
const limitAmount = parseInt(limit)
|
|
20
|
+
return `GitHub rate limit of ${limitAmount} requests per hour execeeded, resets at ${resetDate}`
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return json.message
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch {}
|
|
27
|
+
return `${error.message}`
|
|
28
|
+
}
|
|
@@ -1,33 +1,7 @@
|
|
|
1
1
|
import got, { HTTPError } from 'got'
|
|
2
|
+
import * as GetHttpErrorMessage from '../GetHttpErrorMessage/GetHttpErrorMessage.js'
|
|
2
3
|
import { VError } from '../VError/VError.js'
|
|
3
4
|
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* @param {HTTPError} error
|
|
7
|
-
*/
|
|
8
|
-
const getHttpErrorMessage = (error) => {
|
|
9
|
-
try {
|
|
10
|
-
const body = error.response.body
|
|
11
|
-
if (error.response.url.includes('api.github.com') && typeof body === 'string') {
|
|
12
|
-
const json = JSON.parse(body)
|
|
13
|
-
if (json.message) {
|
|
14
|
-
const message = json.message
|
|
15
|
-
if (message.includes('rate limit exceeded')) {
|
|
16
|
-
const reset = error.response.headers['x-ratelimit-reset']
|
|
17
|
-
const limit = error.response.headers['x-ratelimit-limit']
|
|
18
|
-
if (reset && typeof reset === 'string' && typeof limit === 'string') {
|
|
19
|
-
const resetDate = new Date(parseInt(reset) * 1000)
|
|
20
|
-
const limitAmount = parseInt(limit)
|
|
21
|
-
return `GitHub rate limit of ${limitAmount} requests per hour execeeded, resets at ${resetDate}`
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return json.message
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
} catch {}
|
|
28
|
-
return `${error.message}`
|
|
29
|
-
}
|
|
30
|
-
|
|
31
5
|
const parseVersionFromUrl = (url, repository) => {
|
|
32
6
|
if (!url.includes('releases/tag')) {
|
|
33
7
|
if (url.endsWith('/releases')) {
|
|
@@ -51,7 +25,7 @@ export const getLatestReleaseVersion = async (repository) => {
|
|
|
51
25
|
return version
|
|
52
26
|
} catch (error) {
|
|
53
27
|
if (error instanceof HTTPError) {
|
|
54
|
-
const httpErrorMessage = getHttpErrorMessage(error)
|
|
28
|
+
const httpErrorMessage = GetHttpErrorMessage.getHttpErrorMessage(error)
|
|
55
29
|
throw new VError(`Failed to get latest release for ${repository}: ${httpErrorMessage}`)
|
|
56
30
|
}
|
|
57
31
|
// @ts-ignore
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as ParentIpc from '../ParentIpc/ParentIpc.js'
|
|
2
|
+
|
|
3
|
+
export const create = async (options) => {
|
|
4
|
+
// TODO how to launch process without race condition?
|
|
5
|
+
// when promise resolves, process might have already exited
|
|
6
|
+
const messagePort = await ParentIpc.invoke('IpcParent.create', { ...options })
|
|
7
|
+
return messagePort
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const wrap = (messagePort) => {
|
|
11
|
+
return {}
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const isWindows = process.platform === 'win32'
|
|
@@ -20,8 +20,14 @@ export const load = (moduleId) => {
|
|
|
20
20
|
return import('../Developer/Developer.ipc.js')
|
|
21
21
|
case ModuleId.Download:
|
|
22
22
|
return import('../Download/Download.ipc.js')
|
|
23
|
+
case ModuleId.ElectronContextMenu:
|
|
24
|
+
return import('../ElectronContextMenu/ElectronContextMenu.ipc.js')
|
|
23
25
|
case ModuleId.ElectronInitialize:
|
|
24
26
|
return import('../ElectronInitialize/ElectronInitialize.ipc.js')
|
|
27
|
+
case ModuleId.ElectronProcess:
|
|
28
|
+
return import('../ElectronProcess/ElectronProcess.ipc.js')
|
|
29
|
+
case ModuleId.ElectronSafeStorage:
|
|
30
|
+
return import('../ElectronSafeStorage/ElectronSafeStorage.ipc.js')
|
|
25
31
|
case ModuleId.ExtensionHost:
|
|
26
32
|
return import('../ExtensionHost/ExtensionHost.ipc.js')
|
|
27
33
|
case ModuleId.ExtensionManagement:
|
|
@@ -52,6 +58,8 @@ export const load = (moduleId) => {
|
|
|
52
58
|
return import('../OpenNativeFolder/OpenNativeFolder.ipc.js')
|
|
53
59
|
case ModuleId.OutputChannel:
|
|
54
60
|
return import('../OutputChannel/OutputChannel.ipc.js')
|
|
61
|
+
case ModuleId.Performance:
|
|
62
|
+
return import('../Performance/Performance.ipc.js')
|
|
55
63
|
case ModuleId.Platform:
|
|
56
64
|
return import('../Platform/Platform.ipc.js')
|
|
57
65
|
case ModuleId.Preferences:
|
|
@@ -72,10 +80,10 @@ export const load = (moduleId) => {
|
|
|
72
80
|
return import('../TextSearch/TextSearch.ipc.js')
|
|
73
81
|
case ModuleId.WebSocketServer:
|
|
74
82
|
return import('../WebSocketServer/WebSocketServer.ipc.js')
|
|
83
|
+
case ModuleId.Window:
|
|
84
|
+
return import('../Window/ElectronWindow.ipc.js')
|
|
75
85
|
case ModuleId.Workspace:
|
|
76
86
|
return import('../Workspace/Workspace.ipc.js')
|
|
77
|
-
case ModuleId.Performance:
|
|
78
|
-
return import('../Performance/Performance.ipc.js')
|
|
79
87
|
default:
|
|
80
88
|
throw new Error(`module ${moduleId} not found`)
|
|
81
89
|
}
|
|
@@ -24,14 +24,19 @@ export const IsAutoUpdateSupported = 23
|
|
|
24
24
|
export const AutoUpdaterAppImage = 24
|
|
25
25
|
export const AutoUpdaterWindowsNsis = 25
|
|
26
26
|
export const RebuildNodePty = 26
|
|
27
|
+
export const ElectronSafeStorage = 80
|
|
27
28
|
export const ElectronInitialize = 27
|
|
28
29
|
export const HandleWebSocket = 28
|
|
29
30
|
export const Process = 29
|
|
30
31
|
export const AttachDebugger = 30
|
|
31
32
|
export const HandleElectronMessagePort = 31
|
|
33
|
+
export const ElectronProcess = 70
|
|
32
34
|
export const HandleNodeMessagePort = 32
|
|
33
35
|
export const GetTerminalSpawnOptions = 33
|
|
34
36
|
export const HandleCliArgs = 34
|
|
35
37
|
export const ListProcessesWithMemoryUsage = 35
|
|
38
|
+
export const ElectronContextMenu = 40
|
|
36
39
|
export const IncrementalTextSearch = 36
|
|
37
40
|
export const Performance = 37
|
|
41
|
+
export const Window = 38
|
|
42
|
+
export const PassThroughElectronMessagePort = 39
|
|
@@ -3,6 +3,8 @@ import * as ModuleId from '../ModuleId/ModuleId.js'
|
|
|
3
3
|
|
|
4
4
|
export const getModuleId = (commandId) => {
|
|
5
5
|
switch (commandId) {
|
|
6
|
+
case 'PassthroughElectronMessagePort.passThroughElectronMessagePort':
|
|
7
|
+
return ModuleId.PassThroughElectronMessagePort
|
|
6
8
|
case 'AttachDebugger.attachDebugger':
|
|
7
9
|
return ModuleId.AttachDebugger
|
|
8
10
|
case 'AutoUpdater.getAutoUpdateType':
|
|
@@ -22,6 +24,10 @@ export const getModuleId = (commandId) => {
|
|
|
22
24
|
case 'ClipBoard.readFiles':
|
|
23
25
|
case 'ClipBoard.writeFiles':
|
|
24
26
|
return ModuleId.ClipBoard
|
|
27
|
+
case 'ElectronSafeStorage.encryptString':
|
|
28
|
+
case 'ElectronSafeStorage.decryptString':
|
|
29
|
+
case 'ElectronSafeStorage.isEncryptionAvailable':
|
|
30
|
+
return ModuleId.ElectronSafeStorage
|
|
25
31
|
case 'Developer.allocateMemory':
|
|
26
32
|
case 'Developer.crashSharedProcess':
|
|
27
33
|
case 'Developer.createHeapSnapshot':
|
|
@@ -177,13 +183,25 @@ export const getModuleId = (commandId) => {
|
|
|
177
183
|
case 'Terminal.resize':
|
|
178
184
|
case 'Terminal.write':
|
|
179
185
|
return ModuleId.Terminal
|
|
186
|
+
case 'ElectronProcess.getChromeVersion':
|
|
187
|
+
case 'ElectronProcess.getElectronVersion':
|
|
188
|
+
return ModuleId.ElectronProcess
|
|
180
189
|
case 4820:
|
|
181
190
|
return ModuleId.TextDocument
|
|
191
|
+
case 'ElectronContextMenu.openContextMenu':
|
|
192
|
+
return ModuleId.ElectronContextMenu
|
|
182
193
|
case 'WebSocketServer.handleUpgrade':
|
|
183
194
|
return ModuleId.WebSocketServer
|
|
184
195
|
case 'Workspace.getHomeDir':
|
|
185
196
|
case 'Workspace.resolveRoot':
|
|
186
197
|
return ModuleId.Workspace
|
|
198
|
+
case 'ElectronWindow.minimize':
|
|
199
|
+
case 'ElectronWindow.maximize':
|
|
200
|
+
case 'ElectronWindow.toggleDevtools':
|
|
201
|
+
case 'ElectronWindow.unmaximize':
|
|
202
|
+
case 'ElectronWindow.close':
|
|
203
|
+
case 'ElectronWindow.reload':
|
|
204
|
+
return ModuleId.Window
|
|
187
205
|
default:
|
|
188
206
|
throw new CommandNotFoundError(commandId)
|
|
189
207
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Assert from '../Assert/Assert.js'
|
|
2
|
+
import * as GetTerminalProcessPath from '../GetTerminalProcessPath/GetTerminalProcessPath.js'
|
|
3
|
+
import * as IpcParent from '../IpcParent/IpcParent.js'
|
|
4
|
+
import * as IpcParentType from '../IpcParentType/IpcParentType.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
export const handlePort = async (browserWindowPort, type, name) => {
|
|
11
|
+
Assert.object(browserWindowPort)
|
|
12
|
+
Assert.string(type)
|
|
13
|
+
Assert.string(name)
|
|
14
|
+
const ptyHostPath = GetTerminalProcessPath.getTerminalProcessPath()
|
|
15
|
+
const ipc = await IpcParent.create({
|
|
16
|
+
method: IpcParentType.ElectronUtilityProcess,
|
|
17
|
+
path: ptyHostPath,
|
|
18
|
+
name,
|
|
19
|
+
})
|
|
20
|
+
// TODO use connectIpc for better error handling
|
|
21
|
+
ipc.sendAndTransfer(
|
|
22
|
+
{
|
|
23
|
+
jsonrpc: '2.0',
|
|
24
|
+
method: 'HandleElectronMessagePort.handleElectronMessagePort',
|
|
25
|
+
params: [],
|
|
26
|
+
},
|
|
27
|
+
[browserWindowPort]
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as PassThroughElectronMessagePort from './PassThroughElectronMessagePort.js'
|
|
2
|
+
|
|
3
|
+
export const name = 'PassThroughElectronMessagePort'
|
|
4
|
+
|
|
5
|
+
export const Commands = {
|
|
6
|
+
passThroughElectronMessagePort: PassThroughElectronMessagePort.passThroughElectronMessagePort,
|
|
7
|
+
}
|
|
@@ -21,8 +21,8 @@ export const Commands = {
|
|
|
21
21
|
getRecentlyOpenedPath: Platform.getRecentlyOpenedPath,
|
|
22
22
|
getTestPath: Platform.getTestPath,
|
|
23
23
|
getTmpDir: Platform.getTmpDir,
|
|
24
|
+
getUserKeyBindingsPath: Platform.getUserKeyBindingsPath,
|
|
24
25
|
getUserSettingsPath: Platform.getUserSettingsPath,
|
|
25
26
|
getVersion: Platform.getVersion,
|
|
26
27
|
setEnvironmentVariables: Platform.setEnvironmentVariables,
|
|
27
|
-
getUserKeyBindingsPath: Platform.getUserKeyBindingsPath,
|
|
28
28
|
}
|
|
@@ -169,11 +169,11 @@ export const getSetupName = () => {
|
|
|
169
169
|
return 'Lvce-Setup'
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
export const version = '0.16.
|
|
172
|
+
export const version = '0.16.19'
|
|
173
173
|
|
|
174
|
-
export const commit = '
|
|
174
|
+
export const commit = '6594144'
|
|
175
175
|
|
|
176
|
-
export const date = '2023-07-
|
|
176
|
+
export const date = '2023-07-27T00:13:37.000Z'
|
|
177
177
|
|
|
178
178
|
export const getVersion = () => {
|
|
179
179
|
return version
|
|
@@ -2,6 +2,7 @@ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
|
2
2
|
import * as JsoncFile from '../JsoncFile/JsoncFile.js'
|
|
3
3
|
import * as Platform from '../Platform/Platform.js'
|
|
4
4
|
import * as Process from '../Process/Process.js'
|
|
5
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
5
6
|
import { VError } from '../VError/VError.js'
|
|
6
7
|
// TODO need jsonc parser for settings with comments
|
|
7
8
|
|
|
@@ -12,7 +13,7 @@ export const getUserPreferences = async () => {
|
|
|
12
13
|
try {
|
|
13
14
|
json = await JsoncFile.readJsonc(userSettingsPath)
|
|
14
15
|
} catch (error) {
|
|
15
|
-
if (error
|
|
16
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
16
17
|
return {}
|
|
17
18
|
}
|
|
18
19
|
throw error
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { VError } from '../VError/VError.js'
|
|
2
|
+
import * as IsEsrchError from '../IsEsrchError/IsEsrchError.js'
|
|
2
3
|
|
|
3
4
|
export const crash = (message) => {
|
|
4
5
|
throw new Error(message)
|
|
@@ -34,6 +35,9 @@ export const kill = (pid, signal) => {
|
|
|
34
35
|
try {
|
|
35
36
|
process.kill(pid, signal)
|
|
36
37
|
} catch (error) {
|
|
38
|
+
if (IsEsrchError.isEsrchError(error)) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
37
41
|
throw new VError(error, `Failed to kill process ${pid} with signal ${signal}`)
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -3,12 +3,13 @@ import * as Debug from '../Debug/Debug.js'
|
|
|
3
3
|
import * as IpcParent from '../IpcParent/IpcParent.js'
|
|
4
4
|
import * as IpcParentType from '../IpcParentType/IpcParentType.js'
|
|
5
5
|
import * as PtyHostPath from '../PtyHostPath/PtyHostPath.js'
|
|
6
|
+
import * as JsonRpc from '../JsonRpc/JsonRpc.js'
|
|
6
7
|
|
|
7
8
|
export const state = {
|
|
8
9
|
/**
|
|
9
10
|
* @type {any}
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
+
ipc: undefined,
|
|
12
13
|
/**
|
|
13
14
|
* @type {any}
|
|
14
15
|
*/
|
|
@@ -23,9 +24,9 @@ export const state = {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
const cleanUpAll = () => {
|
|
26
|
-
if (state.
|
|
27
|
-
state.
|
|
28
|
-
state.
|
|
27
|
+
if (state.ipc) {
|
|
28
|
+
state.ipc.dispose()
|
|
29
|
+
state.ipc = undefined
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -46,11 +47,11 @@ const createPtyHost = async () => {
|
|
|
46
47
|
})
|
|
47
48
|
const handleClose = () => {
|
|
48
49
|
ptyHost.off('close', handleClose)
|
|
49
|
-
state.
|
|
50
|
+
state.ipc = undefined
|
|
50
51
|
state.ptyHostPromise = undefined
|
|
51
52
|
}
|
|
52
53
|
ptyHost.on('close', handleClose)
|
|
53
|
-
state.
|
|
54
|
+
state.ipc = ptyHost
|
|
54
55
|
return ptyHost
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -63,15 +64,15 @@ export const getOrCreate = () => {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
export const getCurrentInstance = () => {
|
|
66
|
-
return state.
|
|
67
|
+
return state.ipc
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
export const disposeAll = () => {
|
|
70
|
-
if (state.
|
|
71
|
-
state.
|
|
72
|
-
if (state.
|
|
73
|
-
state.
|
|
74
|
-
state.
|
|
71
|
+
if (state.ipc) {
|
|
72
|
+
state.ipc.removeAllListeners()
|
|
73
|
+
if (state.ipc) {
|
|
74
|
+
state.ipc.dispose()
|
|
75
|
+
state.ipc = undefined
|
|
75
76
|
}
|
|
76
77
|
state.ptyHostState = /* None */ 0
|
|
77
78
|
state.send = (message) => {
|
|
@@ -79,3 +80,7 @@ export const disposeAll = () => {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
}
|
|
83
|
+
|
|
84
|
+
export const invoke = (method, ...params) => {
|
|
85
|
+
return JsonRpc.invoke(state.ipc, method, ...params)
|
|
86
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
3
|
+
import * as GetElectronRebuildPath from '../GetElectronRebuildPath/GetElectronRebuildPath.js'
|
|
4
|
+
import * as GetFirstNodeChildProcessEvent from '../GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} cwd
|
|
8
|
+
*/
|
|
9
|
+
export const rebuild = async (cwd) => {
|
|
10
|
+
const electronRebuildPath = GetElectronRebuildPath.getElectronRebuildPath()
|
|
11
|
+
const childProcess = spawn(electronRebuildPath, [], {
|
|
12
|
+
cwd,
|
|
13
|
+
stdio: 'inherit',
|
|
14
|
+
})
|
|
15
|
+
const { type, event } = await GetFirstNodeChildProcessEvent.getFirstNodeChildProcessEvent(childProcess)
|
|
16
|
+
if (type === FirstNodeWorkerEventType.Error) {
|
|
17
|
+
throw new Error(`Failed to rebuild native module: ${event}`)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
3
|
+
import * as GetFirstNodeChildProcessEvent from '../GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} cwd
|
|
7
|
+
*/
|
|
8
|
+
export const rebuild = async (cwd) => {
|
|
9
|
+
const childProcess = spawn('npm', ['rebuild'], {
|
|
10
|
+
cwd,
|
|
11
|
+
stdio: 'inherit',
|
|
12
|
+
})
|
|
13
|
+
const { type, event } = await GetFirstNodeChildProcessEvent.getFirstNodeChildProcessEvent(childProcess)
|
|
14
|
+
if (type === FirstNodeWorkerEventType.Error) {
|
|
15
|
+
throw new Error(`Failed to rebuild native module: ${event}`)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process'
|
|
2
|
-
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
3
|
-
import * as GetElectronRebuildPath from '../GetElectronRebuildPath/GetElectronRebuildPath.js'
|
|
4
|
-
import * as GetFirstNodeChildProcessEvent from '../GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js'
|
|
5
1
|
import * as IsElectron from '../IsElectron/IsElectron.js'
|
|
6
2
|
import * as Path from '../Path/Path.js'
|
|
7
3
|
import * as Root from '../Root/Root.js'
|
|
@@ -11,47 +7,18 @@ const getPtyHostPath = () => {
|
|
|
11
7
|
return Path.join(Root.root, 'packages', 'pty-host')
|
|
12
8
|
}
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
* @param {string} cwd
|
|
16
|
-
*/
|
|
17
|
-
const rebuildNodePtyElectron = async (cwd) => {
|
|
18
|
-
const electronRebuildPath = GetElectronRebuildPath.getElectronRebuildPath()
|
|
19
|
-
const childProcess = spawn(electronRebuildPath, [], {
|
|
20
|
-
cwd,
|
|
21
|
-
stdio: 'inherit',
|
|
22
|
-
})
|
|
23
|
-
const { type, event } = await GetFirstNodeChildProcessEvent.getFirstNodeChildProcessEvent(childProcess)
|
|
24
|
-
if (type === FirstNodeWorkerEventType.Error) {
|
|
25
|
-
throw new Error(`Failed to rebuild native module: ${event}`)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {string} cwd
|
|
31
|
-
*/
|
|
32
|
-
const rebuildNodePtyNode = async (cwd) => {
|
|
33
|
-
const childProcess = spawn('npm', ['rebuild'], {
|
|
34
|
-
cwd,
|
|
35
|
-
stdio: 'inherit',
|
|
36
|
-
})
|
|
37
|
-
const { type, event } = await GetFirstNodeChildProcessEvent.getFirstNodeChildProcessEvent(childProcess)
|
|
38
|
-
if (type === FirstNodeWorkerEventType.Error) {
|
|
39
|
-
throw new Error(`Failed to rebuild native module: ${event}`)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const getFn = () => {
|
|
10
|
+
const getModule = () => {
|
|
44
11
|
if (IsElectron.isElectron()) {
|
|
45
|
-
return
|
|
12
|
+
return import('../RebuildForElectron/RebuildForElectron.js')
|
|
46
13
|
}
|
|
47
|
-
return
|
|
14
|
+
return import('../RebuildForNode/RebuildForNode.js')
|
|
48
15
|
}
|
|
49
16
|
|
|
50
17
|
export const rebuildNodePty = async () => {
|
|
51
18
|
try {
|
|
52
19
|
const ptyHostPath = getPtyHostPath()
|
|
53
|
-
const
|
|
54
|
-
await rebuild(ptyHostPath)
|
|
20
|
+
const module = await getModule()
|
|
21
|
+
await module.rebuild(ptyHostPath)
|
|
55
22
|
} catch (error) {
|
|
56
23
|
throw new VError(error, `Failed to rebuild node-pty`)
|
|
57
24
|
}
|
|
@@ -5,6 +5,7 @@ import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
|
5
5
|
import * as Json from '../Json/Json.js'
|
|
6
6
|
import * as JsonFile from '../JsonFile/JsonFile.js'
|
|
7
7
|
import * as Platform from '../Platform/Platform.js'
|
|
8
|
+
import * as IsEnoentError from '../IsEnoentError/IsEnoentError.js'
|
|
8
9
|
import { VError } from '../VError/VError.js'
|
|
9
10
|
|
|
10
11
|
const addToArrayUnique = (recentlyOpened, path) => {
|
|
@@ -20,7 +21,7 @@ const getRecentlyOpened = async (recentlyOpenedPath) => {
|
|
|
20
21
|
const parsed = await JsonFile.readJson(recentlyOpenedPath)
|
|
21
22
|
return parsed
|
|
22
23
|
} catch (error) {
|
|
23
|
-
if (error
|
|
24
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
24
25
|
// ignore
|
|
25
26
|
} else if (error && error.code === ErrorCodes.E_JSON_PARSE) {
|
|
26
27
|
// ignore
|
|
@@ -36,7 +37,7 @@ const setRecentlyOpened = async (recentlyOpenedPath, newRecentlyOpened) => {
|
|
|
36
37
|
try {
|
|
37
38
|
await FileSystem.writeFile(recentlyOpenedPath, stringified)
|
|
38
39
|
} catch (error) {
|
|
39
|
-
if (error
|
|
40
|
+
if (IsEnoentError.isEnoentError(error)) {
|
|
40
41
|
await FileSystem.mkdir(dirname(recentlyOpenedPath))
|
|
41
42
|
await FileSystem.writeFile(recentlyOpenedPath, stringified)
|
|
42
43
|
return
|
|
@@ -37,9 +37,11 @@ export const create = async (ipc, id, cwd, command, args) => {
|
|
|
37
37
|
const ptyHost = await PtyHost.getOrCreate()
|
|
38
38
|
const terminal = createTerminal(ptyHost, ipc)
|
|
39
39
|
TerminalState.add(id, terminal)
|
|
40
|
-
// TODO
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
// TODO improve ipc error handling and await promise
|
|
41
|
+
// current can't await promise because when process exits
|
|
42
|
+
// because of native module error, promise is not resolved
|
|
43
|
+
// causing application which waits on this promise to hang
|
|
44
|
+
PtyHost.invoke('Terminal.create', id, cwd, command, args)
|
|
43
45
|
} catch (error) {
|
|
44
46
|
throw new VError(error, `Failed to create terminal`)
|
|
45
47
|
}
|
|
@@ -1,29 +1,9 @@
|
|
|
1
1
|
import * as ProcessExitEventType from '../ProcessExitEventType/ProcessExitEventType.js'
|
|
2
|
+
import * as GetFirstEvent from '../GetFirstEvent/GetFirstEvent.js'
|
|
2
3
|
|
|
3
4
|
export const waitForProcessToExit = async (childProcess) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
childProcess.off('error', handleError)
|
|
8
|
-
resolve(value)
|
|
9
|
-
}
|
|
10
|
-
const handleClose = (event) => {
|
|
11
|
-
cleanup({
|
|
12
|
-
type: ProcessExitEventType.Exit,
|
|
13
|
-
event,
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
const handleError = (event) => {
|
|
17
|
-
cleanup({
|
|
18
|
-
type: ProcessExitEventType.Error,
|
|
19
|
-
event,
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
childProcess.on('close', handleClose)
|
|
23
|
-
childProcess.on('error', handleError)
|
|
5
|
+
return GetFirstEvent.getFirstEvent(childProcess, {
|
|
6
|
+
error: ProcessExitEventType.Error,
|
|
7
|
+
close: ProcessExitEventType.Exit,
|
|
24
8
|
})
|
|
25
|
-
return {
|
|
26
|
-
type,
|
|
27
|
-
event,
|
|
28
|
-
}
|
|
29
9
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as ElectronWindow from './ElectronWindow.js'
|
|
2
|
+
|
|
3
|
+
export const name = 'ElectronWindow'
|
|
4
|
+
|
|
5
|
+
export const Commands = {
|
|
6
|
+
close: ElectronWindow.close,
|
|
7
|
+
maximize: ElectronWindow.maximize,
|
|
8
|
+
minimize: ElectronWindow.minimize,
|
|
9
|
+
reload: ElectronWindow.reload,
|
|
10
|
+
toggleDevtools: ElectronWindow.toggleDevtools,
|
|
11
|
+
unmaximize: ElectronWindow.unmaximize,
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as Assert from '../Assert/Assert.js'
|
|
2
|
+
import * as ParentIpc from '../ParentIpc/ParentIpc.js'
|
|
3
|
+
|
|
4
|
+
export const minimize = (windowId) => {
|
|
5
|
+
Assert.number(windowId)
|
|
6
|
+
return ParentIpc.invoke('ElectronWindow.minimize', windowId)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const toggleDevtools = (windowId) => {
|
|
10
|
+
Assert.number(windowId)
|
|
11
|
+
return ParentIpc.invoke('ElectronWindow.toggleDevtools', windowId)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const maximize = (windowId) => {
|
|
15
|
+
Assert.number(windowId)
|
|
16
|
+
return ParentIpc.invoke('ElectronWindow.maximize', windowId)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const unmaximize = (windowId) => {
|
|
20
|
+
Assert.number(windowId)
|
|
21
|
+
return ParentIpc.invoke('ElectronWindow.unmaximize')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const close = (windowId) => {
|
|
25
|
+
Assert.number(windowId)
|
|
26
|
+
return ParentIpc.invoke('ElectronWindow.close', windowId)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const reload = (windowId) => {
|
|
30
|
+
Assert.number(windowId)
|
|
31
|
+
return ParentIpc.invoke('ElectronWindow.reload', windowId)
|
|
32
|
+
}
|