OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 // This is a copy from blink dev tools, see: |
| 29 // http://src.chromium.org/viewvc/blink/trunk/Source/devtools/front_end/SourceMa
p.js |
| 30 // revision: 153407 |
| 31 |
| 32 // Added to make the file work without dev tools |
| 33 WebInspector = {}; |
| 34 WebInspector.ParsedURL = {}; |
| 35 WebInspector.ParsedURL.completeURL = function(){}; |
| 36 // start of original file content |
| 37 |
| 38 /* |
| 39 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 40 * |
| 41 * Redistribution and use in source and binary forms, with or without |
| 42 * modification, are permitted provided that the following conditions are |
| 43 * met: |
| 44 * |
| 45 * * Redistributions of source code must retain the above copyright |
| 46 * notice, this list of conditions and the following disclaimer. |
| 47 * * Redistributions in binary form must reproduce the above |
| 48 * copyright notice, this list of conditions and the following disclaimer |
| 49 * in the documentation and/or other materials provided with the |
| 50 * distribution. |
| 51 * * Neither the name of Google Inc. nor the names of its |
| 52 * contributors may be used to endorse or promote products derived from |
| 53 * this software without specific prior written permission. |
| 54 * |
| 55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 56 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 57 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 58 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 59 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 60 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 61 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 62 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 63 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 64 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 65 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 66 */ |
| 67 |
| 68 /** |
| 69 * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler
/wiki/SourceMaps |
| 70 * for format description. |
| 71 * @constructor |
| 72 * @param {string} sourceMappingURL |
| 73 * @param {SourceMapV3} payload |
| 74 */ |
| 75 WebInspector.SourceMap = function(sourceMappingURL, payload) |
| 76 { |
| 77 if (!WebInspector.SourceMap.prototype._base64Map) { |
| 78 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
yz0123456789+/"; |
| 79 WebInspector.SourceMap.prototype._base64Map = {}; |
| 80 for (var i = 0; i < base64Digits.length; ++i) |
| 81 WebInspector.SourceMap.prototype._base64Map[base64Digits.charAt(i)]
= i; |
| 82 } |
| 83 |
| 84 this._sourceMappingURL = sourceMappingURL; |
| 85 this._reverseMappingsBySourceURL = {}; |
| 86 this._mappings = []; |
| 87 this._sources = {}; |
| 88 this._sourceContentByURL = {}; |
| 89 this._parseMappingPayload(payload); |
| 90 } |
| 91 |
| 92 /** |
| 93 * @param {string} sourceMapURL |
| 94 * @param {string} compiledURL |
| 95 * @param {function(WebInspector.SourceMap)} callback |
| 96 */ |
| 97 WebInspector.SourceMap.load = function(sourceMapURL, compiledURL, callback) |
| 98 { |
| 99 NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFram
e.id, sourceMapURL, undefined, contentLoaded.bind(this)); |
| 100 |
| 101 /** |
| 102 * @param {?Protocol.Error} error |
| 103 * @param {number} statusCode |
| 104 * @param {NetworkAgent.Headers} headers |
| 105 * @param {string} content |
| 106 */ |
| 107 function contentLoaded(error, statusCode, headers, content) |
| 108 { |
| 109 if (error || !content || statusCode >= 400) { |
| 110 console.error("Could not load content for " + sourceMapURL + " : " +
(error || ("HTTP status code: " + statusCode))); |
| 111 callback(null); |
| 112 return; |
| 113 } |
| 114 |
| 115 if (content.slice(0, 3) === ")]}") |
| 116 content = content.substring(content.indexOf('\n')); |
| 117 try { |
| 118 var payload = /** @type {SourceMapV3} */ (JSON.parse(content)); |
| 119 var baseURL = sourceMapURL.startsWith("data:") ? compiledURL : sourc
eMapURL; |
| 120 callback(new WebInspector.SourceMap(baseURL, payload)); |
| 121 } catch(e) { |
| 122 console.error(e.message); |
| 123 callback(null); |
| 124 } |
| 125 } |
| 126 } |
| 127 |
| 128 WebInspector.SourceMap.prototype = { |
| 129 /** |
| 130 * @return {Array.<string>} |
| 131 */ |
| 132 sources: function() |
| 133 { |
| 134 return Object.keys(this._sources); |
| 135 }, |
| 136 |
| 137 /** |
| 138 * @param {string} sourceURL |
| 139 * @return {string|undefined} |
| 140 */ |
| 141 sourceContent: function(sourceURL) |
| 142 { |
| 143 return this._sourceContentByURL[sourceURL]; |
| 144 }, |
| 145 |
| 146 /** |
| 147 * @param {string} sourceURL |
| 148 * @param {WebInspector.ResourceType} contentType |
| 149 * @return {WebInspector.ContentProvider} |
| 150 */ |
| 151 sourceContentProvider: function(sourceURL, contentType) |
| 152 { |
| 153 var lastIndexOfDot = sourceURL.lastIndexOf("."); |
| 154 var extension = lastIndexOfDot !== -1 ? sourceURL.substr(lastIndexOfDot
+ 1) : ""; |
| 155 var mimeType = WebInspector.ResourceType.mimeTypesForExtensions[extensio
n.toLowerCase()]; |
| 156 var sourceContent = this.sourceContent(sourceURL); |
| 157 if (sourceContent) |
| 158 return new WebInspector.StaticContentProvider(contentType, sourceCon
tent, mimeType); |
| 159 return new WebInspector.CompilerSourceMappingContentProvider(sourceURL,
contentType, mimeType); |
| 160 }, |
| 161 |
| 162 /** |
| 163 * @param {SourceMapV3} mappingPayload |
| 164 */ |
| 165 _parseMappingPayload: function(mappingPayload) |
| 166 { |
| 167 if (mappingPayload.sections) |
| 168 this._parseSections(mappingPayload.sections); |
| 169 else |
| 170 this._parseMap(mappingPayload, 0, 0); |
| 171 }, |
| 172 |
| 173 /** |
| 174 * @param {Array.<SourceMapV3.Section>} sections |
| 175 */ |
| 176 _parseSections: function(sections) |
| 177 { |
| 178 for (var i = 0; i < sections.length; ++i) { |
| 179 var section = sections[i]; |
| 180 this._parseMap(section.map, section.offset.line, section.offset.colu
mn); |
| 181 } |
| 182 }, |
| 183 |
| 184 /** |
| 185 * @param {number} lineNumber in compiled resource |
| 186 * @param {number} columnNumber in compiled resource |
| 187 * @return {?Array} |
| 188 */ |
| 189 findEntry: function(lineNumber, columnNumber) |
| 190 { |
| 191 var first = 0; |
| 192 var count = this._mappings.length; |
| 193 while (count > 1) { |
| 194 var step = count >> 1; |
| 195 var middle = first + step; |
| 196 var mapping = this._mappings[middle]; |
| 197 if (lineNumber < mapping[0] || (lineNumber === mapping[0] && columnNum
ber < mapping[1])) |
| 198 count = step; |
| 199 else { |
| 200 first = middle; |
| 201 count -= step; |
| 202 } |
| 203 } |
| 204 var entry = this._mappings[first]; |
| 205 if (!first && entry && (lineNumber < entry[0] || (lineNumber === entry[0
] && columnNumber < entry[1]))) |
| 206 return null; |
| 207 return entry; |
| 208 }, |
| 209 |
| 210 /** |
| 211 * @param {string} sourceURL of the originating resource |
| 212 * @param {number} lineNumber in the originating resource |
| 213 * @return {Array} |
| 214 */ |
| 215 findEntryReversed: function(sourceURL, lineNumber) |
| 216 { |
| 217 var mappings = this._reverseMappingsBySourceURL[sourceURL]; |
| 218 for ( ; lineNumber < mappings.length; ++lineNumber) { |
| 219 var mapping = mappings[lineNumber]; |
| 220 if (mapping) |
| 221 return mapping; |
| 222 } |
| 223 return this._mappings[0]; |
| 224 }, |
| 225 |
| 226 /** |
| 227 * @override |
| 228 */ |
| 229 _parseMap: function(map, lineNumber, columnNumber) |
| 230 { |
| 231 var sourceIndex = 0; |
| 232 var sourceLineNumber = 0; |
| 233 var sourceColumnNumber = 0; |
| 234 var nameIndex = 0; |
| 235 |
| 236 var sources = []; |
| 237 var originalToCanonicalURLMap = {}; |
| 238 for (var i = 0; i < map.sources.length; ++i) { |
| 239 var originalSourceURL = map.sources[i]; |
| 240 var sourceRoot = map.sourceRoot || ""; |
| 241 if (sourceRoot && !sourceRoot.endsWith("/")) |
| 242 sourceRoot += "/"; |
| 243 var href = sourceRoot + originalSourceURL; |
| 244 var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL,
href) || href; |
| 245 originalToCanonicalURLMap[originalSourceURL] = url; |
| 246 sources.push(url); |
| 247 this._sources[url] = true; |
| 248 |
| 249 if (map.sourcesContent && map.sourcesContent[i]) |
| 250 this._sourceContentByURL[url] = map.sourcesContent[i]; |
| 251 } |
| 252 |
| 253 var stringCharIterator = new WebInspector.SourceMap.StringCharIterator(m
ap.mappings); |
| 254 var sourceURL = sources[sourceIndex]; |
| 255 |
| 256 while (true) { |
| 257 if (stringCharIterator.peek() === ",") |
| 258 stringCharIterator.next(); |
| 259 else { |
| 260 while (stringCharIterator.peek() === ";") { |
| 261 lineNumber += 1; |
| 262 columnNumber = 0; |
| 263 stringCharIterator.next(); |
| 264 } |
| 265 if (!stringCharIterator.hasNext()) |
| 266 break; |
| 267 } |
| 268 |
| 269 columnNumber += this._decodeVLQ(stringCharIterator); |
| 270 if (this._isSeparator(stringCharIterator.peek())) { |
| 271 this._mappings.push([lineNumber, columnNumber]); |
| 272 continue; |
| 273 } |
| 274 |
| 275 var sourceIndexDelta = this._decodeVLQ(stringCharIterator); |
| 276 if (sourceIndexDelta) { |
| 277 sourceIndex += sourceIndexDelta; |
| 278 sourceURL = sources[sourceIndex]; |
| 279 } |
| 280 sourceLineNumber += this._decodeVLQ(stringCharIterator); |
| 281 sourceColumnNumber += this._decodeVLQ(stringCharIterator); |
| 282 if (!this._isSeparator(stringCharIterator.peek())) |
| 283 nameIndex += this._decodeVLQ(stringCharIterator); |
| 284 |
| 285 this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLine
Number, sourceColumnNumber]); |
| 286 } |
| 287 |
| 288 for (var i = 0; i < this._mappings.length; ++i) { |
| 289 var mapping = this._mappings[i]; |
| 290 var url = mapping[2]; |
| 291 if (!url) |
| 292 continue; |
| 293 if (!this._reverseMappingsBySourceURL[url]) |
| 294 this._reverseMappingsBySourceURL[url] = []; |
| 295 var reverseMappings = this._reverseMappingsBySourceURL[url]; |
| 296 var sourceLine = mapping[3]; |
| 297 if (!reverseMappings[sourceLine]) |
| 298 reverseMappings[sourceLine] = [mapping[0], mapping[1]]; |
| 299 } |
| 300 }, |
| 301 |
| 302 /** |
| 303 * @param {string} char |
| 304 * @return {boolean} |
| 305 */ |
| 306 _isSeparator: function(char) |
| 307 { |
| 308 return char === "," || char === ";"; |
| 309 }, |
| 310 |
| 311 /** |
| 312 * @param {WebInspector.SourceMap.StringCharIterator} stringCharIterator |
| 313 * @return {number} |
| 314 */ |
| 315 _decodeVLQ: function(stringCharIterator) |
| 316 { |
| 317 // Read unsigned value. |
| 318 var result = 0; |
| 319 var shift = 0; |
| 320 do { |
| 321 var digit = this._base64Map[stringCharIterator.next()]; |
| 322 result += (digit & this._VLQ_BASE_MASK) << shift; |
| 323 shift += this._VLQ_BASE_SHIFT; |
| 324 } while (digit & this._VLQ_CONTINUATION_MASK); |
| 325 |
| 326 // Fix the sign. |
| 327 var negative = result & 1; |
| 328 result >>= 1; |
| 329 return negative ? -result : result; |
| 330 }, |
| 331 |
| 332 _VLQ_BASE_SHIFT: 5, |
| 333 _VLQ_BASE_MASK: (1 << 5) - 1, |
| 334 _VLQ_CONTINUATION_MASK: 1 << 5 |
| 335 } |
| 336 |
| 337 /** |
| 338 * @constructor |
| 339 * @param {string} string |
| 340 */ |
| 341 WebInspector.SourceMap.StringCharIterator = function(string) |
| 342 { |
| 343 this._string = string; |
| 344 this._position = 0; |
| 345 } |
| 346 |
| 347 WebInspector.SourceMap.StringCharIterator.prototype = { |
| 348 /** |
| 349 * @return {string} |
| 350 */ |
| 351 next: function() |
| 352 { |
| 353 return this._string.charAt(this._position++); |
| 354 }, |
| 355 |
| 356 /** |
| 357 * @return {string} |
| 358 */ |
| 359 peek: function() |
| 360 { |
| 361 return this._string.charAt(this._position); |
| 362 }, |
| 363 |
| 364 /** |
| 365 * @return {boolean} |
| 366 */ |
| 367 hasNext: function() |
| 368 { |
| 369 return this._position < this._string.length; |
| 370 } |
| 371 } |
OLD | NEW |