OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 * @return {string} | 89 * @return {string} |
90 */ | 90 */ |
91 compiledURL: function() { }, | 91 compiledURL: function() { }, |
92 | 92 |
93 /** | 93 /** |
94 * @return {string} | 94 * @return {string} |
95 */ | 95 */ |
96 url: function() { }, | 96 url: function() { }, |
97 | 97 |
98 /** | 98 /** |
99 * @return {!Array<string>} | 99 * @return {!Iterable<string>|!Array<string>} |
lushnikov
2016/09/28 16:48:12
let's keep this array - we try to avoid polymorphi
eostroukhov
2016/09/28 23:26:33
This CL is about saving memory! ;)
(Ok, I fixed t
| |
100 */ | 100 */ |
101 sourceURLs: function() { }, | 101 sourceURLs: function() { }, |
102 | 102 |
103 /** | 103 /** |
104 * @param {string} sourceURL | 104 * @param {string} sourceURL |
105 * @param {!WebInspector.ResourceType} contentType | 105 * @param {!WebInspector.ResourceType} contentType |
106 * @return {!WebInspector.ContentProvider} | 106 * @return {!WebInspector.ContentProvider} |
107 */ | 107 */ |
108 sourceContentProvider: function(sourceURL, contentType) { }, | 108 sourceContentProvider: function(sourceURL, contentType) { }, |
109 | 109 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 */ | 165 */ |
166 WebInspector.TextSourceMap = function(compiledURL, sourceMappingURL, payload) | 166 WebInspector.TextSourceMap = function(compiledURL, sourceMappingURL, payload) |
167 { | 167 { |
168 if (!WebInspector.TextSourceMap.prototype._base64Map) { | 168 if (!WebInspector.TextSourceMap.prototype._base64Map) { |
169 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/"; | 169 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/"; |
170 WebInspector.TextSourceMap.prototype._base64Map = {}; | 170 WebInspector.TextSourceMap.prototype._base64Map = {}; |
171 for (var i = 0; i < base64Digits.length; ++i) | 171 for (var i = 0; i < base64Digits.length; ++i) |
172 WebInspector.TextSourceMap.prototype._base64Map[base64Digits.charAt( i)] = i; | 172 WebInspector.TextSourceMap.prototype._base64Map[base64Digits.charAt( i)] = i; |
173 } | 173 } |
174 | 174 |
175 this._json = payload; | |
175 this._compiledURL = compiledURL; | 176 this._compiledURL = compiledURL; |
176 this._sourceMappingURL = sourceMappingURL; | 177 this._sourceMappingURL = sourceMappingURL; |
177 this._reverseMappingsBySourceURL = new Map(); | 178 /** @type {?Array<!WebInspector.SourceMapEntry>} */ |
178 this._mappings = []; | 179 this._mappings = null; |
179 this._sources = {}; | 180 this._sources = new Map(); |
lushnikov
2016/09/28 16:48:12
1. let's add jsdoc
2. let's name this _sourceURLTo
eostroukhov
2016/09/28 23:26:33
Done.
| |
180 this._sourceContentByURL = {}; | 181 this._sourceContentByURL = {}; |
181 this._parseMappingPayload(payload); | 182 this._eachSection(this._parseSources.bind(this)); |
182 } | 183 } |
183 | 184 |
184 /** | 185 /** |
185 * @param {string} sourceMapURL | 186 * @param {string} sourceMapURL |
186 * @param {string} compiledURL | 187 * @param {string} compiledURL |
187 * @return {!Promise<?WebInspector.TextSourceMap>} | 188 * @return {!Promise<?WebInspector.TextSourceMap>} |
188 * @this {WebInspector.TextSourceMap} | 189 * @this {WebInspector.TextSourceMap} |
189 */ | 190 */ |
190 WebInspector.TextSourceMap.load = function(sourceMapURL, compiledURL) | 191 WebInspector.TextSourceMap.load = function(sourceMapURL, compiledURL) |
191 { | 192 { |
(...skipping 12 matching lines...) Expand all Loading... | |
204 if (!content || statusCode >= 400) { | 205 if (!content || statusCode >= 400) { |
205 callback(null); | 206 callback(null); |
206 return; | 207 return; |
207 } | 208 } |
208 | 209 |
209 if (content.slice(0, 3) === ")]}") | 210 if (content.slice(0, 3) === ")]}") |
210 content = content.substring(content.indexOf("\n")); | 211 content = content.substring(content.indexOf("\n")); |
211 try { | 212 try { |
212 var payload = /** @type {!SourceMapV3} */ (JSON.parse(content)); | 213 var payload = /** @type {!SourceMapV3} */ (JSON.parse(content)); |
213 var baseURL = sourceMapURL.startsWith("data:") ? compiledURL : sourc eMapURL; | 214 var baseURL = sourceMapURL.startsWith("data:") ? compiledURL : sourc eMapURL; |
214 | |
215 callback(new WebInspector.TextSourceMap(compiledURL, baseURL, payloa d)); | 215 callback(new WebInspector.TextSourceMap(compiledURL, baseURL, payloa d)); |
216 } catch (e) { | 216 } catch (e) { |
217 console.error(e); | 217 console.error(e); |
218 WebInspector.console.warn("DevTools failed to parse SourceMap: " + s ourceMapURL); | 218 WebInspector.console.warn("DevTools failed to parse SourceMap: " + s ourceMapURL); |
219 callback(null); | 219 callback(null); |
220 } | 220 } |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 WebInspector.TextSourceMap.prototype = { | 224 WebInspector.TextSourceMap.prototype = { |
(...skipping 10 matching lines...) Expand all Loading... | |
235 * @override | 235 * @override |
236 * @return {string} | 236 * @return {string} |
237 */ | 237 */ |
238 url: function() | 238 url: function() |
239 { | 239 { |
240 return this._sourceMappingURL; | 240 return this._sourceMappingURL; |
241 }, | 241 }, |
242 | 242 |
243 /** | 243 /** |
244 * @override | 244 * @override |
245 * @return {!Array.<string>} | 245 * @return {!Iterable.<string>} |
246 */ | 246 */ |
247 sourceURLs: function() | 247 sourceURLs: function() |
248 { | 248 { |
249 return Object.keys(this._sources); | 249 return this._sources.keys(); |
lushnikov
2016/09/28 16:48:13
let's use .keysArray() to return array
eostroukhov
2016/09/28 23:26:33
Done.
| |
250 }, | 250 }, |
251 | 251 |
252 /** | 252 /** |
253 * @override | 253 * @override |
254 * @param {string} sourceURL | 254 * @param {string} sourceURL |
255 * @param {!WebInspector.ResourceType} contentType | 255 * @param {!WebInspector.ResourceType} contentType |
256 * @return {!WebInspector.ContentProvider} | 256 * @return {!WebInspector.ContentProvider} |
257 */ | 257 */ |
258 sourceContentProvider: function(sourceURL, contentType) | 258 sourceContentProvider: function(sourceURL, contentType) |
259 { | 259 { |
(...skipping 17 matching lines...) Expand all Loading... | |
277 * @param {!Array<!WebInspector.TextRange>} ranges | 277 * @param {!Array<!WebInspector.TextRange>} ranges |
278 * @param {!Array<string>} texts | 278 * @param {!Array<string>} texts |
279 * @return {!Promise<?WebInspector.SourceMap.EditResult>} | 279 * @return {!Promise<?WebInspector.SourceMap.EditResult>} |
280 */ | 280 */ |
281 editCompiled: function(ranges, texts) | 281 editCompiled: function(ranges, texts) |
282 { | 282 { |
283 return Promise.resolve(/** @type {?WebInspector.SourceMap.EditResult} */ (null)); | 283 return Promise.resolve(/** @type {?WebInspector.SourceMap.EditResult} */ (null)); |
284 }, | 284 }, |
285 | 285 |
286 /** | 286 /** |
287 * @param {!SourceMapV3} mappingPayload | |
288 */ | |
289 _parseMappingPayload: function(mappingPayload) | |
290 { | |
291 if (mappingPayload.sections) | |
292 this._parseSections(mappingPayload.sections); | |
293 else | |
294 this._parseMap(mappingPayload, 0, 0); | |
295 }, | |
296 | |
297 /** | |
298 * @param {!Array.<!SourceMapV3.Section>} sections | |
299 */ | |
300 _parseSections: function(sections) | |
301 { | |
302 for (var i = 0; i < sections.length; ++i) { | |
303 var section = sections[i]; | |
304 this._parseMap(section.map, section.offset.line, section.offset.colu mn); | |
305 } | |
306 }, | |
307 | |
308 /** | |
309 * @override | 287 * @override |
310 * @param {number} lineNumber in compiled resource | 288 * @param {number} lineNumber in compiled resource |
311 * @param {number} columnNumber in compiled resource | 289 * @param {number} columnNumber in compiled resource |
312 * @return {?WebInspector.SourceMapEntry} | 290 * @return {?WebInspector.SourceMapEntry} |
313 */ | 291 */ |
314 findEntry: function(lineNumber, columnNumber) | 292 findEntry: function(lineNumber, columnNumber) |
315 { | 293 { |
316 var first = 0; | 294 var first = 0; |
317 var count = this._mappings.length; | 295 var mappings = this.mappings(); |
296 var count = mappings.length; | |
318 while (count > 1) { | 297 while (count > 1) { |
319 var step = count >> 1; | 298 var step = count >> 1; |
320 var middle = first + step; | 299 var middle = first + step; |
321 var mapping = this._mappings[middle]; | 300 var mapping = mappings[middle]; |
322 if (lineNumber < mapping.lineNumber || (lineNumber === mapping.lineN umber && columnNumber < mapping.columnNumber)) { | 301 if (lineNumber < mapping.lineNumber || (lineNumber === mapping.lineN umber && columnNumber < mapping.columnNumber)) { |
323 count = step; | 302 count = step; |
324 } else { | 303 } else { |
325 first = middle; | 304 first = middle; |
326 count -= step; | 305 count -= step; |
327 } | 306 } |
328 } | 307 } |
329 var entry = this._mappings[first]; | 308 var entry = mappings[first]; |
330 if (!first && entry && (lineNumber < entry.lineNumber || (lineNumber === entry.lineNumber && columnNumber < entry.columnNumber))) | 309 if (!first && entry && (lineNumber < entry.lineNumber || (lineNumber === entry.lineNumber && columnNumber < entry.columnNumber))) |
331 return null; | 310 return null; |
332 return entry; | 311 return entry; |
333 }, | 312 }, |
334 | 313 |
335 /** | 314 /** |
336 * @param {string} sourceURL | 315 * @param {string} sourceURL |
337 * @param {number} lineNumber | 316 * @param {number} lineNumber |
338 * @return {?WebInspector.SourceMapEntry} | 317 * @return {?WebInspector.SourceMapEntry} |
339 */ | 318 */ |
(...skipping 14 matching lines...) Expand all Loading... | |
354 { | 333 { |
355 return lineNumber - mapping.sourceLineNumber; | 334 return lineNumber - mapping.sourceLineNumber; |
356 } | 335 } |
357 }, | 336 }, |
358 | 337 |
359 /** | 338 /** |
360 * @return {!Array<!WebInspector.SourceMapEntry>} | 339 * @return {!Array<!WebInspector.SourceMapEntry>} |
361 */ | 340 */ |
362 mappings: function() | 341 mappings: function() |
363 { | 342 { |
364 return this._mappings; | 343 if (this._mappings === null) { |
344 this._mappings = []; | |
345 this._eachSection(this._parseMap.bind(this)); | |
346 this._json = null; | |
347 } | |
348 return /** @type {!Array<!WebInspector.SourceMapEntry>} */ (this._mappin gs); | |
365 }, | 349 }, |
366 | 350 |
367 /** | 351 /** |
368 * @param {string} sourceURL | 352 * @param {string} sourceURL |
369 * @return {!Array.<!WebInspector.SourceMapEntry>} | 353 * @return {!Array.<!WebInspector.SourceMapEntry>} |
370 */ | 354 */ |
371 _reversedMappings: function(sourceURL) | 355 _reversedMappings: function(sourceURL) |
372 { | 356 { |
373 var mappings = this._reverseMappingsBySourceURL.get(sourceURL); | 357 if (this._sources && !this._sources.has(sourceURL)) |
374 if (!mappings) | |
375 return []; | 358 return []; |
376 if (!mappings._sorted) { | 359 let mappings = this.mappings(); |
lushnikov
2016/09/28 16:48:13
nit: we're not yet using "let" in the codebase
eostroukhov
2016/09/28 23:26:34
Done.
| |
377 mappings.sort(sourceMappingComparator); | 360 let reverseMappings = this._sources.get(sourceURL); |
378 mappings._sorted = true; | 361 if (reverseMappings === null) { |
362 reverseMappings = mappings.filter((mapping) => mapping.sourceURL === sourceURL).sort(sourceMappingComparator); | |
363 this._sources.set(sourceURL, reverseMappings); | |
379 } | 364 } |
380 return mappings; | 365 return reverseMappings; |
381 | 366 |
382 /** | 367 /** |
383 * @param {!WebInspector.SourceMapEntry} a | 368 * @param {!WebInspector.SourceMapEntry} a |
384 * @param {!WebInspector.SourceMapEntry} b | 369 * @param {!WebInspector.SourceMapEntry} b |
385 * @return {number} | 370 * @return {number} |
386 */ | 371 */ |
387 function sourceMappingComparator(a, b) | 372 function sourceMappingComparator(a, b) |
388 { | 373 { |
389 if (a.sourceLineNumber !== b.sourceLineNumber) | 374 if (a.sourceLineNumber !== b.sourceLineNumber) |
390 return a.sourceLineNumber - b.sourceLineNumber; | 375 return a.sourceLineNumber - b.sourceLineNumber; |
391 if (a.sourceColumnNumber !== b.sourceColumnNumber) | 376 if (a.sourceColumnNumber !== b.sourceColumnNumber) |
392 return a.sourceColumnNumber - b.sourceColumnNumber; | 377 return a.sourceColumnNumber - b.sourceColumnNumber; |
393 | 378 |
394 if (a.lineNumber !== b.lineNumber) | 379 if (a.lineNumber !== b.lineNumber) |
395 return a.lineNumber - b.lineNumber; | 380 return a.lineNumber - b.lineNumber; |
396 | 381 |
397 return a.columnNumber - b.columnNumber; | 382 return a.columnNumber - b.columnNumber; |
398 } | 383 } |
399 }, | 384 }, |
400 | 385 |
401 /** | 386 /** |
387 * @param {function(!SourceMapV3, number, number)} callback | |
388 */ | |
389 _eachSection: function(callback) { | |
390 const sections = this._json.sections || [this._json]; | |
lushnikov
2016/09/28 16:48:13
let's bail out early instead:
if (!this._json.sec
eostroukhov
2016/09/28 23:26:33
Done.
| |
391 for (const section of sections) { | |
lushnikov
2016/09/28 16:48:13
nit: we're not yet using "const" in the codebase
eostroukhov
2016/09/28 23:26:33
Done.
| |
392 const offset = section.offset || {line: 0, column: 0}; | |
393 callback(section.map || section, offset.line, offset.column); | |
394 } | |
395 }, | |
396 | |
397 /** | |
398 * @param {!SourceMapV3} sourceMap | |
399 */ | |
400 _parseSources: function(sourceMap) { | |
401 var sourceRoot = sourceMap.sourceRoot || ""; | |
402 if (sourceRoot && !sourceRoot.endsWith("/")) | |
403 sourceRoot += "/"; | |
404 for (var i = 0; i < sourceMap.sources.length; ++i) { | |
lushnikov
2016/09/28 16:48:13
this looks like a copy of the code in _parseMap. C
eostroukhov
2016/09/28 23:26:33
There are building different things - one is build
| |
405 var href = sourceRoot + sourceMap.sources[i]; | |
406 var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL, href) || href; | |
407 var hasSource = sourceMap.sourcesContent && sourceMap.sourcesContent [i]; | |
408 if (url === this._compiledURL && hasSource) | |
409 url += WebInspector.UIString(" [sm]"); | |
410 this._sources.set(url, null); | |
411 if (hasSource) | |
412 this._sourceContentByURL[url] = sourceMap.sourcesContent[i]; | |
413 } | |
414 }, | |
415 | |
416 /** | |
402 * @param {!SourceMapV3} map | 417 * @param {!SourceMapV3} map |
403 * @param {number} lineNumber | 418 * @param {number} lineNumber |
404 * @param {number} columnNumber | 419 * @param {number} columnNumber |
405 */ | 420 */ |
406 _parseMap: function(map, lineNumber, columnNumber) | 421 _parseMap: function(map, lineNumber, columnNumber) |
407 { | 422 { |
408 var sourceIndex = 0; | 423 var sourceIndex = 0; |
409 var sourceLineNumber = 0; | 424 var sourceLineNumber = 0; |
410 var sourceColumnNumber = 0; | 425 var sourceColumnNumber = 0; |
411 var nameIndex = 0; | 426 var nameIndex = 0; |
412 | 427 |
413 var sources = []; | 428 var sources = []; |
414 var names = map.names || []; | 429 var names = map.names || []; |
415 var sourceRoot = map.sourceRoot || ""; | 430 var sourceRoot = map.sourceRoot || ""; |
416 if (sourceRoot && !sourceRoot.endsWith("/")) | 431 if (sourceRoot && !sourceRoot.endsWith("/")) |
417 sourceRoot += "/"; | 432 sourceRoot += "/"; |
418 for (var i = 0; i < map.sources.length; ++i) { | 433 for (var i = 0; i < map.sources.length; ++i) { |
419 var href = sourceRoot + map.sources[i]; | 434 var href = sourceRoot + map.sources[i]; |
420 var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL, href) || href; | 435 var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL, href) || href; |
421 var hasSource = map.sourcesContent && map.sourcesContent[i]; | 436 var hasSource = map.sourcesContent && map.sourcesContent[i]; |
422 if (url === this._compiledURL && hasSource) | 437 if (url === this._compiledURL && hasSource) |
423 url += WebInspector.UIString(" [sm]"); | 438 url += WebInspector.UIString(" [sm]"); |
424 sources.push(url); | 439 sources.push(url); |
425 this._sources[url] = true; | |
426 | |
427 if (hasSource) | |
428 this._sourceContentByURL[url] = map.sourcesContent[i]; | |
429 } | 440 } |
430 | 441 |
431 var stringCharIterator = new WebInspector.TextSourceMap.StringCharIterat or(map.mappings); | 442 var stringCharIterator = new WebInspector.TextSourceMap.StringCharIterat or(map.mappings); |
432 var sourceURL = sources[sourceIndex]; | 443 var sourceURL = sources[sourceIndex]; |
433 | 444 |
434 while (true) { | 445 while (true) { |
435 if (stringCharIterator.peek() === ",") | 446 if (stringCharIterator.peek() === ",") |
436 stringCharIterator.next(); | 447 stringCharIterator.next(); |
437 else { | 448 else { |
438 while (stringCharIterator.peek() === ";") { | 449 while (stringCharIterator.peek() === ";") { |
(...skipping 20 matching lines...) Expand all Loading... | |
459 sourceColumnNumber += this._decodeVLQ(stringCharIterator); | 470 sourceColumnNumber += this._decodeVLQ(stringCharIterator); |
460 | 471 |
461 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIte rator.peek())) { | 472 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIte rator.peek())) { |
462 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber)); | 473 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber)); |
463 continue; | 474 continue; |
464 } | 475 } |
465 | 476 |
466 nameIndex += this._decodeVLQ(stringCharIterator); | 477 nameIndex += this._decodeVLQ(stringCharIterator); |
467 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, colu mnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex])); | 478 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, colu mnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex])); |
468 } | 479 } |
469 | |
470 for (var i = 0; i < this._mappings.length; ++i) { | |
471 var mapping = this._mappings[i]; | |
472 var url = mapping.sourceURL; | |
473 if (!url) | |
474 continue; | |
475 if (!this._reverseMappingsBySourceURL.has(url)) | |
476 this._reverseMappingsBySourceURL.set(url, []); | |
477 var reverseMappings = this._reverseMappingsBySourceURL.get(url); | |
478 reverseMappings.push(mapping); | |
479 } | |
480 }, | 480 }, |
481 | 481 |
482 /** | 482 /** |
483 * @param {string} char | 483 * @param {string} char |
484 * @return {boolean} | 484 * @return {boolean} |
485 */ | 485 */ |
486 _isSeparator: function(char) | 486 _isSeparator: function(char) |
487 { | 487 { |
488 return char === "," || char === ";"; | 488 return char === "," || char === ";"; |
489 }, | 489 }, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 }, | 571 }, |
572 | 572 |
573 /** | 573 /** |
574 * @return {boolean} | 574 * @return {boolean} |
575 */ | 575 */ |
576 hasNext: function() | 576 hasNext: function() |
577 { | 577 { |
578 return this._position < this._string.length; | 578 return this._position < this._string.length; |
579 } | 579 } |
580 } | 580 } |
OLD | NEW |