diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Models/SourceMap.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Models/SourceMap.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Models/SourceMap.js | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Models/SourceMap.js b/Source/WebInspectorUI/UserInterface/Models/SourceMap.js new file mode 100644 index 000000000..1824421bc --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Models/SourceMap.js @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.SourceMap = class SourceMap extends WebInspector.Object +{ + constructor(sourceMappingURL, payload, originalSourceCode) + { + super(); + + if (!WebInspector.SourceMap._base64Map) { + var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + WebInspector.SourceMap._base64Map = {}; + for (var i = 0; i < base64Digits.length; ++i) + WebInspector.SourceMap._base64Map[base64Digits.charAt(i)] = i; + } + + this._originalSourceCode = originalSourceCode || null; + this._sourceMapResources = {}; + this._sourceMapResourcesList = []; + + this._sourceMappingURL = sourceMappingURL; + this._reverseMappingsBySourceURL = {}; + this._mappings = []; + this._sources = {}; + this._sourceRoot = null; + this._sourceContentByURL = {}; + this._parseMappingPayload(payload); + } + + // Public + + get originalSourceCode() + { + return this._originalSourceCode; + } + + get sourceMappingBasePathURLComponents() + { + if (this._sourceMappingURLBasePathComponents) + return this._sourceMappingURLBasePathComponents; + + if (this._sourceRoot) { + var baseURLPath = absoluteURL(this._sourceRoot, this._sourceMappingURL); + console.assert(baseURLPath); + if (baseURLPath) { + var urlComponents = parseURL(baseURLPath); + if (!/\/$/.test(urlComponents.path)) + urlComponents.path += "/"; + this._sourceMappingURLBasePathComponents = urlComponents; + return this._sourceMappingURLBasePathComponents; + } + } + + var urlComponents = parseURL(this._sourceMappingURL); + + // Fallback for JavaScript debuggable named scripts that may not have a complete URL. + if (!urlComponents.path) + urlComponents.path = this._sourceMappingURL || ""; + + urlComponents.path = urlComponents.path.substr(0, urlComponents.path.lastIndexOf(urlComponents.lastPathComponent)); + urlComponents.lastPathComponent = null; + this._sourceMappingURLBasePathComponents = urlComponents; + return this._sourceMappingURLBasePathComponents; + } + + get resources() + { + return this._sourceMapResourcesList; + } + + addResource(resource) + { + console.assert(!(resource.url in this._sourceMapResources)); + this._sourceMapResources[resource.url] = resource; + this._sourceMapResourcesList.push(resource); + } + + resourceForURL(url) + { + return this._sourceMapResources[url]; + } + + sources() + { + return Object.keys(this._sources); + } + + sourceContent(sourceURL) + { + return this._sourceContentByURL[sourceURL]; + } + + _parseMappingPayload(mappingPayload) + { + if (mappingPayload.sections) + this._parseSections(mappingPayload.sections); + else + this._parseMap(mappingPayload, 0, 0); + } + + _parseSections(sections) + { + for (var i = 0; i < sections.length; ++i) { + var section = sections[i]; + this._parseMap(section.map, section.offset.line, section.offset.column); + } + } + + findEntry(lineNumber, columnNumber) + { + var first = 0; + var count = this._mappings.length; + while (count > 1) { + var step = count >> 1; + var middle = first + step; + var mapping = this._mappings[middle]; + if (lineNumber < mapping[0] || (lineNumber === mapping[0] && columnNumber < mapping[1])) + count = step; + else { + first = middle; + count -= step; + } + } + var entry = this._mappings[first]; + if (!first && entry && (lineNumber < entry[0] || (lineNumber === entry[0] && columnNumber < entry[1]))) + return null; + return entry; + } + + findEntryReversed(sourceURL, lineNumber) + { + var mappings = this._reverseMappingsBySourceURL[sourceURL]; + for ( ; lineNumber < mappings.length; ++lineNumber) { + var mapping = mappings[lineNumber]; + if (mapping) + return mapping; + } + return this._mappings[0]; + } + + _parseMap(map, lineNumber, columnNumber) + { + var sourceIndex = 0; + var sourceLineNumber = 0; + var sourceColumnNumber = 0; + var nameIndex = 0; + + var sources = []; + var originalToCanonicalURLMap = {}; + for (var i = 0; i < map.sources.length; ++i) { + var originalSourceURL = map.sources[i]; + var href = originalSourceURL; + if (map.sourceRoot && href.charAt(0) !== "/") + href = map.sourceRoot.replace(/\/+$/, "") + "/" + href; + var url = absoluteURL(href, this._sourceMappingURL) || href; + originalToCanonicalURLMap[originalSourceURL] = url; + sources.push(url); + this._sources[url] = true; + + if (map.sourcesContent && map.sourcesContent[i]) + this._sourceContentByURL[url] = map.sourcesContent[i]; + } + + this._sourceRoot = map.sourceRoot || null; + + var stringCharIterator = new WebInspector.SourceMap.StringCharIterator(map.mappings); + var sourceURL = sources[sourceIndex]; + + while (true) { + if (stringCharIterator.peek() === ",") + stringCharIterator.next(); + else { + while (stringCharIterator.peek() === ";") { + lineNumber += 1; + columnNumber = 0; + stringCharIterator.next(); + } + if (!stringCharIterator.hasNext()) + break; + } + + columnNumber += this._decodeVLQ(stringCharIterator); + if (this._isSeparator(stringCharIterator.peek())) { + this._mappings.push([lineNumber, columnNumber]); + continue; + } + + var sourceIndexDelta = this._decodeVLQ(stringCharIterator); + if (sourceIndexDelta) { + sourceIndex += sourceIndexDelta; + sourceURL = sources[sourceIndex]; + } + sourceLineNumber += this._decodeVLQ(stringCharIterator); + sourceColumnNumber += this._decodeVLQ(stringCharIterator); + if (!this._isSeparator(stringCharIterator.peek())) + nameIndex += this._decodeVLQ(stringCharIterator); + + this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]); + } + + for (var i = 0; i < this._mappings.length; ++i) { + var mapping = this._mappings[i]; + var url = mapping[2]; + if (!url) + continue; + if (!this._reverseMappingsBySourceURL[url]) + this._reverseMappingsBySourceURL[url] = []; + var reverseMappings = this._reverseMappingsBySourceURL[url]; + var sourceLine = mapping[3]; + if (!reverseMappings[sourceLine]) + reverseMappings[sourceLine] = [mapping[0], mapping[1]]; + } + } + + _isSeparator(char) + { + return char === "," || char === ";"; + } + + _decodeVLQ(stringCharIterator) + { + // Read unsigned value. + var result = 0; + var shift = 0; + do { + var digit = WebInspector.SourceMap._base64Map[stringCharIterator.next()]; + result += (digit & WebInspector.SourceMap.VLQ_BASE_MASK) << shift; + shift += WebInspector.SourceMap.VLQ_BASE_SHIFT; + } while (digit & WebInspector.SourceMap.VLQ_CONTINUATION_MASK); + + // Fix the sign. + var negative = result & 1; + result >>= 1; + return negative ? -result : result; + } +}; + +WebInspector.SourceMap.VLQ_BASE_SHIFT = 5; +WebInspector.SourceMap.VLQ_BASE_MASK = (1 << 5) - 1; +WebInspector.SourceMap.VLQ_CONTINUATION_MASK = 1 << 5; + +WebInspector.SourceMap.StringCharIterator = class StringCharIterator +{ + constructor(string) + { + this._string = string; + this._position = 0; + } + + next() + { + return this._string.charAt(this._position++); + } + + peek() + { + return this._string.charAt(this._position); + } + + hasNext() + { + return this._position < this._string.length; + } +}; |