@lvce-editor/shared-process 0.11.6 → 0.11.7
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 +1 -1
- package/config/defaultKeyBindings.json +1 -1
- package/extensions/builtin.language-basics-desktop/src/tokenizeDesktop.js +49 -5
- package/extensions/builtin.language-basics-shellscript/extension.json +1 -0
- package/extensions/builtin.language-basics-xml/src/tokenizeXml.js +1 -1
- package/index.js +5 -2
- package/package.json +5 -5
- package/src/parts/ExportStatic/ExportStatic.js +78 -2
- package/src/parts/ExtensionLink/ExtensionLink.js +2 -3
- package/src/parts/ExtensionManagement/ExtensionManagement.js +1 -1
- package/src/parts/ExtensionManifest/ExtensionManifest.js +2 -2
- package/src/parts/Search/Search.js +67 -30
- package/src/parts/TextSearchResultType/TextSearchResultType.js +2 -0
- package/src/parts/VError/VError.js +44 -0
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
export const State = {
|
|
5
5
|
TopLevelContent: 1,
|
|
6
6
|
InsideLineComment: 2,
|
|
7
|
+
AfterPropertyName: 3,
|
|
8
|
+
AfterPropertyNameAfterEqualSign: 4,
|
|
9
|
+
InsideString: 5,
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
export const StateMap = {
|
|
@@ -23,6 +26,10 @@ export const TokenType = {
|
|
|
23
26
|
Comment: 885,
|
|
24
27
|
Query: 886,
|
|
25
28
|
Text: 887,
|
|
29
|
+
PropertyName: 12,
|
|
30
|
+
PropertyValueString: 14,
|
|
31
|
+
Punctuation: 13,
|
|
32
|
+
LanguageConstant: 11,
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
export const TokenMap = {
|
|
@@ -34,13 +41,19 @@ export const TokenMap = {
|
|
|
34
41
|
[TokenType.Comment]: 'Comment',
|
|
35
42
|
[TokenType.Query]: 'Query',
|
|
36
43
|
[TokenType.Text]: 'Text',
|
|
44
|
+
[TokenType.Punctuation]: 'Punctuation',
|
|
45
|
+
[TokenType.LanguageConstant]: 'LanguageConstant',
|
|
46
|
+
[TokenType.PropertyName]: 'JsonPropertyName',
|
|
47
|
+
[TokenType.LanguageConstant]: 'LanguageConstant',
|
|
48
|
+
[TokenType.Punctuation]: 'Punctuation',
|
|
49
|
+
[TokenType.PropertyValueString]: 'YamlPropertyValueString',
|
|
37
50
|
}
|
|
38
51
|
|
|
39
52
|
const RE_LINE_COMMENT_START = /^#/
|
|
40
53
|
const RE_WHITESPACE = /^ +/
|
|
41
54
|
const RE_CURLY_OPEN = /^\{/
|
|
42
55
|
const RE_CURLY_CLOSE = /^\}/
|
|
43
|
-
const RE_PROPERTY_NAME = /^[a-zA-Z
|
|
56
|
+
const RE_PROPERTY_NAME = /^[a-zA-Z\-\_\d]+\b(?=\s*=)/
|
|
44
57
|
const RE_COLON = /^:/
|
|
45
58
|
const RE_PROPERTY_VALUE = /^[^;\}]+/
|
|
46
59
|
const RE_SEMICOLON = /^;/
|
|
@@ -62,6 +75,11 @@ const RE_STAR = /^\*/
|
|
|
62
75
|
const RE_QUERY_NAME = /^[a-z\-]+/
|
|
63
76
|
const RE_QUERY_CONTENT = /^[^\)]+/
|
|
64
77
|
const RE_COMBINATOR = /^[\+\>\~]/
|
|
78
|
+
const RE_EQUAL_SIGN = /^=/
|
|
79
|
+
const RE_QUOTE_DOUBLE = /^"/
|
|
80
|
+
const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
|
|
81
|
+
const RE_LINE_COMMENT = /^#.*/s
|
|
82
|
+
const RE_LANGUAGE_CONSTANT = /^(?:true|false)\b/
|
|
65
83
|
|
|
66
84
|
export const initialLineState = {
|
|
67
85
|
state: State.TopLevelContent,
|
|
@@ -85,9 +103,12 @@ export const tokenizeLine = (line, lineState) => {
|
|
|
85
103
|
const part = line.slice(index)
|
|
86
104
|
switch (state) {
|
|
87
105
|
case State.TopLevelContent:
|
|
88
|
-
if ((next = part.match(
|
|
106
|
+
if ((next = part.match(RE_PROPERTY_NAME))) {
|
|
107
|
+
token = TokenType.PropertyName
|
|
108
|
+
state = State.AfterPropertyName
|
|
109
|
+
} else if ((next = part.match(RE_LINE_COMMENT))) {
|
|
89
110
|
token = TokenType.Comment
|
|
90
|
-
state = State.
|
|
111
|
+
state = State.TopLevelContent
|
|
91
112
|
} else if ((next = part.match(RE_WHITESPACE))) {
|
|
92
113
|
token = TokenType.Whitespace
|
|
93
114
|
state = State.TopLevelContent
|
|
@@ -99,10 +120,33 @@ export const tokenizeLine = (line, lineState) => {
|
|
|
99
120
|
throw new Error('no')
|
|
100
121
|
}
|
|
101
122
|
break
|
|
102
|
-
case State.
|
|
103
|
-
if ((next = part.match(
|
|
123
|
+
case State.AfterPropertyName:
|
|
124
|
+
if ((next = part.match(RE_EQUAL_SIGN))) {
|
|
125
|
+
token = TokenType.Punctuation
|
|
126
|
+
state = State.AfterPropertyNameAfterEqualSign
|
|
127
|
+
} else if ((next = part.match(RE_WHITESPACE))) {
|
|
128
|
+
token = TokenType.Whitespace
|
|
129
|
+
state = State.AfterPropertyName
|
|
130
|
+
} else {
|
|
131
|
+
throw new Error('no')
|
|
132
|
+
}
|
|
133
|
+
break
|
|
134
|
+
case State.AfterPropertyNameAfterEqualSign:
|
|
135
|
+
if ((next = part.match(RE_WHITESPACE))) {
|
|
136
|
+
token = TokenType.Whitespace
|
|
137
|
+
state = State.AfterPropertyNameAfterEqualSign
|
|
138
|
+
} else if ((next = part.match(RE_LANGUAGE_CONSTANT))) {
|
|
139
|
+
token = TokenType.LanguageConstant
|
|
140
|
+
state = State.TopLevelContent
|
|
141
|
+
} else if ((next = part.match(RE_LINE_COMMENT))) {
|
|
104
142
|
token = TokenType.Comment
|
|
105
143
|
state = State.TopLevelContent
|
|
144
|
+
} else if ((next = part.match(RE_QUOTE_DOUBLE))) {
|
|
145
|
+
token = TokenType.Punctuation
|
|
146
|
+
state = State.InsideString
|
|
147
|
+
} else if ((next = part.match(RE_ANYTHING))) {
|
|
148
|
+
token = TokenType.PropertyValueString
|
|
149
|
+
state = State.TopLevelContent
|
|
106
150
|
} else {
|
|
107
151
|
throw new Error('no')
|
|
108
152
|
}
|
|
@@ -79,7 +79,7 @@ const RE_SLASH = /^\//
|
|
|
79
79
|
const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
|
|
80
80
|
const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^']+/
|
|
81
81
|
const RE_TAG_TEXT = /^[^\s>]+/
|
|
82
|
-
const RE_TAGNAME = /^[!\w]+/
|
|
82
|
+
const RE_TAGNAME = /^[!\w\-]+/
|
|
83
83
|
const RE_TEXT = /^[^<>\n]+/
|
|
84
84
|
const RE_WHITESPACE = /^\s+/
|
|
85
85
|
const RE_WORD = /^[^\s]+/
|
package/index.js
CHANGED
|
@@ -5,12 +5,15 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
|
5
5
|
|
|
6
6
|
export const sharedProcessPath = join(__dirname, 'src', 'sharedProcessMain.js')
|
|
7
7
|
|
|
8
|
-
export const exportStatic = async ({
|
|
8
|
+
export const exportStatic = async ({
|
|
9
|
+
extensionPath = process.cwd(),
|
|
10
|
+
testPath = '',
|
|
11
|
+
} = {}) => {
|
|
9
12
|
const fn = await import('./src/parts/ExportStatic/ExportStatic.js')
|
|
10
13
|
const root = process.cwd()
|
|
11
14
|
if (extensionPath !== root) {
|
|
12
15
|
extensionPath = join(root, extensionPath)
|
|
13
16
|
}
|
|
14
17
|
const pathPrefix = process.env.PATH_PREFIX || ''
|
|
15
|
-
await fn.exportStatic({ root, pathPrefix, extensionPath })
|
|
18
|
+
await fn.exportStatic({ root, pathPrefix, extensionPath, testPath })
|
|
16
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/shared-process",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.7",
|
|
4
4
|
"description": "Utility package for @lvce-editor/server",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@babel/code-frame": "^7.18.6",
|
|
20
|
-
"@lvce-editor/extension-host": "0.11.
|
|
21
|
-
"@lvce-editor/extension-host-helper-process": "0.11.
|
|
22
|
-
"@lvce-editor/pty-host": "0.11.
|
|
20
|
+
"@lvce-editor/extension-host": "0.11.7",
|
|
21
|
+
"@lvce-editor/extension-host-helper-process": "0.11.7",
|
|
22
|
+
"@lvce-editor/pty-host": "0.11.7",
|
|
23
23
|
"debug": "^4.3.4",
|
|
24
24
|
"execa": "^6.1.0",
|
|
25
|
-
"exit-hook": "^3.1.
|
|
25
|
+
"exit-hook": "^3.1.4",
|
|
26
26
|
"got": "^12.5.3",
|
|
27
27
|
"is-object": "^1.0.2",
|
|
28
28
|
"lines-and-columns": "^2.0.3",
|
|
@@ -637,11 +637,76 @@ const addExtension = async ({
|
|
|
637
637
|
})
|
|
638
638
|
}
|
|
639
639
|
|
|
640
|
+
const generateTestOverviewHtml = (dirents) => {
|
|
641
|
+
const pre = `<!DOCTYPE html>
|
|
642
|
+
<html lang="en">
|
|
643
|
+
<head>
|
|
644
|
+
<meta charset="UTF-8" />
|
|
645
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
646
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
647
|
+
<title>Tests</title>
|
|
648
|
+
</head>
|
|
649
|
+
<body>
|
|
650
|
+
<h1>Tests</h1>
|
|
651
|
+
<p>Available Tests</p>
|
|
652
|
+
<ul>
|
|
653
|
+
`
|
|
654
|
+
let middle = ``
|
|
655
|
+
// TODO properly escape name
|
|
656
|
+
for (const dirent of dirents) {
|
|
657
|
+
const name = dirent
|
|
658
|
+
middle += ` <li><a href="./${name}.html">${name}</a></li>
|
|
659
|
+
`
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const post = ` </ul>
|
|
663
|
+
</body>
|
|
664
|
+
</html>
|
|
665
|
+
`
|
|
666
|
+
return pre + middle + post
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const getName = (name) => {
|
|
670
|
+
return name.slice(0, -'.js'.length)
|
|
671
|
+
}
|
|
672
|
+
const isTestFile = (file) => {
|
|
673
|
+
return file !== '_all.js'
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const getTestFiles = (testFilesRaw) => {
|
|
677
|
+
return testFilesRaw.map(getName).filter(isTestFile)
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
const addTestFiles = async ({ testPath, commitHash, root, pathPrefix }) => {
|
|
681
|
+
await FileSystem.copy(
|
|
682
|
+
`${root}/${testPath}/src`,
|
|
683
|
+
`${root}/dist/${commitHash}/packages/extension-host-worker-tests/src`
|
|
684
|
+
)
|
|
685
|
+
const testFilesRaw = await FileSystem.readDir(`${root}/${testPath}/src`)
|
|
686
|
+
const testFiles = getTestFiles(testFilesRaw)
|
|
687
|
+
await FileSystem.mkdir(`${root}/dist/${commitHash}/tests`)
|
|
688
|
+
await FileSystem.mkdir(`${root}/dist/tests`)
|
|
689
|
+
console.log({ testFiles })
|
|
690
|
+
for (const testFile of testFiles) {
|
|
691
|
+
await FileSystem.copyFile(
|
|
692
|
+
`${root}/dist/index.html`,
|
|
693
|
+
`${root}/dist/tests/${testFile}.html`
|
|
694
|
+
)
|
|
695
|
+
}
|
|
696
|
+
const testOverviewHtml = generateTestOverviewHtml(testFiles)
|
|
697
|
+
await FileSystem.writeFile(`${root}/dist/tests/index.html`, testOverviewHtml)
|
|
698
|
+
}
|
|
699
|
+
|
|
640
700
|
/**
|
|
641
701
|
*
|
|
642
|
-
* @param {{root:string, pathPrefix:string , extensionPath:string
|
|
702
|
+
* @param {{root:string, pathPrefix:string , extensionPath:string, testPath:string }} param0
|
|
643
703
|
*/
|
|
644
|
-
export const exportStatic = async ({
|
|
704
|
+
export const exportStatic = async ({
|
|
705
|
+
root,
|
|
706
|
+
pathPrefix,
|
|
707
|
+
extensionPath,
|
|
708
|
+
testPath,
|
|
709
|
+
}) => {
|
|
645
710
|
if (pathPrefix === 'auto') {
|
|
646
711
|
const extensionJson = await readExtensionManifest(
|
|
647
712
|
Path.join(extensionPath, 'extension.json')
|
|
@@ -679,4 +744,15 @@ export const exportStatic = async ({ root, pathPrefix, extensionPath }) => {
|
|
|
679
744
|
root,
|
|
680
745
|
})
|
|
681
746
|
console.timeEnd('addExtension')
|
|
747
|
+
|
|
748
|
+
if (testPath) {
|
|
749
|
+
console.time('addTestFiles')
|
|
750
|
+
await addTestFiles({
|
|
751
|
+
testPath,
|
|
752
|
+
commitHash,
|
|
753
|
+
pathPrefix,
|
|
754
|
+
root,
|
|
755
|
+
})
|
|
756
|
+
console.timeEnd('addTestFiles')
|
|
757
|
+
}
|
|
682
758
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
2
2
|
import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
|
|
3
3
|
import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
|
|
4
4
|
import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
5
|
-
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
6
5
|
import * as Path from '../Path/Path.js'
|
|
7
6
|
import * as Platform from '../Platform/Platform.js'
|
|
8
7
|
import * as SymLink from '../SymLink/SymLink.js'
|
|
8
|
+
import { VError } from '../VError/VError.js'
|
|
9
9
|
|
|
10
10
|
const linkFallBack = async (path) => {
|
|
11
11
|
try {
|
|
@@ -19,7 +19,6 @@ const linkFallBack = async (path) => {
|
|
|
19
19
|
await FileSystem.remove(to)
|
|
20
20
|
await SymLink.createSymLink(path, to)
|
|
21
21
|
} catch (error) {
|
|
22
|
-
console.log({ error })
|
|
23
22
|
throw new VError(error, `Failed to link extension`)
|
|
24
23
|
}
|
|
25
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mkdir, rename, rm } from 'node:fs/promises'
|
|
2
|
-
import VError from '
|
|
2
|
+
import { VError } from '../VError/VError.js'
|
|
3
3
|
import * as Debug from '../Debug/Debug.js'
|
|
4
4
|
import * as ExtensionManifestInputType from '../ExtensionManifestInputType/ExtensionManifestInputType.js'
|
|
5
5
|
import * as ExtensionManifests from '../ExtensionManifests/ExtensionManifests.js'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import isObject from 'is-object'
|
|
2
|
-
import
|
|
2
|
+
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
|
|
6
|
+
import { VError } from '../VError/VError.js'
|
|
7
7
|
|
|
8
8
|
const RE_EXTENSION_FRAGMENT = /.+(\/|\\)(.+)$/
|
|
9
9
|
|
|
@@ -2,16 +2,30 @@ import { spawn } from 'node:child_process'
|
|
|
2
2
|
import * as Platform from '../Platform/Platform.js'
|
|
3
3
|
import * as RgPath from '../RgPath/RgPath.js'
|
|
4
4
|
import * as RipGrepParsedLineType from '../RipGrepParsedLineType/RipGrepParsedLineType.js'
|
|
5
|
-
import * as
|
|
5
|
+
import * as TextSearchResultType from '../TextSearchResultType/TextSearchResultType.js'
|
|
6
6
|
|
|
7
7
|
const MAX_SEARCH_RESULTS = 300
|
|
8
8
|
|
|
9
|
+
const BEFORE = 20
|
|
10
|
+
const AFTER = 20
|
|
11
|
+
|
|
9
12
|
const toSearchResult = (parsedLine) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
const results = []
|
|
14
|
+
const lines = parsedLine.data.lines.text
|
|
15
|
+
const lineNumber = parsedLine.data.line_number
|
|
16
|
+
for (const submatch of parsedLine.data.submatches) {
|
|
17
|
+
const previewStart = Math.max(submatch.start - BEFORE, 0)
|
|
18
|
+
const previewEnd = Math.min(submatch.end + AFTER, lines.length)
|
|
19
|
+
const previewText = lines.slice(previewStart, previewEnd)
|
|
20
|
+
results.push({
|
|
21
|
+
type: TextSearchResultType.Match,
|
|
22
|
+
start: submatch.start - previewStart,
|
|
23
|
+
end: submatch.end - previewStart,
|
|
24
|
+
lineNumber,
|
|
25
|
+
text: previewText,
|
|
26
|
+
})
|
|
14
27
|
}
|
|
28
|
+
return results
|
|
15
29
|
}
|
|
16
30
|
|
|
17
31
|
// TODO update vscode-ripgrep when https://github.com/mhinz/vim-grepper/issues/244, https://github.com/BurntSushi/ripgrep/issues/1892 is fixed
|
|
@@ -52,32 +66,53 @@ export const search = async (searchDir, searchString) => {
|
|
|
52
66
|
let numberOfResults = 0
|
|
53
67
|
// TODO use pipeline / transform stream maybe
|
|
54
68
|
|
|
69
|
+
const handleLine = (line) => {
|
|
70
|
+
const parsedLine = JSON.parse(line)
|
|
71
|
+
switch (parsedLine.type) {
|
|
72
|
+
case RipGrepParsedLineType.Begin:
|
|
73
|
+
allSearchResults[parsedLine.data.path.text] = [
|
|
74
|
+
{
|
|
75
|
+
type: TextSearchResultType.File,
|
|
76
|
+
start: 0,
|
|
77
|
+
end: 0,
|
|
78
|
+
lineNumber: 0,
|
|
79
|
+
text: parsedLine.data.path.text,
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
break
|
|
83
|
+
case RipGrepParsedLineType.Match:
|
|
84
|
+
numberOfResults++
|
|
85
|
+
allSearchResults[parsedLine.data.path.text].push(
|
|
86
|
+
...toSearchResult(parsedLine)
|
|
87
|
+
)
|
|
88
|
+
break
|
|
89
|
+
case RipGrepParsedLineType.Summary:
|
|
90
|
+
stats = parsedLine.data
|
|
91
|
+
break
|
|
92
|
+
default:
|
|
93
|
+
break
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let total = 0
|
|
55
98
|
const handleData = (chunk) => {
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
allSearchResults[parsedLine.data.path.text].push(
|
|
71
|
-
toSearchResult(parsedLine)
|
|
72
|
-
)
|
|
73
|
-
break
|
|
74
|
-
case RipGrepParsedLineType.Summary:
|
|
75
|
-
stats = parsedLine.data
|
|
76
|
-
break
|
|
77
|
-
default:
|
|
78
|
-
break
|
|
79
|
-
}
|
|
99
|
+
let newLineIndex = chunk.indexOf('\n')
|
|
100
|
+
const dataString = buffer + chunk
|
|
101
|
+
if (newLineIndex === -1) {
|
|
102
|
+
buffer = dataString
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
total += chunk.length
|
|
106
|
+
newLineIndex += buffer.length
|
|
107
|
+
let previousIndex = 0
|
|
108
|
+
while (newLineIndex >= 0) {
|
|
109
|
+
const line = dataString.slice(previousIndex, newLineIndex)
|
|
110
|
+
handleLine(line)
|
|
111
|
+
previousIndex = newLineIndex + 1
|
|
112
|
+
newLineIndex = dataString.indexOf('\n', previousIndex)
|
|
80
113
|
}
|
|
114
|
+
buffer = dataString.slice(previousIndex)
|
|
115
|
+
|
|
81
116
|
if (numberOfResults > MAX_SEARCH_RESULTS) {
|
|
82
117
|
limitHit = true
|
|
83
118
|
childProcess.kill()
|
|
@@ -85,8 +120,9 @@ export const search = async (searchDir, searchString) => {
|
|
|
85
120
|
}
|
|
86
121
|
|
|
87
122
|
const handleClose = () => {
|
|
123
|
+
const results = Object.values(allSearchResults).flat(1)
|
|
88
124
|
resolve({
|
|
89
|
-
results
|
|
125
|
+
results,
|
|
90
126
|
stats,
|
|
91
127
|
limitHit,
|
|
92
128
|
})
|
|
@@ -100,6 +136,7 @@ export const search = async (searchDir, searchString) => {
|
|
|
100
136
|
limitHit,
|
|
101
137
|
})
|
|
102
138
|
}
|
|
139
|
+
childProcess.stdout.setEncoding('utf8')
|
|
103
140
|
childProcess.stdout.on('data', handleData)
|
|
104
141
|
childProcess.once('close', handleClose)
|
|
105
142
|
childProcess.once('error', handleError)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const getCombinedMessage = (error, message) => {
|
|
2
|
+
let stringifiedError = `${error}`
|
|
3
|
+
if (stringifiedError.startsWith('Error: ')) {
|
|
4
|
+
stringifiedError = stringifiedError.slice(`Error: `.length)
|
|
5
|
+
} else if (stringifiedError.startsWith('VError: ')) {
|
|
6
|
+
stringifiedError = stringifiedError.slice(`VError: `.length)
|
|
7
|
+
}
|
|
8
|
+
if (message) {
|
|
9
|
+
return `${message}: ${stringifiedError}`
|
|
10
|
+
}
|
|
11
|
+
return stringifiedError
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const mergeStacks = (parent, child) => {
|
|
15
|
+
if (!child) {
|
|
16
|
+
return parent
|
|
17
|
+
}
|
|
18
|
+
const parentNewLineIndex = parent.indexOf('\n')
|
|
19
|
+
const childNewLineIndex = child.indexOf('\n')
|
|
20
|
+
const parentFirstLine = parent.slice(0, parentNewLineIndex)
|
|
21
|
+
const childRest = child.slice(childNewLineIndex)
|
|
22
|
+
const childFirstLine = child.slice(0, childNewLineIndex)
|
|
23
|
+
if (parentFirstLine.includes(childFirstLine)) {
|
|
24
|
+
return parentFirstLine + childRest
|
|
25
|
+
}
|
|
26
|
+
return child
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class VError extends Error {
|
|
30
|
+
constructor(error, message) {
|
|
31
|
+
const combinedMessage = getCombinedMessage(error, message)
|
|
32
|
+
super(combinedMessage)
|
|
33
|
+
this.name = 'VError'
|
|
34
|
+
if (error instanceof Error) {
|
|
35
|
+
this.stack = mergeStacks(this.stack, error.stack)
|
|
36
|
+
}
|
|
37
|
+
if (error.codeFrame) {
|
|
38
|
+
this.codeFrame = error.codeFrame
|
|
39
|
+
}
|
|
40
|
+
if (error.code) {
|
|
41
|
+
this.code = error.code
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|