| 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 |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | 31 * @unrestricted |
| 33 */ | 32 */ |
| 34 function SourceMapV3() | 33 var SourceMapV3 = class { |
| 35 { | 34 constructor() { |
| 36 /** @type {number} */ this.version; | 35 /** @type {number} */ this.version; |
| 37 /** @type {string|undefined} */ this.file; | 36 /** @type {string|undefined} */ this.file; |
| 38 /** @type {!Array.<string>} */ this.sources; | 37 /** @type {!Array.<string>} */ this.sources; |
| 39 /** @type {!Array.<!SourceMapV3.Section>|undefined} */ this.sections; | 38 /** @type {!Array.<!SourceMapV3.Section>|undefined} */ this.sections; |
| 40 /** @type {string} */ this.mappings; | 39 /** @type {string} */ this.mappings; |
| 41 /** @type {string|undefined} */ this.sourceRoot; | 40 /** @type {string|undefined} */ this.sourceRoot; |
| 42 /** @type {!Array.<string>|undefined} */ this.names; | 41 /** @type {!Array.<string>|undefined} */ this.names; |
| 43 } | 42 } |
| 44 | |
| 45 /** | |
| 46 * @constructor | |
| 47 */ | |
| 48 SourceMapV3.Section = function() | |
| 49 { | |
| 50 /** @type {!SourceMapV3} */ this.map; | |
| 51 /** @type {!SourceMapV3.Offset} */ this.offset; | |
| 52 }; | 43 }; |
| 53 | 44 |
| 54 /** | 45 /** |
| 55 * @constructor | 46 * @unrestricted |
| 56 */ | 47 */ |
| 57 SourceMapV3.Offset = function() | 48 SourceMapV3.Section = class { |
| 58 { | 49 constructor() { |
| 59 /** @type {number} */ this.line; | 50 /** @type {!SourceMapV3} */ this.map; |
| 60 /** @type {number} */ this.column; | 51 /** @type {!SourceMapV3.Offset} */ this.offset; |
| 52 } |
| 61 }; | 53 }; |
| 62 | 54 |
| 63 /** | 55 /** |
| 64 * @constructor | 56 * @unrestricted |
| 65 * @param {number} lineNumber | |
| 66 * @param {number} columnNumber | |
| 67 * @param {string=} sourceURL | |
| 68 * @param {number=} sourceLineNumber | |
| 69 * @param {number=} sourceColumnNumber | |
| 70 * @param {string=} name | |
| 71 */ | 57 */ |
| 72 WebInspector.SourceMapEntry = function(lineNumber, columnNumber, sourceURL, sour
ceLineNumber, sourceColumnNumber, name) | 58 SourceMapV3.Offset = class { |
| 73 { | 59 constructor() { |
| 60 /** @type {number} */ this.line; |
| 61 /** @type {number} */ this.column; |
| 62 } |
| 63 }; |
| 64 |
| 65 /** |
| 66 * @unrestricted |
| 67 */ |
| 68 WebInspector.SourceMapEntry = class { |
| 69 /** |
| 70 * @param {number} lineNumber |
| 71 * @param {number} columnNumber |
| 72 * @param {string=} sourceURL |
| 73 * @param {number=} sourceLineNumber |
| 74 * @param {number=} sourceColumnNumber |
| 75 * @param {string=} name |
| 76 */ |
| 77 constructor(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColum
nNumber, name) { |
| 74 this.lineNumber = lineNumber; | 78 this.lineNumber = lineNumber; |
| 75 this.columnNumber = columnNumber; | 79 this.columnNumber = columnNumber; |
| 76 this.sourceURL = sourceURL; | 80 this.sourceURL = sourceURL; |
| 77 this.sourceLineNumber = sourceLineNumber; | 81 this.sourceLineNumber = sourceLineNumber; |
| 78 this.sourceColumnNumber = sourceColumnNumber; | 82 this.sourceColumnNumber = sourceColumnNumber; |
| 79 this.name = name; | 83 this.name = name; |
| 84 } |
| 80 }; | 85 }; |
| 81 | 86 |
| 82 /** | 87 /** |
| 83 * @interface | 88 * @interface |
| 84 */ | 89 */ |
| 85 WebInspector.SourceMap = function() { }; | 90 WebInspector.SourceMap = function() {}; |
| 86 | 91 |
| 87 WebInspector.SourceMap.prototype = { | 92 WebInspector.SourceMap.prototype = { |
| 88 /** | 93 /** |
| 89 * @return {string} | 94 * @return {string} |
| 90 */ | 95 */ |
| 91 compiledURL: function() { }, | 96 compiledURL: function() {}, |
| 92 | 97 |
| 93 /** | 98 /** |
| 94 * @return {string} | 99 * @return {string} |
| 95 */ | 100 */ |
| 96 url: function() { }, | 101 url: function() {}, |
| 97 | 102 |
| 98 /** | 103 /** |
| 99 * @return {!Array<string>} | 104 * @return {!Array<string>} |
| 100 */ | 105 */ |
| 101 sourceURLs: function() { }, | 106 sourceURLs: function() {}, |
| 102 | 107 |
| 103 /** | 108 /** |
| 104 * @param {string} sourceURL | 109 * @param {string} sourceURL |
| 105 * @param {!WebInspector.ResourceType} contentType | 110 * @param {!WebInspector.ResourceType} contentType |
| 106 * @return {!WebInspector.ContentProvider} | 111 * @return {!WebInspector.ContentProvider} |
| 107 */ | 112 */ |
| 108 sourceContentProvider: function(sourceURL, contentType) { }, | 113 sourceContentProvider: function(sourceURL, contentType) {}, |
| 109 | 114 |
| 110 /** | 115 /** |
| 111 * @param {string} sourceURL | 116 * @param {string} sourceURL |
| 112 * @return {?string} | 117 * @return {?string} |
| 113 */ | 118 */ |
| 114 embeddedContentByURL: function(sourceURL) { }, | 119 embeddedContentByURL: function(sourceURL) {}, |
| 115 | 120 |
| 116 /** | 121 /** |
| 117 * @param {number} lineNumber in compiled resource | 122 * @param {number} lineNumber in compiled resource |
| 118 * @param {number} columnNumber in compiled resource | 123 * @param {number} columnNumber in compiled resource |
| 119 * @return {?WebInspector.SourceMapEntry} | 124 * @return {?WebInspector.SourceMapEntry} |
| 120 */ | 125 */ |
| 121 findEntry: function(lineNumber, columnNumber) { }, | 126 findEntry: function(lineNumber, columnNumber) {}, |
| 122 | 127 |
| 123 /** | 128 /** |
| 124 * @return {boolean} | 129 * @return {boolean} |
| 125 */ | 130 */ |
| 126 editable: function() { }, | 131 editable: function() {}, |
| 127 | 132 |
| 128 /** | 133 /** |
| 129 * @param {!Array<!WebInspector.TextRange>} ranges | 134 * @param {!Array<!WebInspector.TextRange>} ranges |
| 130 * @param {!Array<string>} texts | 135 * @param {!Array<string>} texts |
| 131 * @return {!Promise<?WebInspector.SourceMap.EditResult>} | 136 * @return {!Promise<?WebInspector.SourceMap.EditResult>} |
| 132 */ | 137 */ |
| 133 editCompiled: function(ranges, texts) { }, | 138 editCompiled: function(ranges, texts) {}, |
| 134 }; | 139 }; |
| 135 | 140 |
| 136 /** | 141 /** |
| 137 * @constructor | 142 * @unrestricted |
| 138 * @param {!WebInspector.SourceMap} map | |
| 139 * @param {!Array<!WebInspector.SourceEdit>} compiledEdits | |
| 140 * @param {!Map<string, string>} newSources | |
| 141 */ | 143 */ |
| 142 WebInspector.SourceMap.EditResult = function(map, compiledEdits, newSources) | 144 WebInspector.SourceMap.EditResult = class { |
| 143 { | 145 /** |
| 146 * @param {!WebInspector.SourceMap} map |
| 147 * @param {!Array<!WebInspector.SourceEdit>} compiledEdits |
| 148 * @param {!Map<string, string>} newSources |
| 149 */ |
| 150 constructor(map, compiledEdits, newSources) { |
| 144 this.map = map; | 151 this.map = map; |
| 145 this.compiledEdits = compiledEdits; | 152 this.compiledEdits = compiledEdits; |
| 146 this.newSources = newSources; | 153 this.newSources = newSources; |
| 154 } |
| 147 }; | 155 }; |
| 148 | 156 |
| 149 /** | 157 /** |
| 150 * @interface | 158 * @interface |
| 151 */ | 159 */ |
| 152 WebInspector.SourceMapFactory = function() { }; | 160 WebInspector.SourceMapFactory = function() {}; |
| 153 | 161 |
| 154 WebInspector.SourceMapFactory.prototype = { | 162 WebInspector.SourceMapFactory.prototype = { |
| 155 /** | 163 /** |
| 156 * @param {!WebInspector.Target} target | 164 * @param {!WebInspector.Target} target |
| 157 * @param {!WebInspector.SourceMap} sourceMap | 165 * @param {!WebInspector.SourceMap} sourceMap |
| 158 * @return {!Promise<?WebInspector.SourceMap>} | 166 * @return {!Promise<?WebInspector.SourceMap>} |
| 159 */ | 167 */ |
| 160 editableSourceMap: function(target, sourceMap) { }, | 168 editableSourceMap: function(target, sourceMap) {}, |
| 161 }; | 169 }; |
| 162 | 170 |
| 163 /** | 171 /** |
| 164 * Implements Source Map V3 model. See https://github.com/google/closure-compile
r/wiki/Source-Maps | |
| 165 * for format description. | |
| 166 * @constructor | |
| 167 * @implements {WebInspector.SourceMap} | 172 * @implements {WebInspector.SourceMap} |
| 168 * @param {string} compiledURL | 173 * @unrestricted |
| 169 * @param {string} sourceMappingURL | |
| 170 * @param {!SourceMapV3} payload | |
| 171 */ | 174 */ |
| 172 WebInspector.TextSourceMap = function(compiledURL, sourceMappingURL, payload) | 175 WebInspector.TextSourceMap = class { |
| 173 { | 176 /** |
| 174 if (!WebInspector.TextSourceMap.prototype._base64Map) { | 177 * Implements Source Map V3 model. See https://github.com/google/closure-compi
ler/wiki/Source-Maps |
| 175 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
yz0123456789+/"; | 178 * for format description. |
| 176 WebInspector.TextSourceMap.prototype._base64Map = {}; | 179 * @param {string} compiledURL |
| 177 for (var i = 0; i < base64Digits.length; ++i) | 180 * @param {string} sourceMappingURL |
| 178 WebInspector.TextSourceMap.prototype._base64Map[base64Digits.charAt(
i)] = i; | 181 * @param {!SourceMapV3} payload |
| 182 */ |
| 183 constructor(compiledURL, sourceMappingURL, payload) { |
| 184 if (!WebInspector.TextSourceMap._base64Map) { |
| 185 const base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789+/'; |
| 186 WebInspector.TextSourceMap._base64Map = {}; |
| 187 for (var i = 0; i < base64Digits.length; ++i) |
| 188 WebInspector.TextSourceMap._base64Map[base64Digits.charAt(i)] = i; |
| 179 } | 189 } |
| 180 | 190 |
| 181 this._json = payload; | 191 this._json = payload; |
| 182 this._compiledURL = compiledURL; | 192 this._compiledURL = compiledURL; |
| 183 this._sourceMappingURL = sourceMappingURL; | 193 this._sourceMappingURL = sourceMappingURL; |
| 184 /** @type {?Array<!WebInspector.SourceMapEntry>} */ | 194 /** @type {?Array<!WebInspector.SourceMapEntry>} */ |
| 185 this._mappings = null; | 195 this._mappings = null; |
| 186 /** @type {!Map<string, !WebInspector.TextSourceMap.SourceInfo>} */ | 196 /** @type {!Map<string, !WebInspector.TextSourceMap.SourceInfo>} */ |
| 187 this._sourceInfos = new Map(); | 197 this._sourceInfos = new Map(); |
| 188 this._eachSection(this._parseSources.bind(this)); | 198 this._eachSection(this._parseSources.bind(this)); |
| 189 }; | 199 } |
| 190 | 200 |
| 191 /** | 201 /** |
| 192 * @param {string} sourceMapURL | 202 * @param {string} sourceMapURL |
| 193 * @param {string} compiledURL | 203 * @param {string} compiledURL |
| 194 * @return {!Promise<?WebInspector.TextSourceMap>} | 204 * @return {!Promise<?WebInspector.TextSourceMap>} |
| 195 * @this {WebInspector.TextSourceMap} | 205 * @this {WebInspector.TextSourceMap} |
| 196 */ | 206 */ |
| 197 WebInspector.TextSourceMap.load = function(sourceMapURL, compiledURL) | 207 static load(sourceMapURL, compiledURL) { |
| 198 { | |
| 199 var callback; | 208 var callback; |
| 200 var promise = new Promise(fulfill => callback = fulfill); | 209 var promise = new Promise(fulfill => callback = fulfill); |
| 201 WebInspector.multitargetNetworkManager.loadResource(sourceMapURL, contentLoa
ded); | 210 WebInspector.multitargetNetworkManager.loadResource(sourceMapURL, contentLoa
ded); |
| 202 return promise; | 211 return promise; |
| 203 | 212 |
| 204 /** | 213 /** |
| 205 * @param {number} statusCode | 214 * @param {number} statusCode |
| 206 * @param {!Object.<string, string>} headers | 215 * @param {!Object.<string, string>} headers |
| 207 * @param {string} content | 216 * @param {string} content |
| 208 */ | 217 */ |
| 209 function contentLoaded(statusCode, headers, content) | 218 function contentLoaded(statusCode, headers, content) { |
| 210 { | 219 if (!content || statusCode >= 400) { |
| 211 if (!content || statusCode >= 400) { | 220 callback(null); |
| 212 callback(null); | 221 return; |
| 213 return; | 222 } |
| 214 } | 223 |
| 215 | 224 if (content.slice(0, 3) === ')]}') |
| 216 if (content.slice(0, 3) === ")]}") | 225 content = content.substring(content.indexOf('\n')); |
| 217 content = content.substring(content.indexOf("\n")); | 226 try { |
| 218 try { | 227 var payload = /** @type {!SourceMapV3} */ (JSON.parse(content)); |
| 219 var payload = /** @type {!SourceMapV3} */ (JSON.parse(content)); | 228 var baseURL = sourceMapURL.startsWith('data:') ? compiledURL : sourceMap
URL; |
| 220 var baseURL = sourceMapURL.startsWith("data:") ? compiledURL : sourc
eMapURL; | 229 callback(new WebInspector.TextSourceMap(compiledURL, baseURL, payload)); |
| 221 callback(new WebInspector.TextSourceMap(compiledURL, baseURL, payloa
d)); | 230 } catch (e) { |
| 222 } catch (e) { | 231 console.error(e); |
| 223 console.error(e); | 232 WebInspector.console.warn('DevTools failed to parse SourceMap: ' + sourc
eMapURL); |
| 224 WebInspector.console.warn("DevTools failed to parse SourceMap: " + s
ourceMapURL); | 233 callback(null); |
| 225 callback(null); | 234 } |
| 226 } | 235 } |
| 227 } | 236 } |
| 228 }; | 237 |
| 229 | 238 /** |
| 230 WebInspector.TextSourceMap.prototype = { | 239 * @override |
| 240 * @return {string} |
| 241 */ |
| 242 compiledURL() { |
| 243 return this._compiledURL; |
| 244 } |
| 245 |
| 246 /** |
| 247 * @override |
| 248 * @return {string} |
| 249 */ |
| 250 url() { |
| 251 return this._sourceMappingURL; |
| 252 } |
| 253 |
| 254 /** |
| 255 * @override |
| 256 * @return {!Array.<string>} |
| 257 */ |
| 258 sourceURLs() { |
| 259 return this._sourceInfos.keysArray(); |
| 260 } |
| 261 |
| 262 /** |
| 263 * @override |
| 264 * @param {string} sourceURL |
| 265 * @param {!WebInspector.ResourceType} contentType |
| 266 * @return {!WebInspector.ContentProvider} |
| 267 */ |
| 268 sourceContentProvider(sourceURL, contentType) { |
| 269 var info = this._sourceInfos.get(sourceURL); |
| 270 if (info.content) |
| 271 return WebInspector.StaticContentProvider.fromString(sourceURL, contentTyp
e, info.content); |
| 272 return new WebInspector.CompilerSourceMappingContentProvider(sourceURL, cont
entType); |
| 273 } |
| 274 |
| 275 /** |
| 276 * @override |
| 277 * @param {string} sourceURL |
| 278 * @return {?string} |
| 279 */ |
| 280 embeddedContentByURL(sourceURL) { |
| 281 if (!this._sourceInfos.has(sourceURL)) |
| 282 return null; |
| 283 return this._sourceInfos.get(sourceURL).content; |
| 284 } |
| 285 |
| 286 /** |
| 287 * @override |
| 288 * @return {boolean} |
| 289 */ |
| 290 editable() { |
| 291 return false; |
| 292 } |
| 293 |
| 294 /** |
| 295 * @override |
| 296 * @param {!Array<!WebInspector.TextRange>} ranges |
| 297 * @param {!Array<string>} texts |
| 298 * @return {!Promise<?WebInspector.SourceMap.EditResult>} |
| 299 */ |
| 300 editCompiled(ranges, texts) { |
| 301 return Promise.resolve(/** @type {?WebInspector.SourceMap.EditResult} */ (nu
ll)); |
| 302 } |
| 303 |
| 304 /** |
| 305 * @override |
| 306 * @param {number} lineNumber in compiled resource |
| 307 * @param {number} columnNumber in compiled resource |
| 308 * @return {?WebInspector.SourceMapEntry} |
| 309 */ |
| 310 findEntry(lineNumber, columnNumber) { |
| 311 var first = 0; |
| 312 var mappings = this.mappings(); |
| 313 var count = mappings.length; |
| 314 while (count > 1) { |
| 315 var step = count >> 1; |
| 316 var middle = first + step; |
| 317 var mapping = mappings[middle]; |
| 318 if (lineNumber < mapping.lineNumber || |
| 319 (lineNumber === mapping.lineNumber && columnNumber < mapping.columnNum
ber)) { |
| 320 count = step; |
| 321 } else { |
| 322 first = middle; |
| 323 count -= step; |
| 324 } |
| 325 } |
| 326 var entry = mappings[first]; |
| 327 if (!first && entry && |
| 328 (lineNumber < entry.lineNumber || (lineNumber === entry.lineNumber && co
lumnNumber < entry.columnNumber))) |
| 329 return null; |
| 330 return entry; |
| 331 } |
| 332 |
| 333 /** |
| 334 * @param {string} sourceURL |
| 335 * @param {number} lineNumber |
| 336 * @return {?WebInspector.SourceMapEntry} |
| 337 */ |
| 338 firstSourceLineMapping(sourceURL, lineNumber) { |
| 339 var mappings = this._reversedMappings(sourceURL); |
| 340 var index = mappings.lowerBound(lineNumber, lineComparator); |
| 341 if (index >= mappings.length || mappings[index].sourceLineNumber !== lineNum
ber) |
| 342 return null; |
| 343 return mappings[index]; |
| 344 |
| 231 /** | 345 /** |
| 232 * @override | |
| 233 * @return {string} | |
| 234 */ | |
| 235 compiledURL: function() | |
| 236 { | |
| 237 return this._compiledURL; | |
| 238 }, | |
| 239 | |
| 240 /** | |
| 241 * @override | |
| 242 * @return {string} | |
| 243 */ | |
| 244 url: function() | |
| 245 { | |
| 246 return this._sourceMappingURL; | |
| 247 }, | |
| 248 | |
| 249 /** | |
| 250 * @override | |
| 251 * @return {!Array.<string>} | |
| 252 */ | |
| 253 sourceURLs: function() | |
| 254 { | |
| 255 return this._sourceInfos.keysArray(); | |
| 256 }, | |
| 257 | |
| 258 /** | |
| 259 * @override | |
| 260 * @param {string} sourceURL | |
| 261 * @param {!WebInspector.ResourceType} contentType | |
| 262 * @return {!WebInspector.ContentProvider} | |
| 263 */ | |
| 264 sourceContentProvider: function(sourceURL, contentType) | |
| 265 { | |
| 266 var info = this._sourceInfos.get(sourceURL); | |
| 267 if (info.content) | |
| 268 return WebInspector.StaticContentProvider.fromString(sourceURL, cont
entType, info.content); | |
| 269 return new WebInspector.CompilerSourceMappingContentProvider(sourceURL,
contentType); | |
| 270 }, | |
| 271 | |
| 272 /** | |
| 273 * @override | |
| 274 * @param {string} sourceURL | |
| 275 * @return {?string} | |
| 276 */ | |
| 277 embeddedContentByURL: function(sourceURL) | |
| 278 { | |
| 279 if (!this._sourceInfos.has(sourceURL)) | |
| 280 return null; | |
| 281 return this._sourceInfos.get(sourceURL).content; | |
| 282 }, | |
| 283 | |
| 284 /** | |
| 285 * @override | |
| 286 * @return {boolean} | |
| 287 */ | |
| 288 editable: function() | |
| 289 { | |
| 290 return false; | |
| 291 }, | |
| 292 | |
| 293 /** | |
| 294 * @override | |
| 295 * @param {!Array<!WebInspector.TextRange>} ranges | |
| 296 * @param {!Array<string>} texts | |
| 297 * @return {!Promise<?WebInspector.SourceMap.EditResult>} | |
| 298 */ | |
| 299 editCompiled: function(ranges, texts) | |
| 300 { | |
| 301 return Promise.resolve(/** @type {?WebInspector.SourceMap.EditResult} */
(null)); | |
| 302 }, | |
| 303 | |
| 304 /** | |
| 305 * @override | |
| 306 * @param {number} lineNumber in compiled resource | |
| 307 * @param {number} columnNumber in compiled resource | |
| 308 * @return {?WebInspector.SourceMapEntry} | |
| 309 */ | |
| 310 findEntry: function(lineNumber, columnNumber) | |
| 311 { | |
| 312 var first = 0; | |
| 313 var mappings = this.mappings(); | |
| 314 var count = mappings.length; | |
| 315 while (count > 1) { | |
| 316 var step = count >> 1; | |
| 317 var middle = first + step; | |
| 318 var mapping = mappings[middle]; | |
| 319 if (lineNumber < mapping.lineNumber || (lineNumber === mapping.lineN
umber && columnNumber < mapping.columnNumber)) { | |
| 320 count = step; | |
| 321 } else { | |
| 322 first = middle; | |
| 323 count -= step; | |
| 324 } | |
| 325 } | |
| 326 var entry = mappings[first]; | |
| 327 if (!first && entry && (lineNumber < entry.lineNumber || (lineNumber ===
entry.lineNumber && columnNumber < entry.columnNumber))) | |
| 328 return null; | |
| 329 return entry; | |
| 330 }, | |
| 331 | |
| 332 /** | |
| 333 * @param {string} sourceURL | |
| 334 * @param {number} lineNumber | 346 * @param {number} lineNumber |
| 335 * @return {?WebInspector.SourceMapEntry} | 347 * @param {!WebInspector.SourceMapEntry} mapping |
| 336 */ | |
| 337 firstSourceLineMapping: function(sourceURL, lineNumber) | |
| 338 { | |
| 339 var mappings = this._reversedMappings(sourceURL); | |
| 340 var index = mappings.lowerBound(lineNumber, lineComparator); | |
| 341 if (index >= mappings.length || mappings[index].sourceLineNumber !== lin
eNumber) | |
| 342 return null; | |
| 343 return mappings[index]; | |
| 344 | |
| 345 /** | |
| 346 * @param {number} lineNumber | |
| 347 * @param {!WebInspector.SourceMapEntry} mapping | |
| 348 * @return {number} | |
| 349 */ | |
| 350 function lineComparator(lineNumber, mapping) | |
| 351 { | |
| 352 return lineNumber - mapping.sourceLineNumber; | |
| 353 } | |
| 354 }, | |
| 355 | |
| 356 /** | |
| 357 * @return {!Array<!WebInspector.SourceMapEntry>} | |
| 358 */ | |
| 359 mappings: function() | |
| 360 { | |
| 361 if (this._mappings === null) { | |
| 362 this._mappings = []; | |
| 363 this._eachSection(this._parseMap.bind(this)); | |
| 364 this._json = null; | |
| 365 } | |
| 366 return /** @type {!Array<!WebInspector.SourceMapEntry>} */ (this._mappin
gs); | |
| 367 }, | |
| 368 | |
| 369 /** | |
| 370 * @param {string} sourceURL | |
| 371 * @return {!Array.<!WebInspector.SourceMapEntry>} | |
| 372 */ | |
| 373 _reversedMappings: function(sourceURL) | |
| 374 { | |
| 375 if (!this._sourceInfos.has(sourceURL)) | |
| 376 return []; | |
| 377 var mappings = this.mappings(); | |
| 378 var info = this._sourceInfos.get(sourceURL); | |
| 379 if (info.reverseMappings === null) | |
| 380 info.reverseMappings = mappings.filter((mapping) => mapping.sourceUR
L === sourceURL).sort(sourceMappingComparator); | |
| 381 return info.reverseMappings; | |
| 382 | |
| 383 /** | |
| 384 * @param {!WebInspector.SourceMapEntry} a | |
| 385 * @param {!WebInspector.SourceMapEntry} b | |
| 386 * @return {number} | |
| 387 */ | |
| 388 function sourceMappingComparator(a, b) | |
| 389 { | |
| 390 if (a.sourceLineNumber !== b.sourceLineNumber) | |
| 391 return a.sourceLineNumber - b.sourceLineNumber; | |
| 392 if (a.sourceColumnNumber !== b.sourceColumnNumber) | |
| 393 return a.sourceColumnNumber - b.sourceColumnNumber; | |
| 394 | |
| 395 if (a.lineNumber !== b.lineNumber) | |
| 396 return a.lineNumber - b.lineNumber; | |
| 397 | |
| 398 return a.columnNumber - b.columnNumber; | |
| 399 } | |
| 400 }, | |
| 401 | |
| 402 /** | |
| 403 * @param {function(!SourceMapV3, number, number)} callback | |
| 404 */ | |
| 405 _eachSection: function(callback) { | |
| 406 if (!this._json.sections) { | |
| 407 callback(this._json, 0, 0); | |
| 408 return; | |
| 409 } | |
| 410 for (var section of this._json.sections) | |
| 411 callback(section.map, section.offset.line, section.offset.column); | |
| 412 }, | |
| 413 | |
| 414 /** | |
| 415 * @param {!SourceMapV3} sourceMap | |
| 416 */ | |
| 417 _parseSources: function(sourceMap) { | |
| 418 var sourcesList = []; | |
| 419 var sourceRoot = sourceMap.sourceRoot || ""; | |
| 420 if (sourceRoot && !sourceRoot.endsWith("/")) | |
| 421 sourceRoot += "/"; | |
| 422 for (var i = 0; i < sourceMap.sources.length; ++i) { | |
| 423 var href = sourceRoot + sourceMap.sources[i]; | |
| 424 var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL,
href) || href; | |
| 425 var source = sourceMap.sourcesContent && sourceMap.sourcesContent[i]
; | |
| 426 if (url === this._compiledURL && source) | |
| 427 url += WebInspector.UIString(" [sm]"); | |
| 428 this._sourceInfos.set(url, new WebInspector.TextSourceMap.SourceInfo
(source, null)); | |
| 429 sourcesList.push(url); | |
| 430 } | |
| 431 sourceMap[WebInspector.TextSourceMap._sourcesListSymbol] = sourcesList; | |
| 432 }, | |
| 433 | |
| 434 /** | |
| 435 * @param {!SourceMapV3} map | |
| 436 * @param {number} lineNumber | |
| 437 * @param {number} columnNumber | |
| 438 */ | |
| 439 _parseMap: function(map, lineNumber, columnNumber) | |
| 440 { | |
| 441 var sourceIndex = 0; | |
| 442 var sourceLineNumber = 0; | |
| 443 var sourceColumnNumber = 0; | |
| 444 var nameIndex = 0; | |
| 445 var sources = map[WebInspector.TextSourceMap._sourcesListSymbol]; | |
| 446 var names = map.names || []; | |
| 447 var stringCharIterator = new WebInspector.TextSourceMap.StringCharIterat
or(map.mappings); | |
| 448 var sourceURL = sources[sourceIndex]; | |
| 449 | |
| 450 while (true) { | |
| 451 if (stringCharIterator.peek() === ",") | |
| 452 stringCharIterator.next(); | |
| 453 else { | |
| 454 while (stringCharIterator.peek() === ";") { | |
| 455 lineNumber += 1; | |
| 456 columnNumber = 0; | |
| 457 stringCharIterator.next(); | |
| 458 } | |
| 459 if (!stringCharIterator.hasNext()) | |
| 460 break; | |
| 461 } | |
| 462 | |
| 463 columnNumber += this._decodeVLQ(stringCharIterator); | |
| 464 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIte
rator.peek())) { | |
| 465 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber,
columnNumber)); | |
| 466 continue; | |
| 467 } | |
| 468 | |
| 469 var sourceIndexDelta = this._decodeVLQ(stringCharIterator); | |
| 470 if (sourceIndexDelta) { | |
| 471 sourceIndex += sourceIndexDelta; | |
| 472 sourceURL = sources[sourceIndex]; | |
| 473 } | |
| 474 sourceLineNumber += this._decodeVLQ(stringCharIterator); | |
| 475 sourceColumnNumber += this._decodeVLQ(stringCharIterator); | |
| 476 | |
| 477 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIte
rator.peek())) { | |
| 478 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber,
columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber)); | |
| 479 continue; | |
| 480 } | |
| 481 | |
| 482 nameIndex += this._decodeVLQ(stringCharIterator); | |
| 483 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, colu
mnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex])); | |
| 484 } | |
| 485 }, | |
| 486 | |
| 487 /** | |
| 488 * @param {string} char | |
| 489 * @return {boolean} | |
| 490 */ | |
| 491 _isSeparator: function(char) | |
| 492 { | |
| 493 return char === "," || char === ";"; | |
| 494 }, | |
| 495 | |
| 496 /** | |
| 497 * @param {!WebInspector.TextSourceMap.StringCharIterator} stringCharIterato
r | |
| 498 * @return {number} | 348 * @return {number} |
| 499 */ | 349 */ |
| 500 _decodeVLQ: function(stringCharIterator) | 350 function lineComparator(lineNumber, mapping) { |
| 501 { | 351 return lineNumber - mapping.sourceLineNumber; |
| 502 // Read unsigned value. | 352 } |
| 503 var result = 0; | 353 } |
| 504 var shift = 0; | 354 |
| 505 do { | 355 /** |
| 506 var digit = this._base64Map[stringCharIterator.next()]; | 356 * @return {!Array<!WebInspector.SourceMapEntry>} |
| 507 result += (digit & this._VLQ_BASE_MASK) << shift; | 357 */ |
| 508 shift += this._VLQ_BASE_SHIFT; | 358 mappings() { |
| 509 } while (digit & this._VLQ_CONTINUATION_MASK); | 359 if (this._mappings === null) { |
| 510 | 360 this._mappings = []; |
| 511 // Fix the sign. | 361 this._eachSection(this._parseMap.bind(this)); |
| 512 var negative = result & 1; | 362 this._json = null; |
| 513 result >>= 1; | 363 } |
| 514 return negative ? -result : result; | 364 return /** @type {!Array<!WebInspector.SourceMapEntry>} */ (this._mappings); |
| 515 }, | 365 } |
| 366 |
| 367 /** |
| 368 * @param {string} sourceURL |
| 369 * @return {!Array.<!WebInspector.SourceMapEntry>} |
| 370 */ |
| 371 _reversedMappings(sourceURL) { |
| 372 if (!this._sourceInfos.has(sourceURL)) |
| 373 return []; |
| 374 var mappings = this.mappings(); |
| 375 var info = this._sourceInfos.get(sourceURL); |
| 376 if (info.reverseMappings === null) |
| 377 info.reverseMappings = |
| 378 mappings.filter((mapping) => mapping.sourceURL === sourceURL).sort(sou
rceMappingComparator); |
| 379 return info.reverseMappings; |
| 516 | 380 |
| 517 /** | 381 /** |
| 518 * @param {string} url | 382 * @param {!WebInspector.SourceMapEntry} a |
| 519 * @param {!WebInspector.TextRange} textRange | 383 * @param {!WebInspector.SourceMapEntry} b |
| 520 * @return {!WebInspector.TextRange} | 384 * @return {number} |
| 521 */ | 385 */ |
| 522 reverseMapTextRange: function(url, textRange) | 386 function sourceMappingComparator(a, b) { |
| 523 { | 387 if (a.sourceLineNumber !== b.sourceLineNumber) |
| 524 /** | 388 return a.sourceLineNumber - b.sourceLineNumber; |
| 525 * @param {!{lineNumber: number, columnNumber: number}} position | 389 if (a.sourceColumnNumber !== b.sourceColumnNumber) |
| 526 * @param {!WebInspector.SourceMapEntry} mapping | 390 return a.sourceColumnNumber - b.sourceColumnNumber; |
| 527 * @return {number} | 391 |
| 528 */ | 392 if (a.lineNumber !== b.lineNumber) |
| 529 function comparator(position, mapping) | 393 return a.lineNumber - b.lineNumber; |
| 530 { | 394 |
| 531 if (position.lineNumber !== mapping.sourceLineNumber) | 395 return a.columnNumber - b.columnNumber; |
| 532 return position.lineNumber - mapping.sourceLineNumber; | 396 } |
| 533 | 397 } |
| 534 return position.columnNumber - mapping.sourceColumnNumber; | 398 |
| 399 /** |
| 400 * @param {function(!SourceMapV3, number, number)} callback |
| 401 */ |
| 402 _eachSection(callback) { |
| 403 if (!this._json.sections) { |
| 404 callback(this._json, 0, 0); |
| 405 return; |
| 406 } |
| 407 for (var section of this._json.sections) |
| 408 callback(section.map, section.offset.line, section.offset.column); |
| 409 } |
| 410 |
| 411 /** |
| 412 * @param {!SourceMapV3} sourceMap |
| 413 */ |
| 414 _parseSources(sourceMap) { |
| 415 var sourcesList = []; |
| 416 var sourceRoot = sourceMap.sourceRoot || ''; |
| 417 if (sourceRoot && !sourceRoot.endsWith('/')) |
| 418 sourceRoot += '/'; |
| 419 for (var i = 0; i < sourceMap.sources.length; ++i) { |
| 420 var href = sourceRoot + sourceMap.sources[i]; |
| 421 var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL, href)
|| href; |
| 422 var source = sourceMap.sourcesContent && sourceMap.sourcesContent[i]; |
| 423 if (url === this._compiledURL && source) |
| 424 url += WebInspector.UIString(' [sm]'); |
| 425 this._sourceInfos.set(url, new WebInspector.TextSourceMap.SourceInfo(sourc
e, null)); |
| 426 sourcesList.push(url); |
| 427 } |
| 428 sourceMap[WebInspector.TextSourceMap._sourcesListSymbol] = sourcesList; |
| 429 } |
| 430 |
| 431 /** |
| 432 * @param {!SourceMapV3} map |
| 433 * @param {number} lineNumber |
| 434 * @param {number} columnNumber |
| 435 */ |
| 436 _parseMap(map, lineNumber, columnNumber) { |
| 437 var sourceIndex = 0; |
| 438 var sourceLineNumber = 0; |
| 439 var sourceColumnNumber = 0; |
| 440 var nameIndex = 0; |
| 441 var sources = map[WebInspector.TextSourceMap._sourcesListSymbol]; |
| 442 var names = map.names || []; |
| 443 var stringCharIterator = new WebInspector.TextSourceMap.StringCharIterator(m
ap.mappings); |
| 444 var sourceURL = sources[sourceIndex]; |
| 445 |
| 446 while (true) { |
| 447 if (stringCharIterator.peek() === ',') |
| 448 stringCharIterator.next(); |
| 449 else { |
| 450 while (stringCharIterator.peek() === ';') { |
| 451 lineNumber += 1; |
| 452 columnNumber = 0; |
| 453 stringCharIterator.next(); |
| 535 } | 454 } |
| 536 | 455 if (!stringCharIterator.hasNext()) |
| 537 var mappings = this._reversedMappings(url); | 456 break; |
| 538 var startIndex = mappings.lowerBound({lineNumber: textRange.startLine, c
olumnNumber: textRange.startColumn}, comparator); | 457 } |
| 539 var endIndex = mappings.upperBound({lineNumber: textRange.endLine, colum
nNumber: textRange.endColumn}, comparator); | 458 |
| 540 | 459 columnNumber += this._decodeVLQ(stringCharIterator); |
| 541 var startMapping = mappings[startIndex]; | 460 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.
peek())) { |
| 542 var endMapping = mappings[endIndex]; | 461 this._mappings.push(new WebInspector.SourceMapEntry(lineNumber, columnNu
mber)); |
| 543 return new WebInspector.TextRange(startMapping.lineNumber, startMapping.
columnNumber, endMapping.lineNumber, endMapping.columnNumber); | 462 continue; |
| 544 }, | 463 } |
| 545 | 464 |
| 546 _VLQ_BASE_SHIFT: 5, | 465 var sourceIndexDelta = this._decodeVLQ(stringCharIterator); |
| 547 _VLQ_BASE_MASK: (1 << 5) - 1, | 466 if (sourceIndexDelta) { |
| 548 _VLQ_CONTINUATION_MASK: 1 << 5 | 467 sourceIndex += sourceIndexDelta; |
| 468 sourceURL = sources[sourceIndex]; |
| 469 } |
| 470 sourceLineNumber += this._decodeVLQ(stringCharIterator); |
| 471 sourceColumnNumber += this._decodeVLQ(stringCharIterator); |
| 472 |
| 473 if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.
peek())) { |
| 474 this._mappings.push( |
| 475 new WebInspector.SourceMapEntry(lineNumber, columnNumber, sourceURL,
sourceLineNumber, sourceColumnNumber)); |
| 476 continue; |
| 477 } |
| 478 |
| 479 nameIndex += this._decodeVLQ(stringCharIterator); |
| 480 this._mappings.push(new WebInspector.SourceMapEntry( |
| 481 lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNum
ber, names[nameIndex])); |
| 482 } |
| 483 } |
| 484 |
| 485 /** |
| 486 * @param {string} char |
| 487 * @return {boolean} |
| 488 */ |
| 489 _isSeparator(char) { |
| 490 return char === ',' || char === ';'; |
| 491 } |
| 492 |
| 493 /** |
| 494 * @param {!WebInspector.TextSourceMap.StringCharIterator} stringCharIterator |
| 495 * @return {number} |
| 496 */ |
| 497 _decodeVLQ(stringCharIterator) { |
| 498 // Read unsigned value. |
| 499 var result = 0; |
| 500 var shift = 0; |
| 501 do { |
| 502 var digit = WebInspector.TextSourceMap._base64Map[stringCharIterator.next(
)]; |
| 503 result += (digit & WebInspector.TextSourceMap._VLQ_BASE_MASK) << shift; |
| 504 shift += WebInspector.TextSourceMap._VLQ_BASE_SHIFT; |
| 505 } while (digit & WebInspector.TextSourceMap._VLQ_CONTINUATION_MASK); |
| 506 |
| 507 // Fix the sign. |
| 508 var negative = result & 1; |
| 509 result >>= 1; |
| 510 return negative ? -result : result; |
| 511 } |
| 512 |
| 513 /** |
| 514 * @param {string} url |
| 515 * @param {!WebInspector.TextRange} textRange |
| 516 * @return {!WebInspector.TextRange} |
| 517 */ |
| 518 reverseMapTextRange(url, textRange) { |
| 519 /** |
| 520 * @param {!{lineNumber: number, columnNumber: number}} position |
| 521 * @param {!WebInspector.SourceMapEntry} mapping |
| 522 * @return {number} |
| 523 */ |
| 524 function comparator(position, mapping) { |
| 525 if (position.lineNumber !== mapping.sourceLineNumber) |
| 526 return position.lineNumber - mapping.sourceLineNumber; |
| 527 |
| 528 return position.columnNumber - mapping.sourceColumnNumber; |
| 529 } |
| 530 |
| 531 var mappings = this._reversedMappings(url); |
| 532 var startIndex = |
| 533 mappings.lowerBound({lineNumber: textRange.startLine, columnNumber: text
Range.startColumn}, comparator); |
| 534 var endIndex = mappings.upperBound({lineNumber: textRange.endLine, columnNum
ber: textRange.endColumn}, comparator); |
| 535 |
| 536 var startMapping = mappings[startIndex]; |
| 537 var endMapping = mappings[endIndex]; |
| 538 return new WebInspector.TextRange( |
| 539 startMapping.lineNumber, startMapping.columnNumber, endMapping.lineNumbe
r, endMapping.columnNumber); |
| 540 } |
| 549 }; | 541 }; |
| 550 | 542 |
| 543 WebInspector.TextSourceMap._VLQ_BASE_SHIFT = 5; |
| 544 WebInspector.TextSourceMap._VLQ_BASE_MASK = (1 << 5) - 1; |
| 545 WebInspector.TextSourceMap._VLQ_CONTINUATION_MASK = 1 << 5; |
| 546 |
| 547 |
| 551 /** | 548 /** |
| 552 * @constructor | 549 * @unrestricted |
| 553 * @param {string} string | |
| 554 */ | 550 */ |
| 555 WebInspector.TextSourceMap.StringCharIterator = function(string) | 551 WebInspector.TextSourceMap.StringCharIterator = class { |
| 556 { | 552 /** |
| 553 * @param {string} string |
| 554 */ |
| 555 constructor(string) { |
| 557 this._string = string; | 556 this._string = string; |
| 558 this._position = 0; | 557 this._position = 0; |
| 558 } |
| 559 |
| 560 /** |
| 561 * @return {string} |
| 562 */ |
| 563 next() { |
| 564 return this._string.charAt(this._position++); |
| 565 } |
| 566 |
| 567 /** |
| 568 * @return {string} |
| 569 */ |
| 570 peek() { |
| 571 return this._string.charAt(this._position); |
| 572 } |
| 573 |
| 574 /** |
| 575 * @return {boolean} |
| 576 */ |
| 577 hasNext() { |
| 578 return this._position < this._string.length; |
| 579 } |
| 559 }; | 580 }; |
| 560 | 581 |
| 561 WebInspector.TextSourceMap.StringCharIterator.prototype = { | |
| 562 /** | |
| 563 * @return {string} | |
| 564 */ | |
| 565 next: function() | |
| 566 { | |
| 567 return this._string.charAt(this._position++); | |
| 568 }, | |
| 569 | |
| 570 /** | |
| 571 * @return {string} | |
| 572 */ | |
| 573 peek: function() | |
| 574 { | |
| 575 return this._string.charAt(this._position); | |
| 576 }, | |
| 577 | |
| 578 /** | |
| 579 * @return {boolean} | |
| 580 */ | |
| 581 hasNext: function() | |
| 582 { | |
| 583 return this._position < this._string.length; | |
| 584 } | |
| 585 }; | |
| 586 | |
| 587 /** | 582 /** |
| 588 * @constructor | 583 * @unrestricted |
| 589 * @param {?string} content | |
| 590 * @param {?Array<!WebInspector.SourceMapEntry>} reverseMappings | |
| 591 */ | 584 */ |
| 592 WebInspector.TextSourceMap.SourceInfo = function(content, reverseMappings) { | 585 WebInspector.TextSourceMap.SourceInfo = class { |
| 586 /** |
| 587 * @param {?string} content |
| 588 * @param {?Array<!WebInspector.SourceMapEntry>} reverseMappings |
| 589 */ |
| 590 constructor(content, reverseMappings) { |
| 593 this.content = content; | 591 this.content = content; |
| 594 this.reverseMappings = reverseMappings; | 592 this.reverseMappings = reverseMappings; |
| 593 } |
| 595 }; | 594 }; |
| 596 | 595 |
| 597 WebInspector.TextSourceMap._sourcesListSymbol = Symbol("sourcesList"); | 596 WebInspector.TextSourceMap._sourcesListSymbol = Symbol('sourcesList'); |
| OLD | NEW |