-
-
Notifications
You must be signed in to change notification settings - Fork 26.9k
/
Copy pathunmapper.js
123 lines (119 loc) · 3.59 KB
/
unmapper.js
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
121
122
123
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/* @flow */
import StackFrame from './stack-frame';
import { getSourceMap } from './getSourceMap';
import { getLinesAround } from './getLinesAround';
import path from 'path';
function count(search: string, string: string): number {
// Count starts at -1 becuse a do-while loop always runs at least once
let count = -1,
index = -1;
do {
// First call or the while case evaluated true, meaning we have to make
// count 0 or we found a character
++count;
// Find the index of our search string, starting after the previous index
index = string.indexOf(search, index + 1);
} while (index !== -1);
return count;
}
/**
* Turns a set of mapped <code>StackFrame</code>s back into their generated code position and enhances them with code.
* @param {string} fileUri The URI of the <code>bundle.js</code> file.
* @param {StackFrame[]} frames A set of <code>StackFrame</code>s which are already mapped and missing their generated positions.
* @param {number} [fileContents=3] The number of lines to provide before and after the line specified in the <code>StackFrame</code>.
*/
async function unmap(
_fileUri: string | { uri: string, contents: string },
frames: StackFrame[],
contextLines: number = 3
): Promise<StackFrame[]> {
let fileContents = typeof _fileUri === 'object' ? _fileUri.contents : null;
let fileUri = typeof _fileUri === 'object' ? _fileUri.uri : _fileUri;
if (fileContents == null) {
fileContents = await fetch(fileUri).then(res => res.text());
}
const map = await getSourceMap(fileUri, fileContents);
return frames.map(frame => {
const {
functionName,
lineNumber,
columnNumber,
_originalLineNumber,
} = frame;
if (_originalLineNumber != null) {
return frame;
}
let { fileName } = frame;
if (fileName) {
fileName = path.normalize(fileName);
}
if (fileName == null) {
return frame;
}
const fN: string = fileName;
const source = map
.getSources()
.map(s => s.replace(/[\\]+/g, '/'))
.filter(p => {
p = path.normalize(p);
const i = p.lastIndexOf(fN);
return i !== -1 && i === p.length - fN.length;
})
.map(p => ({
token: p,
seps: count(path.sep, path.normalize(p)),
penalties: count('node_modules', p) + count('~', p),
}))
.sort((a, b) => {
const s = Math.sign(a.seps - b.seps);
if (s !== 0) {
return s;
}
return Math.sign(a.penalties - b.penalties);
});
if (source.length < 1 || lineNumber == null) {
return new StackFrame(
null,
null,
null,
null,
null,
functionName,
fN,
lineNumber,
columnNumber,
null
);
}
const sourceT = source[0].token;
const { line, column } = map.getGeneratedPosition(
sourceT,
lineNumber,
// $FlowFixMe
columnNumber
);
const originalSource = map.getSource(sourceT);
return new StackFrame(
functionName,
fileUri,
line,
column || null,
getLinesAround(line, contextLines, fileContents || []),
functionName,
fN,
lineNumber,
columnNumber,
getLinesAround(lineNumber, contextLines, originalSource)
);
});
}
export { unmap };
export default unmap;