Index: Source/devtools/front_end/sdk/SourceMap.js |
diff --git a/Source/devtools/front_end/sdk/SourceMap.js b/Source/devtools/front_end/sdk/SourceMap.js |
index bbafb62a08e56495b04ef53da7cac96c4c66db6d..19a8d3dbb87b2a28f00cfa5057117b2854f4b80c 100644 |
--- a/Source/devtools/front_end/sdk/SourceMap.js |
+++ b/Source/devtools/front_end/sdk/SourceMap.js |
@@ -64,7 +64,7 @@ SourceMapV3.Offset = function() |
* for format description. |
* @constructor |
* @param {string} sourceMappingURL |
- * @param {!SourceMapV3} payload |
+ * @param {?SourceMapV3} payload |
*/ |
WebInspector.SourceMap = function(sourceMappingURL, payload) |
{ |
@@ -80,7 +80,8 @@ WebInspector.SourceMap = function(sourceMappingURL, payload) |
this._mappings = []; |
this._sources = {}; |
this._sourceContentByURL = {}; |
- this._parseMappingPayload(payload); |
+ if (payload) |
+ this._parseMappingPayload(payload); |
} |
/** |
@@ -129,6 +130,113 @@ WebInspector.SourceMap.load = function(sourceMapURL, compiledURL, callback) |
WebInspector.SourceMap.prototype = { |
/** |
+ * @return {!WebInspector.SourceMap} |
+ */ |
+ clone: function() |
+ { |
+ var map = new WebInspector.SourceMap(this._sourceMappingURL, null); |
+ map._sources = this._sources; |
+ map._sourceContentByURL = this._sourceContentByURL; |
+ for (var i = 0; i < this._mappings.length; ++i) |
+ map._mappings.push(this._mappings[i].clone()); |
+ map._initializedReversedMappings(); |
+ return map; |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.TextRange} oldRange |
+ * @param {!WebInspector.TextRange} newRange |
+ */ |
+ compiledRangeEdited: function(oldRange, newRange) |
+ { |
+ console.assert(oldRange.startLine === newRange.startLine); |
+ console.assert(oldRange.startColumn === newRange.startColumn); |
+ |
+ var columnOffset = newRange.endColumn - oldRange.endColumn; |
+ var lineOffset = newRange.endLine - oldRange.endLine; |
+ |
+ var newMappings = []; |
+ for (var i = 0; i < this._mappings.length; ++i) { |
+ var mapping = this._mappings[i]; |
+ // Edit destroys mapping. |
+ if (oldRange.containsLocation(mapping.lineNumber, mapping.columnNumber)) |
+ continue; |
+ newMappings.push(mapping); |
+ // Update compiled mapping coordinates if needed. |
+ if (mapping.lineNumber === oldRange.endLine && mapping.columnNumber >= oldRange.endColumn) { |
+ mapping.columnNumber += columnOffset; |
+ mapping.lineNumber += lineOffset; |
+ } else if (mapping.lineNumber > oldRange.endLine) { |
+ mapping.lineNumber += lineOffset; |
+ } |
+ } |
+ this._mappings = newMappings; |
+ this._initializedReversedMappings(); |
+ }, |
+ |
+ /** |
+ * @param {string} sourceURL |
+ * @param {!WebInspector.TextRange} oldRange |
+ * @param {!WebInspector.TextRange} newRange |
+ * @return {boolean} |
+ */ |
+ sourceRangeEdited: function(sourceURL, oldRange, newRange) |
+ { |
+ console.assert(oldRange.startLine === newRange.startLine); |
+ console.assert(oldRange.startColumn === newRange.startColumn); |
+ |
+ var columnOffset = newRange.endColumn - oldRange.endColumn; |
+ var lineOffset = newRange.endLine - oldRange.endLine; |
+ var newMappings = []; |
+ for (var i = 0; i < this._mappings.length; ++i) { |
+ var mapping = this._mappings[i]; |
+ if (mapping.sourceURL !== sourceURL) { |
+ newMappings.push(mapping); |
+ continue; |
+ } |
+ if (oldRange.containsLocation(mapping.sourceLineNumber, mapping.sourceColumnNumber)) |
+ continue; |
+ newMappings.push(mapping); |
+ // Update source mapping coordinates if needed. |
+ if (mapping.sourceLineNumber === oldRange.endLine && mapping.sourceColumnNumber >= oldRange.endColumn) { |
+ mapping.sourceColumnNumber += columnOffset; |
+ mapping.sourceLineNumber += lineOffset; |
+ } else if (mapping.sourceLineNumber > oldRange.endLine) |
+ mapping.sourceLineNumber += lineOffset; |
+ } |
+ this._mappings = newMappings; |
+ this._initializedReversedMappings(); |
+ }, |
+ |
+ ensureHasMapping: function(newEntry) |
+ { |
+ var entry = this.findEntry(newEntry.lineNumber, newEntry.columnNumber); |
+ if (entry && entry.equals(newEntry)) |
+ return; |
+ if (entry && entry.lineNumber === newEntry.lineNumber && entry.columnNumber === newEntry.columnNumber) { |
+ entry.sourceURL = newEntry.sourceURL; |
+ entry.sourceLineNumber = newEntry.sourceLineNumber; |
+ entry.sourceColumnNumber = newEntry.sourceColumnNumber; |
+ this._initializedReversedMappings(); |
+ return; |
+ } |
+ var newMappings = []; |
+ var i = 0; |
+ while (this._mappings[i] !== entry) |
+ newMappings.push(this._mappings[i++]); |
+ newMappings.push(entry); |
+ newMappings.push(newEntry); |
+ ++i; |
+ while (i < this._mappings.length) |
+ newMappings.push(this._mappings[i++]); |
+ |
+ var reverseMappings = this._reverseMappingsBySourceURL.get(newEntry.sourceURL); |
+ reverseMappings.push(newEntry); |
+ reverseMappings._sorted = false; |
+ this._mappings = newMappings; |
+ }, |
+ |
+ /** |
* @return {string} |
*/ |
url: function() |
@@ -214,6 +322,31 @@ WebInspector.SourceMap.prototype = { |
return entry; |
}, |
+ findEntriesReversed: function(sourceURL, lineNumber, columnNumber) |
+ { |
+ var mappings = this._reversedMappings(sourceURL); |
+ var first = 0; |
+ var count = mappings.length; |
+ while (count > 1) { |
+ var step = count >> 1; |
+ var middle = first + step; |
+ var mapping = mappings[middle]; |
+ if (lineNumber < mapping.sourceLineNumber || (lineNumber === mapping.sourceLineNumber && columnNumber < mapping.sourceColumnNumber)) |
+ count = step; |
+ else { |
+ first = middle; |
+ count -= step; |
+ } |
+ } |
+ var entry = mappings[first]; |
+ if (!first && entry && (lineNumber < entry.sourceLineNumber || (lineNumber === entry.sourceLineNumber && columnNumber < entry.sourceColumnNumber))) |
+ return []; |
+ var results = []; |
+ for (var i = first; i >= 0 && mappings[i].sourceLineNumber === entry.sourceLineNumber && mappings[i].sourceColumnNumber === entry.sourceColumnNumber; --i) |
+ results.push(mappings[i]); |
+ return results; |
+ }, |
+ |
/** |
* @param {string} sourceURL |
* @param {number} lineNumber |
@@ -335,6 +468,12 @@ WebInspector.SourceMap.prototype = { |
this._mappings.push(new WebInspector.SourceMap.Entry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber)); |
} |
+ this._initializedReversedMappings(); |
+ }, |
+ |
+ _initializedReversedMappings: function() |
+ { |
+ this._reverseMappingsBySourceURL.clear(); |
for (var i = 0; i < this._mappings.length; ++i) { |
var mapping = this._mappings[i]; |
var url = mapping.sourceURL; |
@@ -434,3 +573,26 @@ WebInspector.SourceMap.Entry = function(lineNumber, columnNumber, sourceURL, sou |
this.sourceLineNumber = sourceLineNumber; |
this.sourceColumnNumber = sourceColumnNumber; |
} |
+ |
+WebInspector.SourceMap.Entry.prototype = { |
+ /** |
+ * @param {!WebInspector.SourceMap.Entry} other |
+ * @return {boolean} |
+ */ |
+ equals: function(other) |
+ { |
+ return this.lineNumber === other.lineNumber && |
+ this.columnNumber === other.columnNumber && |
+ this.sourceURL === other.sourceURL && |
+ this.sourceLineNumber === other.sourceLineNumber && |
+ this.sourceColumnNumber === other.sourceColumnNumber; |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.SourceMap.Entry} |
+ */ |
+ clone: function() |
+ { |
+ return new WebInspector.SourceMap.Entry(this.lineNumber, this.columnNumber, this.sourceURL, this.sourceLineNumber, this.sourceColumnNumber); |
+ }, |
+} |