-
-
Notifications
You must be signed in to change notification settings - Fork 27k
/
Copy pathgetSourceMap.js
129 lines (119 loc) · 3.54 KB
/
getSourceMap.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
124
125
126
127
128
129
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* @flow */
import { SourceMapConsumer } from 'source-map';
/**
* A wrapped instance of a <code>{@link https://github.com/mozilla/source-map SourceMapConsumer}</code>.
*
* This exposes methods which will be indifferent to changes made in <code>{@link https://github.com/mozilla/source-map source-map}</code>.
*/
class SourceMap {
__source_map: SourceMapConsumer;
// $FlowFixMe
constructor(sourceMap) {
this.__source_map = sourceMap;
}
/**
* Returns the original code position for a generated code position.
* @param {number} line The line of the generated code position.
* @param {number} column The column of the generated code position.
*/
getOriginalPosition(
line: number,
column: number
): { source: string, line: number, column: number } {
const {
line: l,
column: c,
source: s,
} = this.__source_map.originalPositionFor({
line,
column,
});
return { line: l, column: c, source: s };
}
/**
* Returns the generated code position for an original position.
* @param {string} source The source file of the original code position.
* @param {number} line The line of the original code position.
* @param {number} column The column of the original code position.
*/
getGeneratedPosition(
source: string,
line: number,
column: number
): { line: number, column: number } {
const { line: l, column: c } = this.__source_map.generatedPositionFor({
source,
line,
column,
});
return {
line: l,
column: c,
};
}
/**
* Returns the code for a given source file name.
* @param {string} sourceName The name of the source file.
*/
getSource(sourceName: string): string {
return this.__source_map.sourceContentFor(sourceName);
}
getSources(): string[] {
return this.__source_map.sources;
}
}
function extractSourceMapUrl(
fileUri: string,
fileContents: string
): Promise<string> {
const regex = /\/\/[#@] ?sourceMappingURL=([^\s'"]+)\s*$/gm;
let match = null;
for (;;) {
let next = regex.exec(fileContents);
if (next == null) {
break;
}
match = next;
}
if (!(match && match[1])) {
return Promise.reject(`Cannot find a source map directive for ${fileUri}.`);
}
return Promise.resolve(match[1].toString());
}
/**
* Returns an instance of <code>{@link SourceMap}</code> for a given fileUri and fileContents.
* @param {string} fileUri The URI of the source file.
* @param {string} fileContents The contents of the source file.
*/
async function getSourceMap(
fileUri: string,
fileContents: string
): Promise<SourceMap> {
let sm = await extractSourceMapUrl(fileUri, fileContents);
if (sm.indexOf('data:') === 0) {
const base64 = /^data:application\/json;([\w=:"-]+;)*base64,/;
const match2 = sm.match(base64);
if (!match2) {
throw new Error(
'Sorry, non-base64 inline source-map encoding is not supported.'
);
}
sm = sm.substring(match2[0].length);
sm = window.atob(sm);
sm = JSON.parse(sm);
return new SourceMap(new SourceMapConsumer(sm));
} else {
const index = fileUri.lastIndexOf('/');
const url = fileUri.substring(0, index + 1) + sm;
const obj = await fetch(url).then(res => res.json());
return new SourceMap(new SourceMapConsumer(obj));
}
}
export { extractSourceMapUrl, getSourceMap };
export default getSourceMap;