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

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: address comments 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
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.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("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); 36 return script.requestContent().then(onContent);
32 if (!sourceMap)
33 return Promise.resolve(new Map());
34
35 var promise = script.requestContent().then(onContent);
36 scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise;
37 return promise;
38 37
39 /** 38 /**
40 * @param {?string} content 39 * @param {?string} content
41 * @return {!Promise<!Map<string, string>>} 40 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier> >}
42 */ 41 */
43 function onContent(content) 42 function onContent(content)
44 { 43 {
45 if (!content) 44 if (!content)
46 return Promise.resolve(new Map()); 45 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 46
52 var text = new WebInspector.Text(content); 47 var text = new WebInspector.Text(content);
53 var scopeText = text.extract(textRange); 48 var scopeRange = new WebInspector.TextRange(startLocation.lineNumber, st artLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber)
54 var scopeStart = text.toSourceRange(textRange).offset; 49 var scopeText = text.extract(scopeRange);
50 var scopeStart = text.toSourceRange(scopeRange).offset;
55 var prefix = "function fui"; 51 var prefix = "function fui";
56 52
57 return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptI dentifiers(prefix + scopeText) 53 return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptI dentifiers(prefix + scopeText)
58 .then(onIdentifiers.bind(null, text, scopeStart, prefix)); 54 .then(onIdentifiers.bind(null, text, scopeStart, prefix));
59 } 55 }
60 56
61 /** 57 /**
62 * @param {!WebInspector.Text} text 58 * @param {!WebInspector.Text} text
63 * @param {number} scopeStart 59 * @param {number} scopeStart
64 * @param {string} prefix 60 * @param {string} prefix
65 * @param {!Array<!{name: string, offset: number}>} identifiers 61 * @param {!Array<!{name: string, offset: number}>} identifiers
66 * @return {!Map<string, string>} 62 * @return {!Array<!WebInspector.SourceMapNamesResolver.Identifier>}
67 */ 63 */
68 function onIdentifiers(text, scopeStart, prefix, identifiers) 64 function onIdentifiers(text, scopeStart, prefix, identifiers)
69 { 65 {
70 var namesMapping = new Map(); 66 var result = [];
71 var lineEndings = text.lineEndings(); 67 var cursor = new WebInspector.TextCursor(text.lineEndings());
72 68 var promises = [];
73 for (var i = 0; i < identifiers.length; ++i) { 69 for (var i = 0; i < identifiers.length; ++i) {
74 var id = identifiers[i]; 70 var id = identifiers[i];
71 if (id.offset < prefix.length)
72 continue;
75 var start = scopeStart + id.offset - prefix.length; 73 var start = scopeStart + id.offset - prefix.length;
74 cursor.resetTo(start);
75 result.push(new WebInspector.SourceMapNamesResolver.Identifier(id.na me, cursor.lineNumber(), cursor.columnNumber()));
76 }
77 return result;
78 }
79 }
76 80
77 var lineNumber = lineEndings.lowerBound(start); 81 /**
78 var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[line Number - 1] + 1)); 82 * @param {!WebInspector.DebuggerModel.Scope} scope
79 var entry = sourceMap.findEntry(lineNumber, columnNumber); 83 * @return {!Promise.<!Map<string, string>>}
80 if (entry) 84 */
85 WebInspector.SourceMapNamesResolver._resolveScope = function(scope)
86 {
87 var identifiersPromise = scope[WebInspector.SourceMapNamesResolver._cachedId entifiersSymbol];
88 if (identifiersPromise)
89 return identifiersPromise;
90
91 var script = scope.callFrame().script;
92 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr ipt);
93 if (!sourceMap)
94 return Promise.resolve(new Map());
95
96 /** @type {!Map<string, !WebInspector.Text>} */
97 var textCache = new Map();
98 identifiersPromise = WebInspector.SourceMapNamesResolver._scopeIdentifiers(s cope).then(onIdentifiers);
99 scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol] = identi fiersPromise;
100 return identifiersPromise;
101
102 /**
103 * @param {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} identifi ers
104 * @return {!Promise<!Map<string, string>>}
105 */
106 function onIdentifiers(identifiers)
107 {
108 var namesMapping = new Map();
109 // Extract as much as possible from SourceMap.
110 for (var i = 0; i < identifiers.length; ++i) {
111 var id = identifiers[i];
112 var entry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
113 if (entry && entry.name)
81 namesMapping.set(id.name, entry.name); 114 namesMapping.set(id.name, entry.name);
82 } 115 }
83 116
84 scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMappi ng; 117 // Resolve missing identifier names from sourcemap ranges.
85 delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; 118 var promises = [];
86 WebInspector.SourceMapNamesResolver._scopeResolvedForTest(); 119 for (var i = 0; i < identifiers.length; ++i) {
87 return namesMapping; 120 var id = identifiers[i];
121 if (namesMapping.has(id.name))
122 continue;
123 var promise = resolveSourceName(id).then(onSourceNameResolved.bind(n ull, namesMapping, id));
124 promises.push(promise);
125 }
126 return Promise.all(promises)
127 .then(() => WebInspector.SourceMapNamesResolver._scopeResolvedForTes t())
128 .then(() => namesMapping)
129 }
130
131 /**
132 * @param {!Map<string, string>} namesMapping
133 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id
134 * @param {?string} sourceName
135 */
136 function onSourceNameResolved(namesMapping, id, sourceName)
137 {
138 if (!sourceName)
139 return;
140 namesMapping.set(id.name, sourceName);
141 }
142
143 /**
144 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id
145 * @return {!Promise<?string>}
146 */
147 function resolveSourceName(id)
148 {
149 var startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
150 var endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.n ame.length);
151 if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sour ceURL !== endEntry.sourceURL
152 || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber
153 || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber)
154 return Promise.resolve(/** @type {?string} */(null));
155 var sourceTextRange = new WebInspector.TextRange(startEntry.sourceLineNu mber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber, endEntry.sourceC olumnNumber);
156 var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForScriptURL( startEntry.sourceURL, script);
157 if (!uiSourceCode)
158 return Promise.resolve(/** @type {?string} */(null));
159
160 return uiSourceCode.requestContent()
161 .then(onSourceContent.bind(null, uiSourceCode))
162 .then(onSourceText.bind(null, sourceTextRange));
163 }
164
165 /**
166 * @param {!WebInspector.UISourceCode} uiSourceCode
167 * @param {?string} content
168 * @return {?WebInspector.Text}
169 */
170 function onSourceContent(uiSourceCode, content)
171 {
172 if (!content)
173 return null;
174 var text = textCache.get(content);
175 if (!text) {
176 text = new WebInspector.Text(content);
177 textCache.set(content, text);
178 }
179 return text;
180 }
181
182 /**
183 * @param {!WebInspector.TextRange} sourceTextRange
184 * @param {?WebInspector.Text} text
185 */
186 function onSourceText(sourceTextRange, text)
dgozman 2016/04/15 00:40:43 Merge this into previous one.
lushnikov 2016/04/15 00:45:48 Done.
187 {
188 if (!text)
189 return null;
190 var originalIdentifier = text.extract(sourceTextRange).trim();
191 return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier : null;
88 } 192 }
89 } 193 }
90 194
91 WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() { } 195 WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() { }
92 196
93 /** 197 /**
94 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame 198 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
95 * @return {!Promise.<!Map<string, string>>} 199 * @return {!Promise.<!Map<string, string>>}
96 */ 200 */
97 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram e) 201 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram e)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 248
145 /** 249 /**
146 * @param {!Map<string, string>} reverseMapping 250 * @param {!Map<string, string>} reverseMapping
147 * @return {!Promise<string>} 251 * @return {!Promise<string>}
148 */ 252 */
149 function findCompiledName(reverseMapping) 253 function findCompiledName(reverseMapping)
150 { 254 {
151 if (reverseMapping.has(originalText)) 255 if (reverseMapping.has(originalText))
152 return Promise.resolve(reverseMapping.get(originalText) || ""); 256 return Promise.resolve(reverseMapping.get(originalText) || "");
153 257
154 return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber) 258 return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber);
155 } 259 }
156 } 260 }
157 261
158 /** 262 /**
159 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame 263 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
160 * @param {!WebInspector.UISourceCode} uiSourceCode 264 * @param {!WebInspector.UISourceCode} uiSourceCode
161 * @param {number} lineNumber 265 * @param {number} lineNumber
162 * @param {number} startColumnNumber 266 * @param {number} startColumnNumber
163 * @param {number} endColumnNumber 267 * @param {number} endColumnNumber
164 * @return {!Promise<string>} 268 * @return {!Promise<string>}
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 651
548 /** 652 /**
549 * @return {!WebInspector.SourceMapNamesResolverWorker} 653 * @return {!WebInspector.SourceMapNamesResolverWorker}
550 */ 654 */
551 WebInspector.SourceMapNamesResolverWorker._instance = function() 655 WebInspector.SourceMapNamesResolverWorker._instance = function()
552 { 656 {
553 if (!WebInspector.SourceMapNamesResolverWorker._instanceObject) 657 if (!WebInspector.SourceMapNamesResolverWorker._instanceObject)
554 WebInspector.SourceMapNamesResolverWorker._instanceObject = new WebInspe ctor.SourceMapNamesResolverWorker(); 658 WebInspector.SourceMapNamesResolverWorker._instanceObject = new WebInspe ctor.SourceMapNamesResolverWorker();
555 return WebInspector.SourceMapNamesResolverWorker._instanceObject; 659 return WebInspector.SourceMapNamesResolverWorker._instanceObject;
556 } 660 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698