OLD | NEW |
---|---|
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 Loading... | |
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 /** | |
205 * @param {!{lineNumber: number, columnNumber: number}} position | |
206 * @param {!WebInspector.SourceMap.Entry} mapping | |
207 * @return {number} | |
208 */ | |
209 function comparator(position, mapping) | |
210 { | |
211 if (position.lineNumber !== mapping.sourceLineNumber) | |
212 return position.lineNumber - mapping.sourceLineNumber; | |
213 | |
214 return position.columnNumber - mapping.sourceColumnNumber; | |
215 } | |
216 | |
217 var mappings = sourceMap.reversedMappings(uiSourceCode.url()); | |
218 var startIndex = mappings.lowerBound({lineNumber: lineNumber, columnNumber: startColumnNumber}, comparator); | |
dgozman
2016/03/08 18:26:42
Let's move this to SourceMap.reverseMapTextRange.
sergeyv
2016/03/08 22:53:04
Done.
| |
219 var endIndex = mappings.upperBound({lineNumber: lineNumber, columnNumber: en dColumnNumber}, comparator); | |
220 | |
221 var startMapping = mappings[startIndex]; | |
222 var endMapping = mappings[endIndex]; | |
223 | |
224 if (startMapping === endMapping) | |
225 return Promise.resolve(""); | |
226 | |
227 return script.requestContent().then(onContent); | |
228 | |
229 /** | |
230 * @param {?string} content | |
231 * @return {string} | |
232 */ | |
233 function onContent(content) | |
234 { | |
235 if (!content) | |
236 return ""; | |
237 | |
238 var textRange = new WebInspector.TextRange(startMapping.lineNumber, star tMapping.columnNumber, endMapping.lineNumber, endMapping.columnNumber); | |
239 var originalText = textRange.extract(content); | |
240 var tokenizer = acorn.tokenizer(originalText, {ecmaVersion: 6}); | |
241 try { | |
242 var token = tokenizer.getToken(); | |
243 while (token.type !== acorn.tokTypes.eof && WebInspector.AcornTokeni zer.punctuator(token)) | |
244 token = tokenizer.getToken(); | |
245 | |
246 var startIndex = token.start; | |
247 var endIndex = token.end; | |
248 while (token.type !== acorn.tokTypes.eof) { | |
249 var isIdentifier = WebInspector.AcornTokenizer.identifier(token) ; | |
250 var isThis = WebInspector.AcornTokenizer.keyword(token, "this"); | |
251 var isString = token.type === acorn.tokTypes.string; | |
252 if (!isThis && !isIdentifier && !isString) | |
253 break; | |
254 | |
255 endIndex = token.end; | |
256 token = tokenizer.getToken(); | |
257 while (WebInspector.AcornTokenizer.punctuator(token, ".[]")) { | |
258 if (WebInspector.AcornTokenizer.punctuator(token, "]")) | |
259 endIndex = token.end; | |
dgozman
2016/03/08 18:26:42
Let's not do this if current balance of [] is zero
sergeyv
2016/03/08 22:53:04
Done.
| |
260 | |
261 token = tokenizer.getToken(); | |
262 } | |
263 } | |
264 return originalText.substring(startIndex, endIndex); | |
265 } catch (e) { | |
266 return ""; | |
267 } | |
268 } | |
269 } | |
270 | |
271 /** | |
120 * @param {!WebInspector.DebuggerModel.Scope} scope | 272 * @param {!WebInspector.DebuggerModel.Scope} scope |
121 * @return {!WebInspector.RemoteObject} | 273 * @return {!WebInspector.RemoteObject} |
122 */ | 274 */ |
123 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope) | 275 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope) |
124 { | 276 { |
125 if (!Runtime.experiments.isEnabled("resolveVariableNames")) | 277 if (!Runtime.experiments.isEnabled("resolveVariableNames")) |
126 return scope.object(); | 278 return scope.object(); |
127 | 279 |
128 var startLocation = scope.startLocation(); | 280 var startLocation = scope.startLocation(); |
129 var endLocation = scope.endLocation(); | 281 var endLocation = scope.endLocation(); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 * @override | 524 * @override |
373 * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback | 525 * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback |
374 */ | 526 */ |
375 collectionEntries: function(callback) | 527 collectionEntries: function(callback) |
376 { | 528 { |
377 this._object.collectionEntries(callback); | 529 this._object.collectionEntries(callback); |
378 }, | 530 }, |
379 | 531 |
380 __proto__: WebInspector.RemoteObject.prototype | 532 __proto__: WebInspector.RemoteObject.prototype |
381 } | 533 } |
OLD | NEW |