summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:20:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:28:57 +0000
commitd17ea114e5ef69ad5d5d7413280a13e6428098aa (patch)
tree2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
parent8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff)
downloadqtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js')
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js623
1 files changed, 623 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
new file mode 100644
index 00000000000..0cb8c58b018
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
@@ -0,0 +1,623 @@
+/*
+ * 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.
+ */
+
+/**
+ * @unrestricted
+ */
+SDK.SourceMapV3 = class {
+ constructor() {
+ /** @type {number} */ this.version;
+ /** @type {string|undefined} */ this.file;
+ /** @type {!Array.<string>} */ this.sources;
+ /** @type {!Array.<!SDK.SourceMapV3.Section>|undefined} */ this.sections;
+ /** @type {string} */ this.mappings;
+ /** @type {string|undefined} */ this.sourceRoot;
+ /** @type {!Array.<string>|undefined} */ this.names;
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.SourceMapV3.Section = class {
+ constructor() {
+ /** @type {!SDK.SourceMapV3} */ this.map;
+ /** @type {!SDK.SourceMapV3.Offset} */ this.offset;
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.SourceMapV3.Offset = class {
+ constructor() {
+ /** @type {number} */ this.line;
+ /** @type {number} */ this.column;
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.SourceMapEntry = class {
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @param {string=} sourceURL
+ * @param {number=} sourceLineNumber
+ * @param {number=} sourceColumnNumber
+ * @param {string=} name
+ */
+ constructor(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, name) {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ this.sourceURL = sourceURL;
+ this.sourceLineNumber = sourceLineNumber;
+ this.sourceColumnNumber = sourceColumnNumber;
+ this.name = name;
+ }
+
+ /**
+ * @param {!SDK.SourceMapEntry} entry1
+ * @param {!SDK.SourceMapEntry} entry2
+ * @return {number}
+ */
+ static compare(entry1, entry2) {
+ if (entry1.lineNumber !== entry2.lineNumber)
+ return entry1.lineNumber - entry2.lineNumber;
+ return entry1.columnNumber - entry2.columnNumber;
+ }
+};
+
+/**
+ * @interface
+ */
+SDK.SourceMap = function() {};
+
+SDK.SourceMap.prototype = {
+ /**
+ * @return {string}
+ */
+ compiledURL() {},
+
+ /**
+ * @return {string}
+ */
+ url() {},
+
+ /**
+ * @return {!Array<string>}
+ */
+ sourceURLs() {},
+
+ /**
+ * @param {string} sourceURL
+ * @param {!Common.ResourceType} contentType
+ * @return {!Common.ContentProvider}
+ */
+ sourceContentProvider(sourceURL, contentType) {},
+
+ /**
+ * @param {string} sourceURL
+ * @return {?string}
+ */
+ embeddedContentByURL(sourceURL) {},
+
+ /**
+ * @param {number} lineNumber in compiled resource
+ * @param {number} columnNumber in compiled resource
+ * @return {?SDK.SourceMapEntry}
+ */
+ findEntry(lineNumber, columnNumber) {},
+
+ /**
+ * @return {boolean}
+ */
+ editable() {},
+
+ /**
+ * @param {!Array<!TextUtils.TextRange>} ranges
+ * @param {!Array<string>} texts
+ * @return {!Promise<?SDK.SourceMap.EditResult>}
+ */
+ editCompiled(ranges, texts) {},
+};
+
+/**
+ * @unrestricted
+ */
+SDK.SourceMap.EditResult = class {
+ /**
+ * @param {!SDK.SourceMap} map
+ * @param {!Array<!TextUtils.SourceEdit>} compiledEdits
+ * @param {!Map<string, string>} newSources
+ */
+ constructor(map, compiledEdits, newSources) {
+ this.map = map;
+ this.compiledEdits = compiledEdits;
+ this.newSources = newSources;
+ }
+};
+
+/**
+ * @interface
+ */
+SDK.SourceMapFactory = function() {};
+
+SDK.SourceMapFactory.prototype = {
+ /**
+ * @param {!SDK.Target} target
+ * @param {!SDK.SourceMap} sourceMap
+ * @return {!Promise<?SDK.SourceMap>}
+ */
+ editableSourceMap(target, sourceMap) {},
+};
+
+/**
+ * @implements {SDK.SourceMap}
+ * @unrestricted
+ */
+SDK.TextSourceMap = class {
+ /**
+ * Implements Source Map V3 model. See https://github.com/google/closure-compiler/wiki/Source-Maps
+ * for format description.
+ * @param {string} compiledURL
+ * @param {string} sourceMappingURL
+ * @param {!SDK.SourceMapV3} payload
+ */
+ constructor(compiledURL, sourceMappingURL, payload) {
+ if (!SDK.TextSourceMap._base64Map) {
+ const base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+ SDK.TextSourceMap._base64Map = {};
+ for (let i = 0; i < base64Digits.length; ++i)
+ SDK.TextSourceMap._base64Map[base64Digits.charAt(i)] = i;
+ }
+
+ this._json = payload;
+ this._compiledURL = compiledURL;
+ this._sourceMappingURL = sourceMappingURL;
+ this._baseURL = sourceMappingURL.startsWith('data:') ? compiledURL : sourceMappingURL;
+
+ /** @type {?Array<!SDK.SourceMapEntry>} */
+ this._mappings = null;
+ /** @type {!Map<string, !SDK.TextSourceMap.SourceInfo>} */
+ this._sourceInfos = new Map();
+ this._eachSection(this._parseSources.bind(this));
+ }
+
+ /**
+ * @param {string} sourceMapURL
+ * @param {string} compiledURL
+ * @return {!Promise<?SDK.TextSourceMap>}
+ * @this {SDK.TextSourceMap}
+ */
+ static load(sourceMapURL, compiledURL) {
+ let callback;
+ const promise = new Promise(fulfill => callback = fulfill);
+ SDK.multitargetNetworkManager.loadResource(sourceMapURL, contentLoaded);
+ return promise;
+
+ /**
+ * @param {number} statusCode
+ * @param {!Object.<string, string>} headers
+ * @param {string} content
+ */
+ function contentLoaded(statusCode, headers, content) {
+ if (!content || statusCode >= 400) {
+ callback(null);
+ return;
+ }
+
+ if (content.slice(0, 3) === ')]}')
+ content = content.substring(content.indexOf('\n'));
+ try {
+ const payload = /** @type {!SDK.SourceMapV3} */ (JSON.parse(content));
+ callback(new SDK.TextSourceMap(compiledURL, sourceMapURL, payload));
+ } catch (e) {
+ console.error(e);
+ Common.console.warn('DevTools failed to parse SourceMap: ' + sourceMapURL);
+ callback(null);
+ }
+ }
+ }
+
+ /**
+ * @override
+ * @return {string}
+ */
+ compiledURL() {
+ return this._compiledURL;
+ }
+
+ /**
+ * @override
+ * @return {string}
+ */
+ url() {
+ return this._sourceMappingURL;
+ }
+
+ /**
+ * @override
+ * @return {!Array.<string>}
+ */
+ sourceURLs() {
+ return this._sourceInfos.keysArray();
+ }
+
+ /**
+ * @override
+ * @param {string} sourceURL
+ * @param {!Common.ResourceType} contentType
+ * @return {!Common.ContentProvider}
+ */
+ sourceContentProvider(sourceURL, contentType) {
+ const info = this._sourceInfos.get(sourceURL);
+ if (info.content)
+ return Common.StaticContentProvider.fromString(sourceURL, contentType, info.content);
+ return new SDK.CompilerSourceMappingContentProvider(sourceURL, contentType);
+ }
+
+ /**
+ * @override
+ * @param {string} sourceURL
+ * @return {?string}
+ */
+ embeddedContentByURL(sourceURL) {
+ if (!this._sourceInfos.has(sourceURL))
+ return null;
+ return this._sourceInfos.get(sourceURL).content;
+ }
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ editable() {
+ return false;
+ }
+
+ /**
+ * @override
+ * @param {!Array<!TextUtils.TextRange>} ranges
+ * @param {!Array<string>} texts
+ * @return {!Promise<?SDK.SourceMap.EditResult>}
+ */
+ editCompiled(ranges, texts) {
+ return Promise.resolve(/** @type {?SDK.SourceMap.EditResult} */ (null));
+ }
+
+ /**
+ * @override
+ * @param {number} lineNumber in compiled resource
+ * @param {number} columnNumber in compiled resource
+ * @return {?SDK.SourceMapEntry}
+ */
+ findEntry(lineNumber, columnNumber) {
+ const mappings = this.mappings();
+ const index = mappings.upperBound(
+ undefined, (unused, entry) => lineNumber - entry.lineNumber || columnNumber - entry.columnNumber);
+ return index ? mappings[index - 1] : null;
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?SDK.SourceMapEntry}
+ */
+ sourceLineMapping(sourceURL, lineNumber, columnNumber) {
+ const mappings = this._reversedMappings(sourceURL);
+ const first = mappings.lowerBound(lineNumber, lineComparator);
+ const last = mappings.upperBound(lineNumber, lineComparator);
+ if (first >= mappings.length || mappings[first].sourceLineNumber !== lineNumber)
+ return null;
+ const columnMappings = mappings.slice(first, last);
+ const index =
+ columnMappings.lowerBound(columnNumber, (columnNumber, mapping) => columnNumber - mapping.sourceColumnNumber);
+ if (index >= columnMappings.length)
+ return null;
+ return columnMappings[index];
+
+ /**
+ * @param {number} lineNumber
+ * @param {!SDK.SourceMapEntry} mapping
+ * @return {number}
+ */
+ function lineComparator(lineNumber, mapping) {
+ return lineNumber - mapping.sourceLineNumber;
+ }
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {!Array<!SDK.SourceMapEntry>}
+ */
+ findReverseEntries(sourceURL, lineNumber, columnNumber) {
+ const mappings = this._reversedMappings(sourceURL);
+ const endIndex = mappings.upperBound(
+ undefined, (unused, entry) => lineNumber - entry.sourceLineNumber || columnNumber - entry.sourceColumnNumber);
+ let startIndex = endIndex;
+ while (startIndex > 0 && mappings[startIndex - 1].sourceLineNumber === mappings[endIndex - 1].sourceLineNumber &&
+ mappings[startIndex - 1].sourceColumnNumber === mappings[endIndex - 1].sourceColumnNumber)
+ --startIndex;
+
+ return mappings.slice(startIndex, endIndex);
+ }
+
+ /**
+ * @return {!Array<!SDK.SourceMapEntry>}
+ */
+ mappings() {
+ if (this._mappings === null) {
+ this._mappings = [];
+ this._eachSection(this._parseMap.bind(this));
+ this._json = null;
+ }
+ return /** @type {!Array<!SDK.SourceMapEntry>} */ (this._mappings);
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @return {!Array.<!SDK.SourceMapEntry>}
+ */
+ _reversedMappings(sourceURL) {
+ if (!this._sourceInfos.has(sourceURL))
+ return [];
+ const mappings = this.mappings();
+ const info = this._sourceInfos.get(sourceURL);
+ if (info.reverseMappings === null)
+ info.reverseMappings = mappings.filter(mapping => mapping.sourceURL === sourceURL).sort(sourceMappingComparator);
+
+ return info.reverseMappings;
+
+ /**
+ * @param {!SDK.SourceMapEntry} a
+ * @param {!SDK.SourceMapEntry} b
+ * @return {number}
+ */
+ function sourceMappingComparator(a, b) {
+ if (a.sourceLineNumber !== b.sourceLineNumber)
+ return a.sourceLineNumber - b.sourceLineNumber;
+ if (a.sourceColumnNumber !== b.sourceColumnNumber)
+ return a.sourceColumnNumber - b.sourceColumnNumber;
+
+ if (a.lineNumber !== b.lineNumber)
+ return a.lineNumber - b.lineNumber;
+
+ return a.columnNumber - b.columnNumber;
+ }
+ }
+
+ /**
+ * @param {function(!SDK.SourceMapV3, number, number)} callback
+ */
+ _eachSection(callback) {
+ if (!this._json.sections) {
+ callback(this._json, 0, 0);
+ return;
+ }
+ for (const section of this._json.sections)
+ callback(section.map, section.offset.line, section.offset.column);
+ }
+
+ /**
+ * @param {!SDK.SourceMapV3} sourceMap
+ */
+ _parseSources(sourceMap) {
+ const sourcesList = [];
+ let sourceRoot = sourceMap.sourceRoot || '';
+ if (sourceRoot && !sourceRoot.endsWith('/'))
+ sourceRoot += '/';
+ for (let i = 0; i < sourceMap.sources.length; ++i) {
+ const href = sourceRoot + sourceMap.sources[i];
+ let url = Common.ParsedURL.completeURL(this._baseURL, href) || href;
+ const source = sourceMap.sourcesContent && sourceMap.sourcesContent[i];
+ if (url === this._compiledURL && source)
+ url += Common.UIString('? [sm]');
+ this._sourceInfos.set(url, new SDK.TextSourceMap.SourceInfo(source, null));
+ sourcesList.push(url);
+ }
+ sourceMap[SDK.TextSourceMap._sourcesListSymbol] = sourcesList;
+ }
+
+ /**
+ * @param {!SDK.SourceMapV3} map
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ */
+ _parseMap(map, lineNumber, columnNumber) {
+ let sourceIndex = 0;
+ let sourceLineNumber = 0;
+ let sourceColumnNumber = 0;
+ let nameIndex = 0;
+ const sources = map[SDK.TextSourceMap._sourcesListSymbol];
+ const names = map.names || [];
+ const stringCharIterator = new SDK.TextSourceMap.StringCharIterator(map.mappings);
+ let 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 (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.peek())) {
+ this._mappings.push(new SDK.SourceMapEntry(lineNumber, columnNumber));
+ continue;
+ }
+
+ const sourceIndexDelta = this._decodeVLQ(stringCharIterator);
+ if (sourceIndexDelta) {
+ sourceIndex += sourceIndexDelta;
+ sourceURL = sources[sourceIndex];
+ }
+ sourceLineNumber += this._decodeVLQ(stringCharIterator);
+ sourceColumnNumber += this._decodeVLQ(stringCharIterator);
+
+ if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.peek())) {
+ this._mappings.push(
+ new SDK.SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber));
+ continue;
+ }
+
+ nameIndex += this._decodeVLQ(stringCharIterator);
+ this._mappings.push(new SDK.SourceMapEntry(
+ lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex]));
+ }
+
+ // As per spec, mappings are not necessarily sorted.
+ this._mappings.stableSort(SDK.SourceMapEntry.compare);
+ }
+
+ /**
+ * @param {string} char
+ * @return {boolean}
+ */
+ _isSeparator(char) {
+ return char === ',' || char === ';';
+ }
+
+ /**
+ * @param {!SDK.TextSourceMap.StringCharIterator} stringCharIterator
+ * @return {number}
+ */
+ _decodeVLQ(stringCharIterator) {
+ // Read unsigned value.
+ let result = 0;
+ let shift = 0;
+ let digit;
+ do {
+ digit = SDK.TextSourceMap._base64Map[stringCharIterator.next()];
+ result += (digit & SDK.TextSourceMap._VLQ_BASE_MASK) << shift;
+ shift += SDK.TextSourceMap._VLQ_BASE_SHIFT;
+ } while (digit & SDK.TextSourceMap._VLQ_CONTINUATION_MASK);
+
+ // Fix the sign.
+ const negative = result & 1;
+ result >>= 1;
+ return negative ? -result : result;
+ }
+
+ /**
+ * @param {string} url
+ * @param {!TextUtils.TextRange} textRange
+ * @return {!TextUtils.TextRange}
+ */
+ reverseMapTextRange(url, textRange) {
+ /**
+ * @param {!{lineNumber: number, columnNumber: number}} position
+ * @param {!SDK.SourceMapEntry} mapping
+ * @return {number}
+ */
+ function comparator(position, mapping) {
+ if (position.lineNumber !== mapping.sourceLineNumber)
+ return position.lineNumber - mapping.sourceLineNumber;
+
+ return position.columnNumber - mapping.sourceColumnNumber;
+ }
+
+ const mappings = this._reversedMappings(url);
+ const startIndex =
+ mappings.lowerBound({lineNumber: textRange.startLine, columnNumber: textRange.startColumn}, comparator);
+ const endIndex =
+ mappings.upperBound({lineNumber: textRange.endLine, columnNumber: textRange.endColumn}, comparator);
+
+ const startMapping = mappings[startIndex];
+ const endMapping = mappings[endIndex];
+ return new TextUtils.TextRange(
+ startMapping.lineNumber, startMapping.columnNumber, endMapping.lineNumber, endMapping.columnNumber);
+ }
+};
+
+SDK.TextSourceMap._VLQ_BASE_SHIFT = 5;
+SDK.TextSourceMap._VLQ_BASE_MASK = (1 << 5) - 1;
+SDK.TextSourceMap._VLQ_CONTINUATION_MASK = 1 << 5;
+
+
+/**
+ * @unrestricted
+ */
+SDK.TextSourceMap.StringCharIterator = class {
+ /**
+ * @param {string} string
+ */
+ constructor(string) {
+ this._string = string;
+ this._position = 0;
+ }
+
+ /**
+ * @return {string}
+ */
+ next() {
+ return this._string.charAt(this._position++);
+ }
+
+ /**
+ * @return {string}
+ */
+ peek() {
+ return this._string.charAt(this._position);
+ }
+
+ /**
+ * @return {boolean}
+ */
+ hasNext() {
+ return this._position < this._string.length;
+ }
+};
+
+/**
+ * @unrestricted
+ */
+SDK.TextSourceMap.SourceInfo = class {
+ /**
+ * @param {?string} content
+ * @param {?Array<!SDK.SourceMapEntry>} reverseMappings
+ */
+ constructor(content, reverseMappings) {
+ this.content = content;
+ this.reverseMappings = reverseMappings;
+ }
+};
+
+SDK.TextSourceMap._sourcesListSymbol = Symbol('sourcesList');