Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1047)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js

Issue 1887913002: DevTools: improve identifier extraction in SourceMapNamesResolver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 WebInspector.SourceMapNamesResolver = {}; 5 WebInspector.SourceMapNamesResolver = {};
6 6
7 WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache"); 7 WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache");
8 WebInspector.SourceMapNamesResolver._cachedPromiseSymbol = Symbol("cachePromise" ); 8 WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol = Symbol("cachedIde ntifiers");
9
10 /**
11 * @constructor
12 * @param {string} name
13 * @param {number} lineNumber
14 * @param {number} columnNumber
15 */
16 WebInspector.SourceMapNamesResolver.Identifier = function(name, lineNumber, colu mnNumber)
17 {
18 this.name = name;
19 this.lineNumber = lineNumber;
20 this.columnNumber = columnNumber;
21 }
9 22
10 /** 23 /**
11 * @param {!WebInspector.DebuggerModel.Scope} scope 24 * @param {!WebInspector.DebuggerModel.Scope} scope
12 * @return {!Promise.<!Map<string, string>>} 25 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>>}
13 */ 26 */
14 WebInspector.SourceMapNamesResolver._resolveScope = function(scope) 27 WebInspector.SourceMapNamesResolver._scopeIdentifiers = function(scope)
15 { 28 {
16 var cachedMap = scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol];
17 if (cachedMap)
18 return Promise.resolve(cachedMap);
19
20 var cachedPromise = scope[WebInspector.SourceMapNamesResolver._cachedPromise Symbol];
21 if (cachedPromise)
22 return cachedPromise;
23
24 var startLocation = scope.startLocation(); 29 var startLocation = scope.startLocation();
25 var endLocation = scope.endLocation(); 30 var endLocation = scope.endLocation();
26 31
27 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en dLocation || !startLocation.script().sourceMapURL || (startLocation.script() !== endLocation.script())) 32 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en dLocation || !startLocation.script().sourceMapURL || (startLocation.script() !== endLocation.script()))
28 return Promise.resolve(new Map()); 33 return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapNamesRes olver.Identifier>}*/([]));
29 34
30 var script = startLocation.script(); 35 var script = startLocation.script();
31 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr ipt);
32 if (!sourceMap)
33 return Promise.resolve(new Map());
34
35 var promise = script.requestContent().then(onContent); 36 var promise = script.requestContent().then(onContent);
dgozman 2016/04/14 19:15:37 return it
lushnikov 2016/04/15 00:16:01 Done.
36 scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise;
37 return promise; 37 return promise;
38 38
39 /** 39 /**
40 * @param {?string} content 40 * @param {?string} content
41 * @return {!Promise<!Map<string, string>>} 41 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier> >}
42 */ 42 */
43 function onContent(content) 43 function onContent(content)
44 { 44 {
45 if (!content) 45 if (!content)
46 return Promise.resolve(new Map()); 46 return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapName sResolver.Identifier>}*/([]));
47
48 var startLocation = scope.startLocation();
49 var endLocation = scope.endLocation();
50 var textRange = new WebInspector.TextRange(startLocation.lineNumber, sta rtLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber);
51 47
52 var text = new WebInspector.Text(content); 48 var text = new WebInspector.Text(content);
53 var scopeText = text.extract(textRange); 49 var scopeRange = new WebInspector.TextRange(startLocation.lineNumber, st artLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber)
54 var scopeStart = text.toSourceRange(textRange).offset; 50 var scopeText = text.extract(scopeRange);
51 var scopeStart = text.toSourceRange(scopeRange).offset;
55 var prefix = "function fui"; 52 var prefix = "function fui";
56 53
57 return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptI dentifiers(prefix + scopeText) 54 return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptI dentifiers(prefix + scopeText)
58 .then(onIdentifiers.bind(null, text, scopeStart, prefix)); 55 .then(onIdentifiers.bind(null, text, scopeStart, prefix));
59 } 56 }
60 57
61 /** 58 /**
62 * @param {!WebInspector.Text} text 59 * @param {!WebInspector.Text} text
63 * @param {number} scopeStart 60 * @param {number} scopeStart
64 * @param {string} prefix 61 * @param {string} prefix
65 * @param {!Array<!{name: string, offset: number}>} identifiers 62 * @param {!Array<!{name: string, offset: number}>} identifiers
66 * @return {!Map<string, string>} 63 * @return {!Array<!WebInspector.SourceMapNamesResolver.Identifier>}
67 */ 64 */
68 function onIdentifiers(text, scopeStart, prefix, identifiers) 65 function onIdentifiers(text, scopeStart, prefix, identifiers)
69 { 66 {
70 var namesMapping = new Map(); 67 var result = [];
71 var lineEndings = text.lineEndings(); 68 var cursor = new WebInspector.TextCursor(text.lineEndings());
72 69 var promises = [];
73 for (var i = 0; i < identifiers.length; ++i) { 70 for (var i = 0; i < identifiers.length; ++i) {
74 var id = identifiers[i]; 71 var id = identifiers[i];
72 if (id.offset < prefix.length)
73 continue;
75 var start = scopeStart + id.offset - prefix.length; 74 var start = scopeStart + id.offset - prefix.length;
75 cursor.setOffset(start);
76 result.push(new WebInspector.SourceMapNamesResolver.Identifier(id.na me, cursor.lineNumber(), cursor.columnNumber()));
77 }
78 return result;
79 }
80 }
76 81
77 var lineNumber = lineEndings.lowerBound(start); 82 /**
78 var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[line Number - 1] + 1)); 83 * @param {!WebInspector.DebuggerModel.Scope} scope
79 var entry = sourceMap.findEntry(lineNumber, columnNumber); 84 * @return {!Promise.<!Map<string, string>>}
80 if (entry) 85 */
86 WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
87 {
88 var identifiersPromise = scope[WebInspector.SourceMapNamesResolver._cachedId entifiersSymbol];
89 if (identifiersPromise)
90 return identifiersPromise;
91
92 var script = scope.callFrame().script;
93 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr ipt);
94 if (!sourceMap)
95 return Promise.resolve(new Map());
96
97 /** @type {!Map<!WebInspector.UISourceCode, !WebInspector.Text>} */
98 var textCache = new Map();
99 identifiersPromise = WebInspector.SourceMapNamesResolver._scopeIdentifiers(s cope).then(onIdentifiers);
100 scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol] = identi fiersPromise;
101 return identifiersPromise;
102
103 /**
104 * @param {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} identifi ers
105 * @return {!Promise<!Map<string, string>>}
106 */
107 function onIdentifiers(identifiers)
108 {
109 var namesMapping = new Map();
110 // Extract as much as possible from SourceMap.
111 for (var i = 0; i < identifiers.length; ++i) {
112 var id = identifiers[i];
113 var entry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
114 if (entry && entry.name)
81 namesMapping.set(id.name, entry.name); 115 namesMapping.set(id.name, entry.name);
82 } 116 }
83 117
84 scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMappi ng; 118 // Resolve missing identifier names from sourcemap ranges.
85 delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; 119 var promises = [];
86 WebInspector.SourceMapNamesResolver._scopeResolvedForTest(); 120 for (var i = 0; i < identifiers.length; ++i) {
87 return namesMapping; 121 var id = identifiers[i];
122 if (namesMapping.has(id.name))
123 continue;
124 var promise = resolveSourceName(id).then(onSourceNameResolved.bind(n ull, namesMapping, id));
125 promises.push(promise);
126 }
127 return Promise.all(promises)
128 .then(() => WebInspector.SourceMapNamesResolver._scopeResolvedForTes t())
129 .then(() => namesMapping)
130 }
131
132 /**
133 * @param {!Map<string, string>} namesMapping
134 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id
135 * @param {?string} sourceName
136 */
137 function onSourceNameResolved(namesMapping, id, sourceName)
138 {
139 if (!sourceName)
140 return;
141 namesMapping.set(id.name, sourceName);
142 }
143
144 /**
145 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id
146 * @return {!Promise<?string>}
147 */
148 function resolveSourceName(id)
149 {
150 var startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
151 var endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.n ame.length);
152 if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sour ceURL !== endEntry.sourceURL
153 || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber
154 || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber)
155 return Promise.resolve(/** @type {?string} */(null));
156 var sourceTextRange = new WebInspector.TextRange(startEntry.sourceLineNu mber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber, endEntry.sourceC olumnNumber);
157 var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForScriptURL( startEntry.sourceURL, script);
158 if (!uiSourceCode)
159 return Promise.resolve(/** @type {?string} */(null));
160
161 var text = textCache.get(uiSourceCode);
dgozman 2016/04/14 19:15:37 Make it per-content instead of per-uisourcecode.
lushnikov 2016/04/15 00:16:01 Done.
162 if (text)
163 return Promise.resolve(onSourceText(sourceTextRange, text));
164
165 return uiSourceCode.requestContent()
166 .then(onSourceContent.bind(null, uiSourceCode))
167 .then(onSourceText.bind(null, sourceTextRange));
168 }
169
170 /**
171 * @param {!WebInspector.UISourceCode} uiSourceCode
172 * @param {?string} content
173 * @return {?WebInspector.Text}
174 */
175 function onSourceContent(uiSourceCode, content)
176 {
177 if (!content)
178 return null;
179 var text = new WebInspector.Text(content);
180 textCache.set(uiSourceCode, text);
181 return text;
182 }
183
184 /**
185 * @param {!WebInspector.TextRange} sourceTextRange
186 * @param {?WebInspector.Text} text
187 */
188 function onSourceText(sourceTextRange, text)
189 {
190 if (!text)
191 return null;
192 var originalIdentifier = text.extract(sourceTextRange).trim();
193 return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier : null;
88 } 194 }
89 } 195 }
90 196
91 WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() { } 197 WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() { }
92 198
93 /** 199 /**
94 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame 200 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
95 * @return {!Promise.<!Map<string, string>>} 201 * @return {!Promise.<!Map<string, string>>}
96 */ 202 */
97 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram e) 203 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram e)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 250
145 /** 251 /**
146 * @param {!Map<string, string>} reverseMapping 252 * @param {!Map<string, string>} reverseMapping
147 * @return {!Promise<string>} 253 * @return {!Promise<string>}
148 */ 254 */
149 function findCompiledName(reverseMapping) 255 function findCompiledName(reverseMapping)
150 { 256 {
151 if (reverseMapping.has(originalText)) 257 if (reverseMapping.has(originalText))
152 return Promise.resolve(reverseMapping.get(originalText) || ""); 258 return Promise.resolve(reverseMapping.get(originalText) || "");
153 259
154 return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber) 260 return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber);
155 } 261 }
156 } 262 }
157 263
158 /** 264 /**
159 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame 265 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
160 * @param {!WebInspector.UISourceCode} uiSourceCode 266 * @param {!WebInspector.UISourceCode} uiSourceCode
161 * @param {number} lineNumber 267 * @param {number} lineNumber
162 * @param {number} startColumnNumber 268 * @param {number} startColumnNumber
163 * @param {number} endColumnNumber 269 * @param {number} endColumnNumber
164 * @return {!Promise<string>} 270 * @return {!Promise<string>}
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 653
548 /** 654 /**
549 * @return {!WebInspector.SourceMapNamesResolverWorker} 655 * @return {!WebInspector.SourceMapNamesResolverWorker}
550 */ 656 */
551 WebInspector.SourceMapNamesResolverWorker._instance = function() 657 WebInspector.SourceMapNamesResolverWorker._instance = function()
552 { 658 {
553 if (!WebInspector.SourceMapNamesResolverWorker._instanceObject) 659 if (!WebInspector.SourceMapNamesResolverWorker._instanceObject)
554 WebInspector.SourceMapNamesResolverWorker._instanceObject = new WebInspe ctor.SourceMapNamesResolverWorker(); 660 WebInspector.SourceMapNamesResolverWorker._instanceObject = new WebInspe ctor.SourceMapNamesResolverWorker();
555 return WebInspector.SourceMapNamesResolverWorker._instanceObject; 661 return WebInspector.SourceMapNamesResolverWorker._instanceObject;
556 } 662 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698