2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
34 WebInspector.CompilerSourceMapping = function()
38 WebInspector.CompilerSourceMapping.prototype = {
39 compiledLocationToSourceLocation: function(lineNumber, columnNumber)
41 // Should be implemented by subclasses.
44 sourceLocationToCompiledLocation: function(sourceURL, lineNumber, columnNumber)
46 // Should be implemented by subclasses.
51 // Should be implemented by subclasses.
56 * Implements Source Map V3 consumer. See http://code.google.com/p/closure-compiler/wiki/SourceMaps
57 * for format description.
58 * @extends {WebInspector.CompilerSourceMapping}
61 WebInspector.ClosureCompilerSourceMapping = function(payload)
63 if (!WebInspector.ClosureCompilerSourceMapping.prototype._base64Map) {
64 base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
65 WebInspector.ClosureCompilerSourceMapping.prototype._base64Map = {};
66 for (var i = 0; i < base64Digits.length; ++i)
67 WebInspector.ClosureCompilerSourceMapping.prototype._base64Map[base64Digits.charAt(i)] = i;
70 this._sources = payload.sources;
72 this._reverseMappingsBySourceURL = {};
73 for (var i = 0; i < this._sources.length; ++i)
74 this._reverseMappingsBySourceURL[this._sources[i]] = [];
75 this._parseMappings(payload.mappings);
78 WebInspector.ClosureCompilerSourceMapping.prototype = {
79 compiledLocationToSourceLocation: function(lineNumber, columnNumber)
81 var mapping = this._findMapping(lineNumber, columnNumber);
82 return { sourceURL: mapping[2], lineNumber: mapping[3], columnNumber: mapping[4] };
85 sourceLocationToCompiledLocation: function(sourceURL, lineNumber)
87 var mappings = this._reverseMappingsBySourceURL[sourceURL];
88 for ( ; lineNumber < mappings.length; ++lineNumber) {
89 var mapping = mappings[lineNumber];
91 return { lineNumber: mapping[0], columnNumber: mapping[1] };
100 _findMapping: function(lineNumber, columnNumber)
103 var count = this._mappings.length;
105 var step = count >> 1;
106 var middle = first + step;
107 var mapping = this._mappings[middle];
108 if (lineNumber < mapping[0] || (lineNumber == mapping[0] && columnNumber < mapping[1]))
115 return this._mappings[first];
118 _parseMappings: function(mappingsPayload)
120 var stringCharIterator = new WebInspector.ClosureCompilerSourceMapping.StringCharIterator(mappingsPayload);
123 var columnNumber = 0;
125 var sourceLineNumber = 0;
126 var sourceColumnNumber = 0;
129 var sourceURL = this._sources[0];
130 var reverseMappings = this._reverseMappingsBySourceURL[sourceURL];
133 columnNumber += this._decodeVLQ(stringCharIterator);
134 if (this._isSeparator(stringCharIterator.peek()))
136 var sourceIndexDelta = this._decodeVLQ(stringCharIterator);
137 if (sourceIndexDelta) {
138 sourceIndex += sourceIndexDelta;
139 sourceURL = this._sources[sourceIndex];
140 reverseMappings = this._reverseMappingsBySourceURL[sourceURL];
142 sourceLineNumber += this._decodeVLQ(stringCharIterator);
143 sourceColumnNumber += this._decodeVLQ(stringCharIterator);
144 if (!this._isSeparator(stringCharIterator.peek()))
145 nameIndex += this._decodeVLQ(stringCharIterator);
147 this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]);
148 if (!reverseMappings[sourceLineNumber])
149 reverseMappings[sourceLineNumber] = [lineNumber, columnNumber];
151 if (stringCharIterator.next() === ";") {
155 } while(stringCharIterator.hasNext());
158 _isSeparator: function(char)
160 return char === "," || char === ";";
163 _decodeVLQ: function(stringCharIterator)
165 // Read unsigned value.
169 var digit = this._base64Map[stringCharIterator.next()];
170 result += (digit & this._VLQ_BASE_MASK) << shift;
171 shift += this._VLQ_BASE_SHIFT;
172 } while (digit & this._VLQ_CONTINUATION_MASK);
175 var negative = result & 1;
177 return negative ? -result : result;
181 _VLQ_BASE_MASK: (1 << 5) - 1,
182 _VLQ_CONTINUATION_MASK: 1 << 5
188 WebInspector.ClosureCompilerSourceMapping.StringCharIterator = function(string)
190 this._string = string;
194 WebInspector.ClosureCompilerSourceMapping.StringCharIterator.prototype = {
197 return this._string.charAt(this._position++);
202 return this._string.charAt(this._position);
207 return this._position < this._string.length;