| 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 | |
| 5 WebInspector.SourceMapNamesResolver = {}; | 4 WebInspector.SourceMapNamesResolver = {}; |
| 6 | 5 |
| 7 WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache"); | 6 WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol('cache'); |
| 8 WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol = Symbol("cachedIde
ntifiers"); | 7 WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol = Symbol('cachedIde
ntifiers'); |
| 9 | 8 |
| 10 /** | 9 /** |
| 11 * @constructor | 10 * @unrestricted |
| 12 * @param {string} name | 11 */ |
| 13 * @param {number} lineNumber | 12 WebInspector.SourceMapNamesResolver.Identifier = class { |
| 14 * @param {number} columnNumber | 13 /** |
| 15 */ | 14 * @param {string} name |
| 16 WebInspector.SourceMapNamesResolver.Identifier = function(name, lineNumber, colu
mnNumber) | 15 * @param {number} lineNumber |
| 17 { | 16 * @param {number} columnNumber |
| 17 */ |
| 18 constructor(name, lineNumber, columnNumber) { |
| 18 this.name = name; | 19 this.name = name; |
| 19 this.lineNumber = lineNumber; | 20 this.lineNumber = lineNumber; |
| 20 this.columnNumber = columnNumber; | 21 this.columnNumber = columnNumber; |
| 22 } |
| 21 }; | 23 }; |
| 22 | 24 |
| 23 /** | 25 /** |
| 24 * @param {!WebInspector.DebuggerModel.Scope} scope | 26 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 25 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>>} | 27 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>>} |
| 26 */ | 28 */ |
| 27 WebInspector.SourceMapNamesResolver._scopeIdentifiers = function(scope) | 29 WebInspector.SourceMapNamesResolver._scopeIdentifiers = function(scope) { |
| 28 { | 30 var startLocation = scope.startLocation(); |
| 29 var startLocation = scope.startLocation(); | 31 var endLocation = scope.endLocation(); |
| 30 var endLocation = scope.endLocation(); | 32 |
| 31 | 33 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !endL
ocation || |
| 32 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en
dLocation || !startLocation.script().sourceMapURL || (startLocation.script() !==
endLocation.script())) | 34 !startLocation.script().sourceMapURL || (startLocation.script() !== endLoc
ation.script())) |
| 33 return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapNamesRes
olver.Identifier>}*/([])); | 35 return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapNamesResolve
r.Identifier>}*/ ([])); |
| 34 | 36 |
| 35 var script = startLocation.script(); | 37 var script = startLocation.script(); |
| 36 return script.requestContent().then(onContent); | 38 return script.requestContent().then(onContent); |
| 37 | 39 |
| 38 /** | 40 /** |
| 39 * @param {?string} content | 41 * @param {?string} content |
| 40 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>
>} | 42 * @return {!Promise<!Array<!WebInspector.SourceMapNamesResolver.Identifier>>} |
| 41 */ | 43 */ |
| 42 function onContent(content) | 44 function onContent(content) { |
| 43 { | 45 if (!content) |
| 44 if (!content) | 46 return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapNamesResol
ver.Identifier>}*/ ([])); |
| 45 return Promise.resolve(/** @type {!Array<!WebInspector.SourceMapName
sResolver.Identifier>}*/([])); | 47 |
| 46 | 48 var text = new WebInspector.Text(content); |
| 47 var text = new WebInspector.Text(content); | 49 var scopeRange = new WebInspector.TextRange( |
| 48 var scopeRange = new WebInspector.TextRange(startLocation.lineNumber, st
artLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber); | 50 startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNu
mber, endLocation.columnNumber); |
| 49 var scopeText = text.extract(scopeRange); | 51 var scopeText = text.extract(scopeRange); |
| 50 var scopeStart = text.toSourceRange(scopeRange).offset; | 52 var scopeStart = text.toSourceRange(scopeRange).offset; |
| 51 var prefix = "function fui"; | 53 var prefix = 'function fui'; |
| 52 return WebInspector.formatterWorkerPool.runTask("javaScriptIdentifiers",
{content: prefix + scopeText}) | 54 return WebInspector.formatterWorkerPool.runTask('javaScriptIdentifiers', {co
ntent: prefix + scopeText}) |
| 53 .then(onIdentifiers.bind(null, text, scopeStart, prefix)); | 55 .then(onIdentifiers.bind(null, text, scopeStart, prefix)); |
| 54 } | 56 } |
| 55 | 57 |
| 56 /** | 58 /** |
| 57 * @param {!WebInspector.Text} text | 59 * @param {!WebInspector.Text} text |
| 58 * @param {number} scopeStart | 60 * @param {number} scopeStart |
| 59 * @param {string} prefix | 61 * @param {string} prefix |
| 60 * @param {?MessageEvent} event | 62 * @param {?MessageEvent} event |
| 61 * @return {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} | 63 * @return {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} |
| 62 */ | 64 */ |
| 63 function onIdentifiers(text, scopeStart, prefix, event) | 65 function onIdentifiers(text, scopeStart, prefix, event) { |
| 64 { | 66 var identifiers = event ? /** @type {!Array<!{name: string, offset: number}>
} */ (event.data) : []; |
| 65 var identifiers = event ? /** @type {!Array<!{name: string, offset: numb
er}>} */(event.data) : []; | 67 var result = []; |
| 66 var result = []; | 68 var cursor = new WebInspector.TextCursor(text.lineEndings()); |
| 67 var cursor = new WebInspector.TextCursor(text.lineEndings()); | 69 var promises = []; |
| 68 var promises = []; | 70 for (var i = 0; i < identifiers.length; ++i) { |
| 69 for (var i = 0; i < identifiers.length; ++i) { | 71 var id = identifiers[i]; |
| 70 var id = identifiers[i]; | 72 if (id.offset < prefix.length) |
| 71 if (id.offset < prefix.length) | 73 continue; |
| 72 continue; | 74 var start = scopeStart + id.offset - prefix.length; |
| 73 var start = scopeStart + id.offset - prefix.length; | 75 cursor.resetTo(start); |
| 74 cursor.resetTo(start); | 76 result.push( |
| 75 result.push(new WebInspector.SourceMapNamesResolver.Identifier(id.na
me, cursor.lineNumber(), cursor.columnNumber())); | 77 new WebInspector.SourceMapNamesResolver.Identifier(id.name, cursor.lin
eNumber(), cursor.columnNumber())); |
| 76 } | 78 } |
| 77 return result; | 79 return result; |
| 78 } | 80 } |
| 79 }; | 81 }; |
| 80 | 82 |
| 81 /** | 83 /** |
| 82 * @param {!WebInspector.DebuggerModel.Scope} scope | 84 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 83 * @return {!Promise.<!Map<string, string>>} | 85 * @return {!Promise.<!Map<string, string>>} |
| 84 */ | 86 */ |
| 85 WebInspector.SourceMapNamesResolver._resolveScope = function(scope) | 87 WebInspector.SourceMapNamesResolver._resolveScope = function(scope) { |
| 86 { | 88 var identifiersPromise = scope[WebInspector.SourceMapNamesResolver._cachedIden
tifiersSymbol]; |
| 87 var identifiersPromise = scope[WebInspector.SourceMapNamesResolver._cachedId
entifiersSymbol]; | 89 if (identifiersPromise) |
| 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; | 90 return identifiersPromise; |
| 101 | 91 |
| 102 /** | 92 var script = scope.callFrame().script; |
| 103 * @param {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} identifi
ers | 93 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scrip
t); |
| 104 * @return {!Promise<!Map<string, string>>} | 94 if (!sourceMap) |
| 105 */ | 95 return Promise.resolve(new Map()); |
| 106 function onIdentifiers(identifiers) | 96 |
| 107 { | 97 /** @type {!Map<string, !WebInspector.Text>} */ |
| 108 var namesMapping = new Map(); | 98 var textCache = new Map(); |
| 109 // Extract as much as possible from SourceMap. | 99 identifiersPromise = WebInspector.SourceMapNamesResolver._scopeIdentifiers(sco
pe).then(onIdentifiers); |
| 110 for (var i = 0; i < identifiers.length; ++i) { | 100 scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol] = identifi
ersPromise; |
| 111 var id = identifiers[i]; | 101 return identifiersPromise; |
| 112 var entry = sourceMap.findEntry(id.lineNumber, id.columnNumber); | 102 |
| 113 if (entry && entry.name) | 103 /** |
| 114 namesMapping.set(id.name, entry.name); | 104 * @param {!Array<!WebInspector.SourceMapNamesResolver.Identifier>} identifier
s |
| 115 } | 105 * @return {!Promise<!Map<string, string>>} |
| 116 | 106 */ |
| 117 // Resolve missing identifier names from sourcemap ranges. | 107 function onIdentifiers(identifiers) { |
| 118 var promises = []; | 108 var namesMapping = new Map(); |
| 119 for (var i = 0; i < identifiers.length; ++i) { | 109 // Extract as much as possible from SourceMap. |
| 120 var id = identifiers[i]; | 110 for (var i = 0; i < identifiers.length; ++i) { |
| 121 if (namesMapping.has(id.name)) | 111 var id = identifiers[i]; |
| 122 continue; | 112 var entry = sourceMap.findEntry(id.lineNumber, id.columnNumber); |
| 123 var promise = resolveSourceName(id).then(onSourceNameResolved.bind(n
ull, namesMapping, id)); | 113 if (entry && entry.name) |
| 124 promises.push(promise); | 114 namesMapping.set(id.name, entry.name); |
| 125 } | 115 } |
| 126 return Promise.all(promises) | 116 |
| 127 .then(() => WebInspector.SourceMapNamesResolver._scopeResolvedForTes
t()) | 117 // Resolve missing identifier names from sourcemap ranges. |
| 128 .then(() => namesMapping); | 118 var promises = []; |
| 129 } | 119 for (var i = 0; i < identifiers.length; ++i) { |
| 130 | 120 var id = identifiers[i]; |
| 131 /** | 121 if (namesMapping.has(id.name)) |
| 132 * @param {!Map<string, string>} namesMapping | 122 continue; |
| 133 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id | 123 var promise = resolveSourceName(id).then(onSourceNameResolved.bind(null, n
amesMapping, id)); |
| 134 * @param {?string} sourceName | 124 promises.push(promise); |
| 135 */ | 125 } |
| 136 function onSourceNameResolved(namesMapping, id, sourceName) | 126 return Promise.all(promises) |
| 137 { | 127 .then(() => WebInspector.SourceMapNamesResolver._scopeResolvedForTest()) |
| 138 if (!sourceName) | 128 .then(() => namesMapping); |
| 139 return; | 129 } |
| 140 namesMapping.set(id.name, sourceName); | 130 |
| 141 } | 131 /** |
| 142 | 132 * @param {!Map<string, string>} namesMapping |
| 143 /** | 133 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id |
| 144 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id | 134 * @param {?string} sourceName |
| 145 * @return {!Promise<?string>} | 135 */ |
| 146 */ | 136 function onSourceNameResolved(namesMapping, id, sourceName) { |
| 147 function resolveSourceName(id) | 137 if (!sourceName) |
| 148 { | 138 return; |
| 149 var startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber); | 139 namesMapping.set(id.name, sourceName); |
| 150 var endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.n
ame.length); | 140 } |
| 151 if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sour
ceURL !== endEntry.sourceURL | 141 |
| 152 || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber | 142 /** |
| 153 || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber) | 143 * @param {!WebInspector.SourceMapNamesResolver.Identifier} id |
| 154 return Promise.resolve(/** @type {?string} */(null)); | 144 * @return {!Promise<?string>} |
| 155 var sourceTextRange = new WebInspector.TextRange(startEntry.sourceLineNu
mber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber, endEntry.sourceC
olumnNumber); | 145 */ |
| 156 var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForScriptURL(
startEntry.sourceURL, script); | 146 function resolveSourceName(id) { |
| 157 if (!uiSourceCode) | 147 var startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber); |
| 158 return Promise.resolve(/** @type {?string} */(null)); | 148 var endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.name.
length); |
| 159 | 149 if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sourceUR
L !== endEntry.sourceURL || |
| 160 return uiSourceCode.requestContent() | 150 !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber || !endEn
try.sourceLineNumber || |
| 161 .then(onSourceContent.bind(null, sourceTextRange)); | 151 !endEntry.sourceColumnNumber) |
| 162 } | 152 return Promise.resolve(/** @type {?string} */ (null)); |
| 163 | 153 var sourceTextRange = new WebInspector.TextRange( |
| 164 /** | 154 startEntry.sourceLineNumber, startEntry.sourceColumnNumber, endEntry.sou
rceLineNumber, |
| 165 * @param {!WebInspector.TextRange} sourceTextRange | 155 endEntry.sourceColumnNumber); |
| 166 * @param {?string} content | 156 var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForScriptURL(star
tEntry.sourceURL, script); |
| 167 * @return {?string} | 157 if (!uiSourceCode) |
| 168 */ | 158 return Promise.resolve(/** @type {?string} */ (null)); |
| 169 function onSourceContent(sourceTextRange, content) | 159 |
| 170 { | 160 return uiSourceCode.requestContent().then(onSourceContent.bind(null, sourceT
extRange)); |
| 171 if (!content) | 161 } |
| 172 return null; | 162 |
| 173 var text = textCache.get(content); | 163 /** |
| 174 if (!text) { | 164 * @param {!WebInspector.TextRange} sourceTextRange |
| 175 text = new WebInspector.Text(content); | 165 * @param {?string} content |
| 176 textCache.set(content, text); | 166 * @return {?string} |
| 177 } | 167 */ |
| 178 var originalIdentifier = text.extract(sourceTextRange).trim(); | 168 function onSourceContent(sourceTextRange, content) { |
| 179 return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier :
null; | 169 if (!content) |
| 180 } | 170 return null; |
| 181 }; | 171 var text = textCache.get(content); |
| 182 | 172 if (!text) { |
| 183 WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() { }; | 173 text = new WebInspector.Text(content); |
| 174 textCache.set(content, text); |
| 175 } |
| 176 var originalIdentifier = text.extract(sourceTextRange).trim(); |
| 177 return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier : null
; |
| 178 } |
| 179 }; |
| 180 |
| 181 WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() {}; |
| 184 | 182 |
| 185 /** | 183 /** |
| 186 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame | 184 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame |
| 187 * @return {!Promise.<!Map<string, string>>} | 185 * @return {!Promise.<!Map<string, string>>} |
| 188 */ | 186 */ |
| 189 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram
e) | 187 WebInspector.SourceMapNamesResolver._allVariablesInCallFrame = function(callFram
e) { |
| 190 { | 188 var cached = callFrame[WebInspector.SourceMapNamesResolver._cachedMapSymbol]; |
| 191 var cached = callFrame[WebInspector.SourceMapNamesResolver._cachedMapSymbol]
; | 189 if (cached) |
| 192 if (cached) | 190 return Promise.resolve(cached); |
| 193 return Promise.resolve(cached); | 191 |
| 194 | 192 var promises = []; |
| 195 var promises = []; | 193 var scopeChain = callFrame.scopeChain(); |
| 196 var scopeChain = callFrame.scopeChain(); | 194 for (var i = 0; i < scopeChain.length; ++i) |
| 197 for (var i = 0; i < scopeChain.length; ++i) | 195 promises.push(WebInspector.SourceMapNamesResolver._resolveScope(scopeChain[i
])); |
| 198 promises.push(WebInspector.SourceMapNamesResolver._resolveScope(scopeCha
in[i])); | 196 |
| 199 | 197 return Promise.all(promises).then(mergeVariables); |
| 200 return Promise.all(promises).then(mergeVariables); | 198 |
| 201 | 199 /** |
| 202 /** | 200 * @param {!Array<!Map<string, string>>} nameMappings |
| 203 * @param {!Array<!Map<string, string>>} nameMappings | 201 * @return {!Map<string, string>} |
| 204 * @return {!Map<string, string>} | 202 */ |
| 205 */ | 203 function mergeVariables(nameMappings) { |
| 206 function mergeVariables(nameMappings) | 204 var reverseMapping = new Map(); |
| 207 { | 205 for (var map of nameMappings) { |
| 208 var reverseMapping = new Map(); | 206 for (var compiledName of map.keys()) { |
| 209 for (var map of nameMappings) { | 207 var originalName = map.get(compiledName); |
| 210 for (var compiledName of map.keys()) { | 208 if (!reverseMapping.has(originalName)) |
| 211 var originalName = map.get(compiledName); | 209 reverseMapping.set(originalName, compiledName); |
| 212 if (!reverseMapping.has(originalName)) | 210 } |
| 213 reverseMapping.set(originalName, compiledName); | 211 } |
| 214 } | 212 callFrame[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = reverseMap
ping; |
| 215 } | 213 return reverseMapping; |
| 216 callFrame[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = revers
eMapping; | 214 } |
| 217 return reverseMapping; | 215 }; |
| 218 } | 216 |
| 219 }; | 217 /** |
| 220 | |
| 221 /** | |
| 222 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame | 218 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame |
| 223 * @param {string} originalText | 219 * @param {string} originalText |
| 224 * @param {!WebInspector.UISourceCode} uiSourceCode | 220 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 225 * @param {number} lineNumber | 221 * @param {number} lineNumber |
| 226 * @param {number} startColumnNumber | 222 * @param {number} startColumnNumber |
| 227 * @param {number} endColumnNumber | 223 * @param {number} endColumnNumber |
| 228 * @return {!Promise<string>} | 224 * @return {!Promise<string>} |
| 229 */ | 225 */ |
| 230 WebInspector.SourceMapNamesResolver.resolveExpression = function(callFrame, orig
inalText, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber) | 226 WebInspector.SourceMapNamesResolver.resolveExpression = function( |
| 231 { | 227 callFrame, originalText, uiSourceCode, lineNumber, startColumnNumber, endCol
umnNumber) { |
| 232 if (!Runtime.experiments.isEnabled("resolveVariableNames") || !uiSourceCode.
contentType().isFromSourceMap()) | 228 if (!Runtime.experiments.isEnabled('resolveVariableNames') || !uiSourceCode.co
ntentType().isFromSourceMap()) |
| 233 return Promise.resolve(""); | 229 return Promise.resolve(''); |
| 234 | 230 |
| 235 return WebInspector.SourceMapNamesResolver._allVariablesInCallFrame(callFram
e).then(findCompiledName); | 231 return WebInspector.SourceMapNamesResolver._allVariablesInCallFrame(callFrame)
.then(findCompiledName); |
| 236 | 232 |
| 237 /** | 233 /** |
| 238 * @param {!Map<string, string>} reverseMapping | 234 * @param {!Map<string, string>} reverseMapping |
| 239 * @return {!Promise<string>} | 235 * @return {!Promise<string>} |
| 240 */ | 236 */ |
| 241 function findCompiledName(reverseMapping) | 237 function findCompiledName(reverseMapping) { |
| 242 { | 238 if (reverseMapping.has(originalText)) |
| 243 if (reverseMapping.has(originalText)) | 239 return Promise.resolve(reverseMapping.get(originalText) || ''); |
| 244 return Promise.resolve(reverseMapping.get(originalText) || ""); | |
| 245 | 240 |
| 246 return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame,
uiSourceCode, lineNumber, startColumnNumber, endColumnNumber); | 241 return WebInspector.SourceMapNamesResolver._resolveExpression( |
| 247 } | 242 callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber)
; |
| 243 } |
| 248 }; | 244 }; |
| 249 | 245 |
| 250 /** | 246 /** |
| 251 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame | 247 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame |
| 252 * @param {!WebInspector.UISourceCode} uiSourceCode | 248 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 253 * @param {number} lineNumber | 249 * @param {number} lineNumber |
| 254 * @param {number} startColumnNumber | 250 * @param {number} startColumnNumber |
| 255 * @param {number} endColumnNumber | 251 * @param {number} endColumnNumber |
| 256 * @return {!Promise<string>} | 252 * @return {!Promise<string>} |
| 257 */ | 253 */ |
| 258 WebInspector.SourceMapNamesResolver._resolveExpression = function(callFrame, uiS
ourceCode, lineNumber, startColumnNumber, endColumnNumber) | 254 WebInspector.SourceMapNamesResolver._resolveExpression = function( |
| 259 { | 255 callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber) { |
| 260 var target = callFrame.target(); | 256 var target = callFrame.target(); |
| 261 var rawLocation = WebInspector.debuggerWorkspaceBinding.uiLocationToRawLocat
ion(target, uiSourceCode, lineNumber, startColumnNumber); | 257 var rawLocation = WebInspector.debuggerWorkspaceBinding.uiLocationToRawLocatio
n( |
| 262 if (!rawLocation) | 258 target, uiSourceCode, lineNumber, startColumnNumber); |
| 263 return Promise.resolve(""); | 259 if (!rawLocation) |
| 264 | 260 return Promise.resolve(''); |
| 265 var script = rawLocation.script(); | 261 |
| 266 if (!script) | 262 var script = rawLocation.script(); |
| 267 return Promise.resolve(""); | 263 if (!script) |
| 268 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scr
ipt); | 264 return Promise.resolve(''); |
| 269 if (!sourceMap) | 265 var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(scrip
t); |
| 270 return Promise.resolve(""); | 266 if (!sourceMap) |
| 271 | 267 return Promise.resolve(''); |
| 272 return script.requestContent().then(onContent); | 268 |
| 273 | 269 return script.requestContent().then(onContent); |
| 274 /** | 270 |
| 275 * @param {?string} content | 271 /** |
| 276 * @return {!Promise<string>} | 272 * @param {?string} content |
| 277 */ | 273 * @return {!Promise<string>} |
| 278 function onContent(content) | 274 */ |
| 279 { | 275 function onContent(content) { |
| 280 if (!content) | 276 if (!content) |
| 281 return Promise.resolve(""); | 277 return Promise.resolve(''); |
| 282 | 278 |
| 283 var text = new WebInspector.Text(content); | 279 var text = new WebInspector.Text(content); |
| 284 var textRange = sourceMap.reverseMapTextRange(uiSourceCode.url(), new We
bInspector.TextRange(lineNumber, startColumnNumber, lineNumber, endColumnNumber)
); | 280 var textRange = sourceMap.reverseMapTextRange( |
| 285 var originalText = text.extract(textRange); | 281 uiSourceCode.url(), new WebInspector.TextRange(lineNumber, startColumnNu
mber, lineNumber, endColumnNumber)); |
| 286 if (!originalText) | 282 var originalText = text.extract(textRange); |
| 287 return Promise.resolve(""); | 283 if (!originalText) |
| 288 return WebInspector.formatterWorkerPool.runTask("evaluatableJavaScriptSu
bstring", {content: originalText}) | 284 return Promise.resolve(''); |
| 289 .then(onResult); | 285 return WebInspector.formatterWorkerPool.runTask('evaluatableJavaScriptSubstr
ing', {content: originalText}) |
| 290 } | 286 .then(onResult); |
| 291 | 287 } |
| 292 /** | 288 |
| 293 * @param {?MessageEvent} event | 289 /** |
| 294 * @return {string} | 290 * @param {?MessageEvent} event |
| 295 */ | 291 * @return {string} |
| 296 function onResult(event) | 292 */ |
| 297 { | 293 function onResult(event) { |
| 298 return event ? /** @type {string} */(event.data) : ""; | 294 return event ? /** @type {string} */ (event.data) : ''; |
| 299 } | 295 } |
| 300 }; | 296 }; |
| 301 | 297 |
| 302 /** | 298 /** |
| 303 * @param {?WebInspector.DebuggerModel.CallFrame} callFrame | 299 * @param {?WebInspector.DebuggerModel.CallFrame} callFrame |
| 304 * @return {!Promise<?WebInspector.RemoteObject>} | 300 * @return {!Promise<?WebInspector.RemoteObject>} |
| 305 */ | 301 */ |
| 306 WebInspector.SourceMapNamesResolver.resolveThisObject = function(callFrame) | 302 WebInspector.SourceMapNamesResolver.resolveThisObject = function(callFrame) { |
| 307 { | 303 if (!callFrame) |
| 308 if (!callFrame) | 304 return Promise.resolve(/** @type {?WebInspector.RemoteObject} */ (null)); |
| 309 return Promise.resolve(/** @type {?WebInspector.RemoteObject} */(null)); | 305 if (!Runtime.experiments.isEnabled('resolveVariableNames') || !callFrame.scope
Chain().length) |
| 310 if (!Runtime.experiments.isEnabled("resolveVariableNames") || !callFrame.sco
peChain().length) | 306 return Promise.resolve(callFrame.thisObject()); |
| 311 return Promise.resolve(callFrame.thisObject()); | 307 |
| 312 | 308 return WebInspector.SourceMapNamesResolver._resolveScope(callFrame.scopeChain(
)[0]).then(onScopeResolved); |
| 313 return WebInspector.SourceMapNamesResolver._resolveScope(callFrame.scopeChai
n()[0]) | 309 |
| 314 .then(onScopeResolved); | 310 /** |
| 315 | 311 * @param {!Map<string, string>} namesMapping |
| 316 /** | 312 * @return {!Promise<?WebInspector.RemoteObject>} |
| 317 * @param {!Map<string, string>} namesMapping | 313 */ |
| 318 * @return {!Promise<?WebInspector.RemoteObject>} | 314 function onScopeResolved(namesMapping) { |
| 319 */ | 315 var thisMappings = namesMapping.inverse().get('this'); |
| 320 function onScopeResolved(namesMapping) | 316 if (!thisMappings || thisMappings.size !== 1) |
| 321 { | 317 return Promise.resolve(callFrame.thisObject()); |
| 322 var thisMappings = namesMapping.inverse().get("this"); | 318 |
| 323 if (!thisMappings || thisMappings.size !== 1) | 319 var thisMapping = thisMappings.valuesArray()[0]; |
| 324 return Promise.resolve(callFrame.thisObject()); | 320 var callback; |
| 325 | 321 var promise = new Promise(fulfill => callback = fulfill); |
| 326 var thisMapping = thisMappings.valuesArray()[0]; | 322 callFrame.evaluate(thisMapping, 'backtrace', false, true, false, true, onEva
luated.bind(null, callback)); |
| 327 var callback; | 323 return promise; |
| 328 var promise = new Promise(fulfill => callback = fulfill); | 324 } |
| 329 callFrame.evaluate(thisMapping, "backtrace", false, true, false, true, o
nEvaluated.bind(null, callback)); | 325 |
| 330 return promise; | 326 /** |
| 331 } | 327 * @param {function(!WebInspector.RemoteObject)} callback |
| 332 | 328 * @param {?RuntimeAgent.RemoteObject} evaluateResult |
| 333 /** | 329 */ |
| 334 * @param {function(!WebInspector.RemoteObject)} callback | 330 function onEvaluated(callback, evaluateResult) { |
| 335 * @param {?RuntimeAgent.RemoteObject} evaluateResult | 331 var remoteObject = |
| 336 */ | 332 evaluateResult ? callFrame.target().runtimeModel.createRemoteObject(eval
uateResult) : callFrame.thisObject(); |
| 337 function onEvaluated(callback, evaluateResult) | 333 callback(remoteObject); |
| 338 { | 334 } |
| 339 var remoteObject = evaluateResult ? callFrame.target().runtimeModel.crea
teRemoteObject(evaluateResult) : callFrame.thisObject(); | |
| 340 callback(remoteObject); | |
| 341 } | |
| 342 }; | 335 }; |
| 343 | 336 |
| 344 /** | 337 /** |
| 345 * @param {!WebInspector.DebuggerModel.Scope} scope | 338 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 346 * @return {!WebInspector.RemoteObject} | 339 * @return {!WebInspector.RemoteObject} |
| 347 */ | 340 */ |
| 348 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope) | 341 WebInspector.SourceMapNamesResolver.resolveScopeInObject = function(scope) { |
| 349 { | 342 if (!Runtime.experiments.isEnabled('resolveVariableNames')) |
| 350 if (!Runtime.experiments.isEnabled("resolveVariableNames")) | 343 return scope.object(); |
| 351 return scope.object(); | 344 |
| 352 | 345 var startLocation = scope.startLocation(); |
| 353 var startLocation = scope.startLocation(); | 346 var endLocation = scope.endLocation(); |
| 354 var endLocation = scope.endLocation(); | 347 |
| 355 | 348 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !endL
ocation || |
| 356 if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !en
dLocation || !startLocation.script().sourceMapURL || startLocation.script() !==
endLocation.script()) | 349 !startLocation.script().sourceMapURL || startLocation.script() !== endLoca
tion.script()) |
| 357 return scope.object(); | 350 return scope.object(); |
| 358 | 351 |
| 359 return new WebInspector.SourceMapNamesResolver.RemoteObject(scope); | 352 return new WebInspector.SourceMapNamesResolver.RemoteObject(scope); |
| 360 }; | 353 }; |
| 361 | 354 |
| 362 /** | 355 /** |
| 363 * @constructor | 356 * @unrestricted |
| 364 * @extends {WebInspector.RemoteObject} | |
| 365 * @param {!WebInspector.DebuggerModel.Scope} scope | |
| 366 */ | 357 */ |
| 367 WebInspector.SourceMapNamesResolver.RemoteObject = function(scope) | 358 WebInspector.SourceMapNamesResolver.RemoteObject = class extends WebInspector.Re
moteObject { |
| 368 { | 359 /** |
| 369 WebInspector.RemoteObject.call(this); | 360 * @param {!WebInspector.DebuggerModel.Scope} scope |
| 361 */ |
| 362 constructor(scope) { |
| 363 super(); |
| 370 this._scope = scope; | 364 this._scope = scope; |
| 371 this._object = scope.object(); | 365 this._object = scope.object(); |
| 366 } |
| 367 |
| 368 /** |
| 369 * @override |
| 370 * @return {?RuntimeAgent.CustomPreview} |
| 371 */ |
| 372 customPreview() { |
| 373 return this._object.customPreview(); |
| 374 } |
| 375 |
| 376 /** |
| 377 * @override |
| 378 * @return {string} |
| 379 */ |
| 380 get type() { |
| 381 return this._object.type; |
| 382 } |
| 383 |
| 384 /** |
| 385 * @override |
| 386 * @return {string|undefined} |
| 387 */ |
| 388 get subtype() { |
| 389 return this._object.subtype; |
| 390 } |
| 391 |
| 392 /** |
| 393 * @override |
| 394 * @return {string|undefined} |
| 395 */ |
| 396 get description() { |
| 397 return this._object.description; |
| 398 } |
| 399 |
| 400 /** |
| 401 * @override |
| 402 * @return {boolean} |
| 403 */ |
| 404 get hasChildren() { |
| 405 return this._object.hasChildren; |
| 406 } |
| 407 |
| 408 /** |
| 409 * @override |
| 410 * @return {number} |
| 411 */ |
| 412 arrayLength() { |
| 413 return this._object.arrayLength(); |
| 414 } |
| 415 |
| 416 /** |
| 417 * @override |
| 418 * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!WebI
nspector.RemoteObjectProperty>)} callback |
| 419 */ |
| 420 getOwnProperties(callback) { |
| 421 this._object.getOwnProperties(callback); |
| 422 } |
| 423 |
| 424 /** |
| 425 * @override |
| 426 * @param {boolean} accessorPropertiesOnly |
| 427 * @param {function(?Array<!WebInspector.RemoteObjectProperty>, ?Array<!WebIns
pector.RemoteObjectProperty>)} callback |
| 428 */ |
| 429 getAllProperties(accessorPropertiesOnly, callback) { |
| 430 /** |
| 431 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| 432 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| 433 * @this {WebInspector.SourceMapNamesResolver.RemoteObject} |
| 434 */ |
| 435 function wrappedCallback(properties, internalProperties) { |
| 436 WebInspector.SourceMapNamesResolver._resolveScope(this._scope) |
| 437 .then(resolveNames.bind(null, properties, internalProperties)); |
| 438 } |
| 439 |
| 440 /** |
| 441 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| 442 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| 443 * @param {!Map<string, string>} namesMapping |
| 444 */ |
| 445 function resolveNames(properties, internalProperties, namesMapping) { |
| 446 var newProperties = []; |
| 447 if (properties) { |
| 448 for (var i = 0; i < properties.length; ++i) { |
| 449 var property = properties[i]; |
| 450 var name = namesMapping.get(property.name) || properties[i].name; |
| 451 newProperties.push(new WebInspector.RemoteObjectProperty( |
| 452 name, property.value, property.enumerable, property.writable, prop
erty.isOwn, property.wasThrown, |
| 453 property.symbol, property.synthetic)); |
| 454 } |
| 455 } |
| 456 |
| 457 callback(newProperties, internalProperties); |
| 458 } |
| 459 |
| 460 this._object.getAllProperties(accessorPropertiesOnly, wrappedCallback.bind(t
his)); |
| 461 } |
| 462 |
| 463 /** |
| 464 * @override |
| 465 * @param {string|!RuntimeAgent.CallArgument} argumentName |
| 466 * @param {string} value |
| 467 * @param {function(string=)} callback |
| 468 */ |
| 469 setPropertyValue(argumentName, value, callback) { |
| 470 WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(resolveN
ame.bind(this)); |
| 471 |
| 472 /** |
| 473 * @param {!Map<string, string>} namesMapping |
| 474 * @this {WebInspector.SourceMapNamesResolver.RemoteObject} |
| 475 */ |
| 476 function resolveName(namesMapping) { |
| 477 var name; |
| 478 if (typeof argumentName === 'string') |
| 479 name = argumentName; |
| 480 else |
| 481 name = /** @type {string} */ (argumentName.value); |
| 482 |
| 483 var actualName = name; |
| 484 for (var compiledName of namesMapping.keys()) { |
| 485 if (namesMapping.get(compiledName) === name) { |
| 486 actualName = compiledName; |
| 487 break; |
| 488 } |
| 489 } |
| 490 this._object.setPropertyValue(actualName, value, callback); |
| 491 } |
| 492 } |
| 493 |
| 494 /** |
| 495 * @override |
| 496 * @return {!Promise<?Array<!WebInspector.EventListener>>} |
| 497 */ |
| 498 eventListeners() { |
| 499 return this._object.eventListeners(); |
| 500 } |
| 501 |
| 502 /** |
| 503 * @override |
| 504 * @param {!RuntimeAgent.CallArgument} name |
| 505 * @param {function(string=)} callback |
| 506 */ |
| 507 deleteProperty(name, callback) { |
| 508 this._object.deleteProperty(name, callback); |
| 509 } |
| 510 |
| 511 /** |
| 512 * @override |
| 513 * @param {function(this:Object, ...)} functionDeclaration |
| 514 * @param {!Array<!RuntimeAgent.CallArgument>=} args |
| 515 * @param {function(?WebInspector.RemoteObject, boolean=)=} callback |
| 516 */ |
| 517 callFunction(functionDeclaration, args, callback) { |
| 518 this._object.callFunction(functionDeclaration, args, callback); |
| 519 } |
| 520 |
| 521 /** |
| 522 * @override |
| 523 * @param {function(this:Object, ...)} functionDeclaration |
| 524 * @param {!Array<!RuntimeAgent.CallArgument>|undefined} args |
| 525 * @param {function(*)} callback |
| 526 */ |
| 527 callFunctionJSON(functionDeclaration, args, callback) { |
| 528 this._object.callFunctionJSON(functionDeclaration, args, callback); |
| 529 } |
| 530 |
| 531 /** |
| 532 * @override |
| 533 * @return {!WebInspector.Target} |
| 534 */ |
| 535 target() { |
| 536 return this._object.target(); |
| 537 } |
| 538 |
| 539 /** |
| 540 * @override |
| 541 * @return {?WebInspector.DebuggerModel} |
| 542 */ |
| 543 debuggerModel() { |
| 544 return this._object.debuggerModel(); |
| 545 } |
| 546 |
| 547 /** |
| 548 * @override |
| 549 * @return {boolean} |
| 550 */ |
| 551 isNode() { |
| 552 return this._object.isNode(); |
| 553 } |
| 372 }; | 554 }; |
| 373 | |
| 374 WebInspector.SourceMapNamesResolver.RemoteObject.prototype = { | |
| 375 /** | |
| 376 * @override | |
| 377 * @return {?RuntimeAgent.CustomPreview} | |
| 378 */ | |
| 379 customPreview: function() | |
| 380 { | |
| 381 return this._object.customPreview(); | |
| 382 }, | |
| 383 | |
| 384 /** | |
| 385 * @override | |
| 386 * @return {string} | |
| 387 */ | |
| 388 get type() | |
| 389 { | |
| 390 return this._object.type; | |
| 391 }, | |
| 392 | |
| 393 /** | |
| 394 * @override | |
| 395 * @return {string|undefined} | |
| 396 */ | |
| 397 get subtype() | |
| 398 { | |
| 399 return this._object.subtype; | |
| 400 }, | |
| 401 | |
| 402 /** | |
| 403 * @override | |
| 404 * @return {string|undefined} | |
| 405 */ | |
| 406 get description() | |
| 407 { | |
| 408 return this._object.description; | |
| 409 }, | |
| 410 | |
| 411 /** | |
| 412 * @override | |
| 413 * @return {boolean} | |
| 414 */ | |
| 415 get hasChildren() | |
| 416 { | |
| 417 return this._object.hasChildren; | |
| 418 }, | |
| 419 | |
| 420 /** | |
| 421 * @override | |
| 422 * @return {number} | |
| 423 */ | |
| 424 arrayLength: function() | |
| 425 { | |
| 426 return this._object.arrayLength(); | |
| 427 }, | |
| 428 | |
| 429 /** | |
| 430 * @override | |
| 431 * @param {function(?Array.<!WebInspector.RemoteObjectProperty>, ?Array.<!We
bInspector.RemoteObjectProperty>)} callback | |
| 432 */ | |
| 433 getOwnProperties: function(callback) | |
| 434 { | |
| 435 this._object.getOwnProperties(callback); | |
| 436 }, | |
| 437 | |
| 438 /** | |
| 439 * @override | |
| 440 * @param {boolean} accessorPropertiesOnly | |
| 441 * @param {function(?Array<!WebInspector.RemoteObjectProperty>, ?Array<!WebI
nspector.RemoteObjectProperty>)} callback | |
| 442 */ | |
| 443 getAllProperties: function(accessorPropertiesOnly, callback) | |
| 444 { | |
| 445 /** | |
| 446 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties | |
| 447 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperti
es | |
| 448 * @this {WebInspector.SourceMapNamesResolver.RemoteObject} | |
| 449 */ | |
| 450 function wrappedCallback(properties, internalProperties) | |
| 451 { | |
| 452 WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(
resolveNames.bind(null, properties, internalProperties)); | |
| 453 } | |
| 454 | |
| 455 /** | |
| 456 * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties | |
| 457 * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperti
es | |
| 458 * @param {!Map<string, string>} namesMapping | |
| 459 */ | |
| 460 function resolveNames(properties, internalProperties, namesMapping) | |
| 461 { | |
| 462 var newProperties = []; | |
| 463 if (properties) { | |
| 464 for (var i = 0; i < properties.length; ++i) { | |
| 465 var property = properties[i]; | |
| 466 var name = namesMapping.get(property.name) || properties[i].
name; | |
| 467 newProperties.push(new WebInspector.RemoteObjectProperty(nam
e, property.value, property.enumerable, property.writable, property.isOwn, prope
rty.wasThrown, property.symbol, property.synthetic)); | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 callback(newProperties, internalProperties); | |
| 472 } | |
| 473 | |
| 474 this._object.getAllProperties(accessorPropertiesOnly, wrappedCallback.bi
nd(this)); | |
| 475 }, | |
| 476 | |
| 477 /** | |
| 478 * @override | |
| 479 * @param {string|!RuntimeAgent.CallArgument} argumentName | |
| 480 * @param {string} value | |
| 481 * @param {function(string=)} callback | |
| 482 */ | |
| 483 setPropertyValue: function(argumentName, value, callback) | |
| 484 { | |
| 485 WebInspector.SourceMapNamesResolver._resolveScope(this._scope).then(reso
lveName.bind(this)); | |
| 486 | |
| 487 /** | |
| 488 * @param {!Map<string, string>} namesMapping | |
| 489 * @this {WebInspector.SourceMapNamesResolver.RemoteObject} | |
| 490 */ | |
| 491 function resolveName(namesMapping) | |
| 492 { | |
| 493 var name; | |
| 494 if (typeof argumentName === "string") | |
| 495 name = argumentName; | |
| 496 else | |
| 497 name = /** @type {string} */ (argumentName.value); | |
| 498 | |
| 499 var actualName = name; | |
| 500 for (var compiledName of namesMapping.keys()) { | |
| 501 if (namesMapping.get(compiledName) === name) { | |
| 502 actualName = compiledName; | |
| 503 break; | |
| 504 } | |
| 505 } | |
| 506 this._object.setPropertyValue(actualName, value, callback); | |
| 507 } | |
| 508 }, | |
| 509 | |
| 510 /** | |
| 511 * @override | |
| 512 * @return {!Promise<?Array<!WebInspector.EventListener>>} | |
| 513 */ | |
| 514 eventListeners: function() | |
| 515 { | |
| 516 return this._object.eventListeners(); | |
| 517 }, | |
| 518 | |
| 519 /** | |
| 520 * @override | |
| 521 * @param {!RuntimeAgent.CallArgument} name | |
| 522 * @param {function(string=)} callback | |
| 523 */ | |
| 524 deleteProperty: function(name, callback) | |
| 525 { | |
| 526 this._object.deleteProperty(name, callback); | |
| 527 }, | |
| 528 | |
| 529 /** | |
| 530 * @override | |
| 531 * @param {function(this:Object, ...)} functionDeclaration | |
| 532 * @param {!Array<!RuntimeAgent.CallArgument>=} args | |
| 533 * @param {function(?WebInspector.RemoteObject, boolean=)=} callback | |
| 534 */ | |
| 535 callFunction: function(functionDeclaration, args, callback) | |
| 536 { | |
| 537 this._object.callFunction(functionDeclaration, args, callback); | |
| 538 }, | |
| 539 | |
| 540 /** | |
| 541 * @override | |
| 542 * @param {function(this:Object, ...)} functionDeclaration | |
| 543 * @param {!Array<!RuntimeAgent.CallArgument>|undefined} args | |
| 544 * @param {function(*)} callback | |
| 545 */ | |
| 546 callFunctionJSON: function(functionDeclaration, args, callback) | |
| 547 { | |
| 548 this._object.callFunctionJSON(functionDeclaration, args, callback); | |
| 549 }, | |
| 550 | |
| 551 /** | |
| 552 * @override | |
| 553 * @return {!WebInspector.Target} | |
| 554 */ | |
| 555 target: function() | |
| 556 { | |
| 557 return this._object.target(); | |
| 558 }, | |
| 559 | |
| 560 /** | |
| 561 * @override | |
| 562 * @return {?WebInspector.DebuggerModel} | |
| 563 */ | |
| 564 debuggerModel: function() | |
| 565 { | |
| 566 return this._object.debuggerModel(); | |
| 567 }, | |
| 568 | |
| 569 /** | |
| 570 * @override | |
| 571 * @return {boolean} | |
| 572 */ | |
| 573 isNode: function() | |
| 574 { | |
| 575 return this._object.isNode(); | |
| 576 }, | |
| 577 | |
| 578 __proto__: WebInspector.RemoteObject.prototype | |
| 579 }; | |
| 580 | |
| OLD | NEW |