@lvce-editor/shared-process 0.15.16 → 0.15.18

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.
Files changed (80) hide show
  1. package/config/builtinCommands.json +8 -0
  2. package/config/defaultSettings.json +2 -0
  3. package/extensions/builtin.language-basics-python/extension.json +1 -1
  4. package/extensions/builtin.language-basics-xml/extension.json +2 -1
  5. package/extensions/builtin.language-basics-xml/src/tokenizeXml.js +1 -1
  6. package/extensions/builtin.theme-atom-one-dark/color-theme.json +4 -0
  7. package/package.json +4 -4
  8. package/src/parts/AttachDebugger/AttachDebugger.ipc.js +7 -0
  9. package/src/parts/AttachDebugger/AttachDebugger.js +6 -0
  10. package/src/parts/Callback/Callback.js +17 -26
  11. package/src/parts/ChildProcessError/ChildProcessError.js +4 -1
  12. package/src/parts/CleanStack/CleanStack.js +4 -0
  13. package/src/parts/CommandNotFoundError/CommandNotFoundError.js +2 -1
  14. package/src/parts/CreateCpuProfile/CreateCpuProfile.js +59 -0
  15. package/src/parts/DestroySocket/DestroySocket.js +5 -0
  16. package/src/parts/DevtoolsProtocolRpc/DevtoolsProtocolRpc.js +32 -0
  17. package/src/parts/ElectronInitialize/ElectronInitialize.ipc.js +8 -0
  18. package/src/parts/ElectronInitialize/ElectronInitialize.js +11 -0
  19. package/src/parts/ErrorCodes/ErrorCodes.js +2 -0
  20. package/src/parts/ErrorHandling/ErrorHandling.js +12 -14
  21. package/src/parts/FirstWebSocketEventType/FirstWebSocketEventType.js +2 -0
  22. package/src/parts/GetActualPath/GetActualPath.js +8 -0
  23. package/src/parts/GetErrorResponse/GetErrorResponse.js +6 -3
  24. package/src/parts/GetFirstWebSocketEvent/GetFirstWebSocketEvent.js +41 -0
  25. package/src/parts/GetHelpfulChildProcessError/GetHelpfulChildProcessError.js +13 -3
  26. package/src/parts/GetResponse/GetResponse.js +3 -3
  27. package/src/parts/HandleElectronMessagePort/HandleElectronMessagePort.ipc.js +7 -0
  28. package/src/parts/HandleElectronMessagePort/HandleElectronMessagePort.js +14 -0
  29. package/src/parts/HandleIpc/HandleIpc.js +30 -0
  30. package/src/parts/HandleNodeMessagePort/HandleNodeMessagePort.ipc.js +7 -0
  31. package/src/parts/HandleNodeMessagePort/HandleNodeMessagePort.js +12 -0
  32. package/src/parts/HandleWebSocket/HandleWebSocket.ipc.js +7 -0
  33. package/src/parts/HandleWebSocket/HandleWebSocket.js +26 -0
  34. package/src/parts/HandleWebSocketForExtensionHost/HandleWebSocketForExtensionHost.js +15 -0
  35. package/src/parts/HandleWebSocketForExtensionHostHelperProcess/HandleWebSocketForExtensionHostHelperProcess.js +6 -0
  36. package/src/parts/HandleWebSocketForSharedProcess/HandleWebSocketForSharedProcess.js +23 -0
  37. package/src/parts/HandleWebSocketForTerminalProcess/HandleWebSocketForTerminalProcess.js +22 -0
  38. package/src/parts/HandleWebSocketForUnknown/HandleWebSocketForUnknown.js +10 -0
  39. package/src/parts/HandleWebSocketModule/HandleWebSocketModule.js +20 -0
  40. package/src/parts/Id/Id.js +7 -0
  41. package/src/parts/IpcChild/IpcChild.js +5 -2
  42. package/src/parts/IpcChildModule/IpcChildModule.js +8 -0
  43. package/src/parts/IpcChildType/IpcChildType.js +7 -0
  44. package/src/parts/IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js +41 -0
  45. package/src/parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js +51 -0
  46. package/src/parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js +25 -1
  47. package/src/parts/IpcChildWithNodeMessagePort/IpcChildWithNodeMessagePort.js +41 -0
  48. package/src/parts/IpcChildWithNodeWorker/IpcChildWithNodeWorker.js +17 -1
  49. package/src/parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js +51 -0
  50. package/src/parts/IpcError/IpcError.js +6 -0
  51. package/src/parts/IpcParentWithNodeForkedProcess/IpcParentWithNodeForkedProcess.js +7 -3
  52. package/src/parts/IsElectron/IsElectron.js +3 -0
  53. package/src/parts/IsMessagePort/IsMessagePort.js +3 -0
  54. package/src/parts/IsMessagePortMain/IsMessagePortMain.js +3 -0
  55. package/src/parts/IsSocket/IsSocket.js +5 -0
  56. package/src/parts/IsWebSocketOpen/IsWebSocketOpen.js +5 -0
  57. package/src/parts/JsonRpc/JsonRpc.js +19 -7
  58. package/src/parts/Module/Module.js +14 -0
  59. package/src/parts/ModuleId/ModuleId.js +7 -0
  60. package/src/parts/ModuleMap/ModuleMap.js +18 -0
  61. package/src/parts/ParentIpc/ParentIpc.js +10 -188
  62. package/src/parts/PrettyError/PrettyError.js +4 -19
  63. package/src/parts/Process/Process.ipc.js +1 -0
  64. package/src/parts/Process/Process.js +8 -0
  65. package/src/parts/ProcessDisplayName/ProcessDisplayName.js +1 -0
  66. package/src/parts/ProtocolType/ProtocolType.js +2 -1
  67. package/src/parts/PtyHost/PtyHost.js +81 -0
  68. package/src/parts/RebuildNodePty/RebuildNodePty.ipc.js +7 -0
  69. package/src/parts/RebuildNodePty/RebuildNodePty.js +48 -0
  70. package/src/parts/Signal/Signal.js +2 -0
  71. package/src/parts/Terminal/Terminal.js +52 -130
  72. package/src/parts/TerminalState/TerminalState.js +15 -0
  73. package/src/parts/WebSocketServer/WebSocketServer.js +11 -25
  74. package/src/sharedProcessMain.cjs +1 -0
  75. package/src/sharedProcessMain.js +3 -2
  76. package/extensions/builtin.language-basics-json5/README.md +0 -16
  77. package/extensions/builtin.language-basics-json5/extension.json +0 -12
  78. package/extensions/builtin.language-basics-json5/src/tokenizeJson5.js +0 -321
  79. package/src/parts/Socket/Socket.js +0 -77
  80. /package/src/parts/{GetWindowsNsisDOwnloadUrl → GetWindowsNsisDownloadUrl}/GetWindowsNsisDownloadUrl.js +0 -0
@@ -226,6 +226,14 @@
226
226
  "id": "Developer.toggleDeveloperTools",
227
227
  "label": "Developer: Toggle Developer Tools"
228
228
  },
229
+ {
230
+ "id": "RebuildNodePty.rebuildNodePty",
231
+ "label": "Developer: Rebuild Node Pty"
232
+ },
233
+ {
234
+ "id": "DebugSharedProcess.debugSharedProcess",
235
+ "label": "Developer: Debug Shared Process"
236
+ },
229
237
  {
230
238
  "id": "Window.reload",
231
239
  "label": "Window: Reload",
@@ -38,6 +38,8 @@
38
38
 
39
39
  "simpleBrowser.suggestions": false,
40
40
 
41
+ "terminal.separateConnection": false,
42
+
41
43
  "window.titleBarStyle": "native",
42
44
  "window.zoomLevel": 0,
43
45
  "window.controlsOverlay.enabled": true,
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "id": "python",
8
8
  "extensions": [".py"],
9
- "fileNames": ["SCsub"],
9
+ "fileNames": ["SCsub", "SConstruct"],
10
10
  "configuration": "./languageConfiguration.json",
11
11
  "tokenize": "src/tokenizePython.js",
12
12
  "firstLine": "^#!\\s*/?.*\\bpython[0-9.-]*\\b"
@@ -72,7 +72,8 @@
72
72
  ".tmtheme",
73
73
  ".mm",
74
74
  ".tmDragCommand",
75
- ".tmCommand"
75
+ ".tmCommand",
76
+ ".natvis"
76
77
  ],
77
78
  "fileNames": [".project", "resources.grd"],
78
79
  "tokenize": "src/tokenizeXml.js"
@@ -81,7 +81,7 @@ const RE_SLASH = /^\//
81
81
  const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
82
82
  const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^']+/
83
83
  const RE_TAG_TEXT = /^[^\s>]+/
84
- const RE_TAGNAME = /^[!\w\-]+/
84
+ const RE_TAGNAME = /^[!\w\-\:]+/
85
85
  const RE_TEXT = /^[^<>\n]+/
86
86
  const RE_WHITESPACE = /^\s+/
87
87
  const RE_WORD = /^[^\s]+/
@@ -96,6 +96,10 @@
96
96
  "name": "CssSelectorId",
97
97
  "foreground": "#61AFEF"
98
98
  },
99
+ {
100
+ "name": "CssAtRule",
101
+ "foreground": "#C678DD"
102
+ },
99
103
  {
100
104
  "name": "CssPropertyName",
101
105
  "foreground": "#ABB2BF"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.15.16",
3
+ "version": "0.15.18",
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.15.16",
21
- "@lvce-editor/extension-host-helper-process": "0.15.16",
22
- "@lvce-editor/pty-host": "0.15.16",
20
+ "@lvce-editor/extension-host": "0.15.18",
21
+ "@lvce-editor/extension-host-helper-process": "0.15.18",
22
+ "@lvce-editor/pty-host": "0.15.18",
23
23
  "debug": "^4.3.4",
24
24
  "execa": "^7.1.1",
25
25
  "exit-hook": "^3.2.0",
@@ -0,0 +1,7 @@
1
+ import * as AttachDebugger from './AttachDebugger.js'
2
+
3
+ export const name = 'AttachDebugger'
4
+
5
+ export const Commands = {
6
+ attachDebugger: AttachDebugger.attachDebugger,
7
+ }
@@ -0,0 +1,6 @@
1
+ import * as Process from '../Process/Process.js'
2
+ import * as Signal from '../Signal/Signal.js'
3
+
4
+ export const attachDebugger = (pid) => {
5
+ Process.kill(pid, Signal.SIGUSR1)
6
+ }
@@ -1,48 +1,39 @@
1
+ import * as Id from '../Id/Id.js'
2
+
1
3
  export const state = {
2
4
  callbacks: Object.create(null),
3
5
  onceListeners: new Set(),
4
- id: 2,
5
- }
6
-
7
- export const register = (resolve, reject) => {
8
- state.callbacks[++state.id] = {
9
- resolve,
10
- reject,
11
- }
12
- return state.id
13
6
  }
14
7
 
15
- export const unregister = (id) => {
16
- delete state.callbacks[id]
8
+ export const registerPromise = () => {
9
+ const id = Id.create()
10
+ const promise = new Promise((resolve, reject) => {
11
+ state.callbacks[id] = { resolve, reject }
12
+ })
13
+ return { id, promise }
17
14
  }
18
15
 
19
16
  // TODO merge resolve and resolveEmpty
20
17
  export const resolve = (id, args) => {
21
- if (!(id in state.callbacks)) {
18
+ const { callbacks } = state
19
+ if (!(id in callbacks)) {
22
20
  console.warn(`callback ${id} may already be disposed`)
23
21
  return
24
22
  }
25
- state.callbacks[id].resolve(args)
26
- }
27
-
28
- export const resolveEmpty = (id) => {
29
- if (!(id in state.callbacks)) {
30
- console.warn(`callback (resolved) ${id} may already be disposed`)
31
- return
32
- }
33
- state.callbacks[id].resolve()
23
+ callbacks[id].resolve(args)
24
+ delete callbacks[id]
34
25
  }
35
26
 
36
27
  export const reject = (id, error) => {
37
- if (!(id in state.callbacks)) {
28
+ const { callbacks } = state
29
+ if (!(id in callbacks)) {
38
30
  console.warn(`callback (rejected) ${id} may already be disposed`)
39
31
  return
40
32
  }
41
- state.callbacks[id].reject(error)
33
+ callbacks[id].reject(error)
34
+ delete callbacks[id]
42
35
  }
43
36
 
44
37
  export const isAllEmpty = () => {
45
- return (
46
- Object.keys(state.callbacks).length === 0 && state.onceListeners.size === 0
47
- )
38
+ return Object.keys(state.callbacks).length === 0 && state.onceListeners.size === 0
48
39
  }
@@ -2,8 +2,11 @@ import * as GetHelpfulChildProcessError from '../GetHelpfulChildProcessError/Get
2
2
 
3
3
  export class ChildProcessError extends Error {
4
4
  constructor(stderr) {
5
- const message = GetHelpfulChildProcessError.getHelpfulChildProcessError('', stderr)
5
+ const { message, code } = GetHelpfulChildProcessError.getHelpfulChildProcessError('', stderr)
6
6
  super(message)
7
7
  this.name = 'ChildProcessError'
8
+ if (code) {
9
+ this.code = code
10
+ }
8
11
  }
9
12
  }
@@ -7,6 +7,7 @@ const RE_GET_RESPONSE = /^\s*at async getResponse/
7
7
  const RE_WEBSOCKET_HANDLE_MESSAGE = /^\s*at async WebSocket.handleMessage/
8
8
  const RE_EXECUTE_COMMAND_ASYNC = /^\s*at executeCommandAsync/
9
9
  const RE_HANDLE_OTHER_MESSAGES_FROM_MESSAGE_PORT = /^\s*at async MessagePort\.handleOtherMessagesFromMessagePort/
10
+ const RE_ASSERT = /^\s*at .*\/Assert\.js/
10
11
 
11
12
  const isInternalLine = (line) => {
12
13
  return line.includes('node:') || RE_AT_PROMISE_INDEX.test(line) || line.includes('node_modules/ws')
@@ -18,6 +19,9 @@ const isRelevantLine = (line) => {
18
19
 
19
20
  const isApplicationUsefulLine = (line, index) => {
20
21
  if (index === 0) {
22
+ if (RE_ASSERT.test(line)) {
23
+ return false
24
+ }
21
25
  return true
22
26
  }
23
27
  if (RE_GET_RESPONSE.test(line)) {
@@ -1,8 +1,9 @@
1
1
  import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
2
+ import * as ProcessDisplayName from '../ProcessDisplayName/ProcessDisplayName.js'
2
3
 
3
4
  export class CommandNotFoundError extends Error {
4
5
  constructor(id) {
5
- super(`command ${id} not found`)
6
+ super(`command ${id} not found in ${ProcessDisplayName.processDisplayName}`)
6
7
  this.name = 'CommandNotFoundError'
7
8
  this.code = ErrorCodes.E_COMMAND_NOT_FOUND
8
9
  }
@@ -0,0 +1,59 @@
1
+ import { writeFile } from 'fs/promises'
2
+ import got from 'got'
3
+ import { tmpdir } from 'os'
4
+ import { join } from 'path'
5
+ import { WebSocket } from 'ws'
6
+ import * as DevtoolsProtocolRpc from '../DevtoolsProtocolRpc/DevtoolsProtocolRpc.js'
7
+
8
+ const createConnection = (webSocketDebuggerUrl) => {
9
+ const webSocket = new WebSocket(webSocketDebuggerUrl)
10
+ // console.log({ webSocket })
11
+ return {
12
+ on(event, listener) {
13
+ if (event === 'message') {
14
+ const wrappedListener = (string) => {
15
+ listener(JSON.parse(string))
16
+ }
17
+ webSocket.on(event, wrappedListener)
18
+ } else {
19
+ webSocket.on(event, listener)
20
+ }
21
+ },
22
+ send(message) {
23
+ webSocket.send(JSON.stringify(message))
24
+ },
25
+ }
26
+ }
27
+
28
+ export const createCpuProfile = async (pid) => {
29
+ // AttachDebugger.attachDebugger(pid)
30
+ const response = await got('http://localhost:9229/json/list').json()
31
+ const first = response[0]
32
+ const webSocketDebuggerUrl = first.webSocketDebuggerUrl
33
+ const ipc = createConnection(webSocketDebuggerUrl)
34
+
35
+ await new Promise((r) => {
36
+ ipc.on('open', r)
37
+ })
38
+ const rpc = DevtoolsProtocolRpc.create(ipc)
39
+ const result = await rpc.invoke('Debugger.enable')
40
+ const debuggerId = result.result.debuggerId
41
+ console.log({ debuggerId })
42
+ const p = await rpc.invoke('Profiler.enable')
43
+ await rpc.invoke('Profiler.start')
44
+ await new Promise((r) => {
45
+ setTimeout(r, 10000)
46
+ })
47
+ const profileResult = await rpc.invoke('Profiler.stop')
48
+ console.log({ profileResult })
49
+ const profile = profileResult.result.profile
50
+ const profilePath = join(tmpdir(), 'node-profile.cpuprofile')
51
+ const profileString = JSON.stringify(profile)
52
+ await writeFile(profilePath, profileString)
53
+ console.log('finished')
54
+ // const value = await rpc.invoke('Runtime.evaluate', {
55
+ // expression: '1+1',
56
+ // })
57
+ // await rpc.invoke('Debugger.pause')
58
+ // console.log({ value })
59
+ }
@@ -0,0 +1,5 @@
1
+ export const destroySocket = (socket) => {
2
+ try {
3
+ socket.destroy()
4
+ } catch {}
5
+ }
@@ -0,0 +1,32 @@
1
+ const Id = {
2
+ id: 1,
3
+ create() {
4
+ return this.id++
5
+ },
6
+ }
7
+
8
+ export const create = (ipc) => {
9
+ const callbacks = Object.create(null)
10
+ const handleMessage = (message) => {
11
+ if ('result' in message) {
12
+ const callback = callbacks[message.id]
13
+ callback(message)
14
+ delete callbacks[message.id]
15
+ }
16
+ }
17
+ ipc.on('message', handleMessage)
18
+ return {
19
+ invoke(method, params = {}) {
20
+ const id = Id.create()
21
+ const promise = new Promise((resolve, reject) => {
22
+ callbacks[id] = resolve
23
+ })
24
+ ipc.send({
25
+ method,
26
+ id,
27
+ params,
28
+ })
29
+ return promise
30
+ },
31
+ }
32
+ }
@@ -0,0 +1,8 @@
1
+ import * as ElectronInitialize from './ElectronInitialize.js'
2
+
3
+ export const name = 'ElectronInitialize'
4
+
5
+ // prettier-ignore
6
+ export const Commands = {
7
+ electronInitialize: ElectronInitialize.electronInitialize,
8
+ }
@@ -0,0 +1,11 @@
1
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
2
+ import * as IpcChild from '../IpcChild/IpcChild.js'
3
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
4
+
5
+ export const electronInitialize = async (port, folder) => {
6
+ const ipc = await IpcChild.listen({
7
+ method: IpcChildType.NodeMessagePort,
8
+ messagePort: port,
9
+ })
10
+ HandleIpc.handleIpc(ipc)
11
+ }
@@ -1,7 +1,9 @@
1
1
  export const E_COLOR_THEME_NOT_FOUND = 'E_COLOR_THEME_NOT_FOUND'
2
2
  export const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND'
3
3
  export const E_ICON_THEME_NOT_FOUND = 'E_ICON_THEME_NOT_FOUND'
4
+ export const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE'
4
5
  export const E_MANIFEST_NOT_FOUND = 'E_MANIFEST_NOT_FOUND'
6
+ export const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON'
5
7
  export const EACCES = 'EACCES'
6
8
  export const ECONNRESET = 'ECONNRESET'
7
9
  export const EEXIST = 'EEXIST'
@@ -1,11 +1,9 @@
1
1
  import * as ExitCode from '../ExitCode/ExitCode.js'
2
+ import * as GetNewLineIndex from '../GetNewLineIndex/GetNewLineIndex.js'
2
3
  import * as IsIgnoredError from '../IsIgnoredError/IsIgnoredError.js'
3
- import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
4
4
  import * as Logger from '../Logger/Logger.js'
5
5
  import * as PrettyError from '../PrettyError/PrettyError.js'
6
6
  import * as Process from '../Process/Process.js'
7
- import * as Socket from '../Socket/Socket.js'
8
- import * as GetNewLineIndex from '../GetNewLineIndex/GetNewLineIndex.js'
9
7
 
10
8
  export const state = {
11
9
  seenErrors: [],
@@ -30,17 +28,17 @@ export const handleError = (error) => {
30
28
  }
31
29
  state.seenErrors.push(error.message)
32
30
  const prettyError = preparePrettyError(error)
33
- Socket.send({
34
- jsonrpc: JsonRpcVersion.Two,
35
- method: /* Dialog.showErrorDialogWithOptions */ 'Dialog.showMessage',
36
- params: [
37
- {
38
- message: prettyError.message,
39
- codeFrame: prettyError.codeFrame,
40
- stack: prettyError.stack,
41
- },
42
- ],
43
- })
31
+ // Socket.send({
32
+ // jsonrpc: JsonRpcVersion.Two,
33
+ // method: /* Dialog.showErrorDialogWithOptions */ 'Dialog.showMessage',
34
+ // params: [
35
+ // {
36
+ // message: prettyError.message,
37
+ // codeFrame: prettyError.codeFrame,
38
+ // stack: prettyError.stack,
39
+ // },
40
+ // ],
41
+ // })
44
42
  printPrettyError(prettyError)
45
43
  }
46
44
 
@@ -0,0 +1,2 @@
1
+ export const Open = 1
2
+ export const Close = 2
@@ -0,0 +1,8 @@
1
+ import { fileURLToPath } from 'node:url'
2
+
3
+ export const getActualPath = (fileUri) => {
4
+ if (fileUri.startsWith('file://')) {
5
+ return fileURLToPath(fileUri)
6
+ }
7
+ return fileUri
8
+ }
@@ -12,7 +12,11 @@ const shouldLogError = (error) => {
12
12
  return true
13
13
  }
14
14
 
15
- export const getErrorResponse = (message, error) => {
15
+ export const getErrorResponse = (message, error, ipc) => {
16
+ const prettyError = PrettyError.prepare(error)
17
+ if (shouldLogError(error) && (!ipc || ipc.shouldLogError !== false)) {
18
+ PrintPrettyError.printPrettyError(prettyError, `[shared-process] `)
19
+ }
16
20
  if (error && error instanceof CommandNotFoundError) {
17
21
  return {
18
22
  jsonrpc: JsonRpcVersion.Two,
@@ -37,8 +41,6 @@ export const getErrorResponse = (message, error) => {
37
41
  },
38
42
  }
39
43
  }
40
- const prettyError = PrettyError.prepare(error)
41
- PrintPrettyError.printPrettyError(prettyError, `[shared-process] `)
42
44
  return {
43
45
  jsonrpc: JsonRpcVersion.Two,
44
46
  id: message.id,
@@ -49,6 +51,7 @@ export const getErrorResponse = (message, error) => {
49
51
  stack: prettyError.stack,
50
52
  codeFrame: prettyError.codeFrame,
51
53
  type: prettyError.type,
54
+ code: prettyError.code,
52
55
  },
53
56
  },
54
57
  }
@@ -0,0 +1,41 @@
1
+ import * as FirstWebSocketEventType from '../FirstWebSocketEventType/FirstWebSocketEventType.js'
2
+ import { WebSocket } from 'ws'
3
+
4
+ export const getFirstWebSocketEvent = async (webSocket) => {
5
+ switch (webSocket.readyState) {
6
+ case WebSocket.OPEN:
7
+ return {
8
+ type: FirstWebSocketEventType.Open,
9
+ event: undefined,
10
+ }
11
+ case WebSocket.CLOSED:
12
+ return {
13
+ type: FirstWebSocketEventType.Close,
14
+ event: undefined,
15
+ }
16
+ default:
17
+ break
18
+ }
19
+ const { type, event } = await new Promise((resolve) => {
20
+ const cleanup = (value) => {
21
+ webSocket.off('open', handleOpen)
22
+ webSocket.off('close', handleClose)
23
+ resolve(value)
24
+ }
25
+ const handleOpen = (event) => {
26
+ cleanup({
27
+ type: FirstWebSocketEventType.Open,
28
+ event,
29
+ })
30
+ }
31
+ const handleClose = (event) => {
32
+ cleanup({
33
+ type: FirstWebSocketEventType.Close,
34
+ event,
35
+ })
36
+ }
37
+ webSocket.on('open', handleOpen)
38
+ webSocket.on('close', handleClose)
39
+ })
40
+ return { type, event }
41
+ }
@@ -1,4 +1,5 @@
1
1
  import * as SplitLines from '../SplitLines/SplitLines.js'
2
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
2
3
 
3
4
  const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/
4
5
  const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/
@@ -29,7 +30,10 @@ const getMessageCodeBlock = (stderr) => {
29
30
 
30
31
  const getNativeModuleErrorMessage = (stderr) => {
31
32
  const message = getMessageCodeBlock(stderr)
32
- return `incompatible native node module: ${message}`
33
+ return {
34
+ message: `Incompatible native node module: ${message}`,
35
+ code: ErrorCodes.E_INCOMPATIBLE_NATIVE_MODULE,
36
+ }
33
37
  }
34
38
 
35
39
  const isModulesSyntaxError = (stderr) => {
@@ -40,7 +44,10 @@ const isModulesSyntaxError = (stderr) => {
40
44
  }
41
45
 
42
46
  const getModuleSyntaxError = (stderr) => {
43
- return `ES Modules are not supported in electron`
47
+ return {
48
+ message: `ES Modules are not supported in electron`,
49
+ code: ErrorCodes.E_MODULES_NOT_SUPPORTED_IN_ELECTRON,
50
+ }
44
51
  }
45
52
 
46
53
  export const getHelpfulChildProcessError = (stdout, stderr) => {
@@ -50,5 +57,8 @@ export const getHelpfulChildProcessError = (stdout, stderr) => {
50
57
  if (isModulesSyntaxError(stderr)) {
51
58
  return getModuleSyntaxError(stderr)
52
59
  }
53
- return 'child process error'
60
+ return {
61
+ message: `child process error: ${stderr}`,
62
+ code: '',
63
+ }
54
64
  }
@@ -3,13 +3,13 @@ import * as GetErrorResponse from '../GetErrorResponse/GetErrorResponse.js'
3
3
  import * as GetSuccessResponse from '../GetSuccessResponse/GetSuccessResponse.js'
4
4
  import * as RequiresSocket from '../RequiresSocket/RequiresSocket.js'
5
5
 
6
- export const getResponse = async (message, handle) => {
6
+ export const getResponse = async (message, ipc) => {
7
7
  try {
8
8
  const result = RequiresSocket.requiresSocket(message.method)
9
- ? await Command.execute(message.method, handle, ...message.params)
9
+ ? await Command.execute(message.method, ipc, ...message.params)
10
10
  : await Command.execute(message.method, ...message.params)
11
11
  return GetSuccessResponse.getSuccessResponse(message, result)
12
12
  } catch (error) {
13
- return GetErrorResponse.getErrorResponse(message, error)
13
+ return GetErrorResponse.getErrorResponse(message, error, ipc)
14
14
  }
15
15
  }
@@ -0,0 +1,7 @@
1
+ import * as HandleElectronMessagePort from './HandleElectronMessagePort.js'
2
+
3
+ export const name = 'HandleElectronMessagePort'
4
+
5
+ export const Commands = {
6
+ handleElectronMessagePort: HandleElectronMessagePort.handleElectronMessagePort,
7
+ }
@@ -0,0 +1,14 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
3
+ import * as IpcChild from '../IpcChild/IpcChild.js'
4
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
5
+
6
+ export const handleElectronMessagePort = async (messagePort) => {
7
+ Assert.object(messagePort)
8
+ const ipc = await IpcChild.listen({
9
+ method: IpcChildType.ElectronMessagePort,
10
+ messagePort,
11
+ })
12
+ HandleIpc.handleIpc(ipc)
13
+ messagePort.start()
14
+ }
@@ -0,0 +1,30 @@
1
+ import * as Callback from '../Callback/Callback.js'
2
+ import * as Command from '../Command/Command.js'
3
+ import * as GetResponse from '../GetResponse/GetResponse.js'
4
+
5
+ const handleJsonRpcResult = (message) => {
6
+ Callback.resolve(message.id, message.result)
7
+ }
8
+
9
+ export const handleIpc = (ipc) => {
10
+ const handleJsonRpcMessage = async (message) => {
11
+ if (message.method) {
12
+ const response = await GetResponse.getResponse(message, ipc)
13
+ ipc.send(response)
14
+ } else {
15
+ // TODO handle error
16
+ Command.execute(message.method, ...message.params)
17
+ }
18
+ }
19
+
20
+ const handleMessageFromParentProcess = async (message) => {
21
+ if (message.result) {
22
+ return handleJsonRpcResult(message)
23
+ }
24
+ if (message.method) {
25
+ return handleJsonRpcMessage(message)
26
+ }
27
+ console.warn('unknown message', message)
28
+ }
29
+ ipc.on('message', handleMessageFromParentProcess)
30
+ }
@@ -0,0 +1,7 @@
1
+ import * as HandleNodeMessagePort from './HandleNodeMessagePort.js'
2
+
3
+ export const name = 'HandleNodeMessagePort'
4
+
5
+ export const Commands = {
6
+ handleNodeMessagePort: HandleNodeMessagePort.handleNodeMessagePort,
7
+ }
@@ -0,0 +1,12 @@
1
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
2
+ import * as IpcChild from '../IpcChild/IpcChild.js'
3
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
4
+
5
+ export const handleNodeMessagePort = async (messagePort) => {
6
+ const ipc = await IpcChild.listen({
7
+ method: IpcChildType.NodeMessagePort,
8
+ messagePort,
9
+ })
10
+ HandleIpc.handleIpc(ipc)
11
+ messagePort.start()
12
+ }
@@ -0,0 +1,7 @@
1
+ import * as HandleWebSocket from './HandleWebSocket.js'
2
+
3
+ export const name = 'HandleWebSocket'
4
+
5
+ export const Commands = {
6
+ handleWebSocket: HandleWebSocket.handleWebSocket,
7
+ }
@@ -0,0 +1,26 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as DestroyWebSocket from '../DestroySocket/DestroySocket.js'
3
+ import * as HandleWebSocketModule from '../HandleWebSocketModule/HandleWebSocketModule.js'
4
+ import { VError } from '../VError/VError.js'
5
+
6
+ export const handleWebSocket = async (message, handle) => {
7
+ try {
8
+ Assert.object(message)
9
+ Assert.object(handle)
10
+ const headers = message.headers
11
+ if (!headers) {
12
+ throw new VError('missing websocket headers')
13
+ }
14
+ const protocol = headers['sec-websocket-protocol']
15
+ if (!protocol) {
16
+ throw new VError('missing sec websocket protocol header')
17
+ }
18
+ handle.pause()
19
+ const module = await HandleWebSocketModule.load(protocol)
20
+ await module.handleWebSocket(message, handle, protocol)
21
+ handle.resume()
22
+ } catch (error) {
23
+ DestroyWebSocket.destroySocket(handle)
24
+ throw new VError(error, `Failed to connect to websocket`)
25
+ }
26
+ }