123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- /*
- * Copyright (C) 2012 Google 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER OR 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.
- */
- /**
- * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler/wiki/SourceMaps
- * for format description.
- * @constructor
- * @param {string} sourceMappingURL
- * @param {SourceMapV3} payload
- */
- WebInspector.SourceMap = function(sourceMappingURL, payload)
- {
- if (!WebInspector.SourceMap.prototype._base64Map) {
- const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- WebInspector.SourceMap.prototype._base64Map = {};
- for (var i = 0; i < base64Digits.length; ++i)
- WebInspector.SourceMap.prototype._base64Map[base64Digits.charAt(i)] = i;
- }
- this._sourceMappingURL = sourceMappingURL;
- this._reverseMappingsBySourceURL = {};
- this._mappings = [];
- this._sources = {};
- this._sourceContentByURL = {};
- this._parseMappingPayload(payload);
- }
- WebInspector.SourceMap._sourceMapRequestHeaderName = "X-Source-Map-Request-From";
- WebInspector.SourceMap._sourceMapRequestHeaderValue = "inspector";
- WebInspector.SourceMap.hasSourceMapRequestHeader = function(request)
- {
- return request && request.requestHeaderValue(WebInspector.SourceMap._sourceMapRequestHeaderName) === WebInspector.SourceMap._sourceMapRequestHeaderValue;
- }
- /**
- * @param {string} sourceMapURL
- * @param {string} compiledURL
- * @param {function(WebInspector.SourceMap)} callback
- */
- WebInspector.SourceMap.load = function(sourceMapURL, compiledURL, callback)
- {
- var headers = {};
- headers[WebInspector.SourceMap._sourceMapRequestHeaderName] = WebInspector.SourceMap._sourceMapRequestHeaderValue;
- NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFrame.id, sourceMapURL, headers, contentLoaded.bind(this));
- /**
- * @param {?Protocol.Error} error
- * @param {number} statusCode
- * @param {NetworkAgent.Headers} headers
- * @param {string} content
- */
- function contentLoaded(error, statusCode, headers, content)
- {
- if (error || !content || statusCode >= 400) {
- callback(null);
- return;
- }
- if (content.slice(0, 3) === ")]}")
- content = content.substring(content.indexOf('\n'));
- try {
- var payload = /** @type {SourceMapV3} */ (JSON.parse(content));
- var baseURL = sourceMapURL.startsWith("data:") ? compiledURL : sourceMapURL;
- callback(new WebInspector.SourceMap(baseURL, payload));
- } catch(e) {
- console.error(e.message);
- callback(null);
- }
- }
- }
- WebInspector.SourceMap.prototype = {
- /**
- * @return {Array.<string>}
- */
- sources: function()
- {
- return Object.keys(this._sources);
- },
- /**
- * @param {string} sourceURL
- * @return {string|undefined}
- */
- sourceContent: function(sourceURL)
- {
- return this._sourceContentByURL[sourceURL];
- },
- /**
- * @param {string} sourceURL
- * @param {WebInspector.ResourceType} contentType
- * @return {WebInspector.ContentProvider}
- */
- sourceContentProvider: function(sourceURL, contentType)
- {
- var lastIndexOfDot = sourceURL.lastIndexOf(".");
- var extension = lastIndexOfDot !== -1 ? sourceURL.substr(lastIndexOfDot + 1) : "";
- var mimeType = WebInspector.ResourceType.mimeTypesForExtensions[extension.toLowerCase()];
- var sourceContent = this.sourceContent(sourceURL);
- if (sourceContent)
- return new WebInspector.StaticContentProvider(contentType, sourceContent, mimeType);
- return new WebInspector.CompilerSourceMappingContentProvider(sourceURL, contentType, mimeType);
- },
- /**
- * @param {SourceMapV3} mappingPayload
- */
- _parseMappingPayload: function(mappingPayload)
- {
- if (mappingPayload.sections)
- this._parseSections(mappingPayload.sections);
- else
- this._parseMap(mappingPayload, 0, 0);
- },
- /**
- * @param {Array.<SourceMapV3.Section>} sections
- */
- _parseSections: function(sections)
- {
- for (var i = 0; i < sections.length; ++i) {
- var section = sections[i];
- this._parseMap(section.map, section.offset.line, section.offset.column);
- }
- },
- /**
- * @param {number} lineNumber in compiled resource
- * @param {number} columnNumber in compiled resource
- * @return {?Array}
- */
- findEntry: function(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;
- },
- /**
- * @param {string} sourceURL of the originating resource
- * @param {number} lineNumber in the originating resource
- * @return {Array}
- */
- findEntryReversed: function(sourceURL, lineNumber)
- {
- var mappings = this._reverseMappingsBySourceURL[sourceURL];
- for ( ; lineNumber < mappings.length; ++lineNumber) {
- var mapping = mappings[lineNumber];
- if (mapping)
- return mapping;
- }
- return this._mappings[0];
- },
- /**
- * @override
- */
- _parseMap: function(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 sourceRoot = map.sourceRoot || "";
- if (sourceRoot && !sourceRoot.endsWith("/"))
- sourceRoot += "/";
- var href = sourceRoot + originalSourceURL;
- var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL, href) || href;
- originalToCanonicalURLMap[originalSourceURL] = url;
- sources.push(url);
- this._sources[url] = true;
- if (map.sourcesContent && map.sourcesContent[i])
- this._sourceContentByURL[url] = map.sourcesContent[i];
- }
- 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]];
- }
- },
- /**
- * @param {string} char
- * @return {boolean}
- */
- _isSeparator: function(char)
- {
- return char === "," || char === ";";
- },
- /**
- * @param {WebInspector.SourceMap.StringCharIterator} stringCharIterator
- * @return {number}
- */
- _decodeVLQ: function(stringCharIterator)
- {
- // Read unsigned value.
- var result = 0;
- var shift = 0;
- do {
- var digit = this._base64Map[stringCharIterator.next()];
- result += (digit & this._VLQ_BASE_MASK) << shift;
- shift += this._VLQ_BASE_SHIFT;
- } while (digit & this._VLQ_CONTINUATION_MASK);
- // Fix the sign.
- var negative = result & 1;
- result >>= 1;
- return negative ? -result : result;
- },
- _VLQ_BASE_SHIFT: 5,
- _VLQ_BASE_MASK: (1 << 5) - 1,
- _VLQ_CONTINUATION_MASK: 1 << 5
- }
- /**
- * @constructor
- * @param {string} string
- */
- WebInspector.SourceMap.StringCharIterator = function(string)
- {
- this._string = string;
- this._position = 0;
- }
- WebInspector.SourceMap.StringCharIterator.prototype = {
- /**
- * @return {string}
- */
- next: function()
- {
- return this._string.charAt(this._position++);
- },
- /**
- * @return {string}
- */
- peek: function()
- {
- return this._string.charAt(this._position);
- },
- /**
- * @return {boolean}
- */
- hasNext: function()
- {
- return this._position < this._string.length;
- }
- }
|