| Index: third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| index 5449ee591c729826df8c31ed855bf6eb613141e9..3eca7c8aecee812240d91218459c44a42f44cd1f 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
|
| @@ -5,53 +5,49 @@
|
| WebInspector.SourceMapNamesResolver = {};
|
|
|
| WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache");
|
| -WebInspector.SourceMapNamesResolver._cachedPromiseSymbol = Symbol("cachePromise");
|
| +WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol = Symbol("cachedIdentifiers");
|
|
|
| /**
|
| - * @param {!WebInspector.DebuggerModel.Scope} scope
|
| - * @return {!Promise.<!Map<string, string>>}
|
| + * @constructor
|
| + * @param {string} name
|
| + * @param {number} lineNumber
|
| + * @param {number} columnNumber
|
| */
|
| -WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
|
| +WebInspector.SourceMapNamesResolver.Identifier = function(name, lineNumber, columnNumber)
|
| {
|
| - var cachedMap = scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol];
|
| - if (cachedMap)
|
| - return Promise.resolve(cachedMap);
|
| -
|
| - var cachedPromise = scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol];
|
| - if (cachedPromise)
|
| - return cachedPromise;
|
| + this.name = name;
|
| + this.lineNumber = lineNumber;
|
| + this.columnNumber = columnNumber;
|
| +}
|
|
|
| +/**
|
| + * @param {!WebInspector.DebuggerModel.Scope} scope
|
| + * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>>}
|
| + */
|
| +WebInspector.SourceMapNamesResolver._scopeIdentifiers = function(scope)
|
| +{
|
| var startLocation = scope.startLocation();
|
| var endLocation = scope.endLocation();
|
|
|
| if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !endLocation || !startLocation.script().sourceMapURL || (startLocation.script() !== endLocation.script()))
|
| - return Promise.resolve(new Map());
|
| + return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapNamesResolver.Identifier>}*/([]));
|
|
|
| var script = startLocation.script();
|
| - var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(script);
|
| - if (!sourceMap)
|
| - return Promise.resolve(new Map());
|
| -
|
| - var promise = script.requestContent().then(onContent);
|
| - scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise;
|
| - return promise;
|
| + return script.requestContent().then(onContent);
|
|
|
| /**
|
| * @param {?string} content
|
| - * @return {!Promise<!Map<string, string>>}
|
| + * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>>}
|
| */
|
| function onContent(content)
|
| {
|
| if (!content)
|
| - return Promise.resolve(new Map());
|
| -
|
| - var startLocation = scope.startLocation();
|
| - var endLocation = scope.endLocation();
|
| - var textRange = new WebInspector.TextRange(startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber);
|
| + return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapNamesResolver.Identifier>}*/([]));
|
|
|
| var text = new WebInspector.Text(content);
|
| - var scopeText = text.extract(textRange);
|
| - var scopeStart = text.toSourceRange(textRange).offset;
|
| + var scopeRange = new WebInspector.TextRange(startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber)
|
| + var scopeText = text.extract(scopeRange);
|
| + var scopeStart = text.toSourceRange(scopeRange).offset;
|
| var prefix = "function fui";
|
|
|
| return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptIdentifiers(prefix + scopeText)
|
| @@ -63,28 +59,124 @@ WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
|
| * @param {number} scopeStart
|
| * @param {string} prefix
|
| * @param {!Array<!{name: string, offset: number}>} identifiers
|
| - * @return {!Map<string, string>}
|
| + * @return {!Array<!WebInspector.SourceMapNamesResolver.Identifier>}
|
| */
|
| function onIdentifiers(text, scopeStart, prefix, identifiers)
|
| {
|
| - var namesMapping = new Map();
|
| - var lineEndings = text.lineEndings();
|
| -
|
| + var result = [];
|
| + var cursor = new WebInspector.TextCursor(text.lineEndings());
|
| + var promises = [];
|
| for (var i = 0; i < identifiers.length; ++i) {
|
| var id = identifiers[i];
|
| + if (id.offset < prefix.length)
|
| + continue;
|
| var start = scopeStart + id.offset - prefix.length;
|
| + cursor.resetTo(start);
|
| + result.push(new WebInspector.SourceMapNamesResolver.Identifier(id.name, cursor.lineNumber(), cursor.columnNumber()));
|
| + }
|
| + return result;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * @param {!WebInspector.DebuggerModel.Scope} scope
|
| + * @return {!Promise.<!Map<string, string>>}
|
| + */
|
| +WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
|
| +{
|
| + var identifiersPromise = scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol];
|
| + if (identifiersPromise)
|
| + return identifiersPromise;
|
| +
|
| + var script = scope.callFrame().script;
|
| + var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(script);
|
| + if (!sourceMap)
|
| + return Promise.resolve(new Map());
|
|
|
| - var lineNumber = lineEndings.lowerBound(start);
|
| - var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[lineNumber - 1] + 1));
|
| - var entry = sourceMap.findEntry(lineNumber, columnNumber);
|
| - if (entry)
|
| + /** @type {!Map<string, !WebInspector.Text>} */
|
| + var textCache = new Map();
|
| + identifiersPromise = WebInspector.SourceMapNamesResolver._scopeIdentifiers(scope).then(onIdentifiers);
|
| + scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol] = identifiersPromise;
|
| + return identifiersPromise;
|
| +
|
| + /**
|
| + * @param {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} identifiers
|
| + * @return {!Promise<!Map<string, string>>}
|
| + */
|
| + function onIdentifiers(identifiers)
|
| + {
|
| + var namesMapping = new Map();
|
| + // Extract as much as possible from SourceMap.
|
| + for (var i = 0; i < identifiers.length; ++i) {
|
| + var id = identifiers[i];
|
| + var entry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
|
| + if (entry && entry.name)
|
| namesMapping.set(id.name, entry.name);
|
| }
|
|
|
| - scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMapping;
|
| - delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol];
|
| - WebInspector.SourceMapNamesResolver._scopeResolvedForTest();
|
| - return namesMapping;
|
| + // Resolve missing identifier names from sourcemap ranges.
|
| + var promises = [];
|
| + for (var i = 0; i < identifiers.length; ++i) {
|
| + var id = identifiers[i];
|
| + if (namesMapping.has(id.name))
|
| + continue;
|
| + var promise = resolveSourceName(id).then(onSourceNameResolved.bind(null, namesMapping, id));
|
| + promises.push(promise);
|
| + }
|
| + return Promise.all(promises)
|
| + .then(() => WebInspector.SourceMapNamesResolver._scopeResolvedForTest())
|
| + .then(() => namesMapping)
|
| + }
|
| +
|
| + /**
|
| + * @param {!Map<string, string>} namesMapping
|
| + * @param {!WebInspector.SourceMapNamesResolver.Identifier} id
|
| + * @param {?string} sourceName
|
| + */
|
| + function onSourceNameResolved(namesMapping, id, sourceName)
|
| + {
|
| + if (!sourceName)
|
| + return;
|
| + namesMapping.set(id.name, sourceName);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.SourceMapNamesResolver.Identifier} id
|
| + * @return {!Promise<?string>}
|
| + */
|
| + function resolveSourceName(id)
|
| + {
|
| + var startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
|
| + var endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.name.length);
|
| + if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sourceURL !== endEntry.sourceURL
|
| + || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber
|
| + || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber)
|
| + return Promise.resolve(/** @type {?string} */(null));
|
| + var sourceTextRange = new WebInspector.TextRange(startEntry.sourceLineNumber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber, endEntry.sourceColumnNumber);
|
| + var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForScriptURL(startEntry.sourceURL, script);
|
| + if (!uiSourceCode)
|
| + return Promise.resolve(/** @type {?string} */(null));
|
| +
|
| + return uiSourceCode.requestContent()
|
| + .then(onSourceContent.bind(null, sourceTextRange));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.TextRange} sourceTextRange
|
| + * @param {?string} content
|
| + * @return {?string}
|
| + */
|
| + function onSourceContent(sourceTextRange, content)
|
| + {
|
| + if (!content)
|
| + return null;
|
| + var text = textCache.get(content);
|
| + if (!text) {
|
| + text = new WebInspector.Text(content);
|
| + textCache.set(content, text);
|
| + }
|
| + var originalIdentifier = text.extract(sourceTextRange).trim();
|
| + return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier : null;
|
| }
|
| }
|
|
|
| @@ -151,7 +243,7 @@ WebInspector.SourceMapNamesResolver.resolveExpression = function(callFrame, orig
|
| if (reverseMapping.has(originalText))
|
| return Promise.resolve(reverseMapping.get(originalText) || "");
|
|
|
| - return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber)
|
| + return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber);
|
| }
|
| }
|
|
|
|
|