OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 WebInspector.SourceMapNamesResolver = {}; |
| 6 |
| 7 WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache"); |
| 8 WebInspector.SourceMapNamesResolver._cachedPromiseSymbol = Symbol("cache"); |
| 9 |
| 10 /** |
| 11 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 12 * @return {!Promise.<!Map<string, string>>} |
| 13 */ |
| 14 WebInspector.SourceMapNamesResolver._resolveScope = function(scope) |
| 15 { |
| 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(); |
| 25 var endLocation = scope.endLocation(); |
| 26 var script = startLocation.script(); |
| 27 |
| 28 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en
dLocation || !script.sourceMapURL || script !== endLocation.script()) |
| 29 return Promise.resolve(new Map()); |
| 30 |
| 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 scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise; |
| 37 return promise; |
| 38 |
| 39 /** |
| 40 * @param {?string} content |
| 41 * @return {!Map<string, string>} |
| 42 */ |
| 43 function onContent(content) |
| 44 { |
| 45 if (!content) |
| 46 return new Map(); |
| 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 |
| 52 var scopeText = textRange.extract(content); |
| 53 var scopeStart = textRange.toSourceRange(content).offset; |
| 54 var prefix = "function fui"; |
| 55 var root = acorn.parse(prefix + scopeText, {}); |
| 56 var declarators = []; |
| 57 var functionDeclarationCounter = 0; |
| 58 var walker = new WebInspector.ESTreeWalker(beforeVisit, afterVisit); |
| 59 |
| 60 /** |
| 61 * @param {!ESTree.Node} node |
| 62 */ |
| 63 function beforeVisit(node) |
| 64 { |
| 65 if (node.type === "FunctionDeclaration" || node.type === "FunctionEx
pression") |
| 66 functionDeclarationCounter++; |
| 67 |
| 68 if (node.type === "VariableDeclarator" && functionDeclarationCounter
=== 1) |
| 69 declarators.push(node); |
| 70 } |
| 71 |
| 72 /** |
| 73 * @param {!ESTree.Node} node |
| 74 */ |
| 75 function afterVisit(node) |
| 76 { |
| 77 if (node.type === "FunctionDeclaration" || node.type === "FunctionEx
pression") |
| 78 functionDeclarationCounter--; |
| 79 } |
| 80 |
| 81 walker.walk(root); |
| 82 |
| 83 var namesMapping = new Map(); |
| 84 var lineEndings = content.lineEndings(); |
| 85 |
| 86 for (var i = 0; i < declarators.length; ++i) { |
| 87 var id = declarators[i].id; |
| 88 var start = scopeStart + id.start - prefix.length; |
| 89 |
| 90 var lineNumber = lineEndings.lowerBound(start); |
| 91 var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[line
Number - 1] + 1)); |
| 92 var entry = sourceMap.findEntry(lineNumber, columnNumber); |
| 93 if (entry) |
| 94 namesMapping.set(id.name, entry.name); |
| 95 } |
| 96 |
| 97 scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMappi
ng; |
| 98 delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; |
| 99 return namesMapping; |
| 100 } |
| 101 } |
| 102 |
| 103 /** |
| 104 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 105 * @return {!WebInspector.RemoteObject} |
| 106 */ |
| 107 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope) |
| 108 { |
| 109 if (!Runtime.experiments.isEnabled("resolveVariableNames")) |
| 110 return scope.object(); |
| 111 |
| 112 var startLocation = scope.startLocation(); |
| 113 var endLocation = scope.endLocation(); |
| 114 |
| 115 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en
dLocation || !startLocation.script().sourceMapURL || startLocation.script() !==
endLocation.script()) |
| 116 return scope.object(); |
| 117 |
| 118 return new WebInspector.SourceMapNamesResolver.RemoteObject(scope); |
| 119 } |
| 120 |
| 121 /** |
| 122 * @constructor |
| 123 * @extends {WebInspector.RemoteObject} |
| 124 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 125 */ |
| 126 WebInspector.SourceMapNamesResolver.RemoteObject = function(scope) |
| 127 { |
| 128 WebInspector.RemoteObject.call(this); |
| 129 this._scope = scope; |
| 130 this._object = scope.object(); |
| 131 }; |
| 132 |
| 133 WebInspector.SourceMapNamesResolver.RemoteObject.prototype = { |
| 134 /** |
| 135 * @override |
| 136 * @return {?RuntimeAgent.CustomPreview} |
| 137 */ |
| 138 customPreview: function() |
| 139 { |
| 140 return this._object.customPreview(); |
| 141 }, |
| 142 |
| 143 /** |
| 144 * @override |
| 145 * @return {string} |
| 146 */ |
| 147 get type() |
| 148 { |
| 149 return this._object.type; |
| 150 }, |
| 151 |
| 152 /** |
| 153 * @override |
| 154 * @return {string|undefined} |
| 155 */ |
| 156 get subtype() |
| 157 { |
| 158 return this._object.subtype; |
| 159 }, |
| 160 |
| 161 /** |
| 162 * @override |
| 163 * @return {string|undefined} |
| 164 */ |
| 165 get description() |
| 166 { |
| 167 return this._object.description; |
| 168 }, |
| 169 |
| 170 /** |
| 171 * @override |
| 172 * @return {boolean} |
| 173 */ |
| 174 get hasChildren() |
| 175 { |
| 176 return this._object.hasChildren; |
| 177 }, |
| 178 |
| 179 /** |
| 180 * @override |
| 181 * @return {number} |
| 182 */ |
| 183 arrayLength: function() |
| 184 { |
| 185 return this._object.arrayLength(); |
| 186 }, |
| 187 |
| 188 /** |
| 189 * @override |
| 190 * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!We
bInspector.RemoteObjectProperty>)} callback |
| 191 */ |
| 192 getOwnProperties: function(callback) |
| 193 { |
| 194 this._object.getOwnProperties(callback); |
| 195 }, |
| 196 |
| 197 /** |
| 198 * @override |
| 199 * @param {boolean} accessorPropertiesOnly |
| 200 * @param {function(?Array<!WebInspector.RemoteObjectProperty>, ?Array<!WebI
nspector.RemoteObjectProperty>)} callback |
| 201 */ |
| 202 getAllProperties: function(accessorPropertiesOnly, callback) |
| 203 { |
| 204 /** |
| 205 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| 206 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperti
es |
| 207 * @this {WebInspector.SourceMapNamesResolver.RemoteObject} |
| 208 */ |
| 209 function wrappedCallback(properties, internalProperties) |
| 210 { |
| 211 WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(
resolveNames.bind(null, properties, internalProperties)) |
| 212 } |
| 213 |
| 214 /** |
| 215 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| 216 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperti
es |
| 217 * @param {!Map<string, string>} namesMapping |
| 218 */ |
| 219 function resolveNames(properties, internalProperties, namesMapping) |
| 220 { |
| 221 var newProperties = []; |
| 222 if (properties) { |
| 223 for (var i = 0; i < properties.length; ++i) { |
| 224 var property = properties[i]; |
| 225 var name = namesMapping.get(property.name) || properties[i].
name; |
| 226 newProperties.push(new WebInspector.RemoteObjectProperty(nam
e, property.value, property.enumerable, property.writable, property.isOwn, prope
rty.wasThrown, property.symbol, property.synthetic)); |
| 227 } |
| 228 } |
| 229 |
| 230 callback(newProperties, internalProperties); |
| 231 } |
| 232 |
| 233 this._object.getAllProperties(accessorPropertiesOnly, wrappedCallback.bi
nd(this)); |
| 234 }, |
| 235 |
| 236 /** |
| 237 * @override |
| 238 * @param {string|!RuntimeAgent.CallArgument} argumentName |
| 239 * @param {string} value |
| 240 * @param {function(string=)} callback |
| 241 */ |
| 242 setPropertyValue: function(argumentName, value, callback) |
| 243 { |
| 244 WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(reso
lveName.bind(this)); |
| 245 |
| 246 /** |
| 247 * @param {!Map<string, string>} namesMapping |
| 248 * @this {WebInspector.SourceMapNamesResolver.RemoteObject} |
| 249 */ |
| 250 function resolveName(namesMapping) |
| 251 { |
| 252 var name; |
| 253 if (typeof argumentName === "string") |
| 254 name = argumentName; |
| 255 else |
| 256 name = /** @type {string} */ (argumentName.value); |
| 257 |
| 258 var actualName = name; |
| 259 for (var compiledName of namesMapping.keys()) { |
| 260 if (namesMapping.get(compiledName) === name) { |
| 261 actualName = compiledName; |
| 262 break; |
| 263 } |
| 264 } |
| 265 this._object.setPropertyValue(actualName, value, callback); |
| 266 } |
| 267 }, |
| 268 |
| 269 /** |
| 270 * @override |
| 271 * @return {!Promise<?Array<!WebInspector.EventListener>>} |
| 272 */ |
| 273 eventListeners: function() |
| 274 { |
| 275 return this._object.eventListeners(); |
| 276 }, |
| 277 |
| 278 /** |
| 279 * @override |
| 280 * @param {!RuntimeAgent.CallArgument} name |
| 281 * @param {function(string=)} callback |
| 282 */ |
| 283 deleteProperty: function(name, callback) |
| 284 { |
| 285 this._object.deleteProperty(name, callback); |
| 286 }, |
| 287 |
| 288 /** |
| 289 * @override |
| 290 * @param {function(this:Object, ...)} functionDeclaration |
| 291 * @param {!Array<!RuntimeAgent.CallArgument>=} args |
| 292 * @param {function(?WebInspector.RemoteObject, boolean=)=} callback |
| 293 */ |
| 294 callFunction: function(functionDeclaration, args, callback) |
| 295 { |
| 296 this._object.callFunction(functionDeclaration, args, callback); |
| 297 }, |
| 298 |
| 299 /** |
| 300 * @override |
| 301 * @param {function(this:Object, ...)} functionDeclaration |
| 302 * @param {!Array<!RuntimeAgent.CallArgument>|undefined} args |
| 303 * @param {function(*)} callback |
| 304 */ |
| 305 callFunctionJSON: function(functionDeclaration, args, callback) |
| 306 { |
| 307 this._object.callFunctionJSON(functionDeclaration, args, callback); |
| 308 }, |
| 309 |
| 310 /** |
| 311 * @override |
| 312 * @return {!WebInspector.Target} |
| 313 */ |
| 314 target: function() |
| 315 { |
| 316 return this._object.target(); |
| 317 }, |
| 318 |
| 319 /** |
| 320 * @override |
| 321 * @return {?WebInspector.DebuggerModel} |
| 322 */ |
| 323 debuggerModel: function() |
| 324 { |
| 325 return this._object.debuggerModel(); |
| 326 }, |
| 327 |
| 328 /** |
| 329 * @override |
| 330 * @return {boolean} |
| 331 */ |
| 332 isNode: function() |
| 333 { |
| 334 return this._object.isNode(); |
| 335 }, |
| 336 |
| 337 /** |
| 338 * @override |
| 339 * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback |
| 340 */ |
| 341 functionDetails: function(callback) |
| 342 { |
| 343 this._object.functionDetails(callback); |
| 344 }, |
| 345 |
| 346 /** |
| 347 * @override |
| 348 * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} cal
lback |
| 349 */ |
| 350 generatorObjectDetails: function(callback) |
| 351 { |
| 352 this._object.generatorObjectDetails(callback); |
| 353 }, |
| 354 |
| 355 /** |
| 356 * @override |
| 357 * @param {function(?Array<!DebuggerAgent.CollectionEntry>)} callback |
| 358 */ |
| 359 collectionEntries: function(callback) |
| 360 { |
| 361 this._object.collectionEntries(callback); |
| 362 }, |
| 363 |
| 364 __proto__: WebInspector.RemoteObject.prototype |
| 365 } |
OLD | NEW |