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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 { | 57 { |
58 /** @type {number} */ this.line; | 58 /** @type {number} */ this.line; |
59 /** @type {number} */ this.column; | 59 /** @type {number} */ this.column; |
60 } | 60 } |
61 | 61 |
62 /** | 62 /** |
63 * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler
/wiki/SourceMaps | 63 * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler
/wiki/SourceMaps |
64 * for format description. | 64 * for format description. |
65 * @constructor | 65 * @constructor |
66 * @param {string} sourceMappingURL | 66 * @param {string} sourceMappingURL |
67 * @param {!SourceMapV3} payload | 67 * @param {?SourceMapV3} payload |
68 */ | 68 */ |
69 WebInspector.SourceMap = function(sourceMappingURL, payload) | 69 WebInspector.SourceMap = function(sourceMappingURL, payload) |
70 { | 70 { |
71 if (!WebInspector.SourceMap.prototype._base64Map) { | 71 if (!WebInspector.SourceMap.prototype._base64Map) { |
72 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
yz0123456789+/"; | 72 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
yz0123456789+/"; |
73 WebInspector.SourceMap.prototype._base64Map = {}; | 73 WebInspector.SourceMap.prototype._base64Map = {}; |
74 for (var i = 0; i < base64Digits.length; ++i) | 74 for (var i = 0; i < base64Digits.length; ++i) |
75 WebInspector.SourceMap.prototype._base64Map[base64Digits.charAt(i)]
= i; | 75 WebInspector.SourceMap.prototype._base64Map[base64Digits.charAt(i)]
= i; |
76 } | 76 } |
77 | 77 |
78 this._sourceMappingURL = sourceMappingURL; | 78 this._sourceMappingURL = sourceMappingURL; |
79 this._reverseMappingsBySourceURL = new Map(); | 79 this._reverseMappingsBySourceURL = new Map(); |
80 this._mappings = []; | 80 this._mappings = []; |
81 this._sources = {}; | 81 this._sources = {}; |
82 this._sourceContentByURL = {}; | 82 this._sourceContentByURL = {}; |
83 this._parseMappingPayload(payload); | 83 if (payload) |
| 84 this._parseMappingPayload(payload); |
84 } | 85 } |
85 | 86 |
86 /** | 87 /** |
87 * @param {string} sourceMapURL | 88 * @param {string} sourceMapURL |
88 * @param {string} compiledURL | 89 * @param {string} compiledURL |
89 * @param {function(?WebInspector.SourceMap)} callback | 90 * @param {function(?WebInspector.SourceMap)} callback |
90 * @this {WebInspector.SourceMap} | 91 * @this {WebInspector.SourceMap} |
91 */ | 92 */ |
92 WebInspector.SourceMap.load = function(sourceMapURL, compiledURL, callback) | 93 WebInspector.SourceMap.load = function(sourceMapURL, compiledURL, callback) |
93 { | 94 { |
(...skipping 28 matching lines...) Expand all Loading... |
122 callback(new WebInspector.SourceMap(baseURL, payload)); | 123 callback(new WebInspector.SourceMap(baseURL, payload)); |
123 } catch(e) { | 124 } catch(e) { |
124 console.error(e.message); | 125 console.error(e.message); |
125 callback(null); | 126 callback(null); |
126 } | 127 } |
127 } | 128 } |
128 } | 129 } |
129 | 130 |
130 WebInspector.SourceMap.prototype = { | 131 WebInspector.SourceMap.prototype = { |
131 /** | 132 /** |
| 133 * @return {!WebInspector.SourceMap} |
| 134 */ |
| 135 clone: function() |
| 136 { |
| 137 var map = new WebInspector.SourceMap(this._sourceMappingURL, null); |
| 138 map._sources = this._sources; |
| 139 map._sourceContentByURL = this._sourceContentByURL; |
| 140 for (var i = 0; i < this._mappings.length; ++i) |
| 141 map._mappings.push(this._mappings[i].clone()); |
| 142 map._initializedReversedMappings(); |
| 143 return map; |
| 144 }, |
| 145 |
| 146 /** |
| 147 * @param {!WebInspector.TextRange} oldRange |
| 148 * @param {!WebInspector.TextRange} newRange |
| 149 */ |
| 150 compiledRangeEdited: function(oldRange, newRange) |
| 151 { |
| 152 console.assert(oldRange.startLine === newRange.startLine); |
| 153 console.assert(oldRange.startColumn === newRange.startColumn); |
| 154 |
| 155 var columnOffset = newRange.endColumn - oldRange.endColumn; |
| 156 var lineOffset = newRange.endLine - oldRange.endLine; |
| 157 |
| 158 var newMappings = []; |
| 159 for (var i = 0; i < this._mappings.length; ++i) { |
| 160 var mapping = this._mappings[i]; |
| 161 // Edit destroys mapping. |
| 162 if (oldRange.containsLocation(mapping.lineNumber, mapping.columnNumb
er)) |
| 163 continue; |
| 164 newMappings.push(mapping); |
| 165 // Update compiled mapping coordinates if needed. |
| 166 if (mapping.lineNumber === oldRange.endLine && mapping.columnNumber
>= oldRange.endColumn) { |
| 167 mapping.columnNumber += columnOffset; |
| 168 mapping.lineNumber += lineOffset; |
| 169 } else if (mapping.lineNumber > oldRange.endLine) { |
| 170 mapping.lineNumber += lineOffset; |
| 171 } |
| 172 } |
| 173 this._mappings = newMappings; |
| 174 this._initializedReversedMappings(); |
| 175 }, |
| 176 |
| 177 /** |
| 178 * @param {string} sourceURL |
| 179 * @param {!WebInspector.TextRange} oldRange |
| 180 * @param {!WebInspector.TextRange} newRange |
| 181 * @return {boolean} |
| 182 */ |
| 183 sourceRangeEdited: function(sourceURL, oldRange, newRange) |
| 184 { |
| 185 console.assert(oldRange.startLine === newRange.startLine); |
| 186 console.assert(oldRange.startColumn === newRange.startColumn); |
| 187 |
| 188 var columnOffset = newRange.endColumn - oldRange.endColumn; |
| 189 var lineOffset = newRange.endLine - oldRange.endLine; |
| 190 var newMappings = []; |
| 191 for (var i = 0; i < this._mappings.length; ++i) { |
| 192 var mapping = this._mappings[i]; |
| 193 if (mapping.sourceURL !== sourceURL) { |
| 194 newMappings.push(mapping); |
| 195 continue; |
| 196 } |
| 197 if (oldRange.containsLocation(mapping.sourceLineNumber, mapping.sour
ceColumnNumber)) |
| 198 continue; |
| 199 newMappings.push(mapping); |
| 200 // Update source mapping coordinates if needed. |
| 201 if (mapping.sourceLineNumber === oldRange.endLine && mapping.sourceC
olumnNumber >= oldRange.endColumn) { |
| 202 mapping.sourceColumnNumber += columnOffset; |
| 203 mapping.sourceLineNumber += lineOffset; |
| 204 } else if (mapping.sourceLineNumber > oldRange.endLine) |
| 205 mapping.sourceLineNumber += lineOffset; |
| 206 } |
| 207 this._mappings = newMappings; |
| 208 this._initializedReversedMappings(); |
| 209 }, |
| 210 |
| 211 ensureHasMapping: function(newEntry) |
| 212 { |
| 213 var entry = this.findEntry(newEntry.lineNumber, newEntry.columnNumber); |
| 214 if (entry && entry.equals(newEntry)) |
| 215 return; |
| 216 if (entry && entry.lineNumber === newEntry.lineNumber && entry.columnNum
ber === newEntry.columnNumber) { |
| 217 entry.sourceURL = newEntry.sourceURL; |
| 218 entry.sourceLineNumber = newEntry.sourceLineNumber; |
| 219 entry.sourceColumnNumber = newEntry.sourceColumnNumber; |
| 220 this._initializedReversedMappings(); |
| 221 return; |
| 222 } |
| 223 var newMappings = []; |
| 224 var i = 0; |
| 225 while (this._mappings[i] !== entry) |
| 226 newMappings.push(this._mappings[i++]); |
| 227 newMappings.push(entry); |
| 228 newMappings.push(newEntry); |
| 229 ++i; |
| 230 while (i < this._mappings.length) |
| 231 newMappings.push(this._mappings[i++]); |
| 232 |
| 233 var reverseMappings = this._reverseMappingsBySourceURL.get(newEntry.sour
ceURL); |
| 234 reverseMappings.push(newEntry); |
| 235 reverseMappings._sorted = false; |
| 236 this._mappings = newMappings; |
| 237 }, |
| 238 |
| 239 /** |
132 * @return {string} | 240 * @return {string} |
133 */ | 241 */ |
134 url: function() | 242 url: function() |
135 { | 243 { |
136 return this._sourceMappingURL; | 244 return this._sourceMappingURL; |
137 }, | 245 }, |
138 | 246 |
139 /** | 247 /** |
140 * @return {!Array.<string>} | 248 * @return {!Array.<string>} |
141 */ | 249 */ |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 first = middle; | 315 first = middle; |
208 count -= step; | 316 count -= step; |
209 } | 317 } |
210 } | 318 } |
211 var entry = this._mappings[first]; | 319 var entry = this._mappings[first]; |
212 if (!first && entry && (lineNumber < entry.lineNumber || (lineNumber ===
entry.lineNumber && columnNumber < entry.columnNumber))) | 320 if (!first && entry && (lineNumber < entry.lineNumber || (lineNumber ===
entry.lineNumber && columnNumber < entry.columnNumber))) |
213 return null; | 321 return null; |
214 return entry; | 322 return entry; |
215 }, | 323 }, |
216 | 324 |
| 325 findEntriesReversed: function(sourceURL, lineNumber, columnNumber) |
| 326 { |
| 327 var mappings = this._reversedMappings(sourceURL); |
| 328 var first = 0; |
| 329 var count = mappings.length; |
| 330 while (count > 1) { |
| 331 var step = count >> 1; |
| 332 var middle = first + step; |
| 333 var mapping = mappings[middle]; |
| 334 if (lineNumber < mapping.sourceLineNumber || (lineNumber === mapping.s
ourceLineNumber && columnNumber < mapping.sourceColumnNumber)) |
| 335 count = step; |
| 336 else { |
| 337 first = middle; |
| 338 count -= step; |
| 339 } |
| 340 } |
| 341 var entry = mappings[first]; |
| 342 if (!first && entry && (lineNumber < entry.sourceLineNumber || (lineNumb
er === entry.sourceLineNumber && columnNumber < entry.sourceColumnNumber))) |
| 343 return []; |
| 344 var results = []; |
| 345 for (var i = first; i >= 0 && mappings[i].sourceLineNumber === entry.sou
rceLineNumber && mappings[i].sourceColumnNumber === entry.sourceColumnNumber; --
i) |
| 346 results.push(mappings[i]); |
| 347 return results; |
| 348 }, |
| 349 |
217 /** | 350 /** |
218 * @param {string} sourceURL | 351 * @param {string} sourceURL |
219 * @param {number} lineNumber | 352 * @param {number} lineNumber |
220 * @return {?WebInspector.SourceMap.Entry} | 353 * @return {?WebInspector.SourceMap.Entry} |
221 */ | 354 */ |
222 firstSourceLineMapping: function(sourceURL, lineNumber) | 355 firstSourceLineMapping: function(sourceURL, lineNumber) |
223 { | 356 { |
224 var mappings = this._reversedMappings(sourceURL); | 357 var mappings = this._reversedMappings(sourceURL); |
225 var index = mappings.lowerBound(lineNumber, lineComparator); | 358 var index = mappings.lowerBound(lineNumber, lineComparator); |
226 if (index >= mappings.length || mappings[index].sourceLineNumber !== lin
eNumber) | 359 if (index >= mappings.length || mappings[index].sourceLineNumber !== lin
eNumber) |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 sourceURL = sources[sourceIndex]; | 461 sourceURL = sources[sourceIndex]; |
329 } | 462 } |
330 sourceLineNumber += this._decodeVLQ(stringCharIterator); | 463 sourceLineNumber += this._decodeVLQ(stringCharIterator); |
331 sourceColumnNumber += this._decodeVLQ(stringCharIterator); | 464 sourceColumnNumber += this._decodeVLQ(stringCharIterator); |
332 if (!this._isSeparator(stringCharIterator.peek())) | 465 if (!this._isSeparator(stringCharIterator.peek())) |
333 nameIndex += this._decodeVLQ(stringCharIterator); | 466 nameIndex += this._decodeVLQ(stringCharIterator); |
334 | 467 |
335 this._mappings.push(new WebInspector.SourceMap.Entry(lineNumber, col
umnNumber, sourceURL, sourceLineNumber, sourceColumnNumber)); | 468 this._mappings.push(new WebInspector.SourceMap.Entry(lineNumber, col
umnNumber, sourceURL, sourceLineNumber, sourceColumnNumber)); |
336 } | 469 } |
337 | 470 |
| 471 this._initializedReversedMappings(); |
| 472 }, |
| 473 |
| 474 _initializedReversedMappings: function() |
| 475 { |
| 476 this._reverseMappingsBySourceURL.clear(); |
338 for (var i = 0; i < this._mappings.length; ++i) { | 477 for (var i = 0; i < this._mappings.length; ++i) { |
339 var mapping = this._mappings[i]; | 478 var mapping = this._mappings[i]; |
340 var url = mapping.sourceURL; | 479 var url = mapping.sourceURL; |
341 if (!url) | 480 if (!url) |
342 continue; | 481 continue; |
343 if (!this._reverseMappingsBySourceURL.has(url)) | 482 if (!this._reverseMappingsBySourceURL.has(url)) |
344 this._reverseMappingsBySourceURL.set(url, []); | 483 this._reverseMappingsBySourceURL.set(url, []); |
345 var reverseMappings = this._reverseMappingsBySourceURL.get(url); | 484 var reverseMappings = this._reverseMappingsBySourceURL.get(url); |
346 reverseMappings.push(mapping); | 485 reverseMappings.push(mapping); |
347 } | 486 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 * @param {number=} sourceColumnNumber | 566 * @param {number=} sourceColumnNumber |
428 */ | 567 */ |
429 WebInspector.SourceMap.Entry = function(lineNumber, columnNumber, sourceURL, sou
rceLineNumber, sourceColumnNumber) | 568 WebInspector.SourceMap.Entry = function(lineNumber, columnNumber, sourceURL, sou
rceLineNumber, sourceColumnNumber) |
430 { | 569 { |
431 this.lineNumber = lineNumber; | 570 this.lineNumber = lineNumber; |
432 this.columnNumber = columnNumber; | 571 this.columnNumber = columnNumber; |
433 this.sourceURL = sourceURL; | 572 this.sourceURL = sourceURL; |
434 this.sourceLineNumber = sourceLineNumber; | 573 this.sourceLineNumber = sourceLineNumber; |
435 this.sourceColumnNumber = sourceColumnNumber; | 574 this.sourceColumnNumber = sourceColumnNumber; |
436 } | 575 } |
| 576 |
| 577 WebInspector.SourceMap.Entry.prototype = { |
| 578 /** |
| 579 * @param {!WebInspector.SourceMap.Entry} other |
| 580 * @return {boolean} |
| 581 */ |
| 582 equals: function(other) |
| 583 { |
| 584 return this.lineNumber === other.lineNumber && |
| 585 this.columnNumber === other.columnNumber && |
| 586 this.sourceURL === other.sourceURL && |
| 587 this.sourceLineNumber === other.sourceLineNumber && |
| 588 this.sourceColumnNumber === other.sourceColumnNumber; |
| 589 }, |
| 590 |
| 591 /** |
| 592 * @return {!WebInspector.SourceMap.Entry} |
| 593 */ |
| 594 clone: function() |
| 595 { |
| 596 return new WebInspector.SourceMap.Entry(this.lineNumber, this.columnNumb
er, this.sourceURL, this.sourceLineNumber, this.sourceColumnNumber); |
| 597 }, |
| 598 } |
OLD | NEW |