diff --git a/BUILD.gn b/BUILD.gn index 7b22252a1a..e0294a700f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -41,7 +41,6 @@ devtools_modules_js_files = gypi_values.devtools_layers_js_files + gypi_values.devtools_network_js_files + gypi_values.devtools_profiler_js_files + - gypi_values.devtools_promises_js_files + gypi_values.devtools_resources_js_files + gypi_values.devtools_sass_js_files + gypi_values.devtools_security_js_files + @@ -150,7 +149,6 @@ action("generate_devtools_grd") { resources_out_dir + "layers_module.js", resources_out_dir + "network_module.js", resources_out_dir + "profiler_module.js", - resources_out_dir + "promises_module.js", resources_out_dir + "resources_module.js", resources_out_dir + "sass_module.js", resources_out_dir + "security_module.js", @@ -282,7 +280,6 @@ action("build_applications") { resources_out_dir + "layers_module.js", resources_out_dir + "network_module.js", resources_out_dir + "profiler_module.js", - resources_out_dir + "promises_module.js", resources_out_dir + "resources_module.js", resources_out_dir + "sass_module.js", resources_out_dir + "security_module.js", diff --git a/devtools.gyp b/devtools.gyp index ab14a9aa8f..bfb3128eee 100644 --- a/devtools.gyp +++ b/devtools.gyp @@ -115,7 +115,6 @@ '<(PRODUCT_DIR)/resources/inspector/layers_module.js', '<(PRODUCT_DIR)/resources/inspector/network_module.js', '<(PRODUCT_DIR)/resources/inspector/profiler_module.js', - '<(PRODUCT_DIR)/resources/inspector/promises_module.js', '<(PRODUCT_DIR)/resources/inspector/resources_module.js', '<(PRODUCT_DIR)/resources/inspector/sass_module.js', '<(PRODUCT_DIR)/resources/inspector/security_module.js', @@ -283,7 +282,6 @@ '<(_output_path)/layers_module.js', '<(_output_path)/network_module.js', '<(_output_path)/profiler_module.js', - '<(_output_path)/promises_module.js', '<(_output_path)/resources_module.js', '<(_output_path)/sass_module.js', '<(_output_path)/security_module.js', diff --git a/devtools.gypi b/devtools.gypi index 27a3c6cb7c..04ddd729ee 100644 --- a/devtools.gypi +++ b/devtools.gypi @@ -105,6 +105,7 @@ 'front_end/components/ObjectPopoverHelper.js', 'front_end/components/ObjectPropertiesSection.js', 'front_end/components/RemoteObjectPreviewFormatter.js', + 'front_end/components/RequestAppBannerActionDelegate.js', 'front_end/components/ShortcutsScreen.js', 'front_end/components/EventListenersUtils.js', 'front_end/components/EventListenersView.js', @@ -337,7 +338,6 @@ 'front_end/network/module.json', 'front_end/platform/module.json', 'front_end/profiler/module.json', - 'front_end/promises/module.json', 'front_end/resources/module.json', 'front_end/sass/module.json', 'front_end/security/module.json', @@ -497,10 +497,6 @@ 'front_end/extensions/ExtensionView.js', '<@(devtools_extension_api_files)', ], - 'devtools_promises_js_files': [ - 'front_end/promises/promisePane.css', - 'front_end/promises/PromisePane.js', - ], 'devtools_heap_snapshot_worker_js_files': [ 'front_end/common/TextUtils.js', 'front_end/common/UIString.js', @@ -775,7 +771,6 @@ '<@(devtools_layers_js_files)', '<@(devtools_network_js_files)', '<@(devtools_profiler_js_files)', - '<@(devtools_promises_js_files)', '<@(devtools_resources_js_files)', '<@(devtools_sass_js_files)', '<@(devtools_security_js_files)', @@ -823,7 +818,6 @@ 'front_end/Images/localStorage.png', 'front_end/Images/navigationControls.png', 'front_end/Images/navigationControls_2x.png', - 'front_end/Images/notifications.svg', 'front_end/Images/paneAddButtons.png', 'front_end/Images/paneFilterButtons.png', 'front_end/Images/paneRefreshButtons.png', @@ -867,7 +861,6 @@ 'front_end/Images/toolbarItemSelected.png', 'front_end/Images/touchCursor.png', 'front_end/Images/touchCursor_2x.png', - 'front_end/Images/updateServiceWorker.svg', ], 'devtools_extension_api_files': [ 'front_end/extensions/ExtensionAPI.js', diff --git a/front_end/Images/notifications.svg b/front_end/Images/notifications.svg deleted file mode 100644 index ec2adeddc5..0000000000 --- a/front_end/Images/notifications.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/front_end/Images/src/optimize_png.hashes b/front_end/Images/src/optimize_png.hashes index 25464fd48b..36fe3b8b14 100644 --- a/front_end/Images/src/optimize_png.hashes +++ b/front_end/Images/src/optimize_png.hashes @@ -3,5 +3,5 @@ "breakpoint.svg": "69cd92d807259c022791112809b97799", "settingsListRemove.svg": "ce9e7c5c5cdaef28e6ee51d9478d5485", "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28", - "toolbarButtonGlyphs.svg": "fcf3159499e07a580dc9bd827d4f627f" + "toolbarButtonGlyphs.svg": "304b6a326639d26c4710d57205413323" } \ No newline at end of file diff --git a/front_end/Images/src/svg2png.hashes b/front_end/Images/src/svg2png.hashes index 25464fd48b..36fe3b8b14 100644 --- a/front_end/Images/src/svg2png.hashes +++ b/front_end/Images/src/svg2png.hashes @@ -3,5 +3,5 @@ "breakpoint.svg": "69cd92d807259c022791112809b97799", "settingsListRemove.svg": "ce9e7c5c5cdaef28e6ee51d9478d5485", "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28", - "toolbarButtonGlyphs.svg": "fcf3159499e07a580dc9bd827d4f627f" + "toolbarButtonGlyphs.svg": "304b6a326639d26c4710d57205413323" } \ No newline at end of file diff --git a/front_end/Images/src/toolbarButtonGlyphs.svg b/front_end/Images/src/toolbarButtonGlyphs.svg index 779809e51e..fd43823dc8 100644 --- a/front_end/Images/src/toolbarButtonGlyphs.svg +++ b/front_end/Images/src/toolbarButtonGlyphs.svg @@ -21,13 +21,13 @@ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> \ No newline at end of file + sketch:type="MSShapeGroup" /> \ No newline at end of file diff --git a/front_end/Images/toolbarButtonGlyphs.png b/front_end/Images/toolbarButtonGlyphs.png index c19a2bf2ae..fad9b5ec30 100644 Binary files a/front_end/Images/toolbarButtonGlyphs.png and b/front_end/Images/toolbarButtonGlyphs.png differ diff --git a/front_end/Images/toolbarButtonGlyphs_2x.png b/front_end/Images/toolbarButtonGlyphs_2x.png index 0a8df07151..939de055b2 100644 Binary files a/front_end/Images/toolbarButtonGlyphs_2x.png and b/front_end/Images/toolbarButtonGlyphs_2x.png differ diff --git a/front_end/Images/updateServiceWorker.svg b/front_end/Images/updateServiceWorker.svg deleted file mode 100644 index 2362003f11..0000000000 --- a/front_end/Images/updateServiceWorker.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/front_end/Tests.js b/front_end/Tests.js index 81e0557550..af9d033d9a 100644 --- a/front_end/Tests.js +++ b/front_end/Tests.js @@ -978,7 +978,7 @@ TestSuite.prototype.evaluateInConsole_ = function(code, callback) function innerEvaluate() { WebInspector.context.removeFlavorChangeListener(WebInspector.ExecutionContext, showConsoleAndEvaluate, this); - var consoleView = WebInspector.ConsolePanel._view(); + var consoleView = WebInspector.ConsoleView.instance(); consoleView._prompt.setText(code); consoleView._promptElement.dispatchEvent(TestSuite.createKeyEvent("Enter")); diff --git a/front_end/animation/AnimationModel.js b/front_end/animation/AnimationModel.js index cbcb11098b..9831cb8873 100644 --- a/front_end/animation/AnimationModel.js +++ b/front_end/animation/AnimationModel.js @@ -771,7 +771,12 @@ WebInspector.AnimationModel.AnimationGroup.prototype = { return !error ? currentTime : 0; } - return this.target().animationAgent().getCurrentTime(this._animations[0].id(), callback).catchException(0); + var longestAnim = null; + for (var anim of this._animations) { + if (!longestAnim || anim.endTime() > longestAnim.endTime()) + longestAnim = anim; + } + return this.target().animationAgent().getCurrentTime(longestAnim.id(), callback).catchException(0); }, /** diff --git a/front_end/bindings/BlackboxManager.js b/front_end/bindings/BlackboxManager.js index 9e16e76f24..16e11e30c9 100644 --- a/front_end/bindings/BlackboxManager.js +++ b/front_end/bindings/BlackboxManager.js @@ -117,6 +117,7 @@ WebInspector.BlackboxManager.prototype = { if (!mappings.length) { if (previousScriptState.length > 0) return this._setScriptState(script, []); + return Promise.resolve(); } var currentBlackboxed = false; diff --git a/front_end/bindings/BreakpointManager.js b/front_end/bindings/BreakpointManager.js index 53446c5b79..867152495d 100644 --- a/front_end/bindings/BreakpointManager.js +++ b/front_end/bindings/BreakpointManager.js @@ -739,8 +739,7 @@ WebInspector.BreakpointManager.TargetBreakpoint = function(debuggerModel, breakp this._networkMapping = networkMapping; this._debuggerWorkspaceBinding = debuggerWorkspaceBinding; - /** @type {!Array.} */ - this._liveLocations = []; + this._liveLocations = new WebInspector.LiveLocationPool(); /** @type {!Object.} */ this._uiLocations = {}; @@ -763,10 +762,7 @@ WebInspector.BreakpointManager.TargetBreakpoint.prototype = { this._breakpoint._removeUILocation(uiLocations[i]); this._uiLocations = {}; - - for (var i = 0; i < this._liveLocations.length; ++i) - this._liveLocations[i].dispose(); - this._liveLocations = []; + this._liveLocations.disposeAll(); }, _scheduleUpdateInDebugger: function() @@ -944,7 +940,7 @@ WebInspector.BreakpointManager.TargetBreakpoint.prototype = { this._breakpoint.remove(); return false; } - this._liveLocations.push(this._debuggerWorkspaceBinding.createLiveLocation(location, this._locationUpdated.bind(this, location))); + this._debuggerWorkspaceBinding.createLiveLocation(location, this._locationUpdated.bind(this, location), this._liveLocations); return true; }, diff --git a/front_end/bindings/CSSWorkspaceBinding.js b/front_end/bindings/CSSWorkspaceBinding.js index 044b691ba2..41bb76a811 100644 --- a/front_end/bindings/CSSWorkspaceBinding.js +++ b/front_end/bindings/CSSWorkspaceBinding.js @@ -101,12 +101,13 @@ WebInspector.CSSWorkspaceBinding.prototype = { /** * @param {!WebInspector.CSSLocation} rawLocation * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool * @return {!WebInspector.CSSWorkspaceBinding.LiveLocation} */ - createLiveLocation: function(rawLocation, updateDelegate) + createLiveLocation: function(rawLocation, updateDelegate, locationPool) { var header = rawLocation.styleSheetId ? rawLocation.cssModel().styleSheetHeaderForId(rawLocation.styleSheetId) : null; - return new WebInspector.CSSWorkspaceBinding.LiveLocation(rawLocation.cssModel(), header, rawLocation, this, updateDelegate); + return new WebInspector.CSSWorkspaceBinding.LiveLocation(rawLocation.cssModel(), header, rawLocation, this, updateDelegate, locationPool); }, /** @@ -313,16 +314,17 @@ WebInspector.CSSWorkspaceBinding.HeaderInfo.prototype = { /** * @constructor - * @extends {WebInspector.LiveLocation} + * @extends {WebInspector.LiveLocationWithPool} * @param {!WebInspector.CSSModel} cssModel * @param {?WebInspector.CSSStyleSheetHeader} header * @param {!WebInspector.CSSLocation} rawLocation * @param {!WebInspector.CSSWorkspaceBinding} binding * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool */ -WebInspector.CSSWorkspaceBinding.LiveLocation = function(cssModel, header, rawLocation, binding, updateDelegate) +WebInspector.CSSWorkspaceBinding.LiveLocation = function(cssModel, header, rawLocation, binding, updateDelegate, locationPool) { - WebInspector.LiveLocation.call(this, updateDelegate); + WebInspector.LiveLocationWithPool.call(this, updateDelegate, locationPool); this._cssModel = cssModel; this._rawLocation = rawLocation; this._binding = binding; @@ -392,9 +394,12 @@ WebInspector.CSSWorkspaceBinding.LiveLocation.prototype = { return uiSourceCode.uiLocation(cssLocation.lineNumber, cssLocation.columnNumber); }, + /** + * @override + */ dispose: function() { - WebInspector.LiveLocation.prototype.dispose.call(this); + WebInspector.LiveLocationWithPool.prototype.dispose.call(this); if (this._header) this._binding._removeLiveLocation(this); this._cssModel.removeEventListener(WebInspector.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this); @@ -410,7 +415,7 @@ WebInspector.CSSWorkspaceBinding.LiveLocation.prototype = { return false; }, - __proto__: WebInspector.LiveLocation.prototype + __proto__: WebInspector.LiveLocationWithPool.prototype } /** diff --git a/front_end/bindings/DebuggerWorkspaceBinding.js b/front_end/bindings/DebuggerWorkspaceBinding.js index 313b8a4d5f..ab89ed06a2 100644 --- a/front_end/bindings/DebuggerWorkspaceBinding.js +++ b/front_end/bindings/DebuggerWorkspaceBinding.js @@ -122,13 +122,14 @@ WebInspector.DebuggerWorkspaceBinding.prototype = { /** * @param {!WebInspector.DebuggerModel.Location} rawLocation * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool * @return {!WebInspector.DebuggerWorkspaceBinding.Location} */ - createLiveLocation: function(rawLocation, updateDelegate) + createLiveLocation: function(rawLocation, updateDelegate, locationPool) { var info = this._infoForScript(rawLocation.target(), rawLocation.scriptId); console.assert(info); - var location = new WebInspector.DebuggerWorkspaceBinding.Location(info._script, rawLocation, this, updateDelegate); + var location = new WebInspector.DebuggerWorkspaceBinding.Location(info._script, rawLocation, this, updateDelegate, locationPool); info._addLocation(location); return location; }, @@ -136,12 +137,13 @@ WebInspector.DebuggerWorkspaceBinding.prototype = { /** * @param {!Array} rawLocations * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool * @return {!WebInspector.LiveLocation} */ - createStackTraceTopFrameLiveLocation: function(rawLocations, updateDelegate) + createStackTraceTopFrameLiveLocation: function(rawLocations, updateDelegate, locationPool) { console.assert(rawLocations.length); - var location = new WebInspector.DebuggerWorkspaceBinding.StackTraceTopFrameLocation(rawLocations, this, updateDelegate); + var location = new WebInspector.DebuggerWorkspaceBinding.StackTraceTopFrameLocation(rawLocations, this, updateDelegate, locationPool); location.update(); return location; }, @@ -149,13 +151,14 @@ WebInspector.DebuggerWorkspaceBinding.prototype = { /** * @param {!WebInspector.DebuggerModel.Location} location * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool * @return {!WebInspector.DebuggerWorkspaceBinding.Location} */ - createCallFrameLiveLocation: function(location, updateDelegate) + createCallFrameLiveLocation: function(location, updateDelegate, locationPool) { var target = location.target(); this._ensureInfoForScript(location.script()); - var liveLocation = this.createLiveLocation(location, updateDelegate); + var liveLocation = this.createLiveLocation(location, updateDelegate, locationPool); this._registerCallFrameLiveLocation(target, liveLocation); return liveLocation; }, @@ -281,7 +284,7 @@ WebInspector.DebuggerWorkspaceBinding.prototype = { _reset: function(target) { var targetData = this._targetToData.get(target); - targetData.callFrameLocations.valuesArray().forEach(function(location) { location.dispose(); }); + targetData.callFrameLocations.valuesArray().forEach((location) => this._removeLiveLocation(location)); targetData.callFrameLocations.clear(); }, @@ -468,7 +471,7 @@ WebInspector.DebuggerWorkspaceBinding.ScriptInfo = function(script) /** @type {!Array.} */ this._sourceMappings = []; - /** @type {!Set.} */ + /** @type {!Set} */ this._locations = new Set(); } @@ -532,15 +535,16 @@ WebInspector.DebuggerWorkspaceBinding.ScriptInfo.prototype = { /** * @constructor - * @extends {WebInspector.LiveLocation} + * @extends {WebInspector.LiveLocationWithPool} * @param {!WebInspector.Script} script * @param {!WebInspector.DebuggerModel.Location} rawLocation * @param {!WebInspector.DebuggerWorkspaceBinding} binding * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool */ -WebInspector.DebuggerWorkspaceBinding.Location = function(script, rawLocation, binding, updateDelegate) +WebInspector.DebuggerWorkspaceBinding.Location = function(script, rawLocation, binding, updateDelegate, locationPool) { - WebInspector.LiveLocation.call(this, updateDelegate); + WebInspector.LiveLocationWithPool.call(this, updateDelegate, locationPool); this._script = script; this._rawLocation = rawLocation; this._binding = binding; @@ -562,7 +566,7 @@ WebInspector.DebuggerWorkspaceBinding.Location.prototype = { */ dispose: function() { - WebInspector.LiveLocation.prototype.dispose.call(this); + WebInspector.LiveLocationWithPool.prototype.dispose.call(this); this._binding._removeLiveLocation(this); }, @@ -575,25 +579,26 @@ WebInspector.DebuggerWorkspaceBinding.Location.prototype = { return WebInspector.blackboxManager.isBlackboxedRawLocation(this._rawLocation); }, - __proto__: WebInspector.LiveLocation.prototype + __proto__: WebInspector.LiveLocationWithPool.prototype } /** * @constructor - * @extends {WebInspector.LiveLocation} + * @extends {WebInspector.LiveLocationWithPool} * @param {!Array} rawLocations * @param {!WebInspector.DebuggerWorkspaceBinding} binding * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool */ -WebInspector.DebuggerWorkspaceBinding.StackTraceTopFrameLocation = function(rawLocations, binding, updateDelegate) +WebInspector.DebuggerWorkspaceBinding.StackTraceTopFrameLocation = function(rawLocations, binding, updateDelegate, locationPool) { - WebInspector.LiveLocation.call(this, updateDelegate); + WebInspector.LiveLocationWithPool.call(this, updateDelegate, locationPool); this._updateScheduled = true; - /** @type {!Array} */ - this._locations = []; + /** @type {!Set} */ + this._locations = new Set(); for (var location of rawLocations) - this._locations.push(binding.createLiveLocation(location, this._scheduleUpdate.bind(this))); + this._locations.add(binding.createCallFrameLiveLocation(location, this._scheduleUpdate.bind(this), locationPool)); this._updateLocation(); } @@ -604,25 +609,26 @@ WebInspector.DebuggerWorkspaceBinding.StackTraceTopFrameLocation.prototype = { */ uiLocation: function() { - return this._currentLocation().uiLocation(); + return this._current.uiLocation(); }, /** * @override + * @return {boolean} */ - dispose: function() + isBlackboxed: function() { - for (var location of this._locations) - location.dispose(); + return this._current.isBlackboxed(); }, /** * @override - * @return {boolean} */ - isBlackboxed: function() + dispose: function() { - return this._currentLocation().isBlackboxed(); + WebInspector.LiveLocationWithPool.prototype.dispose.call(this); + for (var location of this._locations) + location.dispose(); }, _scheduleUpdate: function() @@ -633,24 +639,20 @@ WebInspector.DebuggerWorkspaceBinding.StackTraceTopFrameLocation.prototype = { } }, - /** - * @return {!WebInspector.DebuggerWorkspaceBinding.Location} - */ - _currentLocation: function() - { - return this._locations[this._current < this._locations.length ? this._current : 0]; - }, - _updateLocation: function() { this._updateScheduled = false; - this._current = 0; - while (this._current < this._locations.length && this._locations[this._current].isBlackboxed()) - ++this._current; + this._current = this._locations.values().next().value; + for (var current of this._locations) { + if (!current.isBlackboxed()) { + this._current = current; + break; + } + } this.update(); }, - __proto__: WebInspector.LiveLocation.prototype + __proto__: WebInspector.LiveLocationWithPool.prototype } /** diff --git a/front_end/bindings/LiveLocation.js b/front_end/bindings/LiveLocation.js index 50bd67c120..12625e1b31 100644 --- a/front_end/bindings/LiveLocation.js +++ b/front_end/bindings/LiveLocation.js @@ -2,22 +2,49 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/** @interface */ +WebInspector.LiveLocation = function() {} + +WebInspector.LiveLocation.prototype = { + update: function() {}, + + /** + * @return {?WebInspector.UILocation} + */ + uiLocation: function() {}, + + dispose: function() {}, + + /** + * @return {boolean} + */ + isBlackboxed: function() {} +} + /** * @constructor + * @implements {WebInspector.LiveLocation} * @param {function(!WebInspector.LiveLocation)} updateDelegate + * @param {!WebInspector.LiveLocationPool} locationPool */ -WebInspector.LiveLocation = function(updateDelegate) +WebInspector.LiveLocationWithPool = function(updateDelegate, locationPool) { this._updateDelegate = updateDelegate; + this._locationPool = locationPool; + this._locationPool._add(this); } -WebInspector.LiveLocation.prototype = { +WebInspector.LiveLocationWithPool.prototype = { + /** + * @override + */ update: function() { this._updateDelegate(this); }, /** + * @override * @return {?WebInspector.UILocation} */ uiLocation: function() @@ -25,12 +52,17 @@ WebInspector.LiveLocation.prototype = { throw "Not implemented"; }, + /** + * @override + */ dispose: function() { - // Overridden by subclasses. + this._locationPool._delete(this); + this._updateDelegate = null; }, /** + * @override * @return {boolean} */ isBlackboxed: function() @@ -38,3 +70,35 @@ WebInspector.LiveLocation.prototype = { throw "Not implemented"; } } + +/** + * @constructor + */ +WebInspector.LiveLocationPool = function() +{ + this._locations = new Set(); +} + +WebInspector.LiveLocationPool.prototype = { + /** + * @param {!WebInspector.LiveLocation} location + */ + _add: function(location) + { + this._locations.add(location); + }, + + /** + * @param {!WebInspector.LiveLocation} location + */ + _delete: function(location) + { + this._locations.delete(location); + }, + + disposeAll: function() + { + for (var location of this._locations) + location.dispose(); + } +} diff --git a/front_end/bindings/PresentationConsoleMessageHelper.js b/front_end/bindings/PresentationConsoleMessageHelper.js index 7d54c7041d..77f57d9566 100644 --- a/front_end/bindings/PresentationConsoleMessageHelper.js +++ b/front_end/bindings/PresentationConsoleMessageHelper.js @@ -48,6 +48,8 @@ WebInspector.PresentationConsoleMessageHelper = function(workspace) WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this); WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this); WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this); + + this._locationPool = new WebInspector.LiveLocationPool(); } WebInspector.PresentationConsoleMessageHelper.prototype = { @@ -101,7 +103,7 @@ WebInspector.PresentationConsoleMessageHelper.prototype = { */ _addConsoleMessageToScript: function(message, rawLocation) { - this._presentationConsoleMessages.push(new WebInspector.PresentationConsoleMessage(message, rawLocation)); + this._presentationConsoleMessages.push(new WebInspector.PresentationConsoleMessage(message, rawLocation, this._locationPool)); }, /** @@ -151,6 +153,7 @@ WebInspector.PresentationConsoleMessageHelper.prototype = { for (var i = 0; i < this._presentationConsoleMessages.length; ++i) this._presentationConsoleMessages[i].dispose(); this._presentationConsoleMessages = []; + this._locationPool.disposeAll(); }, _debuggerReset: function() @@ -163,12 +166,13 @@ WebInspector.PresentationConsoleMessageHelper.prototype = { * @constructor * @param {!WebInspector.ConsoleMessage} message * @param {!WebInspector.DebuggerModel.Location} rawLocation + * @param {!WebInspector.LiveLocationPool} locationPool */ -WebInspector.PresentationConsoleMessage = function(message, rawLocation) +WebInspector.PresentationConsoleMessage = function(message, rawLocation, locationPool) { this._text = message.messageText; this._level = message.level === WebInspector.ConsoleMessage.MessageLevel.Error ? WebInspector.UISourceCode.Message.Level.Error : WebInspector.UISourceCode.Message.Level.Warning; - this._liveLocation = WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this._updateLocation.bind(this)); + WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this._updateLocation.bind(this), locationPool); } WebInspector.PresentationConsoleMessage.prototype = { @@ -187,7 +191,6 @@ WebInspector.PresentationConsoleMessage.prototype = { dispose: function() { - this._liveLocation.dispose(); if (this._uiMessage) this._uiMessage.remove(); } diff --git a/front_end/bindings/SASSSourceMapping.js b/front_end/bindings/SASSSourceMapping.js index 6041cebdea..4bb7c5f137 100644 --- a/front_end/bindings/SASSSourceMapping.js +++ b/front_end/bindings/SASSSourceMapping.js @@ -42,6 +42,7 @@ WebInspector.SASSSourceMapping = function(cssModel, networkMapping, networkProje this._networkMapping = networkMapping; this._cssModel.addEventListener(WebInspector.CSSModel.Events.SourceMapAttached, this._sourceMapAttached, this); this._cssModel.addEventListener(WebInspector.CSSModel.Events.SourceMapDetached, this._sourceMapDetached, this); + this._cssModel.addEventListener(WebInspector.CSSModel.Events.SourceMapChanged, this._sourceMapChanged, this); } WebInspector.SASSSourceMapping.prototype = { @@ -70,6 +71,32 @@ WebInspector.SASSSourceMapping.prototype = { WebInspector.cssWorkspaceBinding.updateLocations(header); }, + /** + * @param {!WebInspector.Event} event + */ + _sourceMapChanged: function(event) + { + var sourceMap = /** @type {!WebInspector.SourceMap} */(event.data.sourceMap); + var newSources = /** @type {!Map} */(event.data.newSources); + var headers = this._cssModel.headersForSourceMap(sourceMap); + var handledUISourceCodes = new Set(); + for (var header of headers) { + WebInspector.cssWorkspaceBinding.updateLocations(header); + for (var sourceURL of newSources.keys()) { + var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(sourceURL, header); + if (!uiSourceCode) { + console.error("Failed to update source for " + sourceURL); + continue; + } + if (handledUISourceCodes.has(uiSourceCode)) + continue; + handledUISourceCodes.add(uiSourceCode); + var sassText = /** @type {string} */(newSources.get(sourceURL)); + uiSourceCode.addRevision(sassText); + } + } + }, + /** * @param {!WebInspector.CSSStyleSheetHeader} header */ diff --git a/front_end/common/ResourceType.js b/front_end/common/ResourceType.js index 4cdb4dd318..6e343109eb 100644 --- a/front_end/common/ResourceType.js +++ b/front_end/common/ResourceType.js @@ -190,7 +190,7 @@ WebInspector.resourceTypes = { Other: new WebInspector.ResourceType("other", "Other", WebInspector.resourceCategories.Other, false), SourceMapScript: new WebInspector.ResourceType("sm-script", "Script", WebInspector.resourceCategories.Script, false), SourceMapStyleSheet: new WebInspector.ResourceType("sm-stylesheet", "Stylesheet", WebInspector.resourceCategories.Stylesheet, false), - Manifest: new WebInspector.ResourceType("manifest", "Manifest", WebInspector.resourceCategories.Manifest, false), + Manifest: new WebInspector.ResourceType("manifest", "Manifest", WebInspector.resourceCategories.Manifest, true), } /** diff --git a/front_end/common/Text.js b/front_end/common/Text.js index 4e02e37d91..3e62f17a72 100644 --- a/front_end/common/Text.js +++ b/front_end/common/Text.js @@ -95,3 +95,52 @@ WebInspector.Text.prototype = { return this._value.substr(sourceRange.offset, sourceRange.length); }, } + +/** + * @constructor + * @param {!Array} lineEndings + */ +WebInspector.TextCursor = function(lineEndings) +{ + this._lineEndings = lineEndings; + this._offset = 0; + this._lineNumber = 0; + this._columnNumber = 0; +} + +WebInspector.TextCursor.prototype = { + /** + * @param {number} offset + */ + advance: function(offset) + { + this._offset = offset; + while (this._lineNumber < this._lineEndings.length && this._lineEndings[this._lineNumber] < this._offset) + ++this._lineNumber; + this._columnNumber = this._lineNumber ? this._offset - this._lineEndings[this._lineNumber - 1] - 1 : this._offset; + }, + + /** + * @return {number} + */ + offset: function() + { + return this._offset; + }, + + /** + * @return {number} + */ + lineNumber: function() + { + return this._lineNumber; + }, + + /** + * @return {number} + */ + columnNumber: function() + { + return this._columnNumber; + } +} diff --git a/front_end/common/TextRange.js b/front_end/common/TextRange.js index 661674001f..e478d29bc3 100644 --- a/front_end/common/TextRange.js +++ b/front_end/common/TextRange.js @@ -196,15 +196,6 @@ WebInspector.TextRange.prototype = { this.startColumn === other.startColumn && this.endColumn === other.endColumn; }, - /** - * @param {number} lineOffset - * @return {!WebInspector.TextRange} - */ - shift: function(lineOffset) - { - return new WebInspector.TextRange(this.startLine + lineOffset, this.startColumn, this.endLine + lineOffset, this.endColumn); - }, - /** * @param {number} line * @param {number} column @@ -355,3 +346,12 @@ WebInspector.SourceEdit.prototype = { }, } +/** + * @param {!WebInspector.SourceEdit} edit1 + * @param {!WebInspector.SourceEdit} edit2 + * @return {number} + */ +WebInspector.SourceEdit.comparator = function(edit1, edit2) +{ + return WebInspector.TextRange.comparator(edit1.oldRange, edit2.oldRange); +} diff --git a/front_end/components/Linkifier.js b/front_end/components/Linkifier.js index 6e70d88d6d..fe34672a41 100644 --- a/front_end/components/Linkifier.js +++ b/front_end/components/Linkifier.js @@ -52,8 +52,10 @@ WebInspector.LinkifierFormatter.prototype = { WebInspector.Linkifier = function(formatter) { this._formatter = formatter || new WebInspector.Linkifier.DefaultFormatter(WebInspector.Linkifier.MaxLengthForDisplayedURLs); - /** @type {!Map.>}*/ - this._liveLocationsByTarget = new Map(); + /** @type {!Map>} */ + this._anchorsByTarget = new Map(); + /** @type {!Map} */ + this._locationPoolByTarget = new Map(); WebInspector.targetManager.observeTargets(this); } @@ -115,6 +117,7 @@ WebInspector.Linkifier.linkifyUsingRevealer = function(revealable, text, fallbac WebInspector.Linkifier._uiLocationSymbol = Symbol("uiLocation"); WebInspector.Linkifier._fallbackAnchorSymbol = Symbol("fallbackAnchor"); +WebInspector.Linkifier._liveLocationSymbol = Symbol("liveLocation"); WebInspector.Linkifier.prototype = { /** @@ -123,7 +126,8 @@ WebInspector.Linkifier.prototype = { */ targetAdded: function(target) { - this._liveLocationsByTarget.set(target, new Map()); + this._anchorsByTarget.set(target, []); + this._locationPoolByTarget.set(target, new WebInspector.LiveLocationPool()); }, /** @@ -132,12 +136,11 @@ WebInspector.Linkifier.prototype = { */ targetRemoved: function(target) { - var liveLocations = this._liveLocationsByTarget.remove(target); - var anchors = liveLocations.keysArray(); - for (var i = 0; i < anchors.length; ++i) { - var anchor = anchors[i]; - var location = liveLocations.get(anchor); - delete anchor[WebInspector.Linkifier._uiLocationSymbol]; + var locationPool = /** @type {!WebInspector.LiveLocationPool} */(this._locationPoolByTarget.remove(target)); + locationPool.disposeAll(); + var anchors = this._anchorsByTarget.remove(target); + for (var anchor of anchors) { + delete anchor[WebInspector.Linkifier._liveLocationSymbol]; var fallbackAnchor = anchor[WebInspector.Linkifier._fallbackAnchorSymbol]; if (fallbackAnchor) { anchor.href = fallbackAnchor.href; @@ -147,7 +150,6 @@ WebInspector.Linkifier.prototype = { anchor.textContent = fallbackAnchor.textContent; delete anchor[WebInspector.Linkifier._fallbackAnchorSymbol]; } - location.dispose(); } }, @@ -175,8 +177,10 @@ WebInspector.Linkifier.prototype = { return fallbackAnchor; var anchor = this._createAnchor(classes); - var liveLocation = WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this._updateAnchor.bind(this, anchor)); - this._liveLocationsByTarget.get(rawLocation.target()).set(anchor, liveLocation); + var liveLocation = WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this._updateAnchor.bind(this, anchor), /** @type {!WebInspector.LiveLocationPool} */(this._locationPoolByTarget.get(rawLocation.target()))); + var anchors = /** @type {!Array} */(this._anchorsByTarget.get(rawLocation.target())); + anchors.push(anchor); + anchor[WebInspector.Linkifier._liveLocationSymbol] = liveLocation; anchor[WebInspector.Linkifier._fallbackAnchorSymbol] = fallbackAnchor; return anchor; }, @@ -224,8 +228,10 @@ WebInspector.Linkifier.prototype = { return fallbackAnchor; var anchor = this._createAnchor(classes); - var liveLocation = WebInspector.debuggerWorkspaceBinding.createStackTraceTopFrameLiveLocation(rawLocations, this._updateAnchor.bind(this, anchor)); - this._liveLocationsByTarget.get(target).set(anchor, liveLocation); + var liveLocation = WebInspector.debuggerWorkspaceBinding.createStackTraceTopFrameLiveLocation(rawLocations, this._updateAnchor.bind(this, anchor), /** @type {!WebInspector.LiveLocationPool} */(this._locationPoolByTarget.get(target))); + var anchors = /** @type {!Array} */(this._anchorsByTarget.get(target)); + anchors.push(anchor); + anchor[WebInspector.Linkifier._liveLocationSymbol] = liveLocation; anchor[WebInspector.Linkifier._fallbackAnchorSymbol] = fallbackAnchor; return anchor; }, @@ -238,8 +244,10 @@ WebInspector.Linkifier.prototype = { linkifyCSSLocation: function(rawLocation, classes) { var anchor = this._createAnchor(classes); - var liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation(rawLocation, this._updateAnchor.bind(this, anchor)); - this._liveLocationsByTarget.get(rawLocation.target()).set(anchor, liveLocation); + var liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation(rawLocation, this._updateAnchor.bind(this, anchor), /** @type {!WebInspector.LiveLocationPool} */(this._locationPoolByTarget.get(rawLocation.target()))); + var anchors = /** @type {!Array} */(this._anchorsByTarget.get(rawLocation.target())); + anchors.push(anchor); + anchor[WebInspector.Linkifier._liveLocationSymbol] = liveLocation; return anchor; }, @@ -251,12 +259,10 @@ WebInspector.Linkifier.prototype = { { delete anchor[WebInspector.Linkifier._uiLocationSymbol]; delete anchor[WebInspector.Linkifier._fallbackAnchorSymbol]; - var liveLocations = this._liveLocationsByTarget.get(target); - if (!liveLocations) - return; - var location = liveLocations.remove(anchor); - if (location) - location.dispose(); + var liveLocation = anchor[WebInspector.Linkifier._liveLocationSymbol]; + if (liveLocation) + liveLocation.dispose(); + delete anchor[WebInspector.Linkifier._liveLocationSymbol]; }, /** @@ -289,9 +295,7 @@ WebInspector.Linkifier.prototype = { reset: function() { - var targets = this._liveLocationsByTarget.keysArray(); - for (var i = 0; i < targets.length; ++i) { - var target = targets[i]; + for (var target of this._anchorsByTarget.keysArray()) { this.targetRemoved(target); this.targetAdded(target); } @@ -299,9 +303,9 @@ WebInspector.Linkifier.prototype = { dispose: function() { - this.reset(); + for (var target of this._anchorsByTarget.keysArray()) + this.targetRemoved(target); WebInspector.targetManager.unobserveTargets(this); - this._liveLocationsByTarget.clear(); }, /** diff --git a/front_end/components/NetworkConditionsSelector.js b/front_end/components/NetworkConditionsSelector.js index 4c2db2df48..bf851ab09e 100644 --- a/front_end/components/NetworkConditionsSelector.js +++ b/front_end/components/NetworkConditionsSelector.js @@ -39,7 +39,7 @@ WebInspector.NetworkConditionsSelector._throughputText = function(throughput) /** @type {!Array.} */ WebInspector.NetworkConditionsSelector._presets = [ - {title: "Offline", download: 0 * 1024 / 8, upload: 0 * 1024 / 8, latency: 0}, + WebInspector.NetworkManager.OfflineConditions, {title: "GPRS", download: 50 * 1024 / 8, upload: 20 * 1024 / 8, latency: 500}, {title: "Regular 2G", download: 250 * 1024 / 8, upload: 50 * 1024 / 8, latency: 300}, {title: "Good 2G", download: 450 * 1024 / 8, upload: 150 * 1024 / 8, latency: 150}, @@ -434,3 +434,32 @@ WebInspector.NetworkConditionsSettingsTab.prototype = { __proto__: WebInspector.VBox.prototype } + +/** + * @constructor + * @implements {WebInspector.ActionDelegate} + */ +WebInspector.NetworkConditionsActionDelegate = function() +{ +} + +WebInspector.NetworkConditionsActionDelegate.prototype = { + /** + * @override + * @param {!WebInspector.Context} context + * @param {string} actionId + * @return {boolean} + */ + handleAction: function(context, actionId) + { + if (actionId === "components.network-online") { + WebInspector.multitargetNetworkManager.setNetworkConditions(WebInspector.NetworkManager.NoThrottlingConditions); + return true; + } + if (actionId === "components.network-offline") { + WebInspector.multitargetNetworkManager.setNetworkConditions(WebInspector.NetworkManager.OfflineConditions); + return true; + } + return false; + } +} diff --git a/front_end/components/RequestAppBannerActionDelegate.js b/front_end/components/RequestAppBannerActionDelegate.js new file mode 100644 index 0000000000..21f09f6ecd --- /dev/null +++ b/front_end/components/RequestAppBannerActionDelegate.js @@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @constructor + * @implements {WebInspector.ActionDelegate} + */ +WebInspector.RequestAppBannerActionDelegate = function() +{ +} + +WebInspector.RequestAppBannerActionDelegate.prototype = { + /** + * @override + * @param {!WebInspector.Context} context + * @param {string} actionId + * @return {boolean} + */ + handleAction: function(context, actionId) + { + var target = WebInspector.targetManager.mainTarget(); + if (target && target.isPage()) { + target.pageAgent().requestAppBanner(); + WebInspector.console.show(); + } + return true; + } +} diff --git a/front_end/components/module.json b/front_end/components/module.json index b1fb6ddf9c..bb36a96929 100644 --- a/front_end/components/module.json +++ b/front_end/components/module.json @@ -21,6 +21,22 @@ "settingType": "array", "defaultValue": [] }, + { + "type": "@WebInspector.ActionDelegate", + "actionId": "components.network-offline", + "category": "Network", + "title": "Go offline", + "className": "WebInspector.NetworkConditionsActionDelegate", + "tags": "device" + }, + { + "type": "@WebInspector.ActionDelegate", + "actionId": "components.network-online", + "category": "Network", + "title": "Go online", + "className": "WebInspector.NetworkConditionsActionDelegate", + "tags": "device" + }, { "type": "settings-view", "name": "network-conditions", @@ -30,6 +46,13 @@ "settings": [ "customNetworkConditions" ] + }, + { + "type": "@WebInspector.ActionDelegate", + "category": "Mobile", + "actionId": "components.request-app-banner", + "className": "WebInspector.RequestAppBannerActionDelegate", + "title": "Trigger add to homescreen" } ], "dependencies": [ @@ -52,6 +75,7 @@ "ObjectPopoverHelper.js", "ObjectPropertiesSection.js", "RemoteObjectPreviewFormatter.js", + "RequestAppBannerActionDelegate.js", "ShortcutsScreen.js", "EventListenersUtils.js", "EventListenersView.js", diff --git a/front_end/console/ConsolePanel.js b/front_end/console/ConsolePanel.js index fae8e4491c..47a5027db5 100644 --- a/front_end/console/ConsolePanel.js +++ b/front_end/console/ConsolePanel.js @@ -33,18 +33,7 @@ WebInspector.ConsolePanel = function() { WebInspector.Panel.call(this, "console"); - this._view = WebInspector.ConsolePanel._view(); -} - -/** - * @return {!WebInspector.ConsoleView} - */ -WebInspector.ConsolePanel._view = function() -{ - if (!WebInspector.ConsolePanel._consoleView) - WebInspector.ConsolePanel._consoleView = new WebInspector.ConsoleView(); - - return WebInspector.ConsolePanel._consoleView; + this._view = WebInspector.ConsoleView.instance(); } WebInspector.ConsolePanel.prototype = { @@ -86,7 +75,7 @@ WebInspector.ConsolePanel.prototype = { */ searchableView: function() { - return WebInspector.ConsolePanel._view().searchableView(); + return WebInspector.ConsoleView.instance().searchableView(); }, __proto__: WebInspector.Panel.prototype @@ -103,7 +92,7 @@ WebInspector.ConsolePanel.WrapperView = function() WebInspector.ConsolePanel.WrapperView._instance = this; - this._view = WebInspector.ConsolePanel._view(); + this._view = WebInspector.ConsoleView.instance(); } WebInspector.ConsolePanel.WrapperView.prototype = { @@ -158,7 +147,7 @@ WebInspector.ConsolePanel.ConsoleRevealer.prototype = { */ reveal: function(object) { - var consoleView = WebInspector.ConsolePanel._view(); + var consoleView = WebInspector.ConsoleView.instance(); if (consoleView.isShowing()) { consoleView.focus(); return Promise.resolve(); diff --git a/front_end/console/ConsoleView.js b/front_end/console/ConsoleView.js index da86d912bc..851347821a 100644 --- a/front_end/console/ConsoleView.js +++ b/front_end/console/ConsoleView.js @@ -164,6 +164,12 @@ WebInspector.ConsoleView.prototype = { return this._searchableView; }, + _clearHistory: function() + { + this._consoleHistorySetting.set([]); + this._prompt.setHistoryData([]); + }, + /** * @param {!WebInspector.Event} event */ @@ -578,6 +584,7 @@ WebInspector.ConsoleView.prototype = { contextMenu.appendSeparator(); contextMenu.appendAction("console.clear"); + contextMenu.appendAction("console.clear.history"); contextMenu.appendItem(WebInspector.UIString("Save as..."), this._saveConsole.bind(this)); var request = consoleMessage ? consoleMessage.request : null; @@ -1274,6 +1281,16 @@ WebInspector.ConsoleGroup.prototype = { }, } +/** + * @return {!WebInspector.ConsoleView} + */ +WebInspector.ConsoleView.instance = function() +{ + if (!WebInspector.ConsoleView._instance) + WebInspector.ConsoleView._instance = new WebInspector.ConsoleView(); + return WebInspector.ConsoleView._instance; +} + /** * @constructor * @implements {WebInspector.ActionDelegate} @@ -1298,6 +1315,9 @@ WebInspector.ConsoleView.ActionDelegate.prototype = { case "console.clear": WebInspector.ConsoleModel.clearConsole(); return true; + case "console.clear.history": + WebInspector.ConsoleView.instance()._clearHistory(); + return true; } return false; } diff --git a/front_end/console/module.json b/front_end/console/module.json index 181d9e0804..2cdde5847b 100644 --- a/front_end/console/module.json +++ b/front_end/console/module.json @@ -48,6 +48,13 @@ } ] }, + { + "type": "@WebInspector.ActionDelegate", + "category": "Console", + "actionId": "console.clear.history", + "title": "Clear console history", + "className": "WebInspector.ConsoleView.ActionDelegate" + }, { "type": "setting", "category": "Console", diff --git a/front_end/devtools.js b/front_end/devtools.js index 84325f7a37..8733c4a949 100644 --- a/front_end/devtools.js +++ b/front_end/devtools.js @@ -1001,6 +1001,11 @@ function installBackwardsCompatibility() var styleElement = window.document.createElement("style"); styleElement.type = "text/css"; styleElement.textContent = "html /deep/ * { min-width: 0; min-height: 0; }"; + + // Support for quirky border-image behavior ( WebInspector.actionRegistry.action("elements.edit-as-html").execute()); + }, + __proto__: TreeElement.prototype } diff --git a/front_end/elements/StylesSidebarPane.js b/front_end/elements/StylesSidebarPane.js index 299c2fa4cd..fa507a75a5 100644 --- a/front_end/elements/StylesSidebarPane.js +++ b/front_end/elements/StylesSidebarPane.js @@ -218,10 +218,11 @@ WebInspector.StylesSidebarPane.prototype = { if (!node) return; + var fullRefresh = Runtime.experiments.isEnabled("liveSASS"); for (var section of this.allSections()) { if (section.isBlank) continue; - section.update(section === editedSection); + section.update(fullRefresh || section === editedSection); } if (this._filterRegex) @@ -2391,7 +2392,10 @@ WebInspector.StylePropertyTreeElement.prototype = { if (!isEditingName && this._parentPane._mouseDownTreeElementIsName) moveDirection = "backward"; } - this.editingCommitted((context.isEditingName ? this.name : this.value) || event.target.textContent, context, moveDirection); + var text = event.target.textContent; + if (!context.isEditingName) + text = this.value || text; + this.editingCommitted(text, context, moveDirection); } this._originalPropertyText = this.property.propertyText; diff --git a/front_end/emulation/DeviceModeView.js b/front_end/emulation/DeviceModeView.js index d4c2a4969a..4980cc9c7a 100644 --- a/front_end/emulation/DeviceModeView.js +++ b/front_end/emulation/DeviceModeView.js @@ -16,10 +16,9 @@ WebInspector.DeviceModeView = function() this._model = new WebInspector.DeviceModeModel(this._updateUI.bind(this)); this._mediaInspector = new WebInspector.MediaQueryInspector(() => this._model.appliedDeviceSize().width, this._model.setWidth.bind(this._model)); - // TODO(dgozman): remove CountUpdated event. - this._showMediaInspectorSetting = WebInspector.settings.createSetting("showMediaQueryInspector", false); + this._showMediaInspectorSetting = WebInspector.settings.moduleSetting("showMediaQueryInspector"); this._showMediaInspectorSetting.addChangeListener(this._updateUI, this); - this._showRulersSetting = WebInspector.settings.createSetting("emulation.showRulers", false); + this._showRulersSetting = WebInspector.settings.moduleSetting("emulation.showRulers"); this._showRulersSetting.addChangeListener(this._updateUI, this); this._topRuler = new WebInspector.DeviceModeView.Ruler(true, this._model.setWidthAndScaleToFit.bind(this._model)); @@ -352,6 +351,52 @@ WebInspector.DeviceModeView.prototype = { this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null); }, + captureScreenshot: function() + { + var mainTarget = WebInspector.targetManager.mainTarget(); + if (!mainTarget) + return; + mainTarget.pageAgent().captureScreenshot(screenshotCaptured.bind(this)); + + /** + * @param {?Protocol.Error} error + * @param {string} content + * @this {WebInspector.DeviceModeView} + */ + function screenshotCaptured(error, content) + { + if (error) + return; + + // Create a canvas to splice the images together. + var canvas = createElement("canvas"); + var ctx = canvas.getContext("2d"); + var screenRect = this._model.screenRect(); + canvas.width = screenRect.width; + canvas.height = screenRect.height; + // Add any available screen images. + if (this._model.screenImage()) { + var screenImage = new Image(); + screenImage.crossOrigin = "Anonymous"; + screenImage.srcset = this._model.screenImage(); + ctx.drawImage(screenImage, 0, 0, screenRect.width, screenRect.height); + } + var pageImage = new Image(); + pageImage.src = "data:image/png;base64," + content; + var visiblePageRect = this._model.visiblePageRect(); + ctx.drawImage(pageImage, visiblePageRect.left, visiblePageRect.top, visiblePageRect.width, visiblePageRect.height); + var mainFrame = mainTarget.resourceTreeModel.mainFrame; + var fileName = mainFrame ? mainFrame.url.trimURL().removeURLFragment() : ""; + if (this._model.type() === WebInspector.DeviceModeModel.Type.Device) + fileName += WebInspector.UIString("(%s)", this._model.device().title); + // Trigger download. + var link = createElement("a"); + link.download = fileName + ".png"; + link.href = canvas.toDataURL("image/png"); + link.click(); + } + }, + __proto__: WebInspector.VBox.prototype } diff --git a/front_end/emulation/DeviceModeWrapper.js b/front_end/emulation/DeviceModeWrapper.js index 51515ccc47..f1cfe7f1c7 100644 --- a/front_end/emulation/DeviceModeWrapper.js +++ b/front_end/emulation/DeviceModeWrapper.js @@ -29,6 +29,17 @@ WebInspector.DeviceModeWrapper.prototype = { this._showDeviceModeSetting.set(!this._showDeviceModeSetting.get()); }, + /** + * @return {boolean} + */ + _captureScreenshot: function() + { + if (!this._deviceModeView) + return false; + this._deviceModeView.captureScreenshot(); + return true; + }, + /** * @param {boolean} force */ @@ -80,12 +91,8 @@ WebInspector.DeviceModeWrapper.ActionDelegate.prototype = { WebInspector.DeviceModeView._wrapperInstance._toggleDeviceMode(); return true; } - if (actionId === "emulation.request-app-banner") { - var target = WebInspector.targetManager.mainTarget(); - if (target && target.isPage()) - target.pageAgent().requestAppBanner(); - return true; - } + if (actionId === "emulation.capture-screenshot") + return WebInspector.DeviceModeView._wrapperInstance._captureScreenshot(); } return false; } diff --git a/front_end/emulation/module.json b/front_end/emulation/module.json index 988c5234c0..0375d4f9a4 100644 --- a/front_end/emulation/module.json +++ b/front_end/emulation/module.json @@ -25,6 +25,18 @@ } ] }, + { + "type": "@WebInspector.ActionDelegate", + "actionId": "emulation.capture-screenshot", + "className": "WebInspector.DeviceModeWrapper.ActionDelegate", + "title": "Capture screenshot" + }, + { + "type": "context-menu-item", + "location": "deviceModeMenu/tools", + "order": 12, + "actionId": "emulation.capture-screenshot" + }, { "type": "@WebInspector.ToolbarItem.Provider", "actionId": "emulation.toggle-device-mode", @@ -32,6 +44,30 @@ "location": "main-toolbar-left", "order": 1 }, + { + "type": "setting", + "category": "Mobile", + "settingName": "showMediaQueryInspector", + "settingType": "boolean", + "defaultValue": false, + "options": [ + {"value": true, "title": "Show media queries"}, + {"value": false, "title": "Hide media queries"} + ], + "tags": "device" + }, + { + "type": "setting", + "category": "Mobile", + "settingName": "emulation.showRulers", + "settingType": "boolean", + "defaultValue": false, + "options": [ + {"value": true, "title": "Show rulers"}, + {"value": false, "title": "Hide rulers"} + ], + "tags": "device" + }, { "type": "settings-view", "name": "devices", @@ -64,18 +100,11 @@ "className": "WebInspector.SensorsView", "tags": "geolocation, accelerometer, device orientation" }, - { - "type": "@WebInspector.ActionDelegate", - "actionId": "emulation.request-app-banner", - "className": "WebInspector.DeviceModeWrapper.ActionDelegate", - "title": "Request app banner\u2026" - }, { "type": "context-menu-item", "location": "deviceModeMenu/tools", - "experiment": "appBanner", "order": 10, - "actionId": "emulation.request-app-banner" + "actionId": "components.request-app-banner" } ], "dependencies": [ diff --git a/front_end/formatter_worker/CSSFormatter.js b/front_end/formatter_worker/CSSFormatter.js index 5743e0deb5..3476327b90 100644 --- a/front_end/formatter_worker/CSSFormatter.js +++ b/front_end/formatter_worker/CSSFormatter.js @@ -59,14 +59,11 @@ WebInspector.CSSFormatter.prototype = { * @param {string} token * @param {?string} type * @param {number} startPosition - * @param {number} endPosition */ - _tokenCallback: function(token, type, startPosition, endPosition) + _tokenCallback: function(token, type, startPosition) { startPosition += this._fromOffset; - endPosition += this._fromOffset; var startLine = this._lineEndings.lowerBound(startPosition); - var endLine = this._lineEndings.lowerBound(endPosition); if (startLine !== this._lastLine) this._state.eatWhitespace = true; if (/^property/.test(type) && !this._state.inPropertyValue) @@ -94,7 +91,7 @@ WebInspector.CSSFormatter.prototype = { this._state.afterClosingBrace = true; this._state.inPropertyValue = false; } else if (token === ":" && !this._state.inPropertyValue && this._state.seenProperty) { - this._builder.addToken(token, startPosition, startLine, endLine); + this._builder.addToken(token, startPosition); this._builder.addSoftSpace(); this._state.eatWhitespace = true; this._state.inPropertyValue = true; @@ -102,13 +99,13 @@ WebInspector.CSSFormatter.prototype = { return; } else if (token === "{") { this._builder.addSoftSpace(); - this._builder.addToken(token, startPosition, startLine, endLine); + this._builder.addToken(token, startPosition); this._builder.addNewLine(); this._builder.increaseNestingLevel(); return; } - this._builder.addToken(token, startPosition, startLine, endLine); + this._builder.addToken(token, startPosition); if (type === "comment" && !this._state.inPropertyValue && !this._state.seenProperty) this._builder.addNewLine(); diff --git a/front_end/formatter_worker/FormattedContentBuilder.js b/front_end/formatter_worker/FormattedContentBuilder.js index 4a5428be4f..3d1d266e87 100644 --- a/front_end/formatter_worker/FormattedContentBuilder.js +++ b/front_end/formatter_worker/FormattedContentBuilder.js @@ -17,7 +17,6 @@ WebInspector.FormattedContentBuilder = function(indentString) /** @type {!{original: !Array., formatted: !Array.}} */ this._mapping = { original: [0], formatted: [0] }; - this._lineNumber = 0; this._nestingLevel = 0; this._indentString = indentString; /** @type {!Map} */ @@ -31,15 +30,10 @@ WebInspector.FormattedContentBuilder = function(indentString) WebInspector.FormattedContentBuilder.prototype = { /** * @param {string} token - * @param {number} startPosition - * @param {number} startLine - * @param {number} endLine + * @param {number} offset */ - addToken: function(token, startPosition, startLine, endLine) + addToken: function(token, offset) { - if (this._lineNumber < startLine) - this._newLines = Math.max(this._newLines, startLine - this._lineNumber); - var last = this._formattedContent.peekLast(); if (last && /\w/.test(last[last.length - 1]) && /\w/.test(token)) this.addSoftSpace(); @@ -47,9 +41,8 @@ WebInspector.FormattedContentBuilder.prototype = { this._appendFormatting(); // Insert token. - this._addMappingIfNeeded(startPosition); + this._addMappingIfNeeded(offset); this._addText(token); - this._lineNumber = endLine; }, addSoftSpace: function() diff --git a/front_end/formatter_worker/FormatterWorker.js b/front_end/formatter_worker/FormatterWorker.js index 4d22f1b252..37014ddcfc 100644 --- a/front_end/formatter_worker/FormatterWorker.js +++ b/front_end/formatter_worker/FormatterWorker.js @@ -72,11 +72,112 @@ self.onmessage = function(event) { case "javaScriptOutline": WebInspector.javaScriptOutline(params.content); break; + case "javaScriptIdentifiers": + WebInspector.javaScriptIdentifiers(params.content); + break; + case "evaluatableJavaScriptSubstring": + WebInspector.evaluatableJavaScriptSubstring(params.content); + break; default: console.error("Unsupport method name: " + method); } }; +/** + * @param {string} content + */ +WebInspector.evaluatableJavaScriptSubstring = function(content) +{ + var tokenizer = acorn.tokenizer(content, {ecmaVersion: 6}); + var result = ""; + try { + var token = tokenizer.getToken(); + while (token.type !== acorn.tokTypes.eof && WebInspector.AcornTokenizer.punctuator(token)) + token = tokenizer.getToken(); + + var startIndex = token.start; + var endIndex = token.end; + var openBracketsCounter = 0; + while (token.type !== acorn.tokTypes.eof) { + var isIdentifier = WebInspector.AcornTokenizer.identifier(token); + var isThis = WebInspector.AcornTokenizer.keyword(token, "this"); + var isString = token.type === acorn.tokTypes.string; + if (!isThis && !isIdentifier && !isString) + break; + + endIndex = token.end; + token = tokenizer.getToken(); + while (WebInspector.AcornTokenizer.punctuator(token, ".[]")) { + if (WebInspector.AcornTokenizer.punctuator(token, "[")) + openBracketsCounter++; + + if (WebInspector.AcornTokenizer.punctuator(token, "]")) { + endIndex = openBracketsCounter > 0 ? token.end : endIndex; + openBracketsCounter--; + } + + token = tokenizer.getToken(); + } + } + result = content.substring(startIndex, endIndex); + } catch (e) { + console.error(e); + } + postMessage(result); +} + +/** + * @param {string} content + */ +WebInspector.javaScriptIdentifiers = function(content) +{ + var root = acorn.parse(content, {}); + /** @type {!Array} */ + var identifiers = []; + var functionDeclarationCounter = 0; + var walker = new WebInspector.ESTreeWalker(beforeVisit, afterVisit); + + /** + * @param {!ESTree.Node} node + * @return {boolean} + */ + function isFunction(node) + { + return node.type === "FunctionDeclaration" || node.type === "FunctionExpression"; + } + + /** + * @param {!ESTree.Node} node + */ + function beforeVisit(node) + { + if (isFunction(node)) + functionDeclarationCounter++; + + if (functionDeclarationCounter > 1) + return; + + if (isFunction(node) && node.params) + identifiers.pushAll(node.params); + + if (node.type === "VariableDeclarator") + identifiers.push(/** @type {!ESTree.Node} */(node.id)); + } + + /** + * @param {!ESTree.Node} node + */ + function afterVisit(node) + { + if (isFunction(node)) + functionDeclarationCounter--; + } + + walker.walk(root); + var reduced = identifiers.map(id => ({name: id.name, offset: id.start})); + postMessage(reduced); +} + /** * @param {string} mimeType * @param {string} text diff --git a/front_end/formatter_worker/HTMLFormatter.js b/front_end/formatter_worker/HTMLFormatter.js index ab7f46a5c2..9514125d63 100644 --- a/front_end/formatter_worker/HTMLFormatter.js +++ b/front_end/formatter_worker/HTMLFormatter.js @@ -49,9 +49,7 @@ WebInspector.HTMLFormatter.prototype = { tokenStart += fromOffset; tokenEnd += fromOffset; lastOffset = tokenEnd; - var startLine = lineEndings.lowerBound(tokenStart); - var endLine = lineEndings.lowerBound(tokenEnd); - this._builder.addToken(tokenValue, tokenStart, startLine, endLine); + this._builder.addToken(tokenValue, tokenStart); if (!type) return; diff --git a/front_end/formatter_worker/IdentityFormatter.js b/front_end/formatter_worker/IdentityFormatter.js index bafb5f2b1b..e428b7066a 100644 --- a/front_end/formatter_worker/IdentityFormatter.js +++ b/front_end/formatter_worker/IdentityFormatter.js @@ -21,9 +21,7 @@ WebInspector.IdentityFormatter.prototype = { format: function(text, lineEndings, fromOffset, toOffset) { var content = text.substring(fromOffset, toOffset); - var startLine = lineEndings.lowerBound(fromOffset); - var endLine = lineEndings.lowerBound(toOffset); - this._builder.addToken(content, fromOffset, startLine, endLine); + this._builder.addToken(content, fromOffset); } } diff --git a/front_end/formatter_worker/JavaScriptFormatter.js b/front_end/formatter_worker/JavaScriptFormatter.js index 7a8c611aa5..6a61ddce29 100644 --- a/front_end/formatter_worker/JavaScriptFormatter.js +++ b/front_end/formatter_worker/JavaScriptFormatter.js @@ -46,7 +46,6 @@ WebInspector.JavaScriptFormatter.prototype = { */ format: function(text, lineEndings, fromOffset, toOffset) { - this._lineOffset = lineEndings.lowerBound(fromOffset); this._fromOffset = fromOffset; this._toOffset = toOffset; this._content = text.substring(this._fromOffset, this._toOffset); @@ -74,7 +73,7 @@ WebInspector.JavaScriptFormatter.prototype = { else if (format[i] === "<") this._builder.decreaseNestingLevel(); else if (format[i] === "t") - this._builder.addToken(this._content.substring(token.start, token.end), this._fromOffset + token.start, this._lineOffset + this._tokenizer.tokenLineStart(), this._lineOffset + this._tokenizer.tokenLineEnd()); + this._builder.addToken(this._content.substring(token.start, token.end), this._fromOffset + token.start); } }, @@ -132,7 +131,7 @@ WebInspector.JavaScriptFormatter.prototype = { if (AT.lineComment(token)) return "tn"; if (AT.blockComment(token)) - return "t"; + return "tn"; if (node.type === "ContinueStatement" || node.type === "BreakStatement") { return node.label && AT.keyword(token) ? "ts" : "t"; } else if (node.type === "Identifier") { diff --git a/front_end/inspector.json b/front_end/inspector.json index 657336c6ce..f3a0a2b1dc 100644 --- a/front_end/inspector.json +++ b/front_end/inspector.json @@ -26,7 +26,6 @@ { "name": "cm_modes", "type": "remote" }, { "name": "settings" }, { "name": "layers" }, - { "name": "promises" }, { "name": "snippets" }, { "name": "diff" }, { "name": "sass" }, diff --git a/front_end/main/Main.js b/front_end/main/Main.js index b67f01d7f5..8302a039aa 100644 --- a/front_end/main/Main.js +++ b/front_end/main/Main.js @@ -103,7 +103,6 @@ WebInspector.Main.prototype = { { Runtime.experiments.register("accessibilityInspection", "Accessibility Inspection"); Runtime.experiments.register("applyCustomStylesheet", "Allow custom UI themes"); - Runtime.experiments.register("appBanner", "App banner support", true); Runtime.experiments.register("blackboxJSFramesOnTimeline", "Blackbox JavaScript frames on Timeline", true); Runtime.experiments.register("colorContrastRatio", "Contrast ratio line in color picker", true); Runtime.experiments.register("cpuThrottling", "CPU throttling", true); @@ -112,11 +111,11 @@ WebInspector.Main.prototype = { Runtime.experiments.register("layersPanel", "Layers panel"); Runtime.experiments.register("layoutEditor", "Layout editor", true); Runtime.experiments.register("inspectTooltip", "Dark inspect element tooltip"); + Runtime.experiments.register("liveSASS", "Live SASS", true); Runtime.experiments.register("multipleTimelineViews", "Multiple main views on Timeline", true); Runtime.experiments.register("networkRequestHeadersFilterInDetailsView", "Network request headers filter in details view", true); Runtime.experiments.register("networkRequestsOnTimeline", "Network requests on Timeline", true); Runtime.experiments.register("privateScriptInspection", "Private script inspection"); - Runtime.experiments.register("promiseTracker", "Promise inspector"); Runtime.experiments.register("reducedIndentation", "Reduced indentation in Elements DOM tree"); Runtime.experiments.register("requestBlocking", "Request blocking", true); Runtime.experiments.register("resolveVariableNames", "Resolve variable names", true); @@ -134,8 +133,6 @@ WebInspector.Main.prototype = { if (InspectorFrontendHost.isUnderTest()) { var testPath = JSON.parse(prefs["testPath"] || "\"\""); // Enable experiments for testing. - if (testPath.indexOf("debugger/promise") !== -1) - Runtime.experiments.enableForTest("promiseTracker"); if (testPath.indexOf("layers/") !== -1) Runtime.experiments.enableForTest("layersPanel"); if (testPath.indexOf("timeline/") !== -1 || testPath.indexOf("layers/") !== -1) diff --git a/front_end/main/module.json b/front_end/main/module.json index dfccf28766..0a441fdd47 100644 --- a/front_end/main/module.json +++ b/front_end/main/module.json @@ -59,10 +59,8 @@ }, { "type": "@WebInspector.ActionDelegate", - "category": "Navigation", "actionId": "main.debug-reload", "className": "WebInspector.Main.ReloadActionDelegate", - "title": "Clear cache & hard reload page", "bindings": [ { "shortcut": "Alt+R" diff --git a/front_end/network/NetworkLogView.js b/front_end/network/NetworkLogView.js index fe06f36582..4b7c2d7978 100644 --- a/front_end/network/NetworkLogView.js +++ b/front_end/network/NetworkLogView.js @@ -252,7 +252,7 @@ WebInspector.NetworkLogView.prototype = { _addFilters: function() { - this._textFilterUI = new WebInspector.TextFilterUI(); + this._textFilterUI = new WebInspector.TextFilterUI(true); this._textFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterChanged, this._filterChanged, this); this._filterBar.addFilter(this._textFilterUI); @@ -966,11 +966,16 @@ WebInspector.NetworkLogView.prototype = { var node = this._nodesByRequestId.get(requestId); if (!node) continue; - if (!node[WebInspector.NetworkLogView._isFilteredOutSymbol]) - rootNode.removeChild(node); - node[WebInspector.NetworkLogView._isFilteredOutSymbol] = !this._applyFilter(node); - if (!node[WebInspector.NetworkLogView._isFilteredOutSymbol]) - nodesToInsert.push(node); + var isFilteredOut = !this._applyFilter(node); + if (node[WebInspector.NetworkLogView._isFilteredOutSymbol] !== isFilteredOut) { + if (!node[WebInspector.NetworkLogView._isFilteredOutSymbol]) + rootNode.removeChild(node); + + node[WebInspector.NetworkLogView._isFilteredOutSymbol] = isFilteredOut; + + if (!node[WebInspector.NetworkLogView._isFilteredOutSymbol]) + nodesToInsert.push(node); + } var request = node.request(); this._timeCalculator.updateBoundaries(request); this._durationCalculator.updateBoundaries(request); @@ -1570,7 +1575,7 @@ WebInspector.NetworkLogView.prototype = { */ supportsRegexSearch: function() { - return false; + return true; }, /** @@ -1634,8 +1639,14 @@ WebInspector.NetworkLogView.prototype = { */ _parseFilterQuery: function(query) { - var parsedQuery = this._suggestionBuilder.parseQuery(query); - this._filters = parsedQuery.text.map(this._createTextFilter); + var parsedQuery; + if (this._textFilterUI.isRegexChecked() && query !== "") + parsedQuery = {text: [query], filters: []}; + else + parsedQuery = this._suggestionBuilder.parseQuery(query); + + this._filters = parsedQuery.text.map(this._createTextFilter, this); + var n = parsedQuery.filters.length; for (var i = 0; i < n; ++i) { var filter = parsedQuery.filters[i]; @@ -1651,11 +1662,12 @@ WebInspector.NetworkLogView.prototype = { _createTextFilter: function(text) { var negative = false; - if (text[0] === "-" && text.length > 1) { + if (!this._textFilterUI.isRegexChecked() && text[0] === "-" && text.length > 1) { negative = true; text = text.substring(1); } - var regexp = new RegExp(text.escapeForRegExp(), "i"); + var regexp = this._textFilterUI.regex(); + var filter = WebInspector.NetworkLogView._requestNameOrPathFilter.bind(null, regexp); if (negative) filter = WebInspector.NetworkLogView._negativeFilter.bind(null, filter); @@ -1935,12 +1947,14 @@ WebInspector.NetworkLogView._negativeFilter = function(filter, request) } /** - * @param {!RegExp} regex + * @param {?RegExp} regex * @param {!WebInspector.NetworkRequest} request * @return {boolean} */ WebInspector.NetworkLogView._requestNameOrPathFilter = function(regex, request) { + if (!regex) + return false; return regex.test(request.name()) || regex.test(request.path()); } diff --git a/front_end/platform/utilities.js b/front_end/platform/utilities.js index a4a133262a..6025a3629d 100644 --- a/front_end/platform/utilities.js +++ b/front_end/platform/utilities.js @@ -1239,6 +1239,20 @@ Set.prototype.addAll = function(iterable) this.add(e); } +/** + * @param {!Iterable|!Array} iterable + * @return {boolean} + * @template T + */ +Set.prototype.containsAll = function(iterable) +{ + for (var e of iterable) { + if (!this.has(e)) + return false; + } + return true; +} + /** * @return {T} * @template T @@ -1312,6 +1326,19 @@ Multimap.prototype = { return this._map.has(key); }, + /** + * @param {K} key + * @param {V} value + * @return {boolean} + */ + hasValue: function(key, value) + { + var set = this._map.get(key); + if (!set) + return false; + return set.has(value); + }, + /** * @return {number} */ diff --git a/front_end/profiler/CPUProfileBottomUpDataGrid.js b/front_end/profiler/CPUProfileBottomUpDataGrid.js index 8f3f02db8f..591d4acbb6 100644 --- a/front_end/profiler/CPUProfileBottomUpDataGrid.js +++ b/front_end/profiler/CPUProfileBottomUpDataGrid.js @@ -172,9 +172,6 @@ WebInspector.BottomUpProfileDataGridNode._sharedPopulate = function(container) } } - for (var i = 0; i < container.children.length; ++i) - container.children[i].buildData(); - delete container._remainingNodeInfos; } @@ -325,10 +322,6 @@ WebInspector.BottomUpProfileDataGridTree.prototype = { return this._searchResults.length; }, - buildData: function() - { - }, - /** * @override */ diff --git a/front_end/profiler/CPUProfileDataGrid.js b/front_end/profiler/CPUProfileDataGrid.js index a8430b46a2..863127a0e2 100644 --- a/front_end/profiler/CPUProfileDataGrid.js +++ b/front_end/profiler/CPUProfileDataGrid.js @@ -52,100 +52,62 @@ WebInspector.ProfileDataGridNode = function(profileNode, owningTree, hasChildren WebInspector.ProfileDataGridNode.prototype = { /** * @override - * @param {string} columnIdentifier + * @param {string} columnId * @return {!Element} */ - createCell: function(columnIdentifier) + createCell: function(columnId) { - var cell = this._createValueCell(columnIdentifier) || WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier); - - if (columnIdentifier === "self" && this._searchMatchedSelfColumn) - cell.classList.add("highlight"); - else if (columnIdentifier === "total" && this._searchMatchedTotalColumn) - cell.classList.add("highlight"); - - if (columnIdentifier !== "function") + /** + * @param {number} value + * @param {number} percent + * @return {!Element} + */ + function createValueCell(value, percent) + { + var cell = createElementWithClass("td", "numeric-column"); + var div = cell.createChild("div", "profile-multiple-values"); + div.createChild("span").textContent = WebInspector.UIString("%.1f\u2009ms", value); + div.createChild("span", "percent-column").textContent = percent >= 0 ? WebInspector.UIString("%.2f\u2009%%", percent) : ""; return cell; + } - if (this._deoptReason) - cell.classList.add("not-optimized"); - - if (this._searchMatchedFunctionColumn) - cell.classList.add("highlight"); - - if (this.profileNode.scriptId !== "0") { + var cell; + var isIdleNode = this.profileNode === this.tree.profileView.profile.idleNode; + switch (columnId) { + case "self": + cell = createValueCell(this.selfTime, isIdleNode ? -1 : this.selfPercent); + cell.classList.toggle("highlight", this._searchMatchedSelfColumn); + break; + + case "total": + cell = createValueCell(this.totalTime, isIdleNode ? -1 : this.totalPercent); + cell.classList.toggle("highlight", this._searchMatchedTotalColumn); + break; + + case "function": + cell = this.createTD(columnId); + cell.classList.toggle("highlight", this._searchMatchedFunctionColumn); + if (this._deoptReason) { + cell.classList.add("not-optimized"); + cell.createChild("span", "profile-warn-marker").title = WebInspector.UIString("Not optimized: %s", this._deoptReason); + } + cell.createTextChild(this.functionName); + if (this.profileNode.scriptId === "0") + break; var target = this.tree.profileView.target(); var callFrame = /** @type {!RuntimeAgent.CallFrame} */ (this.profileNode); var urlElement = this.tree.profileView._linkifier.linkifyConsoleCallFrame(target, callFrame, "profile-node-file"); urlElement.style.maxWidth = "75%"; - cell.insertBefore(urlElement, cell.firstChild); - } - - return cell; - }, - - /** - * @param {string} columnIdentifier - * @return {?Element} - */ - _createValueCell: function(columnIdentifier) - { - if (columnIdentifier !== "self" && columnIdentifier !== "total") - return null; + cell.appendChild(urlElement); + break; - var cell = createElement("td"); - cell.className = "numeric-column"; - var div = createElement("div"); - var valueSpan = createElement("span"); - valueSpan.textContent = this.data[columnIdentifier]; - div.appendChild(valueSpan); - var percentColumn = columnIdentifier + "-percent"; - if (percentColumn in this.data) { - var percentSpan = createElement("span"); - percentSpan.className = "percent-column"; - percentSpan.textContent = this.data[percentColumn]; - div.appendChild(percentSpan); - div.classList.add("profile-multiple-values"); + default: + cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnId); + break; } - cell.appendChild(div); return cell; }, - buildData: function() - { - function formatMilliseconds(time) - { - return WebInspector.UIString("%.1f\u2009ms", time); - } - function formatPercent(value) - { - return WebInspector.UIString("%.2f\u2009%%", value); - } - - var functionName; - if (this._deoptReason) { - var content = createDocumentFragment(); - var marker = content.createChild("span", "profile-warn-marker"); - marker.title = WebInspector.UIString("Not optimized: %s", this._deoptReason); - content.createTextChild(this.functionName); - functionName = content; - } else { - functionName = this.functionName; - } - - this.data = { - "function": functionName, - "self-percent": formatPercent(this.selfPercent), - "self": formatMilliseconds(this.selfTime), - "total-percent": formatPercent(this.totalPercent), - "total": formatMilliseconds(this.totalTime), - }; - if (this.profileNode === this.tree.profileView.profile.idleNode) { - this.data['self-percent'] = undefined; - this.data['total-percent'] = undefined - } - }, - select: function(supressSelectedEvent) { WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent); diff --git a/front_end/profiler/CPUProfileTopDownDataGrid.js b/front_end/profiler/CPUProfileTopDownDataGrid.js index 48445c8843..f28e58b314 100644 --- a/front_end/profiler/CPUProfileTopDownDataGrid.js +++ b/front_end/profiler/CPUProfileTopDownDataGrid.js @@ -36,7 +36,6 @@ WebInspector.TopDownProfileDataGridNode = function(profileNode, owningTree) WebInspector.ProfileDataGridNode.call(this, profileNode, owningTree, hasChildren); this._remainingChildren = profileNode.children; - this.buildData(); } WebInspector.TopDownProfileDataGridNode.prototype = { diff --git a/front_end/promises/PromisePane.js b/front_end/promises/PromisePane.js deleted file mode 100644 index 24381fe2a6..0000000000 --- a/front_end/promises/PromisePane.js +++ /dev/null @@ -1,791 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @constructor - * @extends {WebInspector.VBox} - * @implements {WebInspector.TargetManager.Observer} - */ -WebInspector.PromisePane = function() -{ - WebInspector.VBox.call(this); - this.registerRequiredCSS("promises/promisePane.css"); - this.element.classList.add("promises"); - - var toolbar = new WebInspector.Toolbar("", this.element); - this._recordButton = new WebInspector.ToolbarToggle("", "record-toolbar-item"); - this._recordButton.addEventListener("click", this._recordButtonClicked.bind(this)); - toolbar.appendToolbarItem(this._recordButton); - - var clearButton = new WebInspector.ToolbarButton(WebInspector.UIString("Clear"), "clear-toolbar-item"); - clearButton.addEventListener("click", this._clearButtonClicked.bind(this)); - toolbar.appendToolbarItem(clearButton); - toolbar.appendSeparator(); - - this._promiseStatusFiltersSetting = WebInspector.settings.createSetting("promiseStatusFilters", {}); - this._hideCollectedPromisesSetting = WebInspector.settings.createSetting("hideCollectedPromises", false); - - this._createFilterBar(); - toolbar.appendToolbarItem(this._filterBar.filterButton()); - - var garbageCollectButton = new WebInspector.ToolbarButton(WebInspector.UIString("Collect garbage"), "garbage-collect-toolbar-item"); - garbageCollectButton.addEventListener("click", this._garbageCollectButtonClicked, this); - toolbar.appendToolbarItem(garbageCollectButton); - - toolbar.appendSeparator(); - var asyncCheckbox = new WebInspector.ToolbarCheckbox(WebInspector.UIString("Async"), WebInspector.UIString("Capture async stack traces"), WebInspector.moduleSetting("enableAsyncStackTraces")); - toolbar.appendToolbarItem(asyncCheckbox); - - this._filterBar.show(this.element); - - this._hiddenByFilterCount = 0; - this._filterStatusMessageElement = this.element.createChild("div", "promises-filter-status hidden"); - this._filterStatusTextElement = this._filterStatusMessageElement.createChild("span"); - this._filterStatusMessageElement.createTextChild(" "); - var resetFiltersLink = this._filterStatusMessageElement.createChild("span", "link"); - resetFiltersLink.textContent = WebInspector.UIString("Show all promises."); - resetFiltersLink.addEventListener("click", this._resetFilters.bind(this), true); - - // FIXME: Make "status" column width fixed to ~16px. - var columns = [ - { id: "status", weight: 1 }, - { id: "function", title: WebInspector.UIString("Function"), disclosure: true, weight: 10 }, - { id: "created", title: WebInspector.UIString("Created"), weight: 10 }, - { id: "settled", title: WebInspector.UIString("Settled"), weight: 10 }, - { id: "tts", title: WebInspector.UIString("Time to settle"), weight: 10 } - ]; - this._dataGrid = new WebInspector.ViewportDataGrid(columns, undefined, undefined, undefined, this._onContextMenu.bind(this)); - this._dataGrid.setStickToBottom(true); - this._dataGrid.asWidget().show(this.element); - - this._linkifier = new WebInspector.Linkifier(); - - /** @type {!Map.>} */ - this._promiseDetailsByDebuggerModel = new Map(); - /** @type {!Map.} */ - this._promiseIdToNode = new Map(); - - this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); - this._popoverHelper.setTimeout(250, 250); - - this.element.addEventListener("click", this._hidePopover.bind(this), true); - - WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.PromiseUpdated, this._onPromiseUpdated, this); - WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this); - WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targetChanged, this); - - WebInspector.targetManager.observeTargets(this); -} - -WebInspector.PromisePane._maxPromiseCount = 10000; - - -/** - * @constructor - * @param {!DebuggerAgent.PromiseDetails} details - */ -WebInspector.PromiseDetails = function(details) -{ - this.id = details.id; - this.isGarbageCollected = false; - this.update(details); -} - -WebInspector.PromiseDetails.prototype = { - /** - * @param {!DebuggerAgent.PromiseDetails} details - */ - update: function(details) - { - if (this.id !== details.id) - throw new Error("Invalid id, expected " + this.id + " was " + details.id); - if (details.status) - this.status = details.status; - if (details.parentId) - this.parentId = details.parentId; - if (details.creationTime) - this.creationTime = details.creationTime; - if (details.settlementTime) - this.settlementTime = details.settlementTime; - if (details.creationStack) { - this.creationStack = details.creationStack; - if (this.creationStack.callFrames.length) - this.callFrame = this.creationStack.callFrames[0]; - } - if (details.asyncCreationStack) - this.asyncCreationStack = details.asyncCreationStack; - if (details.settlementStack) - this.settlementStack = details.settlementStack; - if (details.asyncSettlementStack) - this.asyncSettlementStack = details.asyncSettlementStack; - } -} - - -WebInspector.PromisePane.prototype = { - _createFilterBar: function() - { - this._filterBar = new WebInspector.FilterBar("promisePane"); - - this._textFilterUI = new WebInspector.TextFilterUI(true); - this._textFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterChanged, this._onFilterChanged, this); - this._filterBar.addFilter(this._textFilterUI); - - var statuses = [ - { name: "pending", label: WebInspector.UIString("Pending") }, - { name: "resolved", label: WebInspector.UIString("Fulfilled") }, - { name: "rejected", label: WebInspector.UIString("Rejected") } - ]; - this._statusFilterUI = new WebInspector.NamedBitSetFilterUI(statuses, this._promiseStatusFiltersSetting); - this._statusFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterChanged, this._onFilterChanged, this); - this._filterBar.addFilter(this._statusFilterUI); - - var hideCollectedCheckbox = new WebInspector.CheckboxFilterUI("hide-collected-promises", WebInspector.UIString("Hide collected promises"), true, this._hideCollectedPromisesSetting); - hideCollectedCheckbox.addEventListener(WebInspector.FilterUI.Events.FilterChanged, this._onFilterChanged, this); - this._filterBar.addFilter(hideCollectedCheckbox); - }, - - /** - * @param {!WebInspector.PromiseDetails} details - * @param {!WebInspector.DataGridNode} node - * @return {boolean} - */ - _shouldBeVisible: function(details, node) - { - if (!this._statusFilterUI.accept(details.status)) - return false; - - if (this._hideCollectedPromisesSetting.get() && details.isGarbageCollected) - return false; - - var regex = this._textFilterUI.regex(); - if (!regex) - return true; - - var text = node.dataTextForSearch(); - regex.lastIndex = 0; - return regex.test(text); - }, - - _onFilterChanged: function() - { - if (this._filterChangedTimeout) - clearTimeout(this._filterChangedTimeout); - this._filterChangedTimeout = setTimeout(onTimerFired.bind(this), 100); - - /** - * @this {WebInspector.PromisePane} - */ - function onTimerFired() - { - delete this._filterChangedTimeout; - this._refresh(); - } - }, - - /** - * @override - * @return {!Array.} - */ - elementsToRestoreScrollPositionsFor: function() - { - return [this._dataGrid.scrollContainer]; - }, - - /** - * @override - * @param {!WebInspector.Target} target - */ - targetAdded: function(target) - { - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); - if (debuggerModel && this._enabled) - this._enablePromiseTracker(debuggerModel); - }, - - /** - * @override - * @param {!WebInspector.Target} target - */ - targetRemoved: function(target) - { - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); - if (!debuggerModel) - return; - this._promiseDetailsByDebuggerModel.delete(debuggerModel); - if (this._debuggerModel === debuggerModel) { - this._clear(); - delete this._debuggerModel; - } - }, - - /** - * @param {!WebInspector.Event} event - */ - _targetChanged: function(event) - { - if (!this._enabled) - return; - var target = /** @type {!WebInspector.Target} */ (event.data); - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); - if (!debuggerModel || this._debuggerModel === debuggerModel) - return; - this._debuggerModel = debuggerModel; - this._refresh(); - }, - - /** - * @param {!WebInspector.Event} event - */ - _mainFrameNavigated: function(event) - { - var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data); - var target = frame.target(); - var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); - if (!debuggerModel) - return; - this._promiseDetailsByDebuggerModel.delete(debuggerModel); - if (this._debuggerModel === debuggerModel) - this._clear(); - }, - - /** @override */ - wasShown: function() - { - // Auto enable upon the very first show. - if (typeof this._enabled === "undefined") { - var target = WebInspector.context.flavor(WebInspector.Target); - this._debuggerModel = WebInspector.DebuggerModel.fromTarget(target); - this._updateRecordingState(true); - } - if (this._refreshIsNeeded) - this._refresh(); - }, - - /** - * @param {!WebInspector.DebuggerModel} debuggerModel - */ - _enablePromiseTracker: function(debuggerModel) - { - debuggerModel.enablePromiseTracker(true); - }, - - /** - * @param {!WebInspector.DebuggerModel} debuggerModel - */ - _disablePromiseTracker: function(debuggerModel) - { - debuggerModel.disablePromiseTracker(); - }, - - /** @override */ - willHide: function() - { - this._hidePopover(); - }, - - _hidePopover: function() - { - this._popoverHelper.hidePopover(); - }, - - _recordButtonClicked: function() - { - this._updateRecordingState(!this._recordButton.toggled()); - }, - - /** - * @param {boolean} enabled - */ - _updateRecordingState: function(enabled) - { - this._enabled = enabled; - this._recordButton.setToggled(this._enabled); - this._recordButton.setTitle(this._enabled ? WebInspector.UIString("Stop Recording Promises Log") : WebInspector.UIString("Record Promises Log")); - WebInspector.DebuggerModel.instances().forEach(this._enabled ? this._enablePromiseTracker : this._disablePromiseTracker, this); - }, - - _clearButtonClicked: function() - { - this._clear(); - if (this._debuggerModel) - this._promiseDetailsByDebuggerModel.delete(this._debuggerModel); - }, - - _resetFilters: function() - { - this._hideCollectedPromisesSetting.set(false); - this._promiseStatusFiltersSetting.set({}); - this._textFilterUI.setValue(""); - }, - - _updateFilterStatus: function() - { - this._filterStatusTextElement.textContent = WebInspector.UIString(this._hiddenByFilterCount === 1 ? "%d promise is hidden by filters." : "%d promises are hidden by filters.", this._hiddenByFilterCount); - this._filterStatusMessageElement.classList.toggle("hidden", !this._hiddenByFilterCount); - }, - - _garbageCollectButtonClicked: function() - { - var targets = WebInspector.targetManager.targets(); - for (var i = 0; i < targets.length; ++i) - targets[i].heapProfilerAgent().collectGarbage(); - }, - - /** - * @param {!WebInspector.DebuggerModel} debuggerModel - * @return {boolean} - */ - _truncateLogIfNeeded: function(debuggerModel) - { - var promiseIdToDetails = this._promiseDetailsByDebuggerModel.get(debuggerModel); - if (!promiseIdToDetails || promiseIdToDetails.size <= WebInspector.PromisePane._maxPromiseCount) - return false; - - var elementsToTruncate = WebInspector.PromisePane._maxPromiseCount / 10; - var sortedDetails = promiseIdToDetails.valuesArray().sort(compare); - for (var i = 0; i < elementsToTruncate; ++i) - promiseIdToDetails.delete(sortedDetails[i].id); - return true; - - /** - * @param {!WebInspector.PromiseDetails} x - * @param {!WebInspector.PromiseDetails} y - * @return {number} - */ - function compare(x, y) - { - var t1 = x.creationTime || 0; - var t2 = y.creationTime || 0; - return t1 - t2 || x.id - y.id; - } - }, - - /** - * @param {!WebInspector.Event} event - */ - _onPromiseUpdated: function(event) - { - var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target); - var eventType = /** @type {string} */ (event.data.eventType); - var protocolDetails = /** @type {!DebuggerAgent.PromiseDetails} */ (event.data.promise); - - var promiseIdToDetails = this._promiseDetailsByDebuggerModel.get(debuggerModel); - if (!promiseIdToDetails) { - promiseIdToDetails = new Map(); - this._promiseDetailsByDebuggerModel.set(debuggerModel, promiseIdToDetails); - } - - var details = promiseIdToDetails.get(protocolDetails.id); - if (!details && eventType === "gc") - return; - - var truncated = this._truncateLogIfNeeded(debuggerModel); - if (details) - details.update(protocolDetails) - else - details = new WebInspector.PromiseDetails(protocolDetails); - promiseIdToDetails.set(details.id, details); - - if (eventType === "gc") - details.isGarbageCollected = true; - - if (debuggerModel === this._debuggerModel) { - if (!this.isShowing()) { - this._refreshIsNeeded = true; - return; - } - if (truncated || this._refreshIsNeeded) { - this._refresh(); - return; - } - - var node = /** @type {!WebInspector.DataGridNode} */ (this._promiseIdToNode.get(details.id)); - var wasVisible = !node || !node._isPromiseHidden; - - // Check for the fast path on GC events. - if (eventType === "gc" && node && node.parent && !this._hideCollectedPromisesSetting.get()) - node.update(details); - else - this._attachDataGridNode(details); - - var isVisible = this._shouldBeVisible(details, /** @type {!WebInspector.DataGridNode} */(this._promiseIdToNode.get(details.id))); - if (wasVisible !== isVisible) { - this._hiddenByFilterCount += wasVisible ? 1 : -1; - this._updateFilterStatus(); - } - } - }, - - /** - * @param {!WebInspector.PromiseDetails} details - */ - _attachDataGridNode: function(details) - { - var node = this._createDataGridNode(details); - var parentNode = this._findVisibleParentNodeDetails(details); - if (parentNode !== node.parent) - parentNode.appendChild(node); - if (this._shouldBeVisible(details, node)) - parentNode.expanded = true; - else - node.remove(); - }, - - /** - * @param {!WebInspector.PromiseDetails} details - * @return {!WebInspector.DataGridNode} - */ - _findVisibleParentNodeDetails: function(details) - { - var promiseIdToDetails = /** @type {!Map.} */ (this._promiseDetailsByDebuggerModel.get(this._debuggerModel)); - var currentDetails = details; - while (currentDetails) { - var parentId = currentDetails.parentId; - if (typeof parentId !== "number") - break; - currentDetails = promiseIdToDetails.get(parentId); - if (!currentDetails) - break; - var node = this._promiseIdToNode.get(currentDetails.id); - if (node && this._shouldBeVisible(currentDetails, node)) - return node; - } - return this._dataGrid.rootNode(); - }, - - /** - * @param {!WebInspector.PromiseDetails} details - * @return {!WebInspector.DataGridNode} - */ - _createDataGridNode: function(details) - { - var node = this._promiseIdToNode.get(details.id); - if (!node) { - node = new WebInspector.PromiseDataGridNode(details, this._debuggerModel, this._linkifier, this._dataGrid); - this._promiseIdToNode.set(details.id, node); - } else { - node.update(details); - } - return node; - }, - - _refresh: function() - { - delete this._refreshIsNeeded; - this._clear(); - if (!this._debuggerModel) - return; - if (!this._promiseDetailsByDebuggerModel.has(this._debuggerModel)) - return; - - var rootNode = this._dataGrid.rootNode(); - var promiseIdToDetails = /** @type {!Map.} */ (this._promiseDetailsByDebuggerModel.get(this._debuggerModel)); - - var nodesToInsert = { __proto__: null }; - // The for..of loop iterates in insertion order. - for (var pair of promiseIdToDetails) { - var id = /** @type {number} */ (pair[0]); - var details = /** @type {!WebInspector.PromiseDetails} */ (pair[1]); - var node = this._createDataGridNode(details); - node._isPromiseHidden = !this._shouldBeVisible(details, node); - if (node._isPromiseHidden) { - ++this._hiddenByFilterCount; - continue; - } - nodesToInsert[id] = { details: details, node: node }; - } - - for (var id in nodesToInsert) { - var node = nodesToInsert[id].node; - var details = nodesToInsert[id].details; - this._findVisibleParentNodeDetails(details).appendChild(node); - } - - for (var id in nodesToInsert) { - var node = nodesToInsert[id].node; - var details = nodesToInsert[id].details; - node.expanded = true; - } - - this._updateFilterStatus(); - }, - - _clear: function() - { - this._hiddenByFilterCount = 0; - this._updateFilterStatus(); - this._promiseIdToNode.clear(); - this._hidePopover(); - this._dataGrid.rootNode().removeChildren(); - this._linkifier.reset(); - }, - - /** - * @param {!WebInspector.ContextMenu} contextMenu - * @param {!WebInspector.DataGridNode} node - */ - _onContextMenu: function(contextMenu, node) - { - var debuggerModel = this._debuggerModel; - if (!debuggerModel) - return; - - var promiseId = node.promiseId(); - if (this._promiseDetailsByDebuggerModel.has(debuggerModel)) { - var details = this._promiseDetailsByDebuggerModel.get(debuggerModel).get(promiseId); - if (details.isGarbageCollected) - return; - } - - contextMenu.appendItem(WebInspector.UIString.capitalize("Show in ^console"), showPromiseInConsole); - contextMenu.show(); - - function showPromiseInConsole() - { - debuggerModel.getPromiseById(promiseId, "console", didGetPromiseById); - } - - /** - * @param {?RuntimeAgent.RemoteObject} promise - */ - function didGetPromiseById(promise) - { - if (!promise) - return; - var object = debuggerModel.target().runtimeModel.createRemoteObject(promise); - object.callFunction(dumpIntoConsole); - object.release(); - /** - * @suppressReceiverCheck - * @this {Object} - */ - function dumpIntoConsole() - { - console.log(this); - } - WebInspector.console.show(); - } - }, - - /** - * @param {!Element} element - * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} - */ - _getPopoverAnchor: function(element, event) - { - if (!this._debuggerModel || !this._promiseDetailsByDebuggerModel.has(this._debuggerModel)) - return undefined; - var node = this._dataGrid.dataGridNodeFromNode(element); - if (!node) - return undefined; - var details = this._promiseDetailsByDebuggerModel.get(this._debuggerModel).get(node.promiseId()); - if (!details) - return undefined; - var anchor = element.enclosingNodeOrSelfWithClass("created-column"); - if (anchor) - return details.creationStack ? anchor : undefined; - anchor = element.enclosingNodeOrSelfWithClass("settled-column"); - return (anchor && details.settlementStack) ? anchor : undefined; - }, - - /** - * @param {!Element} anchor - * @param {!WebInspector.Popover} popover - */ - _showPopover: function(anchor, popover) - { - var node = this._dataGrid.dataGridNodeFromNode(anchor); - var details = this._promiseDetailsByDebuggerModel.get(this._debuggerModel).get(node.promiseId()); - - var stackTrace; - if (anchor.classList.contains("created-column")) - stackTrace = details.creationStack; - else - stackTrace = details.settlementStack; - - var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._debuggerModel.target(), this._linkifier, stackTrace); - popover.setCanShrink(true); - popover.showForAnchor(content, anchor); - }, - - __proto__: WebInspector.VBox.prototype -} - -/** - * @constructor - * @extends {WebInspector.ViewportDataGridNode} - * @param {!WebInspector.PromiseDetails} details - * @param {!WebInspector.DebuggerModel} debuggerModel - * @param {!WebInspector.Linkifier} linkifier - * @param {!WebInspector.ViewportDataGrid} dataGrid - */ -WebInspector.PromiseDataGridNode = function(details, debuggerModel, linkifier, dataGrid) -{ - WebInspector.ViewportDataGridNode.call(this, {}); - this._details = details; - this._debuggerModel = debuggerModel; - this._linkifier = linkifier; - /** @type {!Array.} */ - this._linkifiedAnchors = []; - this.dataGrid = dataGrid; -} - -WebInspector.PromiseDataGridNode.prototype = { - _disposeAnchors: function() - { - for (var i = 0; i < this._linkifiedAnchors.length; ++i) - this._linkifier.disposeAnchor(this._debuggerModel.target(), this._linkifiedAnchors[i]); - this._linkifiedAnchors = []; - }, - - /** - * @param {!WebInspector.PromiseDetails} details - */ - update: function(details) - { - this._disposeAnchors(); - this._details = details; - this.refresh(); - }, - - /** - * @override - */ - wasDetached: function() - { - this._disposeAnchors(); - }, - - /** - * @override - * @return {number} - */ - nodeSelfHeight: function() - { - return 24; - }, - - /** - * @return {number} - */ - promiseId: function() - { - return this._details.id; - }, - - /** - * @override - */ - createCells: function() - { - this._element.classList.toggle("promise-gc", !!this._details.isGarbageCollected); - WebInspector.ViewportDataGridNode.prototype.createCells.call(this); - }, - - /** - * @param {!Element} cell - * @param {?RuntimeAgent.CallFrame=} callFrame - */ - _appendCallFrameAnchor: function(cell, callFrame) - { - if (!callFrame) - return; - var anchor = this._linkifier.linkifyConsoleCallFrame(this._debuggerModel.target(), callFrame); - this._linkifiedAnchors.push(anchor); - cell.appendChild(anchor); - }, - - /** - * @override - * @param {string} columnIdentifier - * @return {!Element} - */ - createCell: function(columnIdentifier) - { - var cell = this.createTD(columnIdentifier); - var details = this._details; - - switch (columnIdentifier) { - case "status": - var title = ""; - switch (details.status) { - case "pending": - title = WebInspector.UIString("Pending"); - break; - case "resolved": - title = WebInspector.UIString("Fulfilled"); - break; - case "rejected": - title = WebInspector.UIString("Rejected"); - break; - } - if (details.isGarbageCollected) - title += " " + WebInspector.UIString("(garbage collected)"); - cell.createChild("div", "status " + details.status).title = title; - break; - - case "function": - cell.createTextChild(WebInspector.beautifyFunctionName(details.callFrame ? details.callFrame.functionName : "")); - break; - - case "created": - this._appendCallFrameAnchor(cell, details.callFrame); - break; - - case "settled": - this._appendCallFrameAnchor(cell, details.settlementStack && details.settlementStack.callFrames.length ? details.settlementStack.callFrames[0] : null); - break; - - case "tts": - cell.createTextChild(this._ttsCellText()); - break; - } - - return cell; - }, - - /** - * @return {string} - */ - _ttsCellText: function() - { - var details = this._details; - if (details.creationTime && details.settlementTime && details.settlementTime >= details.creationTime) - return Number.millisToString(details.settlementTime - details.creationTime); - return ""; - }, - - /** - * @param {?RuntimeAgent.CallFrame=} callFrame - * @return {string} - */ - _callFrameAnchorTextForSearch: function(callFrame) - { - if (!callFrame) - return ""; - var script = callFrame.scriptId && this._debuggerModel ? this._debuggerModel.scriptForId(callFrame.scriptId) : null; - var sourceURL = script ? script.sourceURL : callFrame.url; - var lineNumber = callFrame.lineNumber || 0; - return WebInspector.displayNameForURL(sourceURL) + ":" + lineNumber; - }, - - /** - * @return {string} - */ - dataTextForSearch: function() - { - var details = this._details; - var texts = [ - WebInspector.beautifyFunctionName(details.callFrame ? details.callFrame.functionName : ""), - this._callFrameAnchorTextForSearch(details.callFrame), - this._callFrameAnchorTextForSearch(details.settlementStack && details.settlementStack.callFrames.length ? details.settlementStack.callFrames[0] : null), - this._ttsCellText().replace(/\u2009/g, " ") // \u2009 is a thin space. - ]; - return texts.join(" "); - }, - - __proto__: WebInspector.ViewportDataGridNode.prototype -} diff --git a/front_end/promises/module.json b/front_end/promises/module.json deleted file mode 100644 index 520e4f6a64..0000000000 --- a/front_end/promises/module.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extensions": [ - { - "type": "drawer-view", - "name": "promises", - "title": "Promises", - "order": 30, - "persistence": "permanent", - "className": "WebInspector.PromisePane" - } - ], - "dependencies": ["components", "ui_lazy"], - "experiment": "promiseTracker", - "scripts": [ - "PromisePane.js" - ], - "resources": [ - "promisePane.css" - ] -} diff --git a/front_end/promises/promisePane.css b/front_end/promises/promisePane.css deleted file mode 100644 index 55a61a6998..0000000000 --- a/front_end/promises/promisePane.css +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2014 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -.promises .data-grid { - border: none; - flex: 1 1; -} - -.promises > .toolbar { - border-bottom: 1px solid #dadada; -} - -.promises .promise-gc { - opacity: 0.6; -} - -.promises .data-grid th:hover { - background-color: inherit !important; -} - -.promises .data-grid .odd { - background-color: #eee; -} - -.promises .data-grid .header-container { - height: 30px; -} - -.promises .data-grid .data-container { - top: 29px; -} - -.promises .data-grid table.data { - background: transparent; -} - -.promises .data-grid th { - background-color: white; -} - -.promises .data-grid td { - line-height: 17px; - height: 24px; - vertical-align: middle; -} - -.promises .data-grid th, -.promises .data-grid td { - border-bottom: 1px solid rgb(205, 205, 205); - border-left: 1px solid rgb(205, 205, 205); -} - -.promises .status { - -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); - -webkit-mask-size: 352px 168px; - -webkit-mask-position: -294px -26px; - background-color: #bbb; - height: 20px; - width: 20px; -} - -@media (-webkit-min-device-pixel-ratio: 1.5) { -.promises .status { - -webkit-mask-image: url(Images/toolbarButtonGlyphs_2x.png); -} -} /* media */ - -.promises .status.rejected { - background-color: rgb(216, 0, 0); -} - -.promises .status.resolved { - background-color: #696; -} - -.promises-filters-header { - flex: 0 0 23px; - overflow: hidden; -} - -.promises-filter-status { - flex: 0 0 23px; - padding-left: 18px; - color: rgb(128, 128, 128); - font-style: italic; -} -.promises-filter-status .link:hover { - color: rgb(15%, 15%, 15%); -} -.promises-filter-status .link { - color: rgb(33%, 33%, 33%); -} diff --git a/front_end/resources/ServiceWorkersView.js b/front_end/resources/ServiceWorkersView.js index 23c0f89f20..2aafa6f038 100644 --- a/front_end/resources/ServiceWorkersView.js +++ b/front_end/resources/ServiceWorkersView.js @@ -15,10 +15,10 @@ WebInspector.ServiceWorkersView = function() /** @type {!Set.} */ this._securityOriginHosts = new Set(); - /** @type {!Map.} */ - this._originHostToOriginElementMap = new Map(); - /** @type {!Map.} */ - this._registrationIdToOriginElementMap = new Map(); + /** @type {!Map.} */ + this._originHostToOriginWidgetMap = new Map(); + /** @type {!Map.} */ + this._registrationIdToOriginWidgetMap = new Map(); var settingsDiv = createElementWithClass("div", "service-workers-settings"); var debugOnStartCheckboxLabel = createCheckboxLabel(WebInspector.UIString("Open DevTools window and pause JavaScript execution on Service Worker startup for debugging.")); @@ -28,7 +28,7 @@ WebInspector.ServiceWorkersView = function() settingsDiv.appendChild(debugOnStartCheckboxLabel); this.contentElement.appendChild(settingsDiv); - this._root = this.contentElement.createChild("ol"); + this._root = this.contentElement.createChild("div"); this._root.classList.add("service-workers-root"); WebInspector.targetManager.observeTargets(this); @@ -48,7 +48,6 @@ WebInspector.ServiceWorkersView.prototype = { this._debugOnStartCheckbox.disabled = false; this._debugOnStartCheckbox.checked = this._manager.debugOnStart(); - for (var registration of this._manager.registrations().values()) this._updateRegistration(registration); @@ -91,15 +90,15 @@ WebInspector.ServiceWorkersView.prototype = { if (!parsedURL) return; var originHost = parsedURL.host; - var originElement = this._originHostToOriginElementMap.get(originHost); - if (!originElement) { - originElement = new WebInspector.ServiceWorkerOriginElement(this._manager, originHost); + var originWidget = this._originHostToOriginWidgetMap.get(originHost); + if (!originWidget) { + originWidget = new WebInspector.ServiceWorkerOriginWidget(this._manager, originHost); if (this._securityOriginHosts.has(originHost)) - this._appendOriginNode(originElement); - this._originHostToOriginElementMap.set(originHost, originElement); + originWidget.show(this._root); + this._originHostToOriginWidgetMap.set(originHost, originWidget); } - this._registrationIdToOriginElementMap.set(registration.id, originElement); - originElement._updateRegistration(registration); + this._registrationIdToOriginWidgetMap.set(registration.id, originWidget); + originWidget._updateRegistration(registration); }, /** @@ -109,16 +108,16 @@ WebInspector.ServiceWorkersView.prototype = { { var registration = /** @type {!WebInspector.ServiceWorkerRegistration} */ (event.data); var registrationId = registration.id; - var originElement = this._registrationIdToOriginElementMap.get(registrationId); - if (!originElement) + var originWidget = this._registrationIdToOriginWidgetMap.get(registrationId); + if (!originWidget) return; - this._registrationIdToOriginElementMap.delete(registrationId); - originElement._deleteRegistration(registrationId); - if (originElement._hasRegistration()) + this._registrationIdToOriginWidgetMap.delete(registrationId); + originWidget._deleteRegistration(registrationId); + if (originWidget._hasRegistration()) return; - if (this._securityOriginHosts.has(originElement._originHost)) - this._removeOriginNode(originElement); - this._originHostToOriginElementMap.delete(originElement._originHost); + if (this._securityOriginHosts.has(originWidget._originHost)) + originWidget.detach(); + this._originHostToOriginWidgetMap.delete(originWidget._originHost); }, /** @@ -150,10 +149,10 @@ WebInspector.ServiceWorkersView.prototype = { if (this._securityOriginHosts.has(originHost)) return; this._securityOriginHosts.add(originHost); - var originElement = this._originHostToOriginElementMap.get(originHost); - if (!originElement) + var originWidget = this._originHostToOriginWidgetMap.get(originHost); + if (!originWidget) return; - this._appendOriginNode(originElement); + originWidget.show(this._root); }, /** @@ -169,26 +168,10 @@ WebInspector.ServiceWorkersView.prototype = { if (!this._securityOriginHosts.has(originHost)) return; this._securityOriginHosts.delete(originHost); - var originElement = this._originHostToOriginElementMap.get(originHost); - if (!originElement) + var originWidget = this._originHostToOriginWidgetMap.get(originHost); + if (!originWidget) return; - this._removeOriginNode(originElement); - }, - - /** - * @param {!WebInspector.ServiceWorkerOriginElement} originElement - */ - _appendOriginNode: function(originElement) - { - this._root.appendChild(originElement._element); - }, - - /** - * @param {!WebInspector.ServiceWorkerOriginElement} originElement - */ - _removeOriginNode: function(originElement) - { - this._root.removeChild(originElement._element); + originWidget.detach(); }, _debugOnStartCheckboxChanged: function() @@ -204,28 +187,28 @@ WebInspector.ServiceWorkersView.prototype = { /** * @constructor + * @extends {WebInspector.VBox} * @param {!WebInspector.ServiceWorkerManager} manager * @param {string} originHost */ -WebInspector.ServiceWorkerOriginElement = function(manager, originHost) +WebInspector.ServiceWorkerOriginWidget = function(manager, originHost) { + WebInspector.VBox.call(this); this._manager = manager; - /** @type {!Map.} */ - this._registrationElements = new Map(); + /** @type {!Map.} */ + this._registrationWidgets = new Map(); this._originHost = originHost; - this._element = createElementWithClass("div", "service-workers-origin"); - this._listItemNode = this._element.createChild("li", "service-workers-origin-title"); - this._listItemNode.createChild("div").setTextAndTitle(originHost); - this._childrenListNode = this._element.createChild("ol"); + this.element.classList.add("service-workers-origin"); + this._titleElement = this.element.createChild("span", "service-workers-origin-title"); } -WebInspector.ServiceWorkerOriginElement.prototype = { +WebInspector.ServiceWorkerOriginWidget.prototype = { /** * @return {boolean} */ _hasRegistration: function() { - return this._registrationElements.size != 0; + return this._registrationWidgets.size != 0; }, /** @@ -233,14 +216,16 @@ WebInspector.ServiceWorkerOriginElement.prototype = { */ _updateRegistration: function(registration) { - var swRegistrationElement = this._registrationElements.get(registration.id); - if (swRegistrationElement) { - swRegistrationElement._updateRegistration(registration); + this._titleElement.setTextAndTitle(WebInspector.UIString(registration.isDeleted ? "%s%s - deleted" : "%s%s", this._originHost, registration.scopeURL.asParsedURL().path)); + + var registrationWidget = this._registrationWidgets.get(registration.id); + if (registrationWidget) { + registrationWidget._updateRegistration(registration); return; } - swRegistrationElement = new WebInspector.SWRegistrationElement(this._manager, this, registration); - this._registrationElements.set(registration.id, swRegistrationElement); - this._childrenListNode.appendChild(swRegistrationElement._element); + registrationWidget = new WebInspector.SWRegistrationWidget(this._manager, this, registration); + this._registrationWidgets.set(registration.id, registrationWidget); + registrationWidget.show(this.element); }, /** @@ -248,187 +233,125 @@ WebInspector.ServiceWorkerOriginElement.prototype = { */ _deleteRegistration: function(registrationId) { - var swRegistrationElement = this._registrationElements.get(registrationId); - if (!swRegistrationElement) + var registrationWidget = this._registrationWidgets.get(registrationId); + if (!registrationWidget) return; - this._registrationElements.delete(registrationId); - this._childrenListNode.removeChild(swRegistrationElement._element); + this._registrationWidgets.delete(registrationId); + registrationWidget.detach(); }, - /** - * @return {boolean} - */ - _visible: function() - { - return !!this._element.parentElement; - }, + __proto__: WebInspector.VBox.prototype } /** * @constructor + * @extends {WebInspector.VBox} * @param {!WebInspector.ServiceWorkerManager} manager - * @param {!WebInspector.ServiceWorkerOriginElement} originElement + * @param {!WebInspector.ServiceWorkerOriginWidget} originWidget * @param {!WebInspector.ServiceWorkerRegistration} registration */ -WebInspector.SWRegistrationElement = function(manager, originElement, registration) +WebInspector.SWRegistrationWidget = function(manager, originWidget, registration) { + WebInspector.VBox.call(this); this._manager = manager; - this._originElement = originElement; + this._originWidget = originWidget; this._registration = registration; - this._element = createElementWithClass("div", "service-workers-registration"); - var headerNode = this._element.createChild("div", "service-workers-registration-header"); - this._titleNode = headerNode.createChild("div", "service-workers-registration-title"); - var buttonsNode = headerNode.createChild("div", "service-workers-registration-buttons"); - this._updateButton = buttonsNode.createChild("button", "service-workers-button service-workers-update-button"); - this._updateButton.addEventListener("click", this._updateButtonClicked.bind(this), false); - this._updateButton.title = WebInspector.UIString("Update"); - this._updateButton.disabled = true - this._pushButton = buttonsNode.createChild("button", "service-workers-button service-workers-push-button"); - this._pushButton.addEventListener("click", this._pushButtonClicked.bind(this), false); - this._pushButton.title = WebInspector.UIString("Emulate push event"); - this._pushButton.disabled = true - this._deleteButton = buttonsNode.createChild("button", "service-workers-button service-workers-delete-button"); - this._deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); - this._deleteButton.title = WebInspector.UIString("Delete"); - this._childrenListNode = this._element.createChild("div", "service-workers-registration-content"); + this.element.classList.add("service-workers-registration"); + + var toolbar = new WebInspector.Toolbar("", this.element); + this._updateButton = new WebInspector.ToolbarButton(WebInspector.UIString("Update"), "refresh-toolbar-item", WebInspector.UIString("Update")); + this._updateButton.addEventListener("click", this._updateButtonClicked.bind(this)); + toolbar.appendToolbarItem(this._updateButton); + + toolbar.appendSeparator(); + this._pushButton = new WebInspector.ToolbarButton(WebInspector.UIString("Emulate push event"), "notification-toolbar-item", WebInspector.UIString("Push")); + this._pushButton.addEventListener("click", this._pushButtonClicked.bind(this)); + toolbar.appendToolbarItem(this._pushButton); + toolbar.appendSpacer(); + this._deleteButton = new WebInspector.ToolbarButton(WebInspector.UIString("Delete"), "garbage-collect-toolbar-item", WebInspector.UIString("Delete")); + this._deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this)); + toolbar.appendToolbarItem(this._deleteButton); + + this._tabbedPane = new WebInspector.TabbedPane(); + this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); + var modes = WebInspector.ServiceWorkerVersion.Modes; + this._tabbedPane.appendTab(modes.Installing, WebInspector.UIString("Installing"), new WebInspector.VBox()); + this._tabbedPane.appendTab(modes.Waiting, WebInspector.UIString("Waiting"), new WebInspector.VBox()); + this._tabbedPane.appendTab(modes.Active, WebInspector.UIString("Active"), new WebInspector.VBox()); + this._tabbedPane.appendTab(modes.Redundant, WebInspector.UIString("Redundant"), new WebInspector.VBox()); + this._tabbedPane.show(this.element); + + /** @type {!Map} */ + this._versionWidgets = new Map(); - /** - * @type {!Object.>} - */ - this._categorizedVersions = {}; - for (var mode in WebInspector.ServiceWorkerVersion.Modes) - this._categorizedVersions[WebInspector.ServiceWorkerVersion.Modes[mode]] = []; - - this._selectedMode = WebInspector.ServiceWorkerVersion.Modes.Active; + this._updateRegistration(registration); +} +WebInspector.SWRegistrationWidget.prototype = { /** - * @type {!Array.} + * @param {!WebInspector.Event} event */ - this._versionElements = []; - - this._updateRegistration(registration); -} + _tabSelected: function(event) + { + if (event.data["isUserGesture"]) + this._lastManuallySelectedTab = event.data["tabId"]; + }, -WebInspector.SWRegistrationElement.prototype = { /** * @param {!WebInspector.ServiceWorkerRegistration} registration */ _updateRegistration: function(registration) { this._registration = registration; - this._titleNode.setTextAndTitle(WebInspector.UIString(registration.isDeleted ? "Scope: %s - deleted" : "Scope: %s", registration.scopeURL.asParsedURL().path)); - this._updateButton.disabled = !!registration.isDeleted; - this._deleteButton.disabled = !!registration.isDeleted; - - var lastFocusedVersionId = undefined; - if (this._categorizedVersions[this._selectedMode].length) - lastFocusedVersionId = this._categorizedVersions[this._selectedMode][0].id; - for (var mode in WebInspector.ServiceWorkerVersion.Modes) - this._categorizedVersions[WebInspector.ServiceWorkerVersion.Modes[mode]] = []; + this._updateButton.setEnabled(!registration.isDeleted); + this._deleteButton.setEnabled(!registration.isDeleted); + + /** @type {!Map} */ + var versionWidgets = new Map(); + + var modesWithVersions = new Set(); + var firstMode; for (var version of registration.versions.valuesArray()) { if (version.isStoppedAndRedundant() && !version.errorMessages.length) continue; var mode = version.mode(); - this._categorizedVersions[mode].push(version); - if (version.id === lastFocusedVersionId) - this._selectedMode = mode; + if (!firstMode) + firstMode = mode; + modesWithVersions.add(mode); + var view = this._tabbedPane.tabView(mode); + var versionWidget = this._versionWidgets.get(version.id); + if (versionWidget) + versionWidget._updateVersion(version); + else + versionWidget = new WebInspector.SWVersionWidget(this._manager, this._registration.scopeURL, version); + versionWidget.show(view.element); + versionWidgets.set(version.id, versionWidget); } - if (!this._categorizedVersions[this._selectedMode].length) { - for (var mode of [WebInspector.ServiceWorkerVersion.Modes.Active, - WebInspector.ServiceWorkerVersion.Modes.Waiting, - WebInspector.ServiceWorkerVersion.Modes.Installing, - WebInspector.ServiceWorkerVersion.Modes.Redundant]) { - if (this._categorizedVersions[mode].length) { - this._selectedMode = mode; - break; - } - } + for (var id of this._versionWidgets.keys()) { + if (!versionWidgets.has(id)) + this._versionWidgets.get(id).detach(); } - this._pushButton.disabled = !this._categorizedVersions[WebInspector.ServiceWorkerVersion.Modes.Active].length || !!this._registration.isDeleted; + this._versionWidgets = versionWidgets; - this._updateVersionList(); - }, + for (var id of this._tabbedPane.tabIds()) + this._tabbedPane.setTabEnabled(id, modesWithVersions.has(id)); - _updateVersionList: function() - { - var fragment = createDocumentFragment(); - var modeTabList = createElementWithClass("div", "service-workers-versions-mode-tab-list"); - modeTabList.appendChild(this._createVersionModeTab(WebInspector.ServiceWorkerVersion.Modes.Installing)); - modeTabList.appendChild(this._createVersionModeTab(WebInspector.ServiceWorkerVersion.Modes.Waiting)); - modeTabList.appendChild(this._createVersionModeTab(WebInspector.ServiceWorkerVersion.Modes.Active)); - modeTabList.appendChild(this._createVersionModeTab(WebInspector.ServiceWorkerVersion.Modes.Redundant)); - fragment.appendChild(modeTabList); - fragment.appendChild(this._createSelectedModeVersionsPanel(this._selectedMode)); - this._childrenListNode.removeChildren(); - this._childrenListNode.appendChild(fragment); - }, - - /** - * @param {string} mode - * @return {!Element} - */ - _createVersionModeTab: function(mode) - { - var versions = this._categorizedVersions[mode]; - var modeTitle = WebInspector.UIString(mode); - var selected = this._selectedMode == mode; - var modeTab = createElementWithClass("div", "service-workers-versions-mode-tab"); - for (var version of versions) { - var icon = modeTab.createChild("div", "service-workers-versions-mode-tab-icon service-workers-color-" + (version.id % 10)); - icon.title = WebInspector.UIString("ID: %s", version.id); - } - var modeTabText = modeTab.createChild("div", "service-workers-versions-mode-tab-text"); - modeTabText.setTextAndTitle(WebInspector.UIString(modeTitle)); - if (selected) { - modeTab.classList.add("service-workers-versions-mode-tab-selected"); - modeTabText.classList.add("service-workers-versions-mode-tab-text-selected"); - } - if (versions.length) { - modeTab.addEventListener("click", this._modeTabClicked.bind(this, mode), false); - } else { - modeTab.classList.add("service-workers-versions-mode-tab-disabled"); - modeTabText.classList.add("service-workers-versions-mode-tab-text-disabled"); - } - return modeTab; - }, + this._pushButton.setEnabled(modesWithVersions.has(WebInspector.ServiceWorkerVersion.Modes.Active) && !this._registration.isDeleted); - /** - * @param {string} mode - * @return {!Element} - */ - _createSelectedModeVersionsPanel: function(mode) - { - var versions = this._categorizedVersions[mode]; - var panelContainer = createElementWithClass("div", "service-workers-versions-panel-container"); - var index = 0; - var versionElement; - for (var i = 0; i < versions.length; ++i) { - if (i < this._versionElements.length) { - versionElement = this._versionElements[i]; - versionElement._updateVersion(versions[i]); - } else { - versionElement = new WebInspector.SWVersionElement(this._manager, this._registration.scopeURL, versions[i]); - this._versionElements.push(versionElement); - } - panelContainer.appendChild(versionElement._element); + if (modesWithVersions.has(this._lastManuallySelectedTab)) { + this._tabbedPane.selectTab(this._lastManuallySelectedTab); + return; } - this._versionElements.splice(versions.length); - return panelContainer; - }, - - /** - * @param {string} mode - */ - _modeTabClicked: function(mode) - { - if (this._selectedMode == mode) + if (modesWithVersions.has(WebInspector.ServiceWorkerVersion.Modes.Active)) { + this._tabbedPane.selectTab(WebInspector.ServiceWorkerVersion.Modes.Active); return; - this._selectedMode = mode; - this._updateVersionList(); + } + if (firstMode) + this._tabbedPane.selectTab(firstMode); }, /** - * @param {!Event} event + * @param {!WebInspector.Event} event */ _deleteButtonClicked: function(event) { @@ -436,7 +359,7 @@ WebInspector.SWRegistrationElement.prototype = { }, /** - * @param {!Event} event + * @param {!WebInspector.Event} event */ _updateButtonClicked: function(event) { @@ -444,7 +367,7 @@ WebInspector.SWRegistrationElement.prototype = { }, /** - * @param {!Event} event + * @param {!WebInspector.Event} event */ _pushButtonClicked: function(event) { @@ -452,27 +375,23 @@ WebInspector.SWRegistrationElement.prototype = { this._manager.deliverPushMessage(this._registration.id, data); }, - /** - * @return {boolean} - */ - _visible: function() - { - return this._originElement._visible(); - }, + __proto__: WebInspector.VBox.prototype } /** * @constructor + * @extends {WebInspector.VBox} * @param {!WebInspector.ServiceWorkerManager} manager * @param {string} scopeURL * @param {!WebInspector.ServiceWorkerVersion} version */ -WebInspector.SWVersionElement = function(manager, scopeURL, version) +WebInspector.SWVersionWidget = function(manager, scopeURL, version) { + WebInspector.VBox.call(this); this._manager = manager; this._scopeURL = scopeURL; this._version = version; - this._element = createElementWithClass("div", "service-workers-version"); + this.element.classList.add("service-workers-version", "flex-none"); /** * @type {!Object.} @@ -482,7 +401,7 @@ WebInspector.SWVersionElement = function(manager, scopeURL, version) this._updateVersion(version); } -WebInspector.SWVersionElement.prototype = { +WebInspector.SWVersionWidget.prototype = { _createElements: function() { var panel = createElementWithClass("div", "service-workers-versions-panel"); @@ -500,7 +419,7 @@ WebInspector.SWVersionElement.prototype = { this._clientsTitle = rightPanel.createChild("div", "service-workers-versions-table-clients-title"); this._clientsTitle.createTextChild(WebInspector.UIString("Controlled clients")); this._clientsPanel = rightPanel.createChild("div", "service-workers-versions-table-clients-content"); - this._element.appendChild(panel); + this.element.appendChild(panel); }, /** @@ -516,13 +435,15 @@ WebInspector.SWVersionElement.prototype = { var runningStatusLeftCell = runningStatusCell.createChild("div", "service-workers-versions-table-running-status-left-cell"); var runningStatusRightCell = runningStatusCell.createChild("div", "service-workers-versions-table-running-status-right-cell"); if (version.isRunning() || version.isStarting()) { - var stopButton = runningStatusLeftCell.createChild("button", "service-workers-button service-workers-stop-button"); - stopButton.addEventListener("click", this._stopButtonClicked.bind(this, version.id), false); - stopButton.title = WebInspector.UIString("Stop"); + var toolbar = new WebInspector.Toolbar("", runningStatusLeftCell); + var stopButton = new WebInspector.ToolbarButton(WebInspector.UIString("Stop"), "stop-toolbar-item"); + stopButton.addEventListener("click", this._stopButtonClicked.bind(this, version.id)); + toolbar.appendToolbarItem(stopButton); } else if (version.isStartable()) { - var startButton = runningStatusLeftCell.createChild("button", "service-workers-button service-workers-start-button"); - startButton.addEventListener("click", this._startButtonClicked.bind(this), false); - startButton.title = WebInspector.UIString("Start"); + var toolbar = new WebInspector.Toolbar("", runningStatusLeftCell); + var startButton = new WebInspector.ToolbarButton(WebInspector.UIString("Start"), "play-toolbar-item"); + startButton.addEventListener("click", this._startButtonClicked.bind(this)); + toolbar.appendToolbarItem(startButton); } runningStatusRightCell.setTextAndTitle(version.runningStatus); if (version.isRunning() || version.isStarting()) { @@ -627,7 +548,7 @@ WebInspector.SWVersionElement.prototype = { }, /** - * @param {!Event} event + * @param {!WebInspector.Event} event */ _startButtonClicked: function(event) { @@ -636,7 +557,7 @@ WebInspector.SWVersionElement.prototype = { /** * @param {string} versionId - * @param {!Event} event + * @param {!WebInspector.Event} event */ _stopButtonClicked: function(versionId, event) { @@ -651,4 +572,6 @@ WebInspector.SWVersionElement.prototype = { { this._manager.inspectWorker(versionId); }, + + __proto__: WebInspector.VBox.prototype } diff --git a/front_end/resources/module.json b/front_end/resources/module.json index 29dc86bf50..dc773577fc 100644 --- a/front_end/resources/module.json +++ b/front_end/resources/module.json @@ -11,6 +11,12 @@ "type": "@WebInspector.Revealer", "contextTypes": ["WebInspector.Resource"], "className": "WebInspector.ResourcesPanel.ResourceRevealer" + }, + { + "type": "setting", + "settingName": "serviceWorkerUpdateOnReload", + "settingType": "boolean", + "defaultValue": "false" } ], "dependencies": ["source_frame", "ui_lazy", "components_lazy"], diff --git a/front_end/resources/serviceWorkersView.css b/front_end/resources/serviceWorkersView.css index c7fa7e58b0..a308604b05 100644 --- a/front_end/resources/serviceWorkersView.css +++ b/front_end/resources/serviceWorkersView.css @@ -4,27 +4,25 @@ * found in the LICENSE file. */ -.service-workers-view { - overflow: auto; -} - .service-workers-settings { border-bottom: 1px solid #e1e1e1; min-height: 26px; overflow: hidden; padding: 5px; white-space: nowrap; + flex: none; } .service-workers-root { margin: 0; padding: 5px; -webkit-user-select: text; + display: flex; } .service-workers-root ol { list-style-type: none; - padding-left: 12px; + padding-left: 0; } .service-workers-origin { @@ -32,23 +30,23 @@ } .service-workers-origin-title { - font-size: 20px; + font-size: 17px; + flex: none; } .service-workers-registration { - border-right: 1px solid #e1e1e1; margin-top: 5px; margin-bottom: 10px; padding: 0; + flex: auto; } -.service-workers-registration-header { - border-left: 1px solid #e1e1e1; - border-top: 1px solid #e1e1e1; - display: flex; - flex-wrap: wrap; - overflow: hidden; - position: relative; +.service-workers-registration .tabbed-pane > .widget { + overflow: auto; +} + +.service-workers-registration .toolbar { + flex: none; } .service-workers-registration-title { @@ -57,62 +55,10 @@ padding: 4px; } -.service-workers-registration-buttons { - flex: 1 1 0; - padding: 1px; -} - -.service-workers-registration-content { - border: 0; - padding: 0; -} - -.service-workers-versions-mode-tab-list { - display: flex; -} - -.service-workers-versions-mode-tab { - border-bottom: 1px solid #e1e1e1; - border-left: 1px solid #e1e1e1; - border-top: 1px solid #e1e1e1; - display: flex; - flex: 1 1 0; - flex-wrap: wrap; - overflow: hidden; - padding: 3px; -} - -.service-workers-versions-mode-tab-disabled { - background-color: #eee; -} - -.service-workers-versions-mode-tab-selected { - border-bottom: 0; -} - -.service-workers-versions-mode-tab-icon { - height: 16px; - margin: 1px; - -webkit-mask-image: url(Images/serviceWorker.svg); - -webkit-mask-size: 16px 16px; - width: 16px; -} - -.service-workers-versions-mode-tab-text { - margin: 2px; -} - -.service-workers-versions-mode-tab-text-disabled { - color: #888; -} - -.service-workers-versions-mode-tab-text-selected { - font-weight: bold; -} - .service-workers-versions-panel { border-bottom: 1px solid #e1e1e1; border-left: 1px solid #e1e1e1; + border-right: 1px solid #e1e1e1; display: flex; } @@ -151,8 +97,12 @@ } .service-workers-versions-table-messages-content { - overflow: auto; padding: 3px 3px 3px 10px; + line-height: 22px; + max-height: 150px; + border-left: 1px solid #eee; + overflow: auto; + margin-right: 10px; } .service-workers-versions-table-clients-title { @@ -179,63 +129,6 @@ text-decoration: underline; } -.service-workers-button { - -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); - -webkit-mask-size: 352px 168px; - background-color: rgba(0, 0, 0, 0.75); - height: 24px; - opacity: 0.8; - width: 32px; - border: 0; - padding: 0; -} - -@media (-webkit-min-device-pixel-ratio: 1.5) { -.service-workers-button { - -webkit-mask-image: url(Images/toolbarButtonGlyphs_2x.png); -} -} /* media */ - -.service-workers-button:hover { - opacity: 1; -} - -.service-workers-button:active { - opacity: 0.8; -} - -.service-workers-button:disabled { - opacity: 0.5; -} - -.service-workers-start-button { - -webkit-mask-position: -64px -48px; -} - -.service-workers-stop-button { - -webkit-mask-position: -96px -48px; -} - -.service-workers-delete-button { - float: right; - -webkit-mask-position: -128px -24px; - position: relative; -} - -.service-workers-update-button { - -webkit-mask-image: url(Images/updateServiceWorker.svg); - -webkit-mask-position: 7px 3px; - -webkit-mask-repeat: no-repeat; - -webkit-mask-size: 18px 18px; -} - -.service-workers-push-button { - -webkit-mask-image: url(Images/notifications.svg); - -webkit-mask-position: 7px 3px; - -webkit-mask-repeat: no-repeat; - -webkit-mask-size: 18px 18px; -} - .service-workers-versions-option-panel { border-bottom: 1px solid #e1e1e1; border-left: 1px solid #e1e1e1; @@ -246,12 +139,13 @@ display: flex; } -.service-workers-error-message { - font-weight: bold; +.service-workers-error > label { + flex: none; } .service-workers-info { display: flex; + align-items: center; } .service-worker-client-focus { @@ -260,43 +154,3 @@ padding-left: 4px; text-decoration: underline; } - -.service-workers-color-0 { - background-color: #003366; -} - -.service-workers-color-1 { - background-color: #663300; -} - -.service-workers-color-2 { - background-color: #660066; -} - -.service-workers-color-3 { - background-color: #003300; -} - -.service-workers-color-4 { - background-color: #993333; -} - -.service-workers-color-5 { - background-color: #000066; -} - -.service-workers-color-6 { - background-color: #006666; -} - -.service-workers-color-7 { - background-color: #996600; -} - -.service-workers-color-8 { - background-color: #9900CC; -} - -.service-workers-color-9 { - background-color: #336600; -} diff --git a/front_end/sass/SASSProcessor.js b/front_end/sass/SASSProcessor.js index a747f0c431..62f1dae4c0 100644 --- a/front_end/sass/SASSProcessor.js +++ b/front_end/sass/SASSProcessor.js @@ -120,6 +120,8 @@ WebInspector.SASSProcessor.processCSSEdits = function(astService, map, ranges, n */ function onCSSParsed(newCSSAST) { + if (newCSSAST.rules.length !== map.compiledModel().rules.length) + return Promise.resolve(/** @type {?WebInspector.SourceMap.EditResult} */(null)); //TODO(lushnikov): only diff changed styles. var cssDiff = WebInspector.SASSSupport.diffModels(map.compiledModel(), newCSSAST); var edits = WebInspector.SASSProcessor._editsFromCSSDiff(cssDiff, map); diff --git a/front_end/sass/SASSSupport.js b/front_end/sass/SASSSupport.js index 92dad21eda..78e67d29d2 100644 --- a/front_end/sass/SASSSupport.js +++ b/front_end/sass/SASSSupport.js @@ -80,7 +80,6 @@ WebInspector.SASSSupport.SCSSParserStates = { */ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) { - var lines = document.text.value().split("\n"); var properties = []; var variables = []; var mixins = []; @@ -92,45 +91,50 @@ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) var mixinName, mixinValue; var UndefTokenType = {}; + var cursor = new WebInspector.TextCursor(document.text.lineEndings()); + /** * @param {string} tokenValue * @param {?string} tokenTypes - * @param {number} column - * @param {number} newColumn + * @param {number} startPosition + * @param {number} endPosition */ - function processToken(tokenValue, tokenTypes, column, newColumn) + function processToken(tokenValue, tokenTypes, startPosition, endPosition) { + cursor.advance(startPosition); + var startLine = cursor.lineNumber(); + var startColumn = cursor.columnNumber(); + cursor.advance(endPosition); + var endLine = cursor.lineNumber(); + var endColumn = cursor.columnNumber(); + var tokenType = tokenTypes ? tokenTypes.split(" ").keySet() : UndefTokenType; switch (state) { case States.Initial: if (tokenType["css-variable-2"]) { - variableName = new WebInspector.SASSSupport.TextNode(document, tokenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn)); + variableName = new WebInspector.SASSSupport.TextNode(document, tokenValue, new WebInspector.TextRange(startLine, startColumn, endLine, endColumn)); state = States.VariableName; } else if (tokenType["css-property"] || tokenType["css-meta"]) { - propertyName = new WebInspector.SASSSupport.TextNode(document, tokenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn)); + propertyName = new WebInspector.SASSSupport.TextNode(document, tokenValue, new WebInspector.TextRange(startLine, startColumn, endLine, endColumn)); state = States.PropertyName; } else if (tokenType["css-def"] && tokenValue === "@include") { - mixinName = new WebInspector.SASSSupport.TextNode(document, tokenValue, new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn)); + mixinName = new WebInspector.SASSSupport.TextNode(document, tokenValue, new WebInspector.TextRange(startLine, startColumn, endLine, endColumn)); state = States.MixinName; } else if (tokenType["css-comment"]) { // Support only a one-line comments. - if (tokenValue.substring(0, 2) !== "/*" || tokenValue.substring(tokenValue.length - 2) !== "*/") + if (startLine !== endLine || tokenValue.substring(0, 2) !== "/*" || tokenValue.substring(tokenValue.length - 2) !== "*/") break; var uncommentedText = tokenValue.substring(2, tokenValue.length - 2); - var fakeRuleText = "a{\n" + uncommentedText + "}"; + var fakeRuleText = "a{" + uncommentedText + "}"; var fakeDocument = new WebInspector.SASSSupport.ASTDocument("", new WebInspector.Text(fakeRuleText)); var result = WebInspector.SASSSupport._innerParseSCSS(fakeDocument, tokenizerFactory); if (result.properties.length === 1 && result.variables.length === 0 && result.mixins.length === 0) { var disabledProperty = result.properties[0]; - // We should offset property to current coordinates. - var offset = column + 2; - var nameRange = new WebInspector.TextRange(lineNumber, disabledProperty.name.range.startColumn + offset, - lineNumber, disabledProperty.name.range.endColumn + offset); - var valueRange = new WebInspector.TextRange(lineNumber, disabledProperty.value.range.startColumn + offset, - lineNumber, disabledProperty.value.range.endColumn + offset); + var nameRange = rebaseInsideOneLineComment(disabledProperty.name.range, startLine, startColumn); + var valueRange = rebaseInsideOneLineComment(disabledProperty.value.range, startLine, startColumn); var name = new WebInspector.SASSSupport.TextNode(document, disabledProperty.name.text, nameRange); var value = new WebInspector.SASSSupport.TextNode(document, disabledProperty.value.text, valueRange); - var range = new WebInspector.TextRange(lineNumber, column, lineNumber, newColumn); + var range = new WebInspector.TextRange(startLine, startColumn, startLine, endColumn); var property = new WebInspector.SASSSupport.Property(document, name, value, range, true); properties.push(property); } @@ -145,18 +149,18 @@ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) state = States.Initial; } else if (tokenValue === ":" && tokenType === UndefTokenType) { state = States.VariableValue; - variableValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(lineNumber, newColumn)); + variableValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(startLine, endColumn)); } else if (tokenType !== UndefTokenType) { state = States.Initial; } break; case States.VariableValue: if (tokenValue === ";" && tokenType === UndefTokenType) { - variableValue.range.endLine = lineNumber; - variableValue.range.endColumn = column; + variableValue.range.endLine = startLine; + variableValue.range.endColumn = startColumn; var variable = new WebInspector.SASSSupport.Property(document, variableName, variableValue, variableName.range.clone(), false); - variable.range.endLine = lineNumber; - variable.range.endColumn = newColumn; + variable.range.endLine = startLine; + variable.range.endColumn = endColumn; variables.push(variable); state = States.Initial; } else { @@ -164,22 +168,26 @@ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) } break; case States.PropertyName: - if (tokenValue === ":" && tokenType === UndefTokenType) { + if (tokenValue === "{" && tokenType === UndefTokenType) { + state = States.Initial; + } else if (tokenValue === ":" && tokenType === UndefTokenType) { state = States.PropertyValue; - propertyName.range.endLine = lineNumber; - propertyName.range.endColumn = column; - propertyValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(lineNumber, newColumn)); + propertyName.range.endLine = startLine; + propertyName.range.endColumn = startColumn; + propertyValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(startLine, endColumn)); } else if (tokenType["css-property"]) { propertyName.text += tokenValue; } break; case States.PropertyValue: - if ((tokenValue === "}" || tokenValue === ";") && tokenType === UndefTokenType) { - propertyValue.range.endLine = lineNumber; - propertyValue.range.endColumn = column; + if (tokenValue === "{" && tokenType === UndefTokenType) { + state = States.Initial; + } else if ((tokenValue === "}" || tokenValue === ";") && tokenType === UndefTokenType) { + propertyValue.range.endLine = startLine; + propertyValue.range.endColumn = startColumn; var property = new WebInspector.SASSSupport.Property(document, propertyName, propertyValue, propertyName.range.clone(), false); - property.range.endLine = lineNumber; - property.range.endColumn = newColumn; + property.range.endLine = startLine; + property.range.endColumn = endColumn; properties.push(property); state = States.Initial; } else { @@ -189,9 +197,9 @@ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) case States.MixinName: if (tokenValue === "(" && tokenType === UndefTokenType) { state = States.MixinValue; - mixinName.range.endLine = lineNumber; - mixinName.range.endColumn = column; - mixinValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(lineNumber, newColumn)); + mixinName.range.endLine = startLine; + mixinName.range.endColumn = startColumn; + mixinValue = new WebInspector.SASSSupport.TextNode(document, "", WebInspector.TextRange.createFromLocation(startLine, endColumn)); } else if (tokenValue === ";" && tokenType === UndefTokenType) { state = States.Initial; mixinValue = null; @@ -201,11 +209,11 @@ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) break; case States.MixinValue: if (tokenValue === ")" && tokenType === UndefTokenType) { - mixinValue.range.endLine = lineNumber; - mixinValue.range.endColumn = column; + mixinValue.range.endLine = startLine; + mixinValue.range.endColumn = startColumn; var mixin = new WebInspector.SASSSupport.Property(document, mixinName, /** @type {!WebInspector.SASSSupport.TextNode} */(mixinValue), mixinName.range.clone(), false); - mixin.range.endLine = lineNumber; - mixin.range.endColumn = newColumn; + mixin.range.endLine = startLine; + mixin.range.endColumn = endColumn; mixins.push(mixin); state = States.Initial; } else { @@ -221,17 +229,24 @@ WebInspector.SASSSupport._innerParseSCSS = function(document, tokenizerFactory) } } var tokenizer = tokenizerFactory.createTokenizer("text/x-scss"); - var lineNumber; - for (lineNumber = 0; lineNumber < lines.length; ++lineNumber) { - var line = lines[lineNumber]; - tokenizer(line, processToken); - processToken("\n", null, line.length, line.length + 1); - } + tokenizer(document.text.value(), processToken); + return { variables: variables, properties: properties, mixins: mixins }; + + /** + * @param {!WebInspector.TextRange} range + * @param {number} startLine + * @param {number} startColumn + * @return {!WebInspector.TextRange} + */ + function rebaseInsideOneLineComment(range, startLine, startColumn) + { + return new WebInspector.TextRange(range.startLine + startLine, range.startColumn + startColumn, range.endLine + startLine, range.endColumn + startColumn); + } } /** diff --git a/front_end/sass/module.json b/front_end/sass/module.json index dc9deb47ad..b4983d27b6 100644 --- a/front_end/sass/module.json +++ b/front_end/sass/module.json @@ -6,5 +6,15 @@ "SASSProcessor.js", "ASTSourceMap.js", "SASSSourceMapFactory.js" + ], + "extensions": [ + { + "type": "@WebInspector.SourceMapFactory", + "className": "WebInspector.SASSSourceMapFactory", + "experiment": "liveSASS", + "extensions": [ + "scss" + ] + } ] } diff --git a/front_end/screencast/ScreencastApp.js b/front_end/screencast/ScreencastApp.js index b3f22741a3..8eb98047f4 100644 --- a/front_end/screencast/ScreencastApp.js +++ b/front_end/screencast/ScreencastApp.js @@ -90,12 +90,6 @@ WebInspector.ScreencastApp.prototype = { this._rootSplitWidget.showBoth(); else this._rootSplitWidget.hideMain(); - }, - - _requestAppBanner: function() - { - if (this._target && this._target.pageAgent()) - this._target.pageAgent().requestAppBanner(); } }; @@ -132,33 +126,6 @@ WebInspector.ScreencastApp.ToolbarButtonProvider.prototype = { } } - -/** - * @constructor - * @implements {WebInspector.ActionDelegate} - */ -WebInspector.ScreencastApp.ActionDelegate = function() -{ -}; - -WebInspector.ScreencastApp.ActionDelegate.prototype = { - /** - * @override - * @param {!WebInspector.Context} context - * @param {string} actionId - * @return {boolean} - */ - handleAction: function(context, actionId) - { - if (actionId === "screencast.request-app-banner") { - WebInspector.ScreencastApp._instance()._requestAppBanner() - return true; - } - return false; - } -}; - - /** * @constructor * @implements {WebInspector.AppProvider} diff --git a/front_end/screencast/module.json b/front_end/screencast/module.json index 0f9edda280..64f46d99e7 100644 --- a/front_end/screencast/module.json +++ b/front_end/screencast/module.json @@ -11,19 +11,12 @@ "order": 1, "location": "main-toolbar-left" }, - { - "type": "@WebInspector.ActionDelegate", - "actionId": "screencast.request-app-banner", - "className": "WebInspector.ScreencastApp.ActionDelegate", - "title": "Request app banner\u2026" - }, { "type": "context-menu-item", "condition": "remoteFrontend", "location": "mainMenu/tools", - "experiment": "appBanner", "order": 10, - "actionId": "screencast.request-app-banner" + "actionId": "components.request-app-banner" } ], "dependencies": [ diff --git a/front_end/sdk/CSSModel.js b/front_end/sdk/CSSModel.js index f1860be784..1cd81314e0 100644 --- a/front_end/sdk/CSSModel.js +++ b/front_end/sdk/CSSModel.js @@ -47,8 +47,9 @@ WebInspector.CSSModel = function(target) /** @type {!Map.>>} */ this._styleSheetIdsForURL = new Map(); - /** @type {!Map} */ - this._sourceMapLoadingPromises = new Map(); + /** @type {!Multimap} */ + this._sourceMapLoadingStyleSheetsIds = new Multimap(); + /** @type {!Map} */ this._sourceMapByURL = new Map(); /** @type {!Multimap} */ @@ -65,7 +66,8 @@ WebInspector.CSSModel.Events = { StyleSheetChanged: "StyleSheetChanged", StyleSheetRemoved: "StyleSheetRemoved", SourceMapAttached: "SourceMapAttached", - SourceMapDetached: "SourceMapDetached" + SourceMapDetached: "SourceMapDetached", + SourceMapChanged: "SourceMapChanged" } WebInspector.CSSModel.MediaTypes = ["all", "braille", "embossed", "handheld", "print", "projection", "screen", "speech", "tty", "tv"]; @@ -99,7 +101,7 @@ WebInspector.CSSModel.prototype = { if (enabled) this._attachSourceMap(header); else - this._detachSourceMap(header.sourceMapURL, header); + this._detachSourceMap(header); } }, @@ -112,6 +114,17 @@ WebInspector.CSSModel.prototype = { return this._sourceMapByURL.get(header.sourceMapURL) || null; }, + _sourceMapLoadedForTest: function() { }, + + /** + * @param {!WebInspector.SourceMap} sourceMap + * @return {!Array} + */ + headersForSourceMap: function(sourceMap) + { + return this._sourceMapURLToHeaders.get(sourceMap.url()).valuesArray(); + }, + /** * @param {!WebInspector.CSSStyleSheetHeader} header */ @@ -120,45 +133,104 @@ WebInspector.CSSModel.prototype = { var sourceMapURL = header.sourceMapURL; if (!sourceMapURL || !WebInspector.moduleSetting("cssSourceMapsEnabled").get()) return; - this._sourceMapURLToHeaders.set(sourceMapURL, header); if (this._sourceMapByURL.has(sourceMapURL)) { - this.dispatchEventToListeners(WebInspector.CSSModel.Events.SourceMapAttached, header); + attach.call(this, sourceMapURL, header); return; } - if (this._sourceMapLoadingPromises.has(sourceMapURL)) - return; - var loadingPromise = WebInspector.TextSourceMap.load(sourceMapURL, header.sourceURL) - .then(onSourceMapLoaded.bind(this, sourceMapURL)); - this._sourceMapLoadingPromises.set(sourceMapURL, loadingPromise); + if (!this._sourceMapLoadingStyleSheetsIds.has(sourceMapURL)) { + WebInspector.TextSourceMap.load(sourceMapURL, header.sourceURL) + .then(onTextSourceMapLoaded.bind(this, sourceMapURL)) + .then(onSourceMap.bind(this, sourceMapURL)); + } + this._sourceMapLoadingStyleSheetsIds.set(sourceMapURL, header.id); /** * @param {string} sourceMapURL * @param {?WebInspector.TextSourceMap} sourceMap + * @return {!Promise} * @this {WebInspector.CSSModel} */ - function onSourceMapLoaded(sourceMapURL, sourceMap) + function onTextSourceMapLoaded(sourceMapURL, sourceMap) { - this._sourceMapLoadingPromises.delete(sourceMapURL); - var headers = this._sourceMapURLToHeaders.get(sourceMapURL); - if (!headers || !sourceMap) + if (!sourceMap) + return Promise.resolve(/** @type {?WebInspector.SourceMap} */(null)); + var factoryExtension = this._factoryForSourceMap(sourceMap); + if (!factoryExtension) + return Promise.resolve(/** @type {?WebInspector.SourceMap} */(sourceMap)); + + return factoryExtension.instancePromise() + .then(factory => factory.editableSourceMap(this.target(), sourceMap)) + .then(map => map || sourceMap) + .catchException(/** @type {?WebInspector.SourceMap} */(null)); + } + + /** + * @param {string} sourceMapURL + * @param {?WebInspector.SourceMap} sourceMap + * @this {WebInspector.CSSModel} + */ + function onSourceMap(sourceMapURL, sourceMap) + { + this._sourceMapLoadedForTest(); + var styleSheetIds = this._sourceMapLoadingStyleSheetsIds.get(sourceMapURL); + this._sourceMapLoadingStyleSheetsIds.removeAll(sourceMapURL); + if (!sourceMap) return; + var headers = new Set(); + for (var styleSheetId of styleSheetIds) { + var header = this.styleSheetHeaderForId(styleSheetId); + if (header) + headers.add(header); + } + if (!headers.size) + return; + if (sourceMap.editable()) + WebInspector.console.log(WebInspector.UIString("LiveSASS started: %s", sourceMapURL)); this._sourceMapByURL.set(sourceMapURL, sourceMap); for (var header of headers) - this.dispatchEventToListeners(WebInspector.CSSModel.Events.SourceMapAttached, header); + attach.call(this, sourceMapURL, header); } + + /** + * @param {string} sourceMapURL + * @param {!WebInspector.CSSStyleSheetHeader} header + * @this {WebInspector.CSSModel} + */ + function attach(sourceMapURL, header) + { + this._sourceMapURLToHeaders.set(sourceMapURL, header); + this.dispatchEventToListeners(WebInspector.CSSModel.Events.SourceMapAttached, header); + } + }, + + /** + * @param {!WebInspector.SourceMap} sourceMap + * @return {?Runtime.Extension} + */ + _factoryForSourceMap: function(sourceMap) + { + var sourceExtensions = new Set(sourceMap.sourceURLs().map(url => WebInspector.TextUtils.extension(url))); + for (var runtimeExtension of self.runtime.extensions(WebInspector.SourceMapFactory)) { + var supportedExtensions = new Set(runtimeExtension.descriptor()["extensions"]); + if (supportedExtensions.containsAll(sourceExtensions)) + return runtimeExtension; + } + return null; }, /** - * @param {?string} sourceMapURL * @param {!WebInspector.CSSStyleSheetHeader} header */ - _detachSourceMap: function(sourceMapURL, header) + _detachSourceMap: function(header) { - if (!sourceMapURL) + if (!header.sourceMapURL || !this._sourceMapURLToHeaders.hasValue(header.sourceMapURL, header)) return; - this._sourceMapURLToHeaders.remove(sourceMapURL, header); - if (!this._sourceMapURLToHeaders.has(sourceMapURL)) - this._sourceMapByURL.delete(sourceMapURL); + this._sourceMapURLToHeaders.remove(header.sourceMapURL, header); + if (!this._sourceMapURLToHeaders.has(header.sourceMapURL)) + var sourceMap = this._sourceMapByURL.get(header.sourceMapURL); + if (sourceMap.editable()) + WebInspector.console.log(WebInspector.UIString("LiveSASS stopped: %s", header.sourceMapURL)); + this._sourceMapByURL.delete(header.sourceMapURL); this.dispatchEventToListeners(WebInspector.CSSModel.Events.SourceMapDetached, header); }, @@ -170,6 +242,119 @@ WebInspector.CSSModel.prototype = { return /** @type {!WebInspector.DOMModel} */(this._domModel); }, + /** + * @param {!CSSAgent.StyleSheetId} styleSheetId + * @param {!WebInspector.TextRange} range + * @param {string} text + * @param {boolean} majorChange + * @return {!Promise} + */ + setStyleText: function(styleSheetId, range, text, majorChange) + { + var original = this._innerSetStyleTexts.bind(this, [styleSheetId], [range], [text], majorChange); + var header = this.styleSheetHeaderForId(styleSheetId); + if (!header) + return original(); + + var sourceMap = this.sourceMapForHeader(header); + if (!sourceMap) + return original(); + + var originalAndDetach = originalAndDetachIfSuccess.bind(this, header); + + if (!sourceMap.editable()) + return originalAndDetach(); + + return /** @type {!Promise} */(sourceMap.editCompiled([range], [text]) + .then(onEditingDone.bind(this)) + .catch(onError.bind(this, header))); + + /** + * @param {?WebInspector.SourceMap.EditResult} editResult + * @return {!Promise} + * @this {WebInspector.CSSModel} + */ + function onEditingDone(editResult) + { + if (!editResult) + return originalAndDetach(); + + var edits = editResult.compiledEdits; + if (!edits.length) + return onCSSPatched.call(this, editResult, true); + + edits.sort(WebInspector.SourceEdit.comparator); + edits = edits.reverse(); + + var styleSheetIds = []; + var ranges = []; + var texts = []; + for (var edit of edits) { + styleSheetIds.push(header.id); + ranges.push(edit.oldRange); + texts.push(edit.newText); + } + return this._innerSetStyleTexts(styleSheetIds, ranges, texts, majorChange) + .then(onCSSPatched.bind(this, editResult)); + } + + /** + * @param {!WebInspector.SourceMap.EditResult} editResult + * @param {boolean} success + * @return {!Promise} + * @this {WebInspector.CSSModel} + */ + function onCSSPatched(editResult, success) + { + if (!success) + return originalAndDetach(); + + this._sourceMapByURL.set(header.sourceMapURL, editResult.map); + this.dispatchEventToListeners(WebInspector.CSSModel.Events.SourceMapChanged, { + sourceMap: editResult.map, + newSources: editResult.newSources + }); + return Promise.resolve(true); + } + + /** + * @param {!WebInspector.CSSStyleSheetHeader} header + * @param {*} error + * @return {!Promise} + * @this {WebInspector.CSSModel} + */ + function onError(header, error) + { + WebInspector.console.error(WebInspector.UIString("LiveSASS failed: %s", sourceMap.compiledURL())); + console.error(error); + this._detachSourceMap(header); + return original(); + } + + /** + * @param {!WebInspector.CSSStyleSheetHeader} header + * @return {!Promise} + * @this {WebInspector.CSSModel} + */ + function originalAndDetachIfSuccess(header) + { + return this._innerSetStyleTexts([styleSheetId], [range], [text], majorChange) + .then(detachIfSuccess.bind(this)); + + /** + * @param {boolean} success + * @return {boolean} + * @this {WebInspector.CSSModel} + */ + function detachIfSuccess(success) + { + if (success) + this._detachSourceMap(header); + return success; + } + } + }, + /** * @param {!Array} styleSheetIds * @param {!Array} ranges @@ -177,7 +362,7 @@ WebInspector.CSSModel.prototype = { * @param {boolean} majorChange * @return {!Promise} */ - setStyleTexts: function(styleSheetIds, ranges, texts, majorChange) + _innerSetStyleTexts: function(styleSheetIds, ranges, texts, majorChange) { /** * @param {?Protocol.Error} error @@ -233,7 +418,7 @@ WebInspector.CSSModel.prototype = { return false; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, range, text, selectorPayload); - this._fireStyleSheetChanged(styleSheetId, edit); + this._fireStyleSheetChangedAndDetach(styleSheetId, edit); return true; } @@ -262,7 +447,7 @@ WebInspector.CSSModel.prototype = { return false; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, range, text, payload); - this._fireStyleSheetChanged(styleSheetId, edit); + this._fireStyleSheetChangedAndDetach(styleSheetId, edit); return true; } @@ -494,7 +679,7 @@ WebInspector.CSSModel.prototype = { return false; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(media.parentStyleSheetId, media.range, newMediaText, mediaPayload); - this._fireStyleSheetChanged(media.parentStyleSheetId, edit); + this._fireStyleSheetChangedAndDetach(media.parentStyleSheetId, edit); return true; } @@ -528,7 +713,7 @@ WebInspector.CSSModel.prototype = { return null; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, ruleLocation, ruleText, rulePayload); - this._fireStyleSheetChanged(styleSheetId, edit); + this._fireStyleSheetChangedAndDetach(styleSheetId, edit); return new WebInspector.CSSStyleRule(this, rulePayload); } }, @@ -593,10 +778,19 @@ WebInspector.CSSModel.prototype = { */ _fireStyleSheetChanged: function(styleSheetId, edit) { + this.dispatchEventToListeners(WebInspector.CSSModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, edit: edit }); + }, + + /** + * @param {!CSSAgent.StyleSheetId} styleSheetId + * @param {!WebInspector.CSSModel.Edit=} edit + */ + _fireStyleSheetChangedAndDetach: function(styleSheetId, edit) + { + this.dispatchEventToListeners(WebInspector.CSSModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, edit: edit }); var header = this.styleSheetHeaderForId(styleSheetId); if (header) - this._detachSourceMap(header.sourceMapURL, header); - this.dispatchEventToListeners(WebInspector.CSSModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, edit: edit }); + this._detachSourceMap(header); }, /** @@ -640,7 +834,7 @@ WebInspector.CSSModel.prototype = { if (!Object.keys(frameIdToStyleSheetIds).length) this._styleSheetIdsForURL.remove(url); } - this._detachSourceMap(header.sourceMapURL, header); + this._detachSourceMap(header); this.dispatchEventToListeners(WebInspector.CSSModel.Events.StyleSheetRemoved, header); }, @@ -668,7 +862,7 @@ WebInspector.CSSModel.prototype = { */ setStyleSheetText: function(styleSheetId, newText, majorChange) { - var header = this._styleSheetIdToHeader.get(styleSheetId); + var header = /** @type {!WebInspector.CSSStyleSheetHeader} */(this._styleSheetIdToHeader.get(styleSheetId)); console.assert(header); newText = WebInspector.CSSModel.trimSourceURL(newText); if (header.hasSourceURL) @@ -683,12 +877,9 @@ WebInspector.CSSModel.prototype = { */ function callback(error, sourceMapURL) { - var oldSourceMapURL = header.sourceMapURL; + this._detachSourceMap(header); header.setSourceMapURL(sourceMapURL); - if (oldSourceMapURL !== header.sourceMapURL) { - this._detachSourceMap(oldSourceMapURL, header); - this._attachSourceMap(header); - } + this._attachSourceMap(header); if (error) return error; if (majorChange) @@ -734,12 +925,12 @@ WebInspector.CSSModel.prototype = { this._styleSheetIdsForURL.clear(); this._styleSheetIdToHeader.clear(); for (var i = 0; i < headers.length; ++i) { - this._detachSourceMap(headers[i].sourceMapURL, headers[i]); + this._detachSourceMap(headers[i]); this.dispatchEventToListeners(WebInspector.CSSModel.Events.StyleSheetRemoved, headers[i]); } this._sourceMapByURL.clear(); this._sourceMapURLToHeaders.clear(); - this._sourceMapLoadingPromises.clear(); + this._sourceMapLoadingStyleSheetsIds.clear(); }, /** @@ -868,7 +1059,7 @@ WebInspector.CSSDispatcher.prototype = { */ styleSheetChanged: function(styleSheetId) { - this._cssModel._fireStyleSheetChanged(styleSheetId); + this._cssModel._fireStyleSheetChangedAndDetach(styleSheetId); }, /** diff --git a/front_end/sdk/CSSStyleDeclaration.js b/front_end/sdk/CSSStyleDeclaration.js index c92a61a4b4..f2d3cc72d1 100644 --- a/front_end/sdk/CSSStyleDeclaration.js +++ b/front_end/sdk/CSSStyleDeclaration.js @@ -286,7 +286,7 @@ WebInspector.CSSStyleDeclaration.prototype = { */ setText: function(text, majorChange) { - return this._cssModel.setStyleTexts([this.styleSheetId], [this.range], [text], majorChange) + return this._cssModel.setStyleText(this.styleSheetId, this.range, text, majorChange) }, /** diff --git a/front_end/sdk/DebuggerModel.js b/front_end/sdk/DebuggerModel.js index 3c65ab385b..491729eacb 100644 --- a/front_end/sdk/DebuggerModel.js +++ b/front_end/sdk/DebuggerModel.js @@ -89,8 +89,7 @@ WebInspector.DebuggerModel.Events = { FailedToParseScriptSource: "FailedToParseScriptSource", GlobalObjectCleared: "GlobalObjectCleared", CallFrameSelected: "CallFrameSelected", - ConsoleCommandEvaluatedInSelectedCallFrame: "ConsoleCommandEvaluatedInSelectedCallFrame", - PromiseUpdated: "PromiseUpdated", + ConsoleCommandEvaluatedInSelectedCallFrame: "ConsoleCommandEvaluatedInSelectedCallFrame" } /** @enum {string} */ @@ -351,43 +350,6 @@ WebInspector.DebuggerModel.prototype = { } }, - /** - * @param {boolean} captureStacks - */ - enablePromiseTracker: function(captureStacks) - { - this._agent.enablePromiseTracker(captureStacks); - }, - - disablePromiseTracker: function() - { - this._agent.disablePromiseTracker(); - }, - - /** - * @param {number} promiseId - * @param {string=} objectGroup - * @param {function(?RuntimeAgent.RemoteObject)=} callback - */ - getPromiseById: function(promiseId, objectGroup, callback) - { - this._agent.getPromiseById(promiseId, objectGroup, innerCallback); - - /** - * @param {?Protocol.Error} error - * @param {?RuntimeAgent.RemoteObject} promise - */ - function innerCallback(error, promise) - { - if (error) { - console.error(error); - callback(null); - return; - } - callback(promise); - } - }, - flushAsyncOperationEvents: function() { this._agent.flushAsyncOperationEvents(); @@ -426,15 +388,6 @@ WebInspector.DebuggerModel.prototype = { this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalObjectCleared); }, - /** - * @param {string} eventType - * @param {!DebuggerAgent.PromiseDetails} promise - */ - _promiseUpdated: function(eventType, promise) - { - this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.PromiseUpdated, { eventType: eventType, promise: promise }); - }, - /** * @param {!DebuggerAgent.AsyncOperation} operation */ @@ -1023,16 +976,6 @@ WebInspector.DebuggerDispatcher.prototype = { this._debuggerModel._breakpointResolved(breakpointId, location); }, - /** - * @override - * @param {string} eventType - * @param {!DebuggerAgent.PromiseDetails} promise - */ - promiseUpdated: function(eventType, promise) - { - this._debuggerModel._promiseUpdated(eventType, promise); - }, - /** * @override * @param {!DebuggerAgent.AsyncOperation} operation diff --git a/front_end/sdk/HAREntry.js b/front_end/sdk/HAREntry.js index ce3591f89d..ec7d526f14 100644 --- a/front_end/sdk/HAREntry.js +++ b/front_end/sdk/HAREntry.js @@ -49,13 +49,19 @@ WebInspector.HAREntry.prototype = { */ build: function() { + var ipAddress = this._request.remoteAddress(); + var portPositionInString = ipAddress.lastIndexOf(":"); + if (portPositionInString !== -1) + ipAddress = ipAddress.substr(0, portPositionInString); + var entry = { startedDateTime: WebInspector.HARLog.pseudoWallTime(this._request, this._request.startTime), time: this._request.timing ? WebInspector.HAREntry._toMilliseconds(this._request.duration) : 0, request: this._buildRequest(), response: this._buildResponse(), cache: { }, // Not supported yet. - timings: this._buildTimings() + timings: this._buildTimings(), + serverIPAddress: ipAddress }; if (this._request.connectionId !== "0") diff --git a/front_end/sdk/NetworkManager.js b/front_end/sdk/NetworkManager.js index 45986d2318..55b3b748b8 100644 --- a/front_end/sdk/NetworkManager.js +++ b/front_end/sdk/NetworkManager.js @@ -80,6 +80,8 @@ WebInspector.NetworkManager._MIMETypes = { WebInspector.NetworkManager.Conditions; /** @type {!WebInspector.NetworkManager.Conditions} */ WebInspector.NetworkManager.NoThrottlingConditions = {title: WebInspector.UIString("No throttling"), download: -1, upload: -1, latency: 0}; +/** @type {!WebInspector.NetworkManager.Conditions} */ +WebInspector.NetworkManager.OfflineConditions = {title: WebInspector.UIString("Offline"), download: 0, upload: 0, latency: 0}; WebInspector.NetworkManager.prototype = { /** diff --git a/front_end/source_frame/SourceFrame.js b/front_end/source_frame/SourceFrame.js index f59378c3b8..8b4417bceb 100644 --- a/front_end/source_frame/SourceFrame.js +++ b/front_end/source_frame/SourceFrame.js @@ -29,8 +29,9 @@ */ /** - * @extends {WebInspector.VBoxWithToolbarItems} * @constructor + * @extends {WebInspector.VBoxWithToolbarItems} + * @implements {WebInspector.Searchable} * @implements {WebInspector.Replaceable} * @param {!WebInspector.ContentProvider} contentProvider */ @@ -54,6 +55,11 @@ WebInspector.SourceFrame = function(contentProvider) this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); this._sourcePosition = new WebInspector.ToolbarText(); + + /** + * @type {?WebInspector.SearchableView} + */ + this._searchableView = null; } WebInspector.SourceFrame.Events = { @@ -230,8 +236,8 @@ WebInspector.SourceFrame.prototype = { */ onTextChanged: function(oldRange, newRange) { - if (this._searchResultsChangedCallback) - this._searchResultsChangedCallback(); + if (this._searchConfig && this._searchableView) + this.performSearch(this._searchConfig, false, false); }, /** @@ -299,13 +305,20 @@ WebInspector.SourceFrame.prototype = { onTextEditorContentLoaded: function() {}, + /** + * @param {?WebInspector.SearchableView} view + */ + setSearchableView: function(view) + { + this._searchableView = view; + }, + /** * @param {!WebInspector.SearchableView.SearchConfig} searchConfig * @param {boolean} shouldJump * @param {boolean} jumpBackwards - * @param {function(!WebInspector.Widget, number)} searchFinishedCallback */ - _doFindSearchMatches: function(searchConfig, shouldJump, jumpBackwards, searchFinishedCallback) + _doFindSearchMatches: function(searchConfig, shouldJump, jumpBackwards) { this._currentSearchResultIndex = -1; this._searchResults = []; @@ -313,7 +326,10 @@ WebInspector.SourceFrame.prototype = { var regex = searchConfig.toSearchRegex(); this._searchRegex = regex; this._searchResults = this._collectRegexMatches(regex); - searchFinishedCallback(this, this._searchResults.length); + + if (this._searchableView) + this._searchableView.updateSearchMatchesCount(this._searchResults.length); + if (!this._searchResults.length) this._textEditor.cancelSearchResultsHighlight(); else if (shouldJump && jumpBackwards) @@ -325,23 +341,22 @@ WebInspector.SourceFrame.prototype = { }, /** + * @override * @param {!WebInspector.SearchableView.SearchConfig} searchConfig * @param {boolean} shouldJump - * @param {boolean} jumpBackwards - * @param {function(!WebInspector.Widget, number)} searchFinishedCallback - * @param {function(number)} currentMatchChangedCallback - * @param {function()} searchResultsChangedCallback + * @param {boolean=} jumpBackwards */ - performSearch: function(searchConfig, shouldJump, jumpBackwards, searchFinishedCallback, currentMatchChangedCallback, searchResultsChangedCallback) + performSearch: function(searchConfig, shouldJump, jumpBackwards) { + if (this._searchableView) + this._searchableView.updateSearchMatchesCount(0); + this._resetSearch(); - this._currentSearchMatchChangedCallback = currentMatchChangedCallback; - this._searchResultsChangedCallback = searchResultsChangedCallback; - var searchFunction = this._doFindSearchMatches.bind(this, searchConfig, shouldJump, jumpBackwards, searchFinishedCallback); + this._searchConfig = searchConfig; if (this.loaded) - searchFunction.call(this); + this._doFindSearchMatches(searchConfig, shouldJump, !!jumpBackwards) else - this._delayedFindSearchMatches = searchFunction; + this._delayedFindSearchMatches = this._doFindSearchMatches.bind(this, searchConfig, shouldJump, !!jumpBackwards); this._ensureContentLoaded(); }, @@ -356,21 +371,23 @@ WebInspector.SourceFrame.prototype = { if (!this._searchResults.length) return; this._currentSearchResultIndex = -1; - if (this._currentSearchMatchChangedCallback) - this._currentSearchMatchChangedCallback(this._currentSearchResultIndex); + if (this._searchableView) + this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIndex); this._textEditor.highlightSearchResults(this._searchRegex, null); }, _resetSearch: function() { + delete this._searchConfig; delete this._delayedFindSearchMatches; - delete this._currentSearchMatchChangedCallback; - delete this._searchResultsChangedCallback; this._currentSearchResultIndex = -1; this._searchResults = []; delete this._searchRegex; }, + /** + * @override + */ searchCanceled: function() { var range = this._currentSearchResultIndex !== -1 ? this._searchResults[this._currentSearchResultIndex] : null; @@ -408,6 +425,9 @@ WebInspector.SourceFrame.prototype = { return this._searchResults.lowerBound(this._textEditor.selection().collapseToEnd(), WebInspector.TextRange.comparator); }, + /** + * @override + */ jumpToNextSearchResult: function() { var currentIndex = this._searchResultIndexForCurrentSelection(); @@ -415,12 +435,33 @@ WebInspector.SourceFrame.prototype = { this.jumpToSearchResult(nextIndex); }, + /** + * @override + */ jumpToPreviousSearchResult: function() { var currentIndex = this._searchResultIndexForCurrentSelection(); this.jumpToSearchResult(currentIndex - 1); }, + /** + * @override + * @return {boolean} + */ + supportsCaseSensitiveSearch: function () + { + return true; + }, + + /** + * @override + * @return {boolean} + */ + supportsRegexSearch: function() + { + return true; + }, + get currentSearchResultIndex() { return this._currentSearchResultIndex; @@ -431,8 +472,8 @@ WebInspector.SourceFrame.prototype = { if (!this.loaded || !this._searchResults.length) return; this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length; - if (this._currentSearchMatchChangedCallback) - this._currentSearchMatchChangedCallback(this._currentSearchResultIndex); + if (this._searchableView) + this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIndex); this._textEditor.highlightSearchResults(this._searchRegex, this._searchResults[this._currentSearchResultIndex]); }, diff --git a/front_end/source_frame/TextEditorAutocompleteController.js b/front_end/source_frame/TextEditorAutocompleteController.js index fc755380a3..3c96b052fb 100644 --- a/front_end/source_frame/TextEditorAutocompleteController.js +++ b/front_end/source_frame/TextEditorAutocompleteController.js @@ -138,7 +138,7 @@ WebInspector.TextEditorAutocompleteController.prototype = { this._prefixRange = prefixRange; if (!oldPrefixRange || prefixRange.startLine !== oldPrefixRange.startLine || prefixRange.startColumn !== oldPrefixRange.startColumn) this._updateAnchorBox(); - this._suggestBox.updateSuggestions(this._anchorBox, wordsWithPrefix, 0, true, this._textEditor.copyRange(prefixRange)); + this._suggestBox.updateSuggestions(this._anchorBox, wordsWithPrefix.map(item => ({title: item})), 0, true, this._textEditor.copyRange(prefixRange)); if (!this._suggestBox.visible()) this.finishAutocomplete(); this._onSuggestionsShownForTest(wordsWithPrefix); diff --git a/front_end/sources/CallStackSidebarPane.js b/front_end/sources/CallStackSidebarPane.js index 6f0605b1c7..d2232a31fa 100644 --- a/front_end/sources/CallStackSidebarPane.js +++ b/front_end/sources/CallStackSidebarPane.js @@ -37,6 +37,9 @@ WebInspector.CallStackSidebarPane = function() this._linkifier = new WebInspector.Linkifier(); WebInspector.moduleSetting("enableAsyncStackTraces").addChangeListener(this._asyncStackTracesStateChanged, this); WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._blackboxingStateChanged, this); + /** @type {!Array} */ + this.callFrames = []; + this._locationPool = new WebInspector.LiveLocationPool(); } /** @enum {string} */ @@ -55,6 +58,7 @@ WebInspector.CallStackSidebarPane.prototype = { this.callFrameList.clear(); this._linkifier.reset(); this.element.removeChildren(); + this._locationPool.disposeAll(); if (!details) { var infoElement = this.element.createChild("div", "callstack-info"); @@ -68,7 +72,6 @@ WebInspector.CallStackSidebarPane.prototype = { delete this._statusMessageElement; delete this._hiddenCallFramesMessageElement; - /** @type {!Array.} */ this.callFrames = []; this._hiddenCallFrames = 0; @@ -110,7 +113,7 @@ WebInspector.CallStackSidebarPane.prototype = { var callFrameItems = []; for (var i = 0, n = callFrames.length; i < n; ++i) { var callFrame = callFrames[i]; - var callFrameItem = new WebInspector.CallStackSidebarPane.CallFrame(callFrame.functionName, callFrame.location(), this._linkifier, callFrame); + var callFrameItem = new WebInspector.CallStackSidebarPane.CallFrame(callFrame.functionName, callFrame.location(), this._linkifier, callFrame, this._locationPool); callFrameItem.element.addEventListener("click", this._callFrameSelected.bind(this, callFrameItem), false); callFrameItems.push(callFrameItem); } @@ -131,7 +134,7 @@ WebInspector.CallStackSidebarPane.prototype = { var lineNumber = callFrame.lineNumber ? callFrame.lineNumber - 1 : 0; var columnNumber = callFrame.columnNumber ? callFrame.columnNumber - 1 : 0; var location = new WebInspector.DebuggerModel.Location(this._debuggerModel, callFrame.scriptId, lineNumber, columnNumber); - var callFrameItem = new WebInspector.CallStackSidebarPane.CallFrame(callFrame.functionName, location, this._linkifier, null, asyncCallFrameItem); + var callFrameItem = new WebInspector.CallStackSidebarPane.CallFrame(callFrame.functionName, location, this._linkifier, null, this._locationPool, asyncCallFrameItem); callFrameItem.element.addEventListener("click", this._asyncCallFrameClicked.bind(this, callFrameItem), false); callFrameItems.push(callFrameItem); } @@ -438,9 +441,10 @@ WebInspector.CallStackSidebarPane.prototype = { * @param {!WebInspector.DebuggerModel.Location} location * @param {!WebInspector.Linkifier} linkifier * @param {?WebInspector.DebuggerModel.CallFrame} debuggerCallFrame + * @param {!WebInspector.LiveLocationPool} locationPool * @param {!WebInspector.UIList.Item=} asyncCallFrame */ -WebInspector.CallStackSidebarPane.CallFrame = function(functionName, location, linkifier, debuggerCallFrame, asyncCallFrame) +WebInspector.CallStackSidebarPane.CallFrame = function(functionName, location, linkifier, debuggerCallFrame, locationPool, asyncCallFrame) { WebInspector.UIList.Item.call(this, WebInspector.beautifyFunctionName(functionName), ""); this._location = location; @@ -451,7 +455,8 @@ WebInspector.CallStackSidebarPane.CallFrame = function(functionName, location, l var locationElement = linkifier.linkifyRawLocation(location, location.script().sourceURL); this.subtitleElement.appendChild(locationElement); } else { - WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(location, this._update.bind(this)); + this._liveLocationPool = new WebInspector.LiveLocationPool(); + WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(location, this._update.bind(this), locationPool); } } diff --git a/front_end/sources/SourceMapNamesResolver.js b/front_end/sources/SourceMapNamesResolver.js index 68da339dc6..99802d14e4 100644 --- a/front_end/sources/SourceMapNamesResolver.js +++ b/front_end/sources/SourceMapNamesResolver.js @@ -38,12 +38,12 @@ WebInspector.SourceMapNamesResolver._resolveScope = function(scope) /** * @param {?string} content - * @return {!Map} + * @return {!Promise>} */ function onContent(content) { if (!content) - return new Map(); + return Promise.resolve(new Map()); var startLocation = scope.startLocation(); var endLocation = scope.endLocation(); @@ -53,56 +53,26 @@ WebInspector.SourceMapNamesResolver._resolveScope = function(scope) var scopeText = text.extract(textRange); var scopeStart = text.toSourceRange(textRange).offset; var prefix = "function fui"; - var root = acorn.parse(prefix + scopeText, {}); - /** @type {!Array} */ - var identifiers = []; - var functionDeclarationCounter = 0; - var walker = new WebInspector.ESTreeWalker(beforeVisit, afterVisit); - - /** - * @param {!ESTree.Node} node - * @return {boolean} - */ - function isFunction(node) - { - return node.type === "FunctionDeclaration" || node.type === "FunctionExpression"; - } - - /** - * @param {!ESTree.Node} node - */ - function beforeVisit(node) - { - if (isFunction(node)) - functionDeclarationCounter++; - - if (functionDeclarationCounter > 1) - return; - - if (isFunction(node) && node.params) - identifiers.pushAll(node.params); - - if (node.type === "VariableDeclarator") - identifiers.push(/** @type {!ESTree.Node} */(node.id)); - } - - /** - * @param {!ESTree.Node} node - */ - function afterVisit(node) - { - if (isFunction(node)) - functionDeclarationCounter--; - } - walker.walk(root); + return WebInspector.SourceMapNamesResolverWorker._instance().javaScriptIdentifiers(prefix + scopeText) + .then(onIdentifiers.bind(null, text, scopeStart, prefix)); + } + /** + * @param {!WebInspector.Text} text + * @param {number} scopeStart + * @param {string} prefix + * @param {!Array} identifiers + * @return {!Map} + */ + function onIdentifiers(text, scopeStart, prefix, identifiers) + { var namesMapping = new Map(); - var lineEndings = content.computeLineEndings(); + var lineEndings = text.lineEndings(); for (var i = 0; i < identifiers.length; ++i) { var id = identifiers[i]; - var start = scopeStart + id.start - prefix.length; + var start = scopeStart + id.offset - prefix.length; var lineNumber = lineEndings.lowerBound(start); var columnNumber = start - (lineNumber === 0 ? 0 : (lineEndings[lineNumber - 1] + 1)); @@ -113,10 +83,13 @@ WebInspector.SourceMapNamesResolver._resolveScope = function(scope) scope[WebInspector.SourceMapNamesResolver._cachedMapSymbol] = namesMapping; delete scope[WebInspector.SourceMapNamesResolver._cachedPromiseSymbol]; + WebInspector.SourceMapNamesResolver._scopeResolvedForTest(); return namesMapping; } } +WebInspector.SourceMapNamesResolver._scopeResolvedForTest = function() { } + /** * @param {!WebInspector.DebuggerModel.CallFrame} callFrame * @return {!Promise.>} @@ -206,53 +179,19 @@ WebInspector.SourceMapNamesResolver._resolveExpression = function(callFrame, uiS /** * @param {?string} content - * @return {string} + * @return {!Promise} */ function onContent(content) { if (!content) - return ""; + return Promise.resolve(""); var text = new WebInspector.Text(content); var textRange = sourceMap.reverseMapTextRange(uiSourceCode.url(), new WebInspector.TextRange(lineNumber, startColumnNumber, lineNumber, endColumnNumber)); var originalText = text.extract(textRange); if (!originalText) - return ""; - - var tokenizer = acorn.tokenizer(originalText, {ecmaVersion: 6}); - try { - var token = tokenizer.getToken(); - while (token.type !== acorn.tokTypes.eof && WebInspector.AcornTokenizer.punctuator(token)) - token = tokenizer.getToken(); - - var startIndex = token.start; - var endIndex = token.end; - var openBracketsCounter = 0; - while (token.type !== acorn.tokTypes.eof) { - var isIdentifier = WebInspector.AcornTokenizer.identifier(token); - var isThis = WebInspector.AcornTokenizer.keyword(token, "this"); - var isString = token.type === acorn.tokTypes.string; - if (!isThis && !isIdentifier && !isString) - break; - - endIndex = token.end; - token = tokenizer.getToken(); - while (WebInspector.AcornTokenizer.punctuator(token, ".[]")) { - if (WebInspector.AcornTokenizer.punctuator(token, "[")) - openBracketsCounter++; - - if (WebInspector.AcornTokenizer.punctuator(token, "]")) { - endIndex = openBracketsCounter > 0 ? token.end : endIndex; - openBracketsCounter--; - } - - token = tokenizer.getToken(); - } - } - return originalText.substring(startIndex, endIndex); - } catch (e) { - return ""; - } + return Promise.resolve(""); + return WebInspector.SourceMapNamesResolverWorker._instance().evaluatableJavaScriptSubstring(originalText); } } @@ -519,3 +458,99 @@ WebInspector.SourceMapNamesResolver.RemoteObject.prototype = { __proto__: WebInspector.RemoteObject.prototype } + +/** + * @constructor + */ +WebInspector.SourceMapNamesResolverWorker = function() +{ + this._worker = new WorkerRuntime.Worker("formatter_worker"); + this._worker.onmessage = this._onMessage.bind(this); + this._methodNames = []; + this._contents = []; + this._callbacks = []; +} + +WebInspector.SourceMapNamesResolverWorker.prototype = { + /** + * @param {string} text + * @return {!Promise} + */ + evaluatableJavaScriptSubstring: function(text) + { + var callback; + var promise = new Promise(fulfill => callback = fulfill); + this._methodNames.push("evaluatableJavaScriptSubstring"); + this._contents.push(text); + this._callbacks.push(this._evaluatableJavaScriptSubstringCallback.bind(this, callback)); + this._maybeRunTask(); + return promise; + }, + + /** + * @param {function(string)} callback + * @param {!MessageEvent} event + */ + _evaluatableJavaScriptSubstringCallback: function(callback, event) + { + callback.call(null, /** @type {string} */(event.data)); + }, + + /** + * @param {string} text + * @return {!Promise>} + */ + javaScriptIdentifiers: function(text) + { + var callback; + var promise = new Promise(fulfill => callback = fulfill); + this._methodNames.push("javaScriptIdentifiers"); + this._contents.push(text); + this._callbacks.push(this._javaScriptIdentifiersCallback.bind(this, callback)); + this._maybeRunTask(); + return promise; + }, + + /** + * @param {function(!Array)} callback + * @param {!MessageEvent} event + */ + _javaScriptIdentifiersCallback: function(callback, event) + { + callback.call(null, /** @type {!Array} */(event.data)); + }, + + /** + * @param {!MessageEvent} event + */ + _onMessage: function(event) + { + var callback = this._callbacks[0]; + this._methodNames.shift(); + this._contents.shift(); + this._callbacks.shift(); + callback.call(null, event); + this._runningTask = false; + this._maybeRunTask(); + }, + + _maybeRunTask: function() + { + if (this._runningTask || !this._methodNames.length) + return; + this._runningTask = true; + var methodName = this._methodNames[0]; + var content = this._contents[0]; + this._worker.postMessage({ method: methodName, params: { content: content } }); + } +} + +/** + * @return {!WebInspector.SourceMapNamesResolverWorker} + */ +WebInspector.SourceMapNamesResolverWorker._instance = function() +{ + if (!WebInspector.SourceMapNamesResolverWorker._instanceObject) + WebInspector.SourceMapNamesResolverWorker._instanceObject = new WebInspector.SourceMapNamesResolverWorker(); + return WebInspector.SourceMapNamesResolverWorker._instanceObject; +} \ No newline at end of file diff --git a/front_end/sources/SourcesPanel.js b/front_end/sources/SourcesPanel.js index ff6ae63c74..b24be6139e 100644 --- a/front_end/sources/SourcesPanel.js +++ b/front_end/sources/SourcesPanel.js @@ -103,6 +103,9 @@ WebInspector.SourcesPanel = function(workspaceForTest) this._updateDebuggerButtons(); this._pauseOnExceptionEnabledChanged(); WebInspector.moduleSetting("pauseOnExceptionEnabled").addChangeListener(this._pauseOnExceptionEnabledChanged, this); + + this._liveLocationPool = new WebInspector.LiveLocationPool(); + this._setTarget(WebInspector.context.flavor(WebInspector.Target)); WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this); WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._onCurrentTargetChanged, this); @@ -291,7 +294,7 @@ WebInspector.SourcesPanel.prototype = { } } else { if (details.callFrames.length) - WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(details.callFrames[0].location(), didGetUILocation.bind(this)); + WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(details.callFrames[0].location(), didGetUILocation.bind(this), this._liveLocationPool); else console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better } @@ -436,7 +439,7 @@ WebInspector.SourcesPanel.prototype = { this.sidebarPanes.scopechain.update(callFrame); this.sidebarPanes.watchExpressions.refreshExpressions(); this.sidebarPanes.callstack.setSelectedCallFrame(callFrame); - WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(callFrame.location(), this._executionLineChanged.bind(this)); + WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(callFrame.location(), this._executionLineChanged.bind(this), this._liveLocationPool); }, /** @@ -507,6 +510,7 @@ WebInspector.SourcesPanel.prototype = { if (this._switchToPausedTargetTimeout) clearTimeout(this._switchToPausedTargetTimeout); + this._liveLocationPool.disposeAll(); }, /** diff --git a/front_end/sources/SourcesView.js b/front_end/sources/SourcesView.js index 337ba81e46..e96704fe77 100644 --- a/front_end/sources/SourcesView.js +++ b/front_end/sources/SourcesView.js @@ -316,9 +316,18 @@ WebInspector.SourcesView.prototype = { if (this._currentUISourceCode === uiSourceCode) return sourceView; + var currentFrame = this.currentSourceFrame(); + if (currentFrame) + currentFrame.setSearchableView(null); + this._currentUISourceCode = uiSourceCode; this._editorContainer.showFile(uiSourceCode); this._updateScriptViewToolbarItems(); + + currentFrame = this.currentSourceFrame(); + if (currentFrame) + currentFrame.setSearchableView(this._searchableView); + return sourceView; }, @@ -497,8 +506,6 @@ WebInspector.SourcesView.prototype = { */ performSearch: function(searchConfig, shouldJump, jumpBackwards) { - this._searchableView.updateSearchMatchesCount(0); - var sourceFrame = this.currentSourceFrame(); if (!sourceFrame) return; @@ -506,37 +513,7 @@ WebInspector.SourcesView.prototype = { this._searchView = sourceFrame; this._searchConfig = searchConfig; - /** - * @param {!WebInspector.Widget} view - * @param {number} searchMatches - * @this {WebInspector.SourcesView} - */ - function finishedCallback(view, searchMatches) - { - if (!searchMatches) - return; - - this._searchableView.updateSearchMatchesCount(searchMatches); - } - - /** - * @param {number} currentMatchIndex - * @this {WebInspector.SourcesView} - */ - function currentMatchChanged(currentMatchIndex) - { - this._searchableView.updateCurrentMatchIndex(currentMatchIndex); - } - - /** - * @this {WebInspector.SourcesView} - */ - function searchResultsChanged() - { - this.performSearch(this._searchConfig, false, false); - } - - this._searchView.performSearch(this._searchConfig, shouldJump, !!jumpBackwards, finishedCallback.bind(this), currentMatchChanged.bind(this), searchResultsChanged.bind(this)); + this._searchView.performSearch(this._searchConfig, shouldJump, jumpBackwards); }, /** diff --git a/front_end/sources/module.json b/front_end/sources/module.json index 8903b9bde2..fd07496e71 100644 --- a/front_end/sources/module.json +++ b/front_end/sources/module.json @@ -343,7 +343,6 @@ } ], "dependencies": [ - "es_tree", "components", "source_frame", "snippets", diff --git a/front_end/timeline/TimelineFlameChart.js b/front_end/timeline/TimelineFlameChart.js index aa805541f9..e9e4e1b2b7 100644 --- a/front_end/timeline/TimelineFlameChart.js +++ b/front_end/timeline/TimelineFlameChart.js @@ -291,7 +291,7 @@ WebInspector.TimelineFlameChartDataProvider = function(model, frameModel, irMode color: WebInspector.themeSupport.patchColor("#222", WebInspector.ThemeSupport.ColorUsage.Foreground), font: this._font, backgroundColor: WebInspector.themeSupport.patchColor("white", WebInspector.ThemeSupport.ColorUsage.Background), - nestingLevel: 0, + nestingLevel: 0 }; this._headerLevel2 = { @@ -388,17 +388,16 @@ WebInspector.TimelineFlameChartDataProvider.prototype = { this._appendInteractionRecords(); var threads = this._model.virtualThreads(); + this._appendThreadTimelineData(WebInspector.UIString("Main"), this._model.mainThreadEvents(), this._model.mainThreadAsyncEvents(), true); var compositorThreads = threads.filter(thread => thread.name.startsWith("CompositorTileWorker")); var otherThreads = threads.filter(thread => !thread.name.startsWith("CompositorTileWorker")); if (compositorThreads.length) { - this._appendHeader(WebInspector.UIString("Rasterizer Threads"), this._headerLevel1); + this._appendHeader(WebInspector.UIString("Raster"), this._headerLevel1); for (var i = 0; i < compositorThreads.length; ++i) this._appendSyncEvents(compositorThreads[i].events, WebInspector.UIString("Rasterizer Thread %d", i), this._headerLevel2); } this._appendGPUEvents(); - this._appendThreadTimelineData(WebInspector.UIString("Main Thread"), this._model.mainThreadEvents(), this._model.mainThreadAsyncEvents(), true); - otherThreads.forEach(thread => this._appendThreadTimelineData(thread.name, thread.events, thread.asyncEventsByGroup)); /** @@ -654,7 +653,7 @@ WebInspector.TimelineFlameChartDataProvider.prototype = { if (type === WebInspector.TimelineFlameChartEntryType.Frame) return "white"; if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord) - return WebInspector.TimelineUIUtils.interactionPhaseColor(/** @type {!WebInspector.TimelineIRModel.Phases} */ (this._entryData[entryIndex])); + return "transparent"; return ""; }, @@ -681,10 +680,8 @@ WebInspector.TimelineFlameChartDataProvider.prototype = { barWidth -= 2 * hPadding; barY += vPadding; barHeight -= 2 * vPadding + 1; - context.fillStyle = frame.idle ? "white" : "#eee"; + context.fillStyle = frame.idle ? "white" : (frame.hasWarnings() ? "#fad1d1" : "#d7f0d1"); context.fillRect(barX, barY, barWidth, barHeight); - if (frame.hasWarnings()) - paintWarningDecoration(barX, barWidth); var frameDurationText = Number.preciseMillisToString(frame.duration, 1); var textWidth = context.measureText(frameDurationText).width; if (barWidth >= textWidth) { @@ -694,6 +691,15 @@ WebInspector.TimelineFlameChartDataProvider.prototype = { return true; } + if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord) { + var color = WebInspector.TimelineUIUtils.interactionPhaseColor(/** @type {!WebInspector.TimelineIRModel.Phases} */ (this._entryData[entryIndex])); + context.fillStyle = color; + context.fillRect(barX, barY, barWidth - 1, 2); + context.fillRect(barX, barY - 3, 2, 3); + context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); + return false; + } + if (type === WebInspector.TimelineFlameChartEntryType.Event) { var event = /** @type {!WebInspector.TracingModel.Event} */ (this._entryData[entryIndex]); if (event && event.warning) diff --git a/front_end/timeline/TimelineModel.js b/front_end/timeline/TimelineModel.js index 243d057d79..70686f5f9b 100644 --- a/front_end/timeline/TimelineModel.js +++ b/front_end/timeline/TimelineModel.js @@ -117,6 +117,7 @@ WebInspector.TimelineModel.RecordType = { V8Sample: "V8Sample", JitCodeAdded: "JitCodeAdded", JitCodeMoved: "JitCodeMoved", + ParseScriptOnBackground: "v8.parseOnBackground", UpdateCounters: "UpdateCounters", diff --git a/front_end/timeline/TimelinePanel.js b/front_end/timeline/TimelinePanel.js index a048529b60..fcd5f5b543 100644 --- a/front_end/timeline/TimelinePanel.js +++ b/front_end/timeline/TimelinePanel.js @@ -119,6 +119,7 @@ WebInspector.TimelinePanel = function() this._detailsSplitWidget.hideSidebar(); WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged, this); this._showRecordingHelpMessage(); + this._locationPool = new WebInspector.LiveLocationPool(); } /** @@ -1280,7 +1281,7 @@ WebInspector.TimelinePanel.prototype = { var time = lineInfo[1]; var rawLocation = debuggerModel.createRawLocationByURL(url, line, 0); if (rawLocation) - new WebInspector.TimelineUIUtils.LineLevelProfilePresentation(rawLocation, time); + new WebInspector.TimelineUIUtils.LineLevelProfilePresentation(rawLocation, time, this._locationPool); else if (uiSourceCode) uiSourceCode.addLineDecoration(line, WebInspector.TimelineUIUtils.PerformanceLineDecorator.type, time); } @@ -1289,6 +1290,7 @@ WebInspector.TimelinePanel.prototype = { _resetLineLevelCPUProfile: function() { + this._locationPool.disposeAll(); WebInspector.workspace.uiSourceCodes().forEach(uiSourceCode => uiSourceCode.removeAllLineDecorations(WebInspector.TimelineUIUtils.PerformanceLineDecorator.type)); }, diff --git a/front_end/timeline/TimelineUIUtils.js b/front_end/timeline/TimelineUIUtils.js index 9e77d90fc3..b0cfb04149 100644 --- a/front_end/timeline/TimelineUIUtils.js +++ b/front_end/timeline/TimelineUIUtils.js @@ -90,6 +90,7 @@ WebInspector.TimelineUIUtils._initEventStyles = function() eventStyles[recordTypes.XHRLoad] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("XHR Load"), categories["scripting"]); eventStyles[recordTypes.CompileScript] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Compile Script"), categories["scripting"]); eventStyles[recordTypes.EvaluateScript] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Evaluate Script"), categories["scripting"]); + eventStyles[recordTypes.ParseScriptOnBackground] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Parse Script"), categories["scripting"]); eventStyles[recordTypes.MarkLoad] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Load event"), categories["scripting"], true); eventStyles[recordTypes.MarkDOMContent] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("DOMContentLoaded event"), categories["scripting"], true); eventStyles[recordTypes.MarkFirstPaint] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("First paint"), categories["painting"], true); @@ -391,13 +392,14 @@ WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent = function(event, tar case recordType.EvaluateScript: var url = eventData["url"]; if (url) - detailsText = detailsText = WebInspector.displayNameForURL(url) + ":" + eventData["lineNumber"]; + detailsText = WebInspector.displayNameForURL(url) + ":" + eventData["lineNumber"]; break; + case recordType.ParseScriptOnBackground: case recordType.XHRReadyStateChange: case recordType.XHRLoad: var url = eventData["url"]; if (url) - detailsText = detailsText = WebInspector.displayNameForURL(url); + detailsText = WebInspector.displayNameForURL(url); break; case recordType.WebSocketCreate: @@ -540,6 +542,11 @@ WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent = function(event, tar if (url) details = linkifyLocation("", url, eventData["lineNumber"], 0); break; + case recordType.ParseScriptOnBackground: + var url = eventData["url"]; + if (url) + details = linkifyLocation("", url, 0, 0); + break; default: if (event.hasCategory(WebInspector.TimelineModel.Category.Console)) detailsText = null; @@ -2114,11 +2121,12 @@ WebInspector.TimelineUIUtils.eventWarning = function(event, warningType) * @constructor * @param {!WebInspector.DebuggerModel.Location} rawLocation * @param {number} time + * @param {!WebInspector.LiveLocationPool} locationPool */ -WebInspector.TimelineUIUtils.LineLevelProfilePresentation = function(rawLocation, time) +WebInspector.TimelineUIUtils.LineLevelProfilePresentation = function(rawLocation, time, locationPool) { this._time = time; - WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this.updateLocation.bind(this)); + WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this.updateLocation.bind(this), locationPool); } WebInspector.TimelineUIUtils.LineLevelProfilePresentation.prototype = { diff --git a/front_end/ui/FilterBar.js b/front_end/ui/FilterBar.js index 281deb6fa9..3ff751863e 100644 --- a/front_end/ui/FilterBar.js +++ b/front_end/ui/FilterBar.js @@ -264,6 +264,14 @@ WebInspector.TextFilterUI.prototype = { return this._filterElement; }, + /** + * @return {boolean} + */ + isRegexChecked: function() + { + return this._supportRegex ? this._regexCheckBox.checked : false; + }, + /** * @return {string} */ @@ -341,6 +349,11 @@ WebInspector.TextFilterUI.prototype = { { if (!this._suggestionBuilder) return; + if (this.isRegexChecked()) { + if (this._suggestBox.visible()) + this._suggestBox.hide(); + return; + } var suggestions = this._suggestionBuilder.buildSuggestions(this._filterInputElement); if (suggestions && suggestions.length) { if (this._suppressSuggestion) @@ -348,7 +361,7 @@ WebInspector.TextFilterUI.prototype = { else this._suggestionBuilder.applySuggestion(this._filterInputElement, suggestions[0], true); var anchorBox = this._filterInputElement.boxInWindow().relativeTo(new AnchorBox(-3, 0)); - this._suggestBox.updateSuggestions(anchorBox, suggestions, 0, true, ""); + this._suggestBox.updateSuggestions(anchorBox, suggestions.map(item => ({title: item})), 0, true, ""); } else { this._suggestBox.hide(); } @@ -369,7 +382,7 @@ WebInspector.TextFilterUI.prototype = { this._regex = null; this._filterInputElement.classList.remove("filter-text-invalid"); if (filterQuery) { - if (this._supportRegex && this._regexCheckBox.checked) { + if (this.isRegexChecked()) { try { this._regex = new RegExp(filterQuery, "i"); } catch (e) { diff --git a/front_end/ui/SuggestBox.js b/front_end/ui/SuggestBox.js index f1cb273a04..188772dbbc 100644 --- a/front_end/ui/SuggestBox.js +++ b/front_end/ui/SuggestBox.js @@ -71,6 +71,11 @@ WebInspector.SuggestBox = function(suggestBoxDelegate, maxItemsHeight) this._asyncDetailsPromises = new Map(); } +/** + * @typedef Array.<{title: string, className: (string|undefined)}> + */ +WebInspector.SuggestBox.Suggestions; + WebInspector.SuggestBox.prototype = { /** * @return {boolean} @@ -240,11 +245,12 @@ WebInspector.SuggestBox.prototype = { /** * @param {string} prefix * @param {string} text + * @param {string|undefined} className * @param {number} index */ - _createItemElement: function(prefix, text, index) + _createItemElement: function(prefix, text, className, index) { - var element = createElementWithClass("div", "suggest-box-content-item source-code"); + var element = createElementWithClass("div", "suggest-box-content-item source-code " + (className || "")); element.tabIndex = -1; if (prefix && prefix.length && !text.indexOf(prefix)) { element.createChild("span", "prefix").textContent = prefix; @@ -259,7 +265,7 @@ WebInspector.SuggestBox.prototype = { }, /** - * @param {!Array.} items + * @param {!WebInspector.SuggestBox.Suggestions} items * @param {string} userEnteredText * @param {function(number): !Promise<{detail:string, description:string}>=} asyncDetails */ @@ -273,7 +279,7 @@ WebInspector.SuggestBox.prototype = { for (var i = 0; i < items.length; ++i) { var item = items[i]; - var currentItemElement = this._createItemElement(userEnteredText, item, i); + var currentItemElement = this._createItemElement(userEnteredText, item.title, item.className, i); this._element.appendChild(currentItemElement); } }, @@ -338,7 +344,7 @@ WebInspector.SuggestBox.prototype = { }, /** - * @param {!Array.} completions + * @param {!WebInspector.SuggestBox.Suggestions} completions * @param {boolean} canShowForSingleItem * @param {string} userEnteredText */ @@ -351,7 +357,7 @@ WebInspector.SuggestBox.prototype = { return true; // Do not show a single suggestion if it is the same as user-entered prefix, even if allowed to show single-item suggest boxes. - return canShowForSingleItem && completions[0] !== userEnteredText; + return canShowForSingleItem && completions[0].title !== userEnteredText; }, _ensureRowCountPerViewport: function() @@ -366,7 +372,7 @@ WebInspector.SuggestBox.prototype = { /** * @param {!AnchorBox} anchorBox - * @param {!Array.} completions + * @param {!WebInspector.SuggestBox.Suggestions} completions * @param {number} selectedIndex * @param {boolean} canShowForSingleItem * @param {string} userEnteredText diff --git a/front_end/ui/TabbedPane.js b/front_end/ui/TabbedPane.js index 1a342f310d..75b60c75e1 100644 --- a/front_end/ui/TabbedPane.js +++ b/front_end/ui/TabbedPane.js @@ -83,20 +83,29 @@ WebInspector.TabbedPane.prototype = { return this._currentTab ? this._currentTab.view : null; }, + /** + * @return {!Array.} + */ + tabIds: function() + { + return this._tabs.map(tab => tab._id); + }, + /** * @return {!Array.} */ tabViews: function() { - /** - * @param {!WebInspector.TabbedPaneTab} tab - * @return {!WebInspector.Widget} - */ - function tabToView(tab) - { - return tab.view; - } - return this._tabs.map(tabToView); + return this._tabs.map(tab => tab.view); + }, + + /** + * @param {string} tabId + * @return {?WebInspector.Widget} + */ + tabView: function(tabId) + { + return this._tabsById[tabId] ? this._tabsById[tabId].view : null; }, /** @@ -361,6 +370,16 @@ WebInspector.TabbedPane.prototype = { this._updateTabElements(); }, + /** + * @param {string} id + * @param {boolean} enabled + */ + setTabEnabled: function(id, enabled) + { + var tab = this._tabsById[id]; + tab.tabElement.classList.toggle("disabled", !enabled); + }, + /** * @param {string} id * @param {string} className diff --git a/front_end/ui/TextPrompt.js b/front_end/ui/TextPrompt.js index 84e2a53008..79952d3939 100644 --- a/front_end/ui/TextPrompt.js +++ b/front_end/ui/TextPrompt.js @@ -471,7 +471,7 @@ WebInspector.TextPrompt.prototype = { /** * @param {string} prefix - * @return {!Array.} + * @return {!WebInspector.SuggestBox.Suggestions} */ additionalCompletions: function(prefix) { @@ -489,18 +489,20 @@ WebInspector.TextPrompt.prototype = { _completionsReady: function(selection, originalWordPrefixRange, reverse, force, completions, selectedIndex) { var prefix = originalWordPrefixRange.toString(); - if (prefix || force) { - if (prefix) - completions = completions.concat(this.additionalCompletions(prefix)); - else - completions = this.additionalCompletions(prefix).concat(completions); - } // Filter out dupes. var store = new Set(); completions = completions.filter(item => !store.has(item) && !!store.add(item)); + var annotatedCompletions = completions.map(item => ({title: item})); + + if (prefix || force) { + if (prefix) + annotatedCompletions = annotatedCompletions.concat(this.additionalCompletions(prefix)); + else + annotatedCompletions = this.additionalCompletions(prefix).concat(annotatedCompletions); + } - if (!this._waitingForCompletions || !completions.length) { + if (!this._waitingForCompletions || !annotatedCompletions.length) { this.hideSuggestBox(); return; } @@ -522,7 +524,7 @@ WebInspector.TextPrompt.prototype = { this._userEnteredText = fullWordRange.toString(); if (this._suggestBox) - this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), completions, selectedIndex, !this.isCaretAtEndOfPrompt(), this._userEnteredText); + this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), annotatedCompletions, selectedIndex, !this.isCaretAtEndOfPrompt(), this._userEnteredText); if (selectedIndex === -1) return; @@ -531,7 +533,7 @@ WebInspector.TextPrompt.prototype = { this._commonPrefix = this._buildCommonPrefix(completions, wordPrefixLength); if (this.isCaretAtEndOfPrompt()) { - var completionText = completions[selectedIndex]; + var completionText = annotatedCompletions[selectedIndex].title; var prefixText = this._userEnteredRange.toString(); var suffixText = completionText.substring(wordPrefixLength); this._userEnteredRange.deleteContents(); @@ -827,7 +829,7 @@ WebInspector.TextPromptWithHistory.prototype = { /** * @override * @param {string} prefix - * @return {!Array.} + * @return {!WebInspector.SuggestBox.Suggestions} */ additionalCompletions: function(prefix) { @@ -835,11 +837,15 @@ WebInspector.TextPromptWithHistory.prototype = { return []; var result = []; var text = this.text(); + var set = new Set(); for (var i = this._data.length - 1; i >= 0 && result.length < 50; --i) { var item = this._data[i]; if (!item.startsWith(text)) continue; - result.push(item.substring(text.length - prefix.length)); + if (set.has(item)) + continue; + set.add(item); + result.push({title: item.substring(text.length - prefix.length), className: "additional"}); } return result; }, diff --git a/front_end/ui/Toolbar.js b/front_end/ui/Toolbar.js index 70c374e8dc..c57e0cf7b4 100644 --- a/front_end/ui/Toolbar.js +++ b/front_end/ui/Toolbar.js @@ -101,6 +101,11 @@ WebInspector.Toolbar.prototype = { this.appendToolbarItem(new WebInspector.ToolbarSeparator()); }, + appendSpacer: function() + { + this.appendToolbarItem(new WebInspector.ToolbarSeparator(true)); + }, + /** * @param {string} text */ @@ -719,10 +724,11 @@ WebInspector.ToolbarSettingToggle.prototype = { /** * @constructor * @extends {WebInspector.ToolbarItem} + * @param {boolean=} spacer */ -WebInspector.ToolbarSeparator = function() +WebInspector.ToolbarSeparator = function(spacer) { - WebInspector.ToolbarItem.call(this, createElementWithClass("div", "toolbar-divider")); + WebInspector.ToolbarItem.call(this, createElementWithClass("div", spacer ? "toolbar-spacer" : "toolbar-divider")); } WebInspector.ToolbarSeparator.prototype = { diff --git a/front_end/ui/suggestBox.css b/front_end/ui/suggestBox.css index 4752503cb6..e33ff52c40 100644 --- a/front_end/ui/suggestBox.css +++ b/front_end/ui/suggestBox.css @@ -91,6 +91,30 @@ white-space: nowrap; } +.suggest-box .suggest-box-content-item.additional { + background-color: #f9f9f9; +} + +.suggest-box .suggest-box-content-item.additional::before { + display: inline-block; + content: ""; + -webkit-user-select: none; + background-image: url(Images/toolbarButtonGlyphs.png); + background-size: 352px 168px; + width: 10px; + height: 10px; + position: relative; + top: 2px; + margin-right: 4px; + background-position: -192px -96px; +} + +@media (-webkit-min-device-pixel-ratio: 1.5) { +.suggest-box .suggest-box-content-item.additional::before { + background-image: url(Images/toolbarButtonGlyphs_2x.png); +} +} /* media */ + .suggest-box .suggest-box-content-item .prefix { font-weight: bold; } diff --git a/front_end/ui/tabbedPane.css b/front_end/ui/tabbedPane.css index f2f5b88c3e..2223c6d0d0 100644 --- a/front_end/ui/tabbedPane.css +++ b/front_end/ui/tabbedPane.css @@ -260,6 +260,11 @@ visibility: visible; } +.tabbed-pane-header-tab.disabled { + opacity: 0.5; + pointer-events: none; +} + .tabbed-pane-header.tabbed-pane-no-header-background { background-color: transparent; } diff --git a/front_end/ui/toolbar.css b/front_end/ui/toolbar.css index 45d3c61b75..6b93471648 100644 --- a/front_end/ui/toolbar.css +++ b/front_end/ui/toolbar.css @@ -227,6 +227,10 @@ input.toolbar-item.hover { height: 16px; } +.toolbar-spacer { + flex: auto; +} + /* Long click */ .long-click-glyph { @@ -336,6 +340,10 @@ input.toolbar-item.hover { transform: scaleX(-1); } +.stop-toolbar-item.toolbar-glyph { + -webkit-mask-position: -96px -48px; +} + .pause-on-exceptions-toolbar-item.toolbar-glyph { -webkit-mask-position: -256px 0; } @@ -356,6 +364,10 @@ input.toolbar-item.hover { -webkit-mask-position: 0 -24px; } +.notification-toolbar-item.toolbar-glyph { + -webkit-mask-position: -32px -120px; +} + .format-toolbar-item.toolbar-glyph { -webkit-mask-position: -256px -24px; } diff --git a/front_end/ui_lazy/FlameChart.js b/front_end/ui_lazy/FlameChart.js index da1c28a86d..5cdacf611e 100644 --- a/front_end/ui_lazy/FlameChart.js +++ b/front_end/ui_lazy/FlameChart.js @@ -1354,26 +1354,12 @@ WebInspector.FlameChart.prototype = { if (groups.length && lastGroupOffset < top + height) context.fillRect(0, lastGroupOffset + 2, width, top + height - lastGroupOffset) - context.strokeStyle = WebInspector.themeSupport.patchColor("#ddd", colorUsage.Background); - context.beginPath(); - forEachGroup((offset, index, group, isFirst) => { - if (isFirst) - return; - if (group.style.padding > 1) - hLine(offset - 1.5); - if (group.style.padding > 2) - hLine(offset - group.style.padding + 1.5); - }); - hLine(lastGroupOffset + 1.5); - context.stroke(); - context.strokeStyle = WebInspector.themeSupport.patchColor("#bbb", colorUsage.Background); context.beginPath(); forEachGroup((offset, index, group, isFirst) => { if (isFirst || group.style.padding < 4) return; - hLine(offset - group.style.padding + 0.5); - hLine(offset - 0.5); + hLine(offset - 2.5); }); hLine(lastGroupOffset + 0.5); context.stroke(); @@ -1422,10 +1408,6 @@ WebInspector.FlameChart.prototype = { context.strokeStyle = WebInspector.themeSupport.patchColor("#ddd", colorUsage.Background); context.beginPath(); - forEachGroup((offset, index, group) => { - if (group.expanded) - hLine(offset + barHeight - 0.5); - }); context.stroke(); context.restore(); diff --git a/protocol.json b/protocol.json index 9462985bd0..3b20f37a90 100644 --- a/protocol.json +++ b/protocol.json @@ -455,9 +455,6 @@ }, { "name": "requestAppBanner", - "returns": [ - { "name": "result", "type": "boolean" } - ], "hidden": true, "handlers": ["browser"] } @@ -3454,21 +3451,6 @@ "description": "Error data for setScriptSource command. Contains uncompilable script source error.", "hidden": true }, - { - "id": "PromiseDetails", - "type": "object", - "description": "Information about the promise. All fields but id are optional and if present they reflect the new state of the property on the promise with given id.", - "properties": [ - { "name": "id", "type": "integer", "description": "Unique id of the promise." }, - { "name": "status", "type": "string", "optional": true, "enum": ["pending", "resolved", "rejected"], "description": "Status of the promise." }, - { "name": "parentId", "type": "integer", "optional": true, "description": "Id of the parent promise." }, - { "name": "creationTime", "type": "number", "optional": true, "description": "Creation time of the promise." }, - { "name": "settlementTime", "type": "number", "optional": true, "description": "Settlement time of the promise." }, - { "name": "creationStack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace on promise creation." }, - { "name": "settlementStack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace on promise settlement." } - ], - "hidden": true - }, { "id": "AsyncOperation", "type": "object", @@ -3724,31 +3706,6 @@ "hidden": true, "description": "Enables or disables async call stacks tracking." }, - { - "name": "enablePromiseTracker", - "parameters": [ - { "name": "captureStacks", "type": "boolean", "optional": true, "description": "Whether to capture stack traces for promise creation and settlement events (default: false)." } - ], - "hidden": true, - "description": "Enables promise tracking, information about Promises created or updated will now be stored on the backend." - }, - { - "name": "disablePromiseTracker", - "hidden": true, - "description": "Disables promise tracking." - }, - { - "name": "getPromiseById", - "parameters": [ - { "name": "promiseId", "type": "integer" }, - { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." } - ], - "returns": [ - { "name": "promise", "$ref": "Runtime.RemoteObject", "description": "Object wrapper for Promise with specified ID, if any." } - ], - "hidden": true, - "description": "Returns Promise with specified ID." - }, { "name": "flushAsyncOperationEvents", "hidden": true, @@ -3843,15 +3800,6 @@ "name": "resumed", "description": "Fired when the virtual machine resumed execution." }, - { - "name": "promiseUpdated", - "parameters": [ - { "name": "eventType", "type": "string", "enum": ["new", "update", "gc"], "description": "Type of the event." }, - { "name": "promise", "$ref": "PromiseDetails", "description": "Information about the updated Promise." } - ], - "description": "Fired when a Promise is created, updated or garbage collected.", - "hidden": true - }, { "name": "asyncOperationStarted", "parameters": [ diff --git a/scripts/compile_frontend.py b/scripts/compile_frontend.py index fa792f08ac..b95dee3f18 100755 --- a/scripts/compile_frontend.py +++ b/scripts/compile_frontend.py @@ -78,6 +78,8 @@ def to_platform_path_exact(filepath): protocol_externs_file = path.join(devtools_frontend_path, 'protocol_externs.js') injected_script_source_name = path.join(v8_inspector_path, 'InjectedScriptSource.js') injected_script_externs_file = path.join(v8_inspector_path, 'injected_script_externs.js') +debugger_script_source_name = path.join(v8_inspector_path, 'DebuggerScript.js') +debugger_script_externs_file = path.join(v8_inspector_path, 'debugger_script_externs.js') jsmodule_name_prefix = 'jsmodule_' runtime_module_name = '_runtime' @@ -403,6 +405,16 @@ def replace_function(matchobj): injectedScriptCompileProc = popen(command) +print 'Compiling DebuggerScript.js...' + +command = spawned_compiler_command + [ + '--externs', to_platform_path_exact(debugger_script_externs_file), + '--module', jsmodule_name_prefix + 'debugger_script' + ':1', + '--js', to_platform_path(debugger_script_source_name) +] + +debuggerScriptCompileProc = popen(command) + print 'Compiling devtools.js...' command = spawned_compiler_command + [ @@ -492,6 +504,10 @@ def skip_dependents(module_name): print 'InjectedScriptSource.js compilation output:%s' % os.linesep, injectedScriptCompileOut errors_found |= hasErrors(injectedScriptCompileOut) +(debuggerScriptCompilerOut, _) = debuggerScriptCompileProc.communicate() +print 'DebuggerScript.js compilation output:%s' % os.linesep, debuggerScriptCompilerOut +errors_found |= hasErrors(debuggerScriptCompilerOut) + (devtoolsJSCompileOut, _) = devtoolsJSCompileProc.communicate() print 'devtools.js compilation output:%s' % os.linesep, devtoolsJSCompileOut errors_found |= hasErrors(devtoolsJSCompileOut)