From 47be2d565171a2b31edb11f0927f975e21ed3567 Mon Sep 17 00:00:00 2001 From: Antonin Hildebrand Date: Mon, 18 Apr 2016 19:52:29 +0200 Subject: [PATCH] squash 'resources/unpacked/devtools' changes from 61e53c7..ea1001a ea1001a [DevTools] Support broken UMA metric from M49 frontend. e42e78a Revert of [DevTools] Added keyboard search while in sources (patchset #7 id:120001 of https://codereview.chromium.org/1831903002/ ) b3fb203 DevTools: teach SourceMapNamesResolver to resolve "this" object c0fed8a Revert of DevTools: extract CPU profile independent part of CPUProfileNode. (patchset #3 id:40001 of https://codereview.chromium.org/1873973002/ ) decf4d4 DevTools: improve identifier extraction in SourceMapNamesResolver e2ca0ad Rename Heap to ThreadHeap 8228bda Revert of Rename Heap to ThreadHeap (patchset #13 id:240001 of https://codereview.chromium.org/1845543002/ ) 2a81c34 DevTools: extract CPU profile independent part of CPUProfileNode. 53d311c Rename Heap to ThreadHeap b095eff [DevTools] Fix autocomplete for iframe in top context 81abc28 DevTools: add -webkit-user-select and -webkit-user-modify completions 93a9291 DevTools: cleanup occurences of selection.getRangeAt to avoid NPE bb4305f [DevTools] Fix console history for evaluated object literals 18c6c34 [DevTools] Fix condition in ElementsTreeElement.js 4264bde DevTools: workaround bug in Blink selection API 81e05cb DevTools: deprecate InspectorTest.runAfterPendingDispatches 2dda9ca [DevTools] Added keyboard search while in sources git-subtree-dir: resources/unpacked/devtools git-subtree-split: ea1001a6820d625040879a6438bc8a5240be85c0 --- front_end/Tests.js | 2 +- front_end/common/Text.js | 10 + front_end/devtools.js | 3 + front_end/elements/ElementsTreeElement.js | 2 +- front_end/es_tree/ESTreeWalker.js | 11 +- front_end/externs.js | 2 + front_end/formatter_worker/FormatterWorker.js | 40 ++-- front_end/main/Main.js | 2 +- front_end/platform/DOMExtension.js | 8 +- front_end/platform/utilities.js | 13 ++ front_end/sdk/CSSMetadata.js | 6 + front_end/sdk/ConsoleModel.js | 3 +- front_end/sdk/DebuggerModel.js | 9 +- front_end/sdk/InspectorBackend.js | 6 +- front_end/sdk/RuntimeModel.js | 6 +- front_end/sources/ScopeChainSidebarPane.js | 14 +- front_end/sources/SourceMapNamesResolver.js | 214 ++++++++++++++---- front_end/timeline/TimelineModel.js | 2 +- front_end/ui/TextPrompt.js | 8 +- front_end/ui/ViewportControl.js | 4 +- 20 files changed, 280 insertions(+), 85 deletions(-) diff --git a/front_end/Tests.js b/front_end/Tests.js index af9d033d9a..c2bddb4981 100644 --- a/front_end/Tests.js +++ b/front_end/Tests.js @@ -578,7 +578,7 @@ TestSuite.prototype.testPauseInSharedWorkerInitialization1 = function() function callback() { var target = WebInspector.targetManager.targetsWithJSContext()[0]; - target._connection.runAfterPendingDispatches(this.releaseControl.bind(this)); + target._connection.deprecatedRunAfterPendingDispatches(this.releaseControl.bind(this)); } }; diff --git a/front_end/common/Text.js b/front_end/common/Text.js index 3e62f17a72..cc49351d8d 100644 --- a/front_end/common/Text.js +++ b/front_end/common/Text.js @@ -128,6 +128,16 @@ WebInspector.TextCursor.prototype = { return this._offset; }, + /** + * @param {number} offset + */ + resetTo: function(offset) + { + this._offset = offset; + this._lineNumber = this._lineEndings.lowerBound(offset); + this._columnNumber = this._lineNumber ? this._offset - this._lineEndings[this._lineNumber - 1] - 1 : this._offset; + }, + /** * @return {number} */ diff --git a/front_end/devtools.js b/front_end/devtools.js index 8733c4a949..dcbcd758db 100644 --- a/front_end/devtools.js +++ b/front_end/devtools.js @@ -525,6 +525,9 @@ InspectorFrontendHostImpl.prototype = { */ recordEnumeratedHistogram: function(actionName, actionCode, bucketSize) { + // Support for M49 frontend. + if (actionName === "DevTools.DrawerShown") + return; DevToolsAPI.sendMessageToEmbedder("recordEnumeratedHistogram", [actionName, actionCode, bucketSize], null); }, diff --git a/front_end/elements/ElementsTreeElement.js b/front_end/elements/ElementsTreeElement.js index d2de4a1e27..0d8deeef4a 100644 --- a/front_end/elements/ElementsTreeElement.js +++ b/front_end/elements/ElementsTreeElement.js @@ -1281,7 +1281,7 @@ WebInspector.ElementsTreeElement.prototype = { return anchor; } - if (node && name === "src" || name === "href") { + if (node && (name === "src" || name === "href")) { attrValueElement.appendChild(linkifyValue.call(this, value)); } else if (node && node.nodeName().toLowerCase() === "img" && name === "srcset") { var sources = value.split(","); diff --git a/front_end/es_tree/ESTreeWalker.js b/front_end/es_tree/ESTreeWalker.js index 6f564dbcac..dfa926c0ba 100644 --- a/front_end/es_tree/ESTreeWalker.js +++ b/front_end/es_tree/ESTreeWalker.js @@ -5,14 +5,16 @@ /** * @constructor * @param {function(!ESTree.Node)} beforeVisit - * @param {function(!ESTree.Node)} afterVisit + * @param {function(!ESTree.Node)=} afterVisit */ WebInspector.ESTreeWalker = function(beforeVisit, afterVisit) { this._beforeVisit = beforeVisit; - this._afterVisit = afterVisit; + this._afterVisit = afterVisit || new Function(); } +WebInspector.ESTreeWalker.SkipSubtree = {}; + WebInspector.ESTreeWalker.prototype = { /** * @param {!ESTree.Node} ast @@ -32,7 +34,10 @@ WebInspector.ESTreeWalker.prototype = { return; node.parent = parent; - this._beforeVisit.call(null, node); + if (this._beforeVisit.call(null, node) === WebInspector.ESTreeWalker.SkipSubtree) { + this._afterVisit.call(null, node); + return; + } var walkOrder = WebInspector.ESTreeWalker._walkOrder[node.type]; if (!walkOrder) { diff --git a/front_end/externs.js b/front_end/externs.js index 8933a5f1c2..6104f88f88 100644 --- a/front_end/externs.js +++ b/front_end/externs.js @@ -683,6 +683,8 @@ ESTree.Node = function() this.name; /** @type {(?ESTree.Node|undefined)} */ this.id; + /** @type {(number|undefined)} */ + this.length; } /** diff --git a/front_end/formatter_worker/FormatterWorker.js b/front_end/formatter_worker/FormatterWorker.js index 37014ddcfc..2c8fd46057 100644 --- a/front_end/formatter_worker/FormatterWorker.js +++ b/front_end/formatter_worker/FormatterWorker.js @@ -131,11 +131,11 @@ WebInspector.evaluatableJavaScriptSubstring = function(content) */ WebInspector.javaScriptIdentifiers = function(content) { - var root = acorn.parse(content, {}); + var root = acorn.parse(content, { ranges: false, ecmaVersion: 6 }); + /** @type {!Array} */ var identifiers = []; - var functionDeclarationCounter = 0; - var walker = new WebInspector.ESTreeWalker(beforeVisit, afterVisit); + var walker = new WebInspector.ESTreeWalker(beforeVisit); /** * @param {!ESTree.Node} node @@ -143,7 +143,7 @@ WebInspector.javaScriptIdentifiers = function(content) */ function isFunction(node) { - return node.type === "FunctionDeclaration" || node.type === "FunctionExpression"; + return node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; } /** @@ -151,29 +151,29 @@ WebInspector.javaScriptIdentifiers = function(content) */ function beforeVisit(node) { - if (isFunction(node)) - functionDeclarationCounter++; + if (isFunction(node)) { + if (node.id) + identifiers.push(node.id); + return WebInspector.ESTreeWalker.SkipSubtree; + } - if (functionDeclarationCounter > 1) + if (node.type !== "Identifier") return; - if (isFunction(node) && node.params) - identifiers.pushAll(node.params); - - if (node.type === "VariableDeclarator") - identifiers.push(/** @type {!ESTree.Node} */(node.id)); + if (node.parent && node.parent.type === "MemberExpression" && node.parent.property === node && !node.parent.computed) + return; + identifiers.push(node); } - /** - * @param {!ESTree.Node} node - */ - function afterVisit(node) - { - if (isFunction(node)) - functionDeclarationCounter--; + if (!root || root.type !== "Program" || root.body.length !== 1 || !isFunction(root.body[0])) { + postMessage([]); + return; } - walker.walk(root); + var functionNode = root.body[0]; + for (var param of functionNode.params) + walker.walk(param); + walker.walk(functionNode.body); var reduced = identifiers.map(id => ({name: id.name, offset: id.start})); postMessage(reduced); } diff --git a/front_end/main/Main.js b/front_end/main/Main.js index 4af1079396..7261054cf6 100644 --- a/front_end/main/Main.js +++ b/front_end/main/Main.js @@ -592,7 +592,7 @@ WebInspector.Main.prototype = { } } - this._mainConnection.runAfterPendingDispatches(invokeMethod); + this._mainConnection.deprecatedRunAfterPendingDispatches(invokeMethod); } } diff --git a/front_end/platform/DOMExtension.js b/front_end/platform/DOMExtension.js index 24da159bf9..90abdf26d6 100644 --- a/front_end/platform/DOMExtension.js +++ b/front_end/platform/DOMExtension.js @@ -301,7 +301,8 @@ Node.prototype.isComponentSelectionCollapsed = function() { // FIXME: crbug.com/447523, use selection.isCollapsed when it is fixed for shadow dom. var selection = this.getComponentSelection(); - return selection && selection.rangeCount ? selection.getRangeAt(0).collapsed : true; + var range = selection && selection.rangeCount ? selection.getRangeAt(0) : null; + return range ? range.collapsed : true; } /** @@ -348,9 +349,10 @@ Element.prototype.removeChildren = function() Element.prototype.isInsertionCaretInside = function() { var selection = this.getComponentSelection(); - if (!selection.rangeCount || !selection.isCollapsed) + // @see crbug.com/602541 + var selectionRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null; + if (!selectionRange || !selection.isCollapsed) return false; - var selectionRange = selection.getRangeAt(0); return selectionRange.startContainer.isSelfOrDescendant(this); } diff --git a/front_end/platform/utilities.js b/front_end/platform/utilities.js index 6025a3629d..23b353d1b0 100644 --- a/front_end/platform/utilities.js +++ b/front_end/platform/utilities.js @@ -1280,6 +1280,19 @@ Map.prototype.keysArray = function() return Array.from(this.keys()); } +/** + * @return {!Multimap} + */ +Map.prototype.inverse = function() +{ + var result = new Multimap(); + for (var key of this.keys()) { + var value = this.get(key); + result.set(value, key); + } + return result; +} + /** * @constructor * @template K, V diff --git a/front_end/sdk/CSSMetadata.js b/front_end/sdk/CSSMetadata.js index 5070d7a287..1fd86ce7ad 100644 --- a/front_end/sdk/CSSMetadata.js +++ b/front_end/sdk/CSSMetadata.js @@ -601,6 +601,12 @@ WebInspector.CSSMetadata._propertyDataMap = { "-webkit-line-break": { values: [ "auto", "loose", "normal", "strict" ] }, + "-webkit-user-select": { values: [ + "none", "text", "all" + ] }, + "-webkit-user-modify": { values: [ + "read-only", "read-write", "read-write-plaintext-only" + ] }, "text-align-last": { values: [ "auto", "start", "end", "left", "right", "center", "justify" ] }, diff --git a/front_end/sdk/ConsoleModel.js b/front_end/sdk/ConsoleModel.js index 05bff62db4..a8c69904fd 100644 --- a/front_end/sdk/ConsoleModel.js +++ b/front_end/sdk/ConsoleModel.js @@ -190,6 +190,7 @@ WebInspector.ConsoleModel.prototype = { WebInspector.ConsoleModel.evaluateCommandInConsole = function(executionContext, text, useCommandLineAPI) { var target = executionContext.target(); + var requestedText = text; var commandMessage = new WebInspector.ConsoleMessage(target, WebInspector.ConsoleMessage.MessageSource.JS, null, text, WebInspector.ConsoleMessage.MessageType.Command); commandMessage.setExecutionContextId(executionContext.id); @@ -209,7 +210,7 @@ WebInspector.ConsoleModel.evaluateCommandInConsole = function(executionContext, WebInspector.console.showPromise().then(reportUponEvaluation); function reportUponEvaluation() { - target.consoleModel.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: text, commandMessage: commandMessage, exceptionDetails: exceptionDetails}); + target.consoleModel.dispatchEventToListeners(WebInspector.ConsoleModel.Events.CommandEvaluated, {result: result, wasThrown: wasThrown, text: requestedText, commandMessage: commandMessage, exceptionDetails: exceptionDetails}); } } if (/^\s*\{/.test(text) && /\}\s*$/.test(text)) diff --git a/front_end/sdk/DebuggerModel.js b/front_end/sdk/DebuggerModel.js index f94d688c7b..2290fec752 100644 --- a/front_end/sdk/DebuggerModel.js +++ b/front_end/sdk/DebuggerModel.js @@ -1038,7 +1038,6 @@ WebInspector.DebuggerModel.CallFrame.fromPayloadArray = function(debuggerModel, } WebInspector.DebuggerModel.CallFrame.prototype = { - /** * @return {!WebInspector.Script} */ @@ -1205,6 +1204,14 @@ WebInspector.DebuggerModel.Scope = function(callFrame, ordinal) } WebInspector.DebuggerModel.Scope.prototype = { + /** + * @return {!WebInspector.DebuggerModel.CallFrame} + */ + callFrame: function() + { + return this._callFrame; + }, + /** * @return {string} */ diff --git a/front_end/sdk/InspectorBackend.js b/front_end/sdk/InspectorBackend.js index 07f58c2dad..158c143121 100644 --- a/front_end/sdk/InspectorBackend.js +++ b/front_end/sdk/InspectorBackend.js @@ -346,7 +346,7 @@ InspectorBackendClass.Connection.prototype = { console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime)); if (this._scripts && !this._pendingResponsesCount) - this.runAfterPendingDispatches(); + this.deprecatedRunAfterPendingDispatches(); return; } else { var method = messageObject.method.split("."); @@ -376,7 +376,7 @@ InspectorBackendClass.Connection.prototype = { /** * @param {function()=} script */ - runAfterPendingDispatches: function(script) + deprecatedRunAfterPendingDispatches: function(script) { if (!this._scripts) this._scripts = []; @@ -389,7 +389,7 @@ InspectorBackendClass.Connection.prototype = { if (!this._pendingResponsesCount) this._executeAfterPendingDispatches(); else - this.runAfterPendingDispatches(); + this.deprecatedRunAfterPendingDispatches(); }.bind(this), 0); }, diff --git a/front_end/sdk/RuntimeModel.js b/front_end/sdk/RuntimeModel.js index bd8c6cb9f3..45f1aebd2c 100644 --- a/front_end/sdk/RuntimeModel.js +++ b/front_end/sdk/RuntimeModel.js @@ -495,8 +495,8 @@ WebInspector.ExecutionContext.prototype = { object = this; var resultSet = {}; - for (var o = object; o; o = o.__proto__) { - try { + try { + for (var o = object; o; o = o.__proto__) { if (type === "array" && o === object && ArrayBuffer.isView(o) && o.length > 9999) continue; var names = Object.getOwnPropertyNames(o); @@ -507,8 +507,8 @@ WebInspector.ExecutionContext.prototype = { continue; resultSet[names[i]] = true; } - } catch (e) { } + } catch (e) { } return resultSet; } diff --git a/front_end/sources/ScopeChainSidebarPane.js b/front_end/sources/ScopeChainSidebarPane.js index ac4a2ef80e..53a773a127 100644 --- a/front_end/sources/ScopeChainSidebarPane.js +++ b/front_end/sources/ScopeChainSidebarPane.js @@ -41,6 +41,16 @@ WebInspector.ScopeChainSidebarPane.prototype = { * @param {?WebInspector.DebuggerModel.CallFrame} callFrame */ update: function(callFrame) + { + WebInspector.SourceMapNamesResolver.resolveThisObject(callFrame) + .then(this._innerUpdate.bind(this, callFrame)); + }, + + /** + * @param {?WebInspector.DebuggerModel.CallFrame} callFrame + * @param {?WebInspector.RemoteObject} thisObject + */ + _innerUpdate: function(callFrame, thisObject) { this.element.removeChildren(); @@ -65,7 +75,6 @@ WebInspector.ScopeChainSidebarPane.prototype = { foundLocalScope = true; title = WebInspector.UIString("Local"); emptyPlaceholder = WebInspector.UIString("No Variables"); - var thisObject = callFrame.thisObject(); if (thisObject) extraProperties.push(new WebInspector.RemoteObjectProperty("this", thisObject)); if (i == 0) { @@ -122,7 +131,10 @@ WebInspector.ScopeChainSidebarPane.prototype = { section.element.classList.add("scope-chain-sidebar-pane-section"); this.element.appendChild(section.element); } + this._sidebarPaneUpdatedForTest(); }, + _sidebarPaneUpdatedForTest: function() { }, + __proto__: WebInspector.SidebarPane.prototype } \ No newline at end of file diff --git a/front_end/sources/SourceMapNamesResolver.js b/front_end/sources/SourceMapNamesResolver.js index 5449ee591c..a3a1c9aa8e 100644 --- a/front_end/sources/SourceMapNamesResolver.js +++ b/front_end/sources/SourceMapNamesResolver.js @@ -5,53 +5,49 @@ WebInspector.SourceMapNamesResolver = {}; WebInspector.SourceMapNamesResolver._cachedMapSymbol = Symbol("cache"); -WebInspector.SourceMapNamesResolver._cachedPromiseSymbol = Symbol("cachePromise"); +WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol = Symbol("cachedIdentifiers"); /** - * @param {!WebInspector.DebuggerModel.Scope} scope - * @return {!Promise.>} + * @constructor + * @param {string} name + * @param {number} lineNumber + * @param {number} columnNumber */ -WebInspector.SourceMapNamesResolver._resolveScope = function(scope) +WebInspector.SourceMapNamesResolver.Identifier = function(name, lineNumber, columnNumber) { - var cachedMap = scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol]; - if (cachedMap) - return Promise.resolve(cachedMap); - - var cachedPromise = scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; - if (cachedPromise) - return cachedPromise; + this.name = name; + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; +} +/** + * @param {!WebInspector.DebuggerModel.Scope} scope + * @return {!Promise>} + */ +WebInspector.SourceMapNamesResolver._scopeIdentifiers = function(scope) +{ var startLocation = scope.startLocation(); var endLocation = scope.endLocation(); if (scope.type() === DebuggerAgent.ScopeType.Global || !startLocation || !endLocation || !startLocation.script().sourceMapURL || (startLocation.script() !== endLocation.script())) - return Promise.resolve(new Map()); + return Promise.resolve(/** @type {!Array}*/([])); var script = startLocation.script(); - var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(script); - if (!sourceMap) - return Promise.resolve(new Map()); - - var promise = script.requestContent().then(onContent); - scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol] = promise; - return promise; + return script.requestContent().then(onContent); /** * @param {?string} content - * @return {!Promise>} + * @return {!Promise>} */ function onContent(content) { if (!content) - return Promise.resolve(new Map()); - - var startLocation = scope.startLocation(); - var endLocation = scope.endLocation(); - var textRange = new WebInspector.TextRange(startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber); + return Promise.resolve(/** @type {!Array}*/([])); var text = new WebInspector.Text(content); - var scopeText = text.extract(textRange); - var scopeStart = text.toSourceRange(textRange).offset; + var scopeRange = new WebInspector.TextRange(startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber) + var scopeText = text.extract(scopeRange); + var scopeStart = text.toSourceRange(scopeRange).offset; var prefix = "function fui"; return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptIdentifiers(prefix + scopeText) @@ -63,28 +59,124 @@ WebInspector.SourceMapNamesResolver._resolveScope = function(scope) * @param {number} scopeStart * @param {string} prefix * @param {!Array} identifiers - * @return {!Map} + * @return {!Array} */ function onIdentifiers(text, scopeStart, prefix, identifiers) { - var namesMapping = new Map(); - var lineEndings = text.lineEndings(); - + var result = []; + var cursor = new WebInspector.TextCursor(text.lineEndings()); + var promises = []; for (var i = 0; i < identifiers.length; ++i) { var id = identifiers[i]; + if (id.offset < prefix.length) + continue; var start = scopeStart + id.offset - prefix.length; + cursor.resetTo(start); + result.push(new WebInspector.SourceMapNamesResolver.Identifier(id.name, cursor.lineNumber(), cursor.columnNumber())); + } + return result; + } +} + +/** + * @param {!WebInspector.DebuggerModel.Scope} scope + * @return {!Promise.>} + */ +WebInspector.SourceMapNamesResolver._resolveScope = function(scope) +{ + var identifiersPromise = scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol]; + if (identifiersPromise) + return identifiersPromise; + + var script = scope.callFrame().script; + var sourceMap = WebInspector.debuggerWorkspaceBinding.sourceMapForScript(script); + if (!sourceMap) + return Promise.resolve(new Map()); - var lineNumber = lineEndings.lowerBound(start); - var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[lineNumber - 1] + 1)); - var entry = sourceMap.findEntry(lineNumber, columnNumber); - if (entry) + /** @type {!Map} */ + var textCache = new Map(); + identifiersPromise = WebInspector.SourceMapNamesResolver._scopeIdentifiers(scope).then(onIdentifiers); + scope[WebInspector.SourceMapNamesResolver._cachedIdentifiersSymbol] = identifiersPromise; + return identifiersPromise; + + /** + * @param {!Array} identifiers + * @return {!Promise>} + */ + function onIdentifiers(identifiers) + { + var namesMapping = new Map(); + // Extract as much as possible from SourceMap. + for (var i = 0; i < identifiers.length; ++i) { + var id = identifiers[i]; + var entry = sourceMap.findEntry(id.lineNumber, id.columnNumber); + if (entry && entry.name) namesMapping.set(id.name, entry.name); } - scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMapping; - delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; - WebInspector.SourceMapNamesResolver._scopeResolvedForTest(); - return namesMapping; + // Resolve missing identifier names from sourcemap ranges. + var promises = []; + for (var i = 0; i < identifiers.length; ++i) { + var id = identifiers[i]; + if (namesMapping.has(id.name)) + continue; + var promise = resolveSourceName(id).then(onSourceNameResolved.bind(null, namesMapping, id)); + promises.push(promise); + } + return Promise.all(promises) + .then(() => WebInspector.SourceMapNamesResolver._scopeResolvedForTest()) + .then(() => namesMapping) + } + + /** + * @param {!Map} namesMapping + * @param {!WebInspector.SourceMapNamesResolver.Identifier} id + * @param {?string} sourceName + */ + function onSourceNameResolved(namesMapping, id, sourceName) + { + if (!sourceName) + return; + namesMapping.set(id.name, sourceName); + } + + /** + * @param {!WebInspector.SourceMapNamesResolver.Identifier} id + * @return {!Promise} + */ + function resolveSourceName(id) + { + var startEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber); + var endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.name.length); + if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sourceURL !== endEntry.sourceURL + || !startEntry.sourceLineNumber || !startEntry.sourceColumnNumber + || !endEntry.sourceLineNumber || !endEntry.sourceColumnNumber) + return Promise.resolve(/** @type {?string} */(null)); + var sourceTextRange = new WebInspector.TextRange(startEntry.sourceLineNumber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber, endEntry.sourceColumnNumber); + var uiSourceCode = WebInspector.networkMapping.uiSourceCodeForScriptURL(startEntry.sourceURL, script); + if (!uiSourceCode) + return Promise.resolve(/** @type {?string} */(null)); + + return uiSourceCode.requestContent() + .then(onSourceContent.bind(null, sourceTextRange)); + } + + /** + * @param {!WebInspector.TextRange} sourceTextRange + * @param {?string} content + * @return {?string} + */ + function onSourceContent(sourceTextRange, content) + { + if (!content) + return null; + var text = textCache.get(content); + if (!text) { + text = new WebInspector.Text(content); + textCache.set(content, text); + } + var originalIdentifier = text.extract(sourceTextRange).trim(); + return /[a-zA-Z0-9_$]+/.test(originalIdentifier) ? originalIdentifier : null; } } @@ -151,7 +243,7 @@ WebInspector.SourceMapNamesResolver.resolveExpression = function(callFrame, orig if (reverseMapping.has(originalText)) return Promise.resolve(reverseMapping.get(originalText) || ""); - return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber) + return WebInspector.SourceMapNamesResolver._resolveExpression(callFrame, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber); } } @@ -195,6 +287,48 @@ WebInspector.SourceMapNamesResolver._resolveExpression = function(callFrame, uiS } } +/** + * @param {?WebInspector.DebuggerModel.CallFrame} callFrame + * @return {!Promise} + */ +WebInspector.SourceMapNamesResolver.resolveThisObject = function(callFrame) +{ + if (!callFrame) + return Promise.resolve(/** @type {?WebInspector.RemoteObject} */(null)); + if (!Runtime.experiments.isEnabled("resolveVariableNames")) + return Promise.resolve(callFrame.thisObject()); + + return WebInspector.SourceMapNamesResolver._resolveScope(callFrame.scopeChain()[0]) + .then(onScopeResolved); + + /** + * @param {!Map} namesMapping + * @return {!Promise} + */ + function onScopeResolved(namesMapping) + { + var thisMappings = namesMapping.inverse().get("this"); + if (!thisMappings || thisMappings.size !== 1) + return Promise.resolve(callFrame.thisObject()); + + var thisMapping = thisMappings.valuesArray()[0]; + var callback; + var promise = new Promise(fulfill => callback = fulfill); + callFrame.evaluate(thisMapping, "backtrace", false, true, false, true, onEvaluated.bind(null, callback)); + return promise; + } + + /** + * @param {function(!WebInspector.RemoteObject)} callback + * @param {?RuntimeAgent.RemoteObject} evaluateResult + */ + function onEvaluated(callback, evaluateResult) + { + var remoteObject = evaluateResult ? callFrame.target().runtimeModel.createRemoteObject(evaluateResult) : callFrame.thisObject(); + callback(remoteObject); + } +} + /** * @param {!WebInspector.DebuggerModel.Scope} scope * @return {!WebInspector.RemoteObject} diff --git a/front_end/timeline/TimelineModel.js b/front_end/timeline/TimelineModel.js index 70686f5f9b..289b2dc6fa 100644 --- a/front_end/timeline/TimelineModel.js +++ b/front_end/timeline/TimelineModel.js @@ -156,7 +156,7 @@ WebInspector.TimelineModel.RecordType = { ImplSideFling: "InputHandlerProxy::HandleGestureFling::started", GCIdleLazySweep: "ThreadState::performIdleLazySweep", GCCompleteSweep: "ThreadState::completeSweep", - GCCollectGarbage: "Heap::collectGarbage", + GCCollectGarbage: "BlinkGCMarking", // CpuProfile is a virtual event created on frontend to support // serialization of CPU Profiles within tracing timeline data. diff --git a/front_end/ui/TextPrompt.js b/front_end/ui/TextPrompt.js index 4b7917c161..ce58e04b87 100644 --- a/front_end/ui/TextPrompt.js +++ b/front_end/ui/TextPrompt.js @@ -392,10 +392,10 @@ WebInspector.TextPrompt.prototype = { { this.clearAutoComplete(true); var selection = this._element.getComponentSelection(); - if (!selection.rangeCount) + var selectionRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null; + if (!selectionRange) return; - var selectionRange = selection.getRangeAt(0); var shouldExit; if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible()) @@ -684,10 +684,10 @@ WebInspector.TextPrompt.prototype = { isCaretAtEndOfPrompt: function() { var selection = this._element.getComponentSelection(); - if (!selection.rangeCount || !selection.isCollapsed) + var selectionRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null; + if (!selectionRange || !selection.isCollapsed) return false; - var selectionRange = selection.getRangeAt(0); var node = selectionRange.startContainer; if (!node.isSelfOrDescendant(this._element)) return false; diff --git a/front_end/ui/ViewportControl.js b/front_end/ui/ViewportControl.js index c8db4dbaef..7db48ee418 100644 --- a/front_end/ui/ViewportControl.js +++ b/front_end/ui/ViewportControl.js @@ -278,7 +278,8 @@ WebInspector.ViewportControl.prototype = { */ _updateSelectionModel: function(selection) { - if (!selection || !selection.rangeCount || selection.isCollapsed) { + var range = selection && selection.rangeCount ? selection.getRangeAt(0) : null; + if (!range || selection.isCollapsed) { this._headSelection = null; this._anchorSelection = null; return false; @@ -287,7 +288,6 @@ WebInspector.ViewportControl.prototype = { var firstSelected = Number.MAX_VALUE; var lastSelected = -1; - var range = selection.getRangeAt(0); var hasVisibleSelection = false; for (var i = 0; i < this._renderedItems.length; ++i) { if (range.intersectsNode(this._renderedItems[i].element())) {