forked from react/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseHermesStack.js
More file actions
120 lines (107 loc) · 2.9 KB
/
Copy pathparseHermesStack.js
File metadata and controls
120 lines (107 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/
'use strict';
type HermesStackLocationNative = {|
+type: 'NATIVE',
|};
type HermesStackLocationSource = {|
+type: 'SOURCE',
+sourceUrl: string,
+line1Based: number,
+column1Based: number,
|};
type HermesStackLocationBytecode = {|
+type: 'BYTECODE',
+sourceUrl: string,
+line1Based: number,
+virtualOffset0Based: number,
|};
type HermesStackLocation =
| HermesStackLocationNative
| HermesStackLocationSource
| HermesStackLocationBytecode;
type HermesStackEntryFrame = {|
+type: 'FRAME',
+location: HermesStackLocation,
+functionName: string,
|};
type HermesStackEntrySkipped = {|
+type: 'SKIPPED',
+count: number,
|};
type HermesStackEntry = HermesStackEntryFrame | HermesStackEntrySkipped;
export type HermesParsedStack = {|
+message: string,
+entries: $ReadOnlyArray<HermesStackEntry>,
|};
// Capturing groups:
// 1. function name
// 2. is this a native stack frame?
// 3. is this a bytecode address or a source location?
// 4. source URL (filename)
// 5. line number (1 based)
// 6. column number (1 based) or virtual offset (0 based)
const RE_FRAME = /^ {4}at (.+?)(?: \((native)\)?| \((address at )?(.+?):(\d+):(\d+)\))$/;
// Capturing groups:
// 1. count of skipped frames
const RE_SKIPPED = /^ {4}... skipping (\d+) frames$/;
function parseLine(line: string): ?HermesStackEntry {
const asFrame = line.match(RE_FRAME);
if (asFrame) {
return {
type: 'FRAME',
functionName: asFrame[1],
location:
asFrame[2] === 'native'
? {type: 'NATIVE'}
: asFrame[3] === 'address at '
? {
type: 'BYTECODE',
sourceUrl: asFrame[4],
line1Based: Number.parseInt(asFrame[5], 10),
virtualOffset0Based: Number.parseInt(asFrame[6], 10),
}
: {
type: 'SOURCE',
sourceUrl: asFrame[4],
line1Based: Number.parseInt(asFrame[5], 10),
column1Based: Number.parseInt(asFrame[6], 10),
},
};
}
const asSkipped = line.match(RE_SKIPPED);
if (asSkipped) {
return {
type: 'SKIPPED',
count: Number.parseInt(asSkipped[1], 10),
};
}
}
module.exports = function parseHermesStack(stack: string): HermesParsedStack {
const lines = stack.split(/\n/);
let entries = [];
let lastMessageLine = -1;
for (let i = 0; i < lines.length; ++i) {
const line = lines[i];
if (!line) {
continue;
}
const entry = parseLine(line);
if (entry) {
entries.push(entry);
continue;
}
// No match - we're still in the message
lastMessageLine = i;
entries = [];
}
const message = lines.slice(0, lastMessageLine + 1).join('\n');
return {message, entries};
};