@lvce-editor/shared-process 0.14.15 → 0.15.0
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 +5 -5
- package/src/parts/ChildProcessError/ChildProcessError.js +3 -39
- package/src/parts/GetErrorResponse/GetErrorResponse.js +55 -0
- package/src/parts/GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js +5 -7
- package/src/parts/GetFirstNodeWorkerEvent/GetFirstNodeWorkerEvent.js +4 -5
- package/src/parts/GetHelpfulChildProcessError/GetHelpfulChildProcessError.js +54 -0
- package/src/parts/GetResponse/GetResponse.js +4 -57
- package/src/parts/GetSuccessResponse/GetSuccessResponse.js +9 -0
- package/src/parts/ParentIpc/ParentIpc.js +11 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/shared-process",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
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.21.4",
|
|
20
|
-
"@lvce-editor/extension-host": "0.
|
|
21
|
-
"@lvce-editor/extension-host-helper-process": "0.
|
|
22
|
-
"@lvce-editor/pty-host": "0.
|
|
20
|
+
"@lvce-editor/extension-host": "0.15.0",
|
|
21
|
+
"@lvce-editor/extension-host-helper-process": "0.15.0",
|
|
22
|
+
"@lvce-editor/pty-host": "0.15.0",
|
|
23
23
|
"debug": "^4.3.4",
|
|
24
24
|
"execa": "^7.1.1",
|
|
25
25
|
"exit-hook": "^3.2.0",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"lines-and-columns": "^2.0.3",
|
|
29
29
|
"open": "^9.1.0",
|
|
30
30
|
"p-queue": "^7.3.4",
|
|
31
|
-
"parse-json": "^
|
|
31
|
+
"parse-json": "^7.0.0",
|
|
32
32
|
"symlink-dir": "^5.1.1",
|
|
33
33
|
"tail": "^2.2.6",
|
|
34
34
|
"tar-fs": "^2.1.1",
|
|
@@ -1,45 +1,9 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
|
|
3
|
-
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/
|
|
4
|
-
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/
|
|
5
|
-
|
|
6
|
-
const RE_MASSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/
|
|
7
|
-
const RE_MASSAGE_CODE_BLOCK_END = /^\s* at/
|
|
8
|
-
|
|
9
|
-
const isUnhelpfulNativeModuleError = (stderr) => {
|
|
10
|
-
return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const isMessageCodeBlockStartIndex = (line) => {
|
|
14
|
-
return RE_MASSAGE_CODE_BLOCK_START.test(line)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const isMessageCodeBlockEndIndex = (line) => {
|
|
18
|
-
return RE_MASSAGE_CODE_BLOCK_END.test(line)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const getMessageCodeBlock = (stderr) => {
|
|
22
|
-
const lines = SplitLines.splitLines(stderr)
|
|
23
|
-
const startIndex = lines.findIndex(isMessageCodeBlockStartIndex)
|
|
24
|
-
const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex)
|
|
25
|
-
const relevantLines = lines.slice(startIndex, endIndex)
|
|
26
|
-
const relevantMessage = relevantLines.join(' ').slice('Error: '.length)
|
|
27
|
-
return relevantMessage
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const getNativeModuleErrorMessage = (stderr) => {
|
|
31
|
-
const message = getMessageCodeBlock(stderr)
|
|
32
|
-
return `incompatible native node module: ${message}`
|
|
33
|
-
}
|
|
1
|
+
import * as GetHelpfulChildProcessError from '../GetHelpfulChildProcessError/GetHelpfulChildProcessError.js'
|
|
34
2
|
|
|
35
3
|
export class ChildProcessError extends Error {
|
|
36
4
|
constructor(stderr) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
super(message)
|
|
40
|
-
} else {
|
|
41
|
-
super('child process error')
|
|
42
|
-
}
|
|
5
|
+
const message = GetHelpfulChildProcessError.getHelpfulChildProcessError('', stderr)
|
|
6
|
+
super(message)
|
|
43
7
|
this.name = 'ChildProcessError'
|
|
44
8
|
}
|
|
45
9
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CommandNotFoundError } from '../CommandNotFoundError/CommandNotFoundError.js'
|
|
2
|
+
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
3
|
+
import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
|
|
4
|
+
import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
|
|
5
|
+
import * as PrettyError from '../PrettyError/PrettyError.js'
|
|
6
|
+
import * as PrintPrettyError from '../PrintPrettyError/PrintPrettyError.js'
|
|
7
|
+
|
|
8
|
+
const shouldLogError = (error) => {
|
|
9
|
+
if (error && error.code === ErrorCodes.ENOENT) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const getErrorResponse = (message, error) => {
|
|
16
|
+
if (error && error instanceof CommandNotFoundError) {
|
|
17
|
+
return {
|
|
18
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
19
|
+
id: message.id,
|
|
20
|
+
error: {
|
|
21
|
+
code: JsonRpcErrorCode.MethodNotFound,
|
|
22
|
+
message: error.message,
|
|
23
|
+
data: error.stack,
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!shouldLogError(error)) {
|
|
28
|
+
return {
|
|
29
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
30
|
+
id: message.id,
|
|
31
|
+
error: {
|
|
32
|
+
code: JsonRpcErrorCode.Custom,
|
|
33
|
+
message: `${error}`,
|
|
34
|
+
data: {
|
|
35
|
+
code: error.code,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const prettyError = PrettyError.prepare(error)
|
|
41
|
+
PrintPrettyError.printPrettyError(prettyError, `[shared-process] `)
|
|
42
|
+
return {
|
|
43
|
+
jsonrpc: JsonRpcVersion.Two,
|
|
44
|
+
id: message.id,
|
|
45
|
+
error: {
|
|
46
|
+
code: JsonRpcErrorCode.Custom,
|
|
47
|
+
message: prettyError.message,
|
|
48
|
+
data: {
|
|
49
|
+
stack: prettyError.stack,
|
|
50
|
+
codeFrame: prettyError.codeFrame,
|
|
51
|
+
type: prettyError.type,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -4,12 +4,13 @@ export const getFirstNodeChildProcessEvent = async (childProcess) => {
|
|
|
4
4
|
const { type, event, stdout, stderr } = await new Promise((resolve, reject) => {
|
|
5
5
|
let stderr = ''
|
|
6
6
|
let stdout = ''
|
|
7
|
-
const cleanup = () => {
|
|
7
|
+
const cleanup = (value) => {
|
|
8
8
|
childProcess.stderr.off('data', handleStdErrData)
|
|
9
9
|
childProcess.stdout.off('data', handleStdoutData)
|
|
10
10
|
childProcess.off('message', handleMessage)
|
|
11
11
|
childProcess.off('exit', handleExit)
|
|
12
12
|
childProcess.off('error', handleError)
|
|
13
|
+
resolve(value)
|
|
13
14
|
}
|
|
14
15
|
const handleStdErrData = (data) => {
|
|
15
16
|
stderr += data
|
|
@@ -18,16 +19,13 @@ export const getFirstNodeChildProcessEvent = async (childProcess) => {
|
|
|
18
19
|
stdout += data
|
|
19
20
|
}
|
|
20
21
|
const handleMessage = (event) => {
|
|
21
|
-
cleanup()
|
|
22
|
-
resolve({ type: FirstNodeWorkerEventType.Message, event, stdout, stderr })
|
|
22
|
+
cleanup({ type: FirstNodeWorkerEventType.Message, event, stdout, stderr })
|
|
23
23
|
}
|
|
24
24
|
const handleExit = (event) => {
|
|
25
|
-
cleanup()
|
|
26
|
-
resolve({ type: FirstNodeWorkerEventType.Exit, event, stdout, stderr })
|
|
25
|
+
cleanup({ type: FirstNodeWorkerEventType.Exit, event, stdout, stderr })
|
|
27
26
|
}
|
|
28
27
|
const handleError = (event) => {
|
|
29
|
-
cleanup()
|
|
30
|
-
resolve({ type: FirstNodeWorkerEventType.Error, event, stdout, stderr })
|
|
28
|
+
cleanup({ type: FirstNodeWorkerEventType.Error, event, stdout, stderr })
|
|
31
29
|
}
|
|
32
30
|
childProcess.stderr.on('data', handleStdErrData)
|
|
33
31
|
childProcess.stdout.on('data', handleStdoutData)
|
|
@@ -2,17 +2,16 @@ import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNode
|
|
|
2
2
|
|
|
3
3
|
export const getFirstNodeWorkerEvent = async (worker) => {
|
|
4
4
|
const { type, event } = await new Promise((resolve, reject) => {
|
|
5
|
-
const cleanup = () => {
|
|
5
|
+
const cleanup = (value) => {
|
|
6
6
|
worker.off('exit', handleExit)
|
|
7
7
|
worker.off('error', handleError)
|
|
8
|
+
resolve(value)
|
|
8
9
|
}
|
|
9
10
|
const handleExit = (event) => {
|
|
10
|
-
cleanup()
|
|
11
|
-
resolve({ type: FirstNodeWorkerEventType.Exit, event })
|
|
11
|
+
cleanup({ type: FirstNodeWorkerEventType.Exit, event })
|
|
12
12
|
}
|
|
13
13
|
const handleError = (event) => {
|
|
14
|
-
cleanup()
|
|
15
|
-
resolve({ type: FirstNodeWorkerEventType.Error, event })
|
|
14
|
+
cleanup({ type: FirstNodeWorkerEventType.Error, event })
|
|
16
15
|
}
|
|
17
16
|
worker.on('exit', handleExit)
|
|
18
17
|
worker.on('error', handleError)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as SplitLines from '../SplitLines/SplitLines.js'
|
|
2
|
+
|
|
3
|
+
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/
|
|
4
|
+
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/
|
|
5
|
+
|
|
6
|
+
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/
|
|
7
|
+
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/
|
|
8
|
+
|
|
9
|
+
const isUnhelpfulNativeModuleError = (stderr) => {
|
|
10
|
+
return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const isMessageCodeBlockStartIndex = (line) => {
|
|
14
|
+
return RE_MESSAGE_CODE_BLOCK_START.test(line)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const isMessageCodeBlockEndIndex = (line) => {
|
|
18
|
+
return RE_MESSAGE_CODE_BLOCK_END.test(line)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const getMessageCodeBlock = (stderr) => {
|
|
22
|
+
const lines = SplitLines.splitLines(stderr)
|
|
23
|
+
const startIndex = lines.findIndex(isMessageCodeBlockStartIndex)
|
|
24
|
+
const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex)
|
|
25
|
+
const relevantLines = lines.slice(startIndex, endIndex)
|
|
26
|
+
const relevantMessage = relevantLines.join(' ').slice('Error: '.length)
|
|
27
|
+
return relevantMessage
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const getNativeModuleErrorMessage = (stderr) => {
|
|
31
|
+
const message = getMessageCodeBlock(stderr)
|
|
32
|
+
return `incompatible native node module: ${message}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const isModulesSyntaxError = (stderr) => {
|
|
36
|
+
if (!stderr) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
return stderr.includes('SyntaxError: Cannot use import statement outside a module')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const getModuleSyntaxError = (stderr) => {
|
|
43
|
+
return `ES Modules are not supported in electron`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const getHelpfulChildProcessError = (stdout, stderr) => {
|
|
47
|
+
if (isUnhelpfulNativeModuleError(stderr)) {
|
|
48
|
+
return getNativeModuleErrorMessage(stderr)
|
|
49
|
+
}
|
|
50
|
+
if (isModulesSyntaxError(stderr)) {
|
|
51
|
+
return getModuleSyntaxError(stderr)
|
|
52
|
+
}
|
|
53
|
+
return 'child process error'
|
|
54
|
+
}
|
|
@@ -1,68 +1,15 @@
|
|
|
1
1
|
import * as Command from '../Command/Command.js'
|
|
2
|
-
import
|
|
3
|
-
import * as
|
|
4
|
-
import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
|
|
5
|
-
import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
|
|
6
|
-
import * as PrettyError from '../PrettyError/PrettyError.js'
|
|
7
|
-
import * as PrintPrettyError from '../PrintPrettyError/PrintPrettyError.js'
|
|
2
|
+
import * as GetErrorResponse from '../GetErrorResponse/GetErrorResponse.js'
|
|
3
|
+
import * as GetSuccessResponse from '../GetSuccessResponse/GetSuccessResponse.js'
|
|
8
4
|
import * as RequiresSocket from '../RequiresSocket/RequiresSocket.js'
|
|
9
5
|
|
|
10
|
-
const shouldLogError = (error) => {
|
|
11
|
-
if (error && error.code === ErrorCodes.ENOENT) {
|
|
12
|
-
return false
|
|
13
|
-
}
|
|
14
|
-
return true
|
|
15
|
-
}
|
|
16
|
-
|
|
17
6
|
export const getResponse = async (message, handle) => {
|
|
18
7
|
try {
|
|
19
8
|
const result = RequiresSocket.requiresSocket(message.method)
|
|
20
9
|
? await Command.execute(message.method, handle, ...message.params)
|
|
21
10
|
: await Command.execute(message.method, ...message.params)
|
|
22
|
-
return
|
|
23
|
-
jsonrpc: JsonRpcVersion.Two,
|
|
24
|
-
id: message.id,
|
|
25
|
-
result: result ?? null,
|
|
26
|
-
}
|
|
11
|
+
return GetSuccessResponse.getSuccessResponse(message, result)
|
|
27
12
|
} catch (error) {
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
jsonrpc: JsonRpcVersion.Two,
|
|
31
|
-
id: message.id,
|
|
32
|
-
error: {
|
|
33
|
-
code: JsonRpcErrorCode.MethodNotFound,
|
|
34
|
-
message: error.message,
|
|
35
|
-
data: error.stack,
|
|
36
|
-
},
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (!shouldLogError(error)) {
|
|
40
|
-
return {
|
|
41
|
-
jsonrpc: JsonRpcVersion.Two,
|
|
42
|
-
id: message.id,
|
|
43
|
-
error: {
|
|
44
|
-
code: JsonRpcErrorCode.Custom,
|
|
45
|
-
message: `${error}`,
|
|
46
|
-
data: {
|
|
47
|
-
code: error.code,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const prettyError = PrettyError.prepare(error)
|
|
53
|
-
PrintPrettyError.printPrettyError(prettyError, `[shared-process] `)
|
|
54
|
-
return {
|
|
55
|
-
jsonrpc: JsonRpcVersion.Two,
|
|
56
|
-
id: message.id,
|
|
57
|
-
error: {
|
|
58
|
-
code: JsonRpcErrorCode.Custom,
|
|
59
|
-
message: prettyError.message,
|
|
60
|
-
data: {
|
|
61
|
-
stack: prettyError.stack,
|
|
62
|
-
codeFrame: prettyError.codeFrame,
|
|
63
|
-
type: prettyError.type,
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
}
|
|
13
|
+
return GetErrorResponse.getErrorResponse(message, error)
|
|
67
14
|
}
|
|
68
15
|
}
|
|
@@ -7,6 +7,7 @@ import * as ExtensionHostHelperProcessIpc from '../ExtensionHostHelperProcessIpc
|
|
|
7
7
|
import * as ExtensionHostIpc from '../ExtensionHostIpc/ExtensionHostIpc.js'
|
|
8
8
|
import * as ExtensionHostRpc from '../ExtensionHostRpc/ExtensionHostRpc.js'
|
|
9
9
|
import * as GetResponse from '../GetResponse/GetResponse.js'
|
|
10
|
+
import * as Logger from '../Logger/Logger.js'
|
|
10
11
|
import * as ProtocolType from '../ProtocolType/ProtocolType.js'
|
|
11
12
|
import { VError } from '../VError/VError.js'
|
|
12
13
|
// TODO add tests for this
|
|
@@ -63,6 +64,15 @@ const handleWebSocketExtensionHostHelperProcess = async (message, handle) => {
|
|
|
63
64
|
ipc._process.send(message, handle)
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
const handleWebSocketUnknown = (message, handle, protocol) => {
|
|
68
|
+
Logger.warn(`[shared-process] unsupported sec-websocket-procotol ${protocol}`)
|
|
69
|
+
try {
|
|
70
|
+
handle.destroy()
|
|
71
|
+
} catch {
|
|
72
|
+
// ignore
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
const handleWebSocket = (message, handle) => {
|
|
67
77
|
const headers = message.headers
|
|
68
78
|
if (!headers) {
|
|
@@ -80,7 +90,7 @@ const handleWebSocket = (message, handle) => {
|
|
|
80
90
|
case ProtocolType.ExtensionHostHelperProcess:
|
|
81
91
|
return handleWebSocketExtensionHostHelperProcess(message, handle)
|
|
82
92
|
default:
|
|
83
|
-
|
|
93
|
+
return handleWebSocketUnknown(message, handle, protocol)
|
|
84
94
|
}
|
|
85
95
|
}
|
|
86
96
|
|