|
133 | 133 | }
|
134 | 134 | }
|
135 | 135 |
|
136 |
| - function _extractLocationInfoFromSourceMap(stackframe, rawSourceMap, sourceCache) { |
137 |
| - return new Promise(function(resolve, reject) { |
138 |
| - var mapConsumer = new SourceMap.SourceMapConsumer(rawSourceMap); |
139 | 136 |
|
140 |
| - var loc = mapConsumer.originalPositionFor({ |
| 137 | + |
| 138 | + function _extractLocationInfoFromSourceMapSource(stackframe, sourceMapConsumer, sourceCache) { |
| 139 | + return new Promise(function(resolve, reject) { |
| 140 | + var loc = sourceMapConsumer.originalPositionFor({ |
141 | 141 | line: stackframe.lineNumber,
|
142 | 142 | column: stackframe.columnNumber
|
143 | 143 | });
|
144 | 144 |
|
145 | 145 | if (loc.source) {
|
146 |
| - var mappedSource = mapConsumer.sourceContentFor(loc.source); |
| 146 | + var mappedSource = sourceMapConsumer.sourceContentFor(loc.source); |
147 | 147 | if (mappedSource) {
|
148 | 148 | sourceCache[loc.source] = mappedSource;
|
149 | 149 | }
|
|
165 | 165 | * @constructor
|
166 | 166 | * @param {Object} opts
|
167 | 167 | * opts.sourceCache = {url: "Source String"} => preload source cache
|
| 168 | + * opts.sourceMapConsumerCache = {/path/file.js.map: SourceMapConsumer} |
168 | 169 | * opts.offline = True to prevent network requests.
|
169 | 170 | * Best effort without sources or source maps.
|
170 | 171 | * opts.ajax = Promise returning function to make X-Domain requests
|
|
176 | 177 | opts = opts || {};
|
177 | 178 |
|
178 | 179 | this.sourceCache = opts.sourceCache || {};
|
| 180 | + this.sourceMapConsumerCache = opts.sourceMapConsumerCache || {}; |
179 | 181 |
|
180 | 182 | this.ajax = opts.ajax || _xdr;
|
181 | 183 |
|
|
276 | 278 | _ensureStackFrameIsLegit(stackframe);
|
277 | 279 |
|
278 | 280 | var sourceCache = this.sourceCache;
|
| 281 | + var sourceMapConsumerCache = this.sourceMapConsumerCache; |
279 | 282 | var fileName = stackframe.fileName;
|
280 | 283 | this._get(fileName).then(function(source) {
|
281 | 284 | var sourceMappingURL = _findSourceMappingURL(source);
|
|
286 | 289 | sourceMappingURL = base + sourceMappingURL;
|
287 | 290 | }
|
288 | 291 |
|
289 |
| - return this._get(sourceMappingURL).then(function(sourceMap) { |
290 |
| - if (typeof sourceMap === 'string') { |
291 |
| - sourceMap = _parseJson(sourceMap.replace(/^\)\]\}'/, '')); |
| 292 | + var cachedSourceMapConsumer = sourceMapConsumerCache[sourceMappingURL]; |
| 293 | + if (cachedSourceMapConsumer !== undefined) { |
| 294 | + return _extractLocationInfoFromSourceMapSource(stackframe, cachedSourceMapConsumer, sourceCache) |
| 295 | + .then(resolve)['catch'](function() { |
| 296 | + resolve(stackframe); |
| 297 | + }); |
| 298 | + } |
| 299 | + |
| 300 | + return this._get(sourceMappingURL).then(function(sourceMapSource) { |
| 301 | + if (typeof sourceMapSource === 'string') { |
| 302 | + sourceMapSource = _parseJson(sourceMapSource.replace(/^\)\]\}'/, '')); |
292 | 303 | }
|
293 |
| - if (typeof sourceMap.sourceRoot === 'undefined') { |
294 |
| - sourceMap.sourceRoot = base; |
| 304 | + if (typeof sourceMapSource.sourceRoot === 'undefined') { |
| 305 | + sourceMapSource.sourceRoot = base; |
295 | 306 | }
|
296 | 307 |
|
297 |
| - return _extractLocationInfoFromSourceMap(stackframe, sourceMap, sourceCache) |
| 308 | + var sourceMapConsumer = new SourceMap.SourceMapConsumer(sourceMapSource); |
| 309 | + sourceMapConsumerCache[sourceMappingURL] = sourceMapConsumer; |
| 310 | + return _extractLocationInfoFromSourceMapSource(stackframe, sourceMapConsumer, sourceCache) |
298 | 311 | .then(resolve)['catch'](function() {
|
299 | 312 | resolve(stackframe);
|
300 | 313 | });
|
|
0 commit comments