Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/source_map_support.js
6162 views
1
/**
2
* @license
3
* Copyright 2019 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
class WasmSourceMap {
8
mapping = {};
9
offsets = [];
10
11
constructor(sourceMap) {
12
this.version = sourceMap.version;
13
this.sources = sourceMap.sources;
14
this.names = sourceMap.names;
15
16
var vlqMap = {};
17
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split('').forEach((c, i) => vlqMap[c] = i);
18
19
// based on https://github.com/Rich-Harris/vlq/blob/master/src/vlq.ts
20
function decodeVLQ(string) {
21
var result = [];
22
var shift = 0;
23
var value = 0;
24
25
for (var ch of string) {
26
var integer = vlqMap[ch];
27
if (integer === undefined) {
28
throw new Error(`Invalid character (${ch})`);
29
}
30
31
value += (integer & 31) << shift;
32
33
if (integer & 32) {
34
shift += 5;
35
} else {
36
var negate = value & 1;
37
value >>= 1;
38
result.push(negate ? -value : value);
39
value = shift = 0;
40
}
41
}
42
return result;
43
}
44
45
var offset = 0, src = 0, line = 1, col = 1, name = 0;
46
for (const [index, segment] of sourceMap.mappings.split(',').entries()) {
47
if (!segment) continue;
48
var data = decodeVLQ(segment);
49
var info = {};
50
51
offset += data[0];
52
if (data.length >= 2) info.source = src += data[1];
53
if (data.length >= 3) info.line = line += data[2];
54
if (data.length >= 4) info.column = col += data[3];
55
if (data.length >= 5) info.name = name += data[4];
56
this.mapping[offset] = info;
57
this.offsets.push(offset);
58
}
59
this.offsets.sort((a, b) => a - b);
60
}
61
62
lookup(offset) {
63
var normalized = this.normalizeOffset(offset);
64
var info = this.mapping[normalized];
65
if (!info) {
66
return null;
67
}
68
return {
69
file: this.sources[info.source],
70
line: info.line,
71
column: info.column,
72
name: this.names[info.name],
73
};
74
}
75
76
normalizeOffset(offset) {
77
var lo = 0;
78
var hi = this.offsets.length;
79
var mid;
80
81
while (lo < hi) {
82
mid = Math.floor((lo + hi) / 2);
83
if (this.offsets[mid] > offset) {
84
hi = mid;
85
} else {
86
lo = mid + 1;
87
}
88
}
89
return this.offsets[lo - 1];
90
}
91
}
92
93
var wasmSourceMap;
94
#if MINIMAL_RUNTIME
95
var wasmSourceMapFile = '{{{ WASM_BINARY_FILE }}}.map';
96
#else
97
var wasmSourceMapFile = locateFile('{{{ WASM_BINARY_FILE }}}.map');
98
#endif
99
100
function receiveSourceMapJSON(sourceMap) {
101
wasmSourceMap = new WasmSourceMap(sourceMap);
102
}
103
104
function getSourceMap() {
105
var buf = readBinary(wasmSourceMapFile);
106
return JSON.parse(UTF8ArrayToString(buf));
107
}
108
109
async function getSourceMapAsync() {
110
if (ENVIRONMENT_IS_WEB
111
#if ENVIRONMENT_MAY_BE_WORKER
112
|| ENVIRONMENT_IS_WORKER
113
#endif
114
) {
115
try {
116
var response = await fetch(wasmSourceMapFile, {{{ makeModuleReceiveExpr('fetchSettings', "{ credentials: 'same-origin' }") }}});
117
return response.json();
118
} catch {
119
// Fall back to getSourceMap below
120
}
121
}
122
return getSourceMap();
123
}
124
125
126
#if PTHREADS || WASM_WORKERS
127
// Source map is received via postMessage on worker threads.
128
if ({{{ ENVIRONMENT_IS_MAIN_THREAD() }}}) {
129
#endif
130
131
#if !MINIMAL_RUNTIME // MINIMAL_RUNTIME integrates source map loading into postamble_minimal.js
132
#if WASM_ASYNC_COMPILATION
133
addRunDependency('source-map');
134
getSourceMapAsync().then((json) => {
135
receiveSourceMapJSON(json);
136
removeRunDependency('source-map');
137
});
138
#else
139
receiveSourceMapJSON(getSourceMap());
140
#endif
141
#endif
142
143
#if PTHREADS || WASM_WORKERS
144
}
145
#endif
146
147