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

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

Issue 1770263002: Devtools: resolve expressions in minified scripts with sourcemaps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 4 years, 9 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
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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("cache"); 8 WebInspector.SourceMapNamesResolver._cachedPromiseSymbol = Symbol("cachePromise" );
9 9
10 /** 10 /**
11 * @param {!WebInspector.DebuggerModel.Scope} scope 11 * @param {!WebInspector.DebuggerModel.Scope} scope
12 * @return {!Promise.<!Map<string, string>>} 12 * @return {!Promise.<!Map<string, string>>}
13 */ 13 */
14 WebInspector.SourceMapNamesResolver._resolveScope = function(scope) 14 WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
15 { 15 {
16 var cachedMap = scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol]; 16 var cachedMap = scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol];
17 if (cachedMap) 17 if (cachedMap)
18 return Promise.resolve(cachedMap); 18 return Promise.resolve(cachedMap);
19 19
20 var cachedPromise = scope[WebInspector.SourceMapNamesResolver._cachedPromise Symbol]; 20 var cachedPromise = scope[WebInspector.SourceMapNamesResolver._cachedPromise Symbol];
21 if (cachedPromise) 21 if (cachedPromise)
22 return cachedPromise; 22 return cachedPromise;
23 23
24 var startLocation = scope.startLocation(); 24 var startLocation = scope.startLocation();
25 var endLocation = scope.endLocation(); 25 var endLocation = scope.endLocation();
26 var script = startLocation.script();
27 26
28 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en dLocation || !script.sourceMapURL || script !== endLocation.script()) 27 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en dLocation || !startLocation.script().sourceMapURL || (startLocation.script() !== endLocation.script()))
29 return Promise.resolve(new Map()); 28 return Promise.resolve(new Map());
30 29
30 var script = startLocation.script();
31 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr ipt); 31 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr ipt);
32 if (!sourceMap) 32 if (!sourceMap)
33 return Promise.resolve(new Map()); 33 return Promise.resolve(new Map());
34 34
35 var promise = script.requestContent().then(onContent); 35 var promise = script.requestContent().then(onContent);
36 scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise; 36 scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise;
37 return promise; 37 return promise;
38 38
39 /** 39 /**
40 * @param {?string} content 40 * @param {?string} content
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 namesMapping.set(id.name, entry.name); 110 namesMapping.set(id.name, entry.name);
111 } 111 }
112 112
113 scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMappi ng; 113 scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMappi ng;
114 delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; 114 delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol];
115 return namesMapping; 115 return namesMapping;
116 } 116 }
117 } 117 }
118 118
119 /** 119 /**
120 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
121 * @return {!Promise.<!Map<string, string>>}
122 */
123 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram e)
124 {
125 var cached = callFrame[WebInspector.SourceMapNamesResolver._cachedMapSymbol] ;
126 if (cached)
127 return Promise.resolve(cached);
128
129 var promises = [];
130 var scopeChain = callFrame.scopeChain();
131 for (var i = 0; i < scopeChain.length; ++i)
132 promises.push(WebInspector.SourceMapNamesResolver._resolveScope(scopeCha in[i]));
133
134 return Promise.all(promises).then(mergeVariables);
135
136 /**
137 * @param {!Array<!Map<string, string>>} nameMappings
138 * @return {!Map<string, string>}
139 */
140 function mergeVariables(nameMappings)
141 {
142 var reverseMapping = new Map();
143 for (var map of nameMappings) {
144 for (var compiledName of map.keys()) {
145 var originalName = map.get(compiledName);
146 if (!reverseMapping.has(originalName))
147 reverseMapping.set(originalName, compiledName);
148 }
149 }
150 callFrame[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = revers eMapping;
151 return reverseMapping;
152 }
153 }
154
155 /**
156 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
157 * @param {string} originalText
158 * @param {!WebInspector.UISourceCode} uiSourceCode
159 * @param {number} lineNumber
160 * @param {number} startColumnNumber
161 * @param {number} endColumnNumber
162 * @return {!Promise<string>}
163 */
164 WebInspector.SourceMapNamesResolver.resolveExpression = function(callFrame, orig inalText, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber)
165 {
166 if (!Runtime.experiments.isEnabled("resolveVariableNames"))
167 return Promise.resolve("");
168
169 return WebInspector.SourceMapNamesResolver._allVariablesInCallFrame(callFram e).then(findCompiledName);
170
171 /**
172 * @param {!Map<string, string>} reverseMapping
173 * @return {!Promise<string>}
174 */
175 function findCompiledName(reverseMapping)
176 {
177 if (reverseMapping.has(originalText))
178 return Promise.resolve(reverseMapping.get(originalText) || "");
179
180 return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber)
181 }
182 }
183
184 /**
185 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
186 * @param {!WebInspector.UISourceCode} uiSourceCode
187 * @param {number} lineNumber
188 * @param {number} startColumnNumber
189 * @param {number} endColumnNumber
190 * @return {!Promise<string>}
191 */
192 WebInspector.SourceMapNamesResolver._resolveExpression = function(callFrame, uiS ourceCode, lineNumber, startColumnNumber, endColumnNumber)
193 {
194 var target = callFrame.target();
195 var rawLocation = WebInspector.debuggerWorkspaceBinding.uiLocationToRawLocat ion(target, uiSourceCode, lineNumber, startColumnNumber);
196 if (!rawLocation)
197 return Promise.resolve("");
198
199 var script = rawLocation.script();
200 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr ipt);
201 if (!sourceMap)
202 return Promise.resolve("");
203
204 return script.requestContent().then(onContent);
205
206 /**
207 * @param {?string} content
208 * @return {string}
209 */
210 function onContent(content)
211 {
212 if (!content)
213 return "";
214
215 var textRange = sourceMap.reverseMapTextRange(uiSourceCode.url(), new We bInspector.TextRange(lineNumber, startColumnNumber, lineNumber, endColumnNumber) );
216 var originalText = textRange.extract(content);
217 if (!originalText)
218 return "";
219
220 var tokenizer = acorn.tokenizer(originalText, {ecmaVersion: 6});
221 try {
222 var token = tokenizer.getToken();
223 while (token.type !== acorn.tokTypes.eof && WebInspector.AcornTokeni zer.punctuator(token))
224 token = tokenizer.getToken();
225
226 var startIndex = token.start;
227 var endIndex = token.end;
228 var openBracketsCounter = 0;
229 while (token.type !== acorn.tokTypes.eof) {
230 var isIdentifier = WebInspector.AcornTokenizer.identifier(token) ;
231 var isThis = WebInspector.AcornTokenizer.keyword(token, "this");
232 var isString = token.type === acorn.tokTypes.string;
233 if (!isThis && !isIdentifier && !isString)
234 break;
235
236 endIndex = token.end;
237 token = tokenizer.getToken();
238 while (WebInspector.AcornTokenizer.punctuator(token, ".[]")) {
239 if (WebInspector.AcornTokenizer.punctuator(token, "["))
240 openBracketsCounter++;
241
242 if (WebInspector.AcornTokenizer.punctuator(token, "]")) {
243 endIndex = openBracketsCounter > 0 ? token.end : endInde x;
244 openBracketsCounter--;
245 }
246
247 token = tokenizer.getToken();
248 }
249 }
250 return originalText.substring(startIndex, endIndex);
251 } catch (e) {
252 return "";
253 }
254 }
255 }
256
257 /**
120 * @param {!WebInspector.DebuggerModel.Scope} scope 258 * @param {!WebInspector.DebuggerModel.Scope} scope
121 * @return {!WebInspector.RemoteObject} 259 * @return {!WebInspector.RemoteObject}
122 */ 260 */
123 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope) 261 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope)
124 { 262 {
125 if (!Runtime.experiments.isEnabled("resolveVariableNames")) 263 if (!Runtime.experiments.isEnabled("resolveVariableNames"))
126 return scope.object(); 264 return scope.object();
127 265
128 var startLocation = scope.startLocation(); 266 var startLocation = scope.startLocation();
129 var endLocation = scope.endLocation(); 267 var endLocation = scope.endLocation();
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 * @override 510 * @override
373 * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback 511 * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback
374 */ 512 */
375 collectionEntries: function(callback) 513 collectionEntries: function(callback)
376 { 514 {
377 this._object.collectionEntries(callback); 515 this._object.collectionEntries(callback);
378 }, 516 },
379 517
380 __proto__: WebInspector.RemoteObject.prototype 518 __proto__: WebInspector.RemoteObject.prototype
381 } 519 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698