Changeset 138500 in webkit
- Timestamp:
- Dec 27, 2012 6:13:53 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 10 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r138499 r138500 1 2012-12-27 Alexander Pavlov <apavlov@chromium.org> 2 3 Web Inspector: Refactor SourceMapParser to enable range-based sourcemap 4 https://bugs.webkit.org/show_bug.cgi?id=105764 5 6 Reviewed by Vsevolod Vlasov. 7 8 * http/tests/inspector/compiler-script-mapping-expected.txt: 9 * http/tests/inspector/compiler-script-mapping.html: 10 * inspector/styles/range-based-mapping-expected.txt: Added. 11 * inspector/styles/range-based-mapping.html: Added. 12 1 13 2012-12-27 Andrey Adaikin <aandrey@chromium.org> 2 14 -
trunk/LayoutTests/http/tests/inspector/compiler-script-mapping-expected.txt
r116843 r138500 1 Tests SourceMapParserand CompilerScriptMapping.1 Tests PositionBasedSourceMap and CompilerScriptMapping. 2 2 3 3 -
trunk/LayoutTests/http/tests/inspector/compiler-script-mapping.html
r138496 r138500 59 59 "sources":["example.js"] 60 60 }; 61 var mapping = new WebInspector. SourceMapParser("source-map.json", mappingPayload);61 var mapping = new WebInspector.PositionBasedSourceMap("source-map.json", mappingPayload); 62 62 63 63 checkMapping(0, 9, "example.js", 0, 9, mapping); … … 83 83 "sources":["example.js"] 84 84 }; 85 var mapping = new WebInspector. SourceMapParser("source-map.json", mappingPayload);85 var mapping = new WebInspector.PositionBasedSourceMap("source-map.json", mappingPayload); 86 86 checkMapping(0, 0, "example.js", 0, 0, mapping); 87 87 var entry = mapping.findEntry(0, 1); … … 97 97 "sources":["example.js"] 98 98 }; 99 var mapping = new WebInspector. SourceMapParser("source-map.json", mappingPayload);99 var mapping = new WebInspector.PositionBasedSourceMap("source-map.json", mappingPayload); 100 100 checkMapping(0, 0, "example.js", 0, 0, mapping); 101 101 checkReverseMapping(3, 1, "example.js", 1, mapping); … … 120 120 } 121 121 ]}; 122 var mapping = new WebInspector. SourceMapParser("source-map.json", mappingPayload);122 var mapping = new WebInspector.PositionBasedSourceMap("source-map.json", mappingPayload); 123 123 InspectorTest.assertEquals(2, mapping.sources().length); 124 124 checkMapping(0, 0, "source1.js", 0, 0, mapping); … … 131 131 function testResolveSourceMapURL(next) 132 132 { 133 var func = WebInspector. SourceMapParser.prototype._canonicalizeURL;133 var func = WebInspector.PositionBasedSourceMap.prototype._canonicalizeURL; 134 134 InspectorTest.assertEquals("http://example.com/map.json", func("http://example.com/map.json", "http://example.com/script.js")); 135 135 InspectorTest.assertEquals("http://example.com/map.json", func("/map.json", "http://example.com/script.js")); … … 271 271 272 272 <body onload="runTest()"> 273 <p>Tests SourceMapParserand CompilerScriptMapping.</p>273 <p>Tests PositionBasedSourceMap and CompilerScriptMapping.</p> 274 274 </body> 275 275 </html> -
trunk/Source/WebCore/ChangeLog
r138497 r138500 1 2012-12-27 Alexander Pavlov <apavlov@chromium.org> 2 3 Web Inspector: Refactor SourceMapParser to enable range-based sourcemap 4 https://bugs.webkit.org/show_bug.cgi?id=105764 5 6 Reviewed by Vsevolod Vlasov. 7 8 Test: inspector/styles/range-based-mapping.html 9 10 * WebCore.gypi: 11 * WebCore.vcproj/WebCore.vcproj: 12 * inspector/compile-front-end.py: 13 * inspector/front-end/CompilerScriptMapping.js: 14 (WebInspector.CompilerScriptMapping): 15 (WebInspector.CompilerScriptMapping.prototype.loadSourceMapForScript): 16 * inspector/front-end/SourceMap.js: Copied from Source/WebCore/inspector/front-end/CompilerScriptMapping.js. 17 (WebInspector.SourceMap): 18 Abstract. Renamed from SourceMapParser and supports only direct (generated -> originating source) mapping via findEntry() 19 (WebInspector.SourceMap.prototype.sources): 20 (WebInspector.SourceMap.prototype.sourceContent): 21 (WebInspector.SourceMap.prototype._parseMappingPayload): 22 (WebInspector.SourceMap.prototype._parseSections): 23 (WebInspector.SourceMap.prototype._parseMap): 24 (WebInspector.SourceMap.prototype._isSeparator): 25 (WebInspector.SourceMap.prototype._decodeVLQ): 26 (WebInspector.SourceMap.prototype._canonicalizeURL): 27 (WebInspector.SourceMap.StringCharIterator): 28 (WebInspector.SourceMap.StringCharIterator.prototype.next): 29 (WebInspector.SourceMap.StringCharIterator.prototype.peek): 30 (WebInspector.SourceMap.StringCharIterator.prototype.hasNext): 31 (WebInspector.PositionBasedSourceMap): 32 Extends SourceMap and provides direct (compiled -> original source) 33 and reverse (original -> compiled source) position mapping via findEntryReversed(). 34 (WebInspector.PositionBasedSourceMap.prototype.findEntry): 35 (WebInspector.PositionBasedSourceMap.prototype.findEntryReversed): 36 (WebInspector.PositionBasedSourceMap.prototype._parseMap): 37 (WebInspector.RangeBasedSourceMap): 38 Extends SourceMap and provides direct range mapping 39 (compiled source position -> original source range) via findSourceRange(). 40 (WebInspector.RangeBasedSourceMap.MappingComparator): 41 (WebInspector.RangeBasedSourceMap.prototype.findSourceRange): 42 (WebInspector.RangeBasedSourceMap.prototype._rangeForStartIndex): 43 (WebInspector.SourceRange): 44 * inspector/front-end/WebKit.qrc: 45 * inspector/front-end/inspector.html: 46 1 47 2012-12-25 Andrey Adaikin <aandrey@chromium.org> 2 48 -
trunk/Source/WebCore/WebCore.gypi
r138496 r138500 5192 5192 'inspector/front-end/SourceHTMLTokenizer.js', 5193 5193 'inspector/front-end/SourceJavaScriptTokenizer.js', 5194 'inspector/front-end/SourceMap.js', 5194 5195 'inspector/front-end/SourceMapping.js', 5195 5196 'inspector/front-end/SourceTokenizer.js', -
trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj
r138496 r138500 77114 77114 </File> 77115 77115 <File 77116 RelativePath="..\inspector\front-end\SourceMap.js" 77117 > 77118 </File> 77119 <File 77116 77120 RelativePath="..\inspector\front-end\SourceMapping.js" 77117 77121 > -
trunk/Source/WebCore/inspector/compile-front-end.py
r138496 r138500 104 104 "ResourceType.js", 105 105 "ResourceUtils.js", 106 "SourceMap.js", 106 107 "NetworkManager.js", 107 108 "NetworkRequest.js", -
trunk/Source/WebCore/inspector/front-end/CompilerScriptMapping.js
r138496 r138500 39 39 this._workspace = workspace; 40 40 this._networkWorkspaceProvider = networkWorkspaceProvider; 41 /** @type {Object.<string, WebInspector. SourceMapParser>} */41 /** @type {Object.<string, WebInspector.PositionBasedSourceMap>} */ 42 42 this._sourceMapForSourceMapURL = {}; 43 /** @type {Object.<string, WebInspector. SourceMapParser>} */43 /** @type {Object.<string, WebInspector.PositionBasedSourceMap>} */ 44 44 this._sourceMapForScriptId = {}; 45 45 this._scriptForSourceMap = new Map(); 46 /** @type {Object.<string, WebInspector. SourceMapParser>} */46 /** @type {Object.<string, WebInspector.PositionBasedSourceMap>} */ 47 47 this._sourceMapForURL = {}; 48 48 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); … … 118 118 /** 119 119 * @param {WebInspector.Script} script 120 * @return {WebInspector. SourceMapParser}120 * @return {WebInspector.PositionBasedSourceMap} 121 121 */ 122 122 loadSourceMapForScript: function(script) 123 123 { 124 var sourceMapURL = WebInspector. SourceMapParser.prototype._canonicalizeURL(script.sourceMapURL, script.sourceURL);124 var sourceMapURL = WebInspector.PositionBasedSourceMap.prototype._canonicalizeURL(script.sourceMapURL, script.sourceURL); 125 125 var sourceMap = this._sourceMapForSourceMapURL[sourceMapURL]; 126 126 if (sourceMap) … … 132 132 if (response.slice(0, 3) === ")]}") 133 133 response = response.substring(response.indexOf('\n')); 134 var payload = /** @type { WebInspector.SourceMapPayload} */ (JSON.parse(response));135 sourceMap = new WebInspector. SourceMapParser(sourceMapURL, payload);134 var payload = /** @type {SourceMapV3} */ (JSON.parse(response)); 135 sourceMap = new WebInspector.PositionBasedSourceMap(sourceMapURL, payload); 136 136 } catch(e) { 137 137 console.error(e.message); … … 150 150 } 151 151 } 152 153 /**154 * @constructor155 */156 WebInspector.SourceMapPayload = function()157 {158 this.sections = [];159 this.mappings = "";160 this.sourceRoot = "";161 this.sources = [];162 }163 164 /**165 * Implements Source Map V3 consumer. See http://code.google.com/p/closure-compiler/wiki/SourceMaps166 * for format description.167 * @constructor168 * @param {string} sourceMappingURL169 * @param {WebInspector.SourceMapPayload} payload170 */171 WebInspector.SourceMapParser = function(sourceMappingURL, payload)172 {173 if (!WebInspector.SourceMapParser.prototype._base64Map) {174 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";175 WebInspector.SourceMapParser.prototype._base64Map = {};176 for (var i = 0; i < base64Digits.length; ++i)177 WebInspector.SourceMapParser.prototype._base64Map[base64Digits.charAt(i)] = i;178 }179 180 this._sourceMappingURL = sourceMappingURL;181 this._mappings = [];182 this._reverseMappingsBySourceURL = {};183 this._sourceContentByURL = {};184 this._parseMappingPayload(payload);185 }186 187 WebInspector.SourceMapParser.prototype = {188 /**189 * @return {Array.<string>}190 */191 sources: function()192 {193 var sources = [];194 for (var sourceURL in this._reverseMappingsBySourceURL)195 sources.push(sourceURL);196 return sources;197 },198 199 sourceContent: function(sourceURL)200 {201 return this._sourceContentByURL[sourceURL];202 },203 204 findEntry: function(lineNumber, columnNumber)205 {206 var first = 0;207 var count = this._mappings.length;208 while (count > 1) {209 var step = count >> 1;210 var middle = first + step;211 var mapping = this._mappings[middle];212 if (lineNumber < mapping[0] || (lineNumber == mapping[0] && columnNumber < mapping[1]))213 count = step;214 else {215 first = middle;216 count -= step;217 }218 }219 return this._mappings[first];220 },221 222 findEntryReversed: function(sourceURL, lineNumber)223 {224 var mappings = this._reverseMappingsBySourceURL[sourceURL];225 for ( ; lineNumber < mappings.length; ++lineNumber) {226 var mapping = mappings[lineNumber];227 if (mapping)228 return mapping;229 }230 return this._mappings[0];231 },232 233 _parseMappingPayload: function(mappingPayload)234 {235 if (mappingPayload.sections)236 this._parseSections(mappingPayload.sections);237 else238 this._parseMap(mappingPayload, 0, 0);239 },240 241 /**242 * @param {Array.<SourceMapV3.Section>} sections243 */244 _parseSections: function(sections)245 {246 for (var i = 0; i < sections.length; ++i) {247 var section = sections[i];248 this._parseMap(section.map, section.offset.line, section.offset.column)249 }250 },251 252 /**253 * @param {SourceMapV3} map254 * @param {number} lineNumber255 * @param {number} columnNumber256 */257 _parseMap: function(map, lineNumber, columnNumber)258 {259 var sourceIndex = 0;260 var sourceLineNumber = 0;261 var sourceColumnNumber = 0;262 var nameIndex = 0;263 264 var sources = [];265 for (var i = 0; i < map.sources.length; ++i) {266 var sourceURL = map.sources[i];267 if (map.sourceRoot)268 sourceURL = map.sourceRoot + "/" + sourceURL;269 var url = this._canonicalizeURL(sourceURL, this._sourceMappingURL);270 sources.push(url);271 if (!this._reverseMappingsBySourceURL[url])272 this._reverseMappingsBySourceURL[url] = [];273 if (map.sourcesContent && map.sourcesContent[i])274 this._sourceContentByURL[url] = map.sourcesContent[i];275 }276 277 var stringCharIterator = new WebInspector.SourceMapParser.StringCharIterator(map.mappings);278 var sourceURL = sources[sourceIndex];279 var reverseMappings = this._reverseMappingsBySourceURL[sourceURL];280 281 while (true) {282 if (stringCharIterator.peek() === ",")283 stringCharIterator.next();284 else {285 while (stringCharIterator.peek() === ";") {286 lineNumber += 1;287 columnNumber = 0;288 stringCharIterator.next();289 }290 if (!stringCharIterator.hasNext())291 break;292 }293 294 columnNumber += this._decodeVLQ(stringCharIterator);295 if (this._isSeparator(stringCharIterator.peek())) {296 this._mappings.push([lineNumber, columnNumber]);297 continue;298 }299 300 var sourceIndexDelta = this._decodeVLQ(stringCharIterator);301 if (sourceIndexDelta) {302 sourceIndex += sourceIndexDelta;303 sourceURL = sources[sourceIndex];304 reverseMappings = this._reverseMappingsBySourceURL[sourceURL];305 }306 sourceLineNumber += this._decodeVLQ(stringCharIterator);307 sourceColumnNumber += this._decodeVLQ(stringCharIterator);308 if (!this._isSeparator(stringCharIterator.peek()))309 nameIndex += this._decodeVLQ(stringCharIterator);310 311 this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]);312 if (!reverseMappings[sourceLineNumber])313 reverseMappings[sourceLineNumber] = [lineNumber, columnNumber];314 }315 },316 317 _isSeparator: function(char)318 {319 return char === "," || char === ";";320 },321 322 _decodeVLQ: function(stringCharIterator)323 {324 // Read unsigned value.325 var result = 0;326 var shift = 0;327 do {328 var digit = this._base64Map[stringCharIterator.next()];329 result += (digit & this._VLQ_BASE_MASK) << shift;330 shift += this._VLQ_BASE_SHIFT;331 } while (digit & this._VLQ_CONTINUATION_MASK);332 333 // Fix the sign.334 var negative = result & 1;335 result >>= 1;336 return negative ? -result : result;337 },338 339 _canonicalizeURL: function(url, baseURL)340 {341 if (!url || !baseURL || url.asParsedURL() || url.substring(0, 5) === "data:")342 return url;343 344 var base = baseURL.asParsedURL();345 if (!base)346 return url;347 348 var baseHost = base.scheme + "://" + base.host + (base.port ? ":" + base.port : "");349 if (url[0] === "/")350 return baseHost + url;351 return baseHost + base.folderPathComponents + "/" + url;352 },353 354 _VLQ_BASE_SHIFT: 5,355 _VLQ_BASE_MASK: (1 << 5) - 1,356 _VLQ_CONTINUATION_MASK: 1 << 5357 }358 359 /**360 * @constructor361 */362 WebInspector.SourceMapParser.StringCharIterator = function(string)363 {364 this._string = string;365 this._position = 0;366 }367 368 WebInspector.SourceMapParser.StringCharIterator.prototype = {369 next: function()370 {371 return this._string.charAt(this._position++);372 },373 374 peek: function()375 {376 return this._string.charAt(this._position);377 },378 379 hasNext: function()380 {381 return this._position < this._string.length;382 }383 } -
trunk/Source/WebCore/inspector/front-end/SourceMap.js
r138499 r138500 30 30 31 31 /** 32 * @constructor 33 * @implements {WebInspector.ScriptSourceMapping} 34 * @param {WebInspector.Workspace} workspace 35 * @param {WebInspector.NetworkWorkspaceProvider} networkWorkspaceProvider 36 */ 37 WebInspector.CompilerScriptMapping = function(workspace, networkWorkspaceProvider) 38 { 39 this._workspace = workspace; 40 this._networkWorkspaceProvider = networkWorkspaceProvider; 41 /** @type {Object.<string, WebInspector.SourceMapParser>} */ 42 this._sourceMapForSourceMapURL = {}; 43 /** @type {Object.<string, WebInspector.SourceMapParser>} */ 44 this._sourceMapForScriptId = {}; 45 this._scriptForSourceMap = new Map(); 46 /** @type {Object.<string, WebInspector.SourceMapParser>} */ 47 this._sourceMapForURL = {}; 48 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); 49 } 50 51 WebInspector.CompilerScriptMapping.prototype = { 52 /** 53 * @param {WebInspector.RawLocation} rawLocation 54 * @return {WebInspector.UILocation} 55 */ 56 rawLocationToUILocation: function(rawLocation) 57 { 58 var debuggerModelLocation = /** @type {WebInspector.DebuggerModel.Location} */ (rawLocation); 59 var sourceMap = this._sourceMapForScriptId[debuggerModelLocation.scriptId]; 60 var lineNumber = debuggerModelLocation.lineNumber; 61 var columnNumber = debuggerModelLocation.columnNumber || 0; 62 var entry = sourceMap.findEntry(lineNumber, columnNumber); 63 if (entry.length === 2) 64 return null; 65 var uiSourceCode = this._workspace.uiSourceCodeForURL(entry[2]); 66 return new WebInspector.UILocation(uiSourceCode, entry[3], entry[4]); 67 }, 68 69 /** 70 * @param {WebInspector.UISourceCode} uiSourceCode 71 * @param {number} lineNumber 72 * @param {number} columnNumber 73 * @return {WebInspector.DebuggerModel.Location} 74 */ 75 uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) 76 { 77 var sourceMap = this._sourceMapForURL[uiSourceCode.url]; 78 var entry = sourceMap.findEntryReversed(uiSourceCode.url, lineNumber); 79 return WebInspector.debuggerModel.createRawLocation(this._scriptForSourceMap.get(sourceMap), entry[0], entry[1]); 80 }, 81 82 /** 83 * @param {WebInspector.Script} script 84 */ 85 addScript: function(script) 86 { 87 var sourceMap = this.loadSourceMapForScript(script); 88 89 if (this._scriptForSourceMap.get(sourceMap)) { 90 this._sourceMapForScriptId[script.scriptId] = sourceMap; 91 script.pushSourceMapping(this); 92 return; 93 } 94 95 var sourceURLs = sourceMap.sources(); 96 for (var i = 0; i < sourceURLs.length; ++i) { 97 var sourceURL = sourceURLs[i]; 98 if (this._workspace.uiSourceCodeForURL(sourceURL)) 99 continue; 100 this._sourceMapForURL[sourceURL] = sourceMap; 101 var sourceContent = sourceMap.sourceContent(sourceURL); 102 var contentProvider; 103 if (sourceContent) 104 contentProvider = new WebInspector.StaticContentProvider(WebInspector.resourceTypes.Script, sourceContent); 105 else 106 contentProvider = new WebInspector.CompilerSourceMappingContentProvider(sourceURL); 107 this._networkWorkspaceProvider.addFile(sourceURL, contentProvider, true); 108 var uiSourceCode = this._workspace.uiSourceCodeForURL(sourceURL); 109 uiSourceCode.setSourceMapping(this); 110 uiSourceCode.isContentScript = script.isContentScript; 111 } 112 113 this._sourceMapForScriptId[script.scriptId] = sourceMap; 114 this._scriptForSourceMap.put(sourceMap, script); 115 script.pushSourceMapping(this); 116 }, 117 118 /** 119 * @param {WebInspector.Script} script 120 * @return {WebInspector.SourceMapParser} 121 */ 122 loadSourceMapForScript: function(script) 123 { 124 var sourceMapURL = WebInspector.SourceMapParser.prototype._canonicalizeURL(script.sourceMapURL, script.sourceURL); 125 var sourceMap = this._sourceMapForSourceMapURL[sourceMapURL]; 126 if (sourceMap) 127 return sourceMap; 128 129 try { 130 // FIXME: make sendRequest async. 131 var response = InspectorFrontendHost.loadResourceSynchronously(sourceMapURL); 132 if (response.slice(0, 3) === ")]}") 133 response = response.substring(response.indexOf('\n')); 134 var payload = /** @type {WebInspector.SourceMapPayload} */ (JSON.parse(response)); 135 sourceMap = new WebInspector.SourceMapParser(sourceMapURL, payload); 136 } catch(e) { 137 console.error(e.message); 138 return null; 139 } 140 this._sourceMapForSourceMapURL[sourceMapURL] = sourceMap; 141 return sourceMap; 142 }, 143 144 _reset: function() 145 { 146 this._sourceMapForSourceMapURL = {}; 147 this._sourceMapForScriptId = {}; 148 this._scriptForSourceMap = new Map(); 149 this._sourceMapForURL = {}; 150 } 151 } 152 153 /** 154 * @constructor 155 */ 156 WebInspector.SourceMapPayload = function() 157 { 158 this.sections = []; 159 this.mappings = ""; 160 this.sourceRoot = ""; 161 this.sources = []; 162 } 163 164 /** 165 * Implements Source Map V3 consumer. See http://code.google.com/p/closure-compiler/wiki/SourceMaps 32 * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler/wiki/SourceMaps 166 33 * for format description. 167 34 * @constructor 168 35 * @param {string} sourceMappingURL 169 * @param { WebInspector.SourceMapPayload} payload170 */ 171 WebInspector.SourceMap Parser= function(sourceMappingURL, payload)172 { 173 if (!WebInspector.SourceMap Parser.prototype._base64Map) {36 * @param {SourceMapV3} payload 37 */ 38 WebInspector.SourceMap = function(sourceMappingURL, payload) 39 { 40 if (!WebInspector.SourceMap.prototype._base64Map) { 174 41 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 175 WebInspector.SourceMap Parser.prototype._base64Map = {};42 WebInspector.SourceMap.prototype._base64Map = {}; 176 43 for (var i = 0; i < base64Digits.length; ++i) 177 WebInspector.SourceMap Parser.prototype._base64Map[base64Digits.charAt(i)] = i;44 WebInspector.SourceMap.prototype._base64Map[base64Digits.charAt(i)] = i; 178 45 } 179 46 180 47 this._sourceMappingURL = sourceMappingURL; 181 48 this._mappings = []; 182 this._ reverseMappingsBySourceURL= {};49 this._sources = {}; 183 50 this._sourceContentByURL = {}; 184 51 this._parseMappingPayload(payload); 185 52 } 186 53 187 WebInspector.SourceMap Parser.prototype = {54 WebInspector.SourceMap.prototype = { 188 55 /** 189 56 * @return {Array.<string>} … … 191 58 sources: function() 192 59 { 60 return Object.keys(this._sources); 61 }, 62 63 /** 64 * @param {string} sourceURL 65 * @return {string|undefined} 66 */ 67 sourceContent: function(sourceURL) 68 { 69 return this._sourceContentByURL[sourceURL]; 70 }, 71 72 /** 73 * @param {SourceMapV3} mappingPayload 74 */ 75 _parseMappingPayload: function(mappingPayload) 76 { 77 if (mappingPayload.sections) 78 this._parseSections(mappingPayload.sections); 79 else 80 this._parseMap(mappingPayload, 0, 0); 81 }, 82 83 /** 84 * @param {Array.<SourceMapV3.Section>} sections 85 */ 86 _parseSections: function(sections) 87 { 88 for (var i = 0; i < sections.length; ++i) { 89 var section = sections[i]; 90 this._parseMap(section.map, section.offset.line, section.offset.column); 91 } 92 }, 93 94 /** 95 * @param {SourceMapV3} map 96 * @param {number} lineNumber 97 * @param {number} columnNumber 98 */ 99 _parseMap: function(map, lineNumber, columnNumber) 100 { 101 var sourceIndex = 0; 102 var sourceLineNumber = 0; 103 var sourceColumnNumber = 0; 104 var nameIndex = 0; 105 193 106 var sources = []; 194 for (var sourceURL in this._reverseMappingsBySourceURL) 195 sources.push(sourceURL); 196 return sources; 197 }, 198 199 sourceContent: function(sourceURL) 200 { 201 return this._sourceContentByURL[sourceURL]; 202 }, 203 107 var originalToCanonicalURLMap = {}; 108 for (var i = 0; i < map.sources.length; ++i) { 109 var originalSourceURL = map.sources[i]; 110 var url = this._canonicalizeURL((map.sourceRoot ? map.sourceRoot + "/" : "") + originalSourceURL, this._sourceMappingURL); 111 originalToCanonicalURLMap[originalSourceURL] = url; 112 sources.push(url); 113 this._sources[url] = true; 114 115 if (map.sourcesContent && map.sourcesContent[i]) 116 this._sourceContentByURL[url] = map.sourcesContent[i]; 117 } 118 119 var stringCharIterator = new WebInspector.SourceMap.StringCharIterator(map.mappings); 120 var sourceURL = sources[sourceIndex]; 121 122 while (true) { 123 if (stringCharIterator.peek() === ",") 124 stringCharIterator.next(); 125 else { 126 while (stringCharIterator.peek() === ";") { 127 lineNumber += 1; 128 columnNumber = 0; 129 stringCharIterator.next(); 130 } 131 if (!stringCharIterator.hasNext()) 132 break; 133 } 134 135 columnNumber += this._decodeVLQ(stringCharIterator); 136 if (this._isSeparator(stringCharIterator.peek())) { 137 this._mappings.push([lineNumber, columnNumber]); 138 continue; 139 } 140 141 var sourceIndexDelta = this._decodeVLQ(stringCharIterator); 142 if (sourceIndexDelta) { 143 sourceIndex += sourceIndexDelta; 144 sourceURL = sources[sourceIndex]; 145 } 146 sourceLineNumber += this._decodeVLQ(stringCharIterator); 147 sourceColumnNumber += this._decodeVLQ(stringCharIterator); 148 if (!this._isSeparator(stringCharIterator.peek())) 149 nameIndex += this._decodeVLQ(stringCharIterator); 150 151 this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]); 152 } 153 }, 154 155 /** 156 * @param {string} char 157 * @return {boolean} 158 */ 159 _isSeparator: function(char) 160 { 161 return char === "," || char === ";"; 162 }, 163 164 /** 165 * @param {WebInspector.SourceMap.StringCharIterator} stringCharIterator 166 * @return {number} 167 */ 168 _decodeVLQ: function(stringCharIterator) 169 { 170 // Read unsigned value. 171 var result = 0; 172 var shift = 0; 173 do { 174 var digit = this._base64Map[stringCharIterator.next()]; 175 result += (digit & this._VLQ_BASE_MASK) << shift; 176 shift += this._VLQ_BASE_SHIFT; 177 } while (digit & this._VLQ_CONTINUATION_MASK); 178 179 // Fix the sign. 180 var negative = result & 1; 181 result >>= 1; 182 return negative ? -result : result; 183 }, 184 185 /** 186 * @param {string} url 187 * @param {string} baseURL 188 */ 189 _canonicalizeURL: function(url, baseURL) 190 { 191 if (!url || !baseURL || url.asParsedURL() || url.substring(0, 5) === "data:") 192 return url; 193 194 var base = baseURL.asParsedURL(); 195 if (!base) 196 return url; 197 198 var baseHost = base.scheme + "://" + base.host + (base.port ? ":" + base.port : ""); 199 if (url[0] === "/") 200 return baseHost + url; 201 return baseHost + base.folderPathComponents + "/" + url; 202 }, 203 204 _VLQ_BASE_SHIFT: 5, 205 _VLQ_BASE_MASK: (1 << 5) - 1, 206 _VLQ_CONTINUATION_MASK: 1 << 5 207 } 208 209 /** 210 * @constructor 211 * @param {string} string 212 */ 213 WebInspector.SourceMap.StringCharIterator = function(string) 214 { 215 this._string = string; 216 this._position = 0; 217 } 218 219 WebInspector.SourceMap.StringCharIterator.prototype = { 220 /** 221 * @return {string} 222 */ 223 next: function() 224 { 225 return this._string.charAt(this._position++); 226 }, 227 228 /** 229 * @return {string} 230 */ 231 peek: function() 232 { 233 return this._string.charAt(this._position); 234 }, 235 236 /** 237 * @return {boolean} 238 */ 239 hasNext: function() 240 { 241 return this._position < this._string.length; 242 } 243 } 244 245 /** 246 * @constructor 247 * @extends WebInspector.SourceMap 248 * @param {string} sourceMappingURL 249 * @param {SourceMapV3} payload 250 */ 251 WebInspector.PositionBasedSourceMap = function(sourceMappingURL, payload) 252 { 253 this._reverseMappingsBySourceURL = {}; 254 WebInspector.SourceMap.call(this, sourceMappingURL, payload); 255 } 256 257 WebInspector.PositionBasedSourceMap.prototype = { 258 /** 259 * @param {number} lineNumber in compiled resource 260 * @param {number} columnNumber in compiled resource 261 */ 204 262 findEntry: function(lineNumber, columnNumber) 205 263 { … … 220 278 }, 221 279 280 /** 281 * @param {string} sourceURL of the originating resource 282 * @param {number} lineNumber in the originating resource 283 * @return {Array} 284 */ 222 285 findEntryReversed: function(sourceURL, lineNumber) 223 286 { … … 231 294 }, 232 295 233 _parseMappingPayload: function(mappingPayload) 234 { 235 if (mappingPayload.sections) 236 this._parseSections(mappingPayload.sections); 237 else 238 this._parseMap(mappingPayload, 0, 0); 239 }, 240 241 /** 242 * @param {Array.<SourceMapV3.Section>} sections 243 */ 244 _parseSections: function(sections) 245 { 246 for (var i = 0; i < sections.length; ++i) { 247 var section = sections[i]; 248 this._parseMap(section.map, section.offset.line, section.offset.column) 249 } 250 }, 251 252 /** 253 * @param {SourceMapV3} map 254 * @param {number} lineNumber 255 * @param {number} columnNumber 296 /** 297 * @override 256 298 */ 257 299 _parseMap: function(map, lineNumber, columnNumber) 258 300 { 259 var sourceIndex = 0; 260 var sourceLineNumber = 0; 261 var sourceColumnNumber = 0; 262 var nameIndex = 0; 263 264 var sources = []; 265 for (var i = 0; i < map.sources.length; ++i) { 266 var sourceURL = map.sources[i]; 267 if (map.sourceRoot) 268 sourceURL = map.sourceRoot + "/" + sourceURL; 269 var url = this._canonicalizeURL(sourceURL, this._sourceMappingURL); 270 sources.push(url); 301 WebInspector.SourceMap.prototype._parseMap.call(this, map, lineNumber, columnNumber); 302 303 for (var i = 0; i < this._mappings.length; ++i) { 304 var mapping = this._mappings[i]; 305 var url = mapping[2]; 306 if (!url) 307 continue; 271 308 if (!this._reverseMappingsBySourceURL[url]) 272 309 this._reverseMappingsBySourceURL[url] = []; 273 if (map.sourcesContent && map.sourcesContent[i]) 274 this._sourceContentByURL[url] = map.sourcesContent[i]; 275 } 276 277 var stringCharIterator = new WebInspector.SourceMapParser.StringCharIterator(map.mappings); 278 var sourceURL = sources[sourceIndex]; 279 var reverseMappings = this._reverseMappingsBySourceURL[sourceURL]; 280 281 while (true) { 282 if (stringCharIterator.peek() === ",") 283 stringCharIterator.next(); 284 else { 285 while (stringCharIterator.peek() === ";") { 286 lineNumber += 1; 287 columnNumber = 0; 288 stringCharIterator.next(); 289 } 290 if (!stringCharIterator.hasNext()) 291 break; 292 } 293 294 columnNumber += this._decodeVLQ(stringCharIterator); 295 if (this._isSeparator(stringCharIterator.peek())) { 296 this._mappings.push([lineNumber, columnNumber]); 297 continue; 298 } 299 300 var sourceIndexDelta = this._decodeVLQ(stringCharIterator); 301 if (sourceIndexDelta) { 302 sourceIndex += sourceIndexDelta; 303 sourceURL = sources[sourceIndex]; 304 reverseMappings = this._reverseMappingsBySourceURL[sourceURL]; 305 } 306 sourceLineNumber += this._decodeVLQ(stringCharIterator); 307 sourceColumnNumber += this._decodeVLQ(stringCharIterator); 308 if (!this._isSeparator(stringCharIterator.peek())) 309 nameIndex += this._decodeVLQ(stringCharIterator); 310 311 this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]); 312 if (!reverseMappings[sourceLineNumber]) 313 reverseMappings[sourceLineNumber] = [lineNumber, columnNumber]; 314 } 315 }, 316 317 _isSeparator: function(char) 318 { 319 return char === "," || char === ";"; 320 }, 321 322 _decodeVLQ: function(stringCharIterator) 323 { 324 // Read unsigned value. 325 var result = 0; 326 var shift = 0; 327 do { 328 var digit = this._base64Map[stringCharIterator.next()]; 329 result += (digit & this._VLQ_BASE_MASK) << shift; 330 shift += this._VLQ_BASE_SHIFT; 331 } while (digit & this._VLQ_CONTINUATION_MASK); 332 333 // Fix the sign. 334 var negative = result & 1; 335 result >>= 1; 336 return negative ? -result : result; 337 }, 338 339 _canonicalizeURL: function(url, baseURL) 340 { 341 if (!url || !baseURL || url.asParsedURL() || url.substring(0, 5) === "data:") 342 return url; 343 344 var base = baseURL.asParsedURL(); 345 if (!base) 346 return url; 347 348 var baseHost = base.scheme + "://" + base.host + (base.port ? ":" + base.port : ""); 349 if (url[0] === "/") 350 return baseHost + url; 351 return baseHost + base.folderPathComponents + "/" + url; 352 }, 353 354 _VLQ_BASE_SHIFT: 5, 355 _VLQ_BASE_MASK: (1 << 5) - 1, 356 _VLQ_CONTINUATION_MASK: 1 << 5 310 var reverseMappings = this._reverseMappingsBySourceURL[url]; 311 var sourceLine = mapping[3]; 312 if (!reverseMappings[sourceLine]) 313 reverseMappings[sourceLine] = [mapping[0], mapping[1]]; 314 } 315 }, 316 317 __proto__: WebInspector.SourceMap.prototype 357 318 } 358 319 359 320 /** 360 321 * @constructor 361 */ 362 WebInspector.SourceMapParser.StringCharIterator = function(string) 363 { 364 this._string = string; 365 this._position = 0; 366 } 367 368 WebInspector.SourceMapParser.StringCharIterator.prototype = { 369 next: function() 370 { 371 return this._string.charAt(this._position++); 372 }, 373 374 peek: function() 375 { 376 return this._string.charAt(this._position); 377 }, 378 379 hasNext: function() 380 { 381 return this._position < this._string.length; 322 * @extends WebInspector.SourceMap 323 * @param {string} sourceMappingURL 324 * @param {SourceMapV3} payload 325 */ 326 WebInspector.RangeBasedSourceMap = function(sourceMappingURL, payload) 327 { 328 WebInspector.SourceMap.call(this, sourceMappingURL, payload); 329 330 // Empty mappings should not normally be found in a range-based map. 331 function callback(value) 332 { 333 return !!value[2]; 382 334 } 383 } 335 this._mappings = this._mappings.filter(callback); 336 } 337 338 WebInspector.RangeBasedSourceMap.MappingComparator = function(a, b) 339 { 340 if (a[0] !== b[0]) 341 return a[0] - b[0]; 342 return a[1] - b[1]; 343 } 344 345 WebInspector.RangeBasedSourceMap.prototype = { 346 /** 347 * @param {number} lineNumber in the compiled resource 348 * @param {number} columnNumber in the compiled resource 349 * @return {?WebInspector.RangeBasedSourceMap.SourceRange} 350 */ 351 findSourceRange: function(lineNumber, columnNumber) 352 { 353 var comparator = WebInspector.RangeBasedSourceMap.MappingComparator; 354 var lookupEntry = [lineNumber, columnNumber]; 355 var index = binarySearch(lookupEntry, this._mappings, comparator); 356 if (index >= 0) { 357 if (index % 2) { 358 // Range end hit. Check if there's a following range that starts from the same position. 359 if (index + 1 >= this._mappings.length || comparator(lookupEntry, this._mappings[index + 1])) 360 return null; 361 return this._rangeForStartIndex(index + 1); 362 } 363 364 return this._rangeForStartIndex(index); 365 } 366 367 index = -(index + 1); 368 if ((index % 2) && comparator(lookupEntry, this._mappings[index - 1]) >= 0 && comparator(lookupEntry, this._mappings[index]) <= 0) 369 return this._rangeForStartIndex(index - 1); 370 371 return null; 372 }, 373 374 /** 375 * @param {number} index 376 * @return {?WebInspector.RangeBasedSourceMap.SourceRange} 377 */ 378 _rangeForStartIndex: function(index) 379 { 380 var startEntry = this._mappings[index]; 381 var endEntry = this._mappings[index + 1]; 382 if (startEntry[2] !== endEntry[2]) { 383 console.error("Mismatched source URLs in adjacent range-based sourcemap entries: %s vs %s", JSON.stringify(startEntry), JSON.stringify(endEntry)); 384 return null; 385 } 386 387 return new WebInspector.RangeBasedSourceMap.SourceRange(startEntry[2], startEntry[3], startEntry[4], endEntry[3], endEntry[4]); 388 }, 389 390 __proto__: WebInspector.SourceMap.prototype 391 } 392 393 /** 394 * @constructor 395 * @param {string} url 396 * @param {number} startLine 397 * @param {number} startColumn 398 * @param {number} endLine 399 * @param {number} endColumn 400 */ 401 WebInspector.RangeBasedSourceMap.SourceRange = function(url, startLine, startColumn, endLine, endColumn) 402 { 403 this.url = url; 404 this.startLine = startLine; 405 this.endLine = endLine; 406 this.startColumn = startColumn; 407 this.endColumn = endColumn; 408 } -
trunk/Source/WebCore/inspector/front-end/WebKit.qrc
r138496 r138500 185 185 <file>SourceHTMLTokenizer.js</file> 186 186 <file>SourceJavaScriptTokenizer.js</file> 187 <file>SourceMap.js</file> 187 188 <file>SourceMapping.js</file> 188 189 <file>SourceTokenizer.js</file> -
trunk/Source/WebCore/inspector/front-end/inspector.html
r138496 r138500 132 132 <script type="text/javascript" src="FileUtils.js"></script> 133 133 <script type="text/javascript" src="DebuggerModel.js"></script> 134 <script type="text/javascript" src="SourceMap.js"></script> 134 135 <script type="text/javascript" src="SourceMapping.js"></script> 135 136 <script type="text/javascript" src="Script.js"></script>
Note: See TracChangeset
for help on using the changeset viewer.