OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Provides communication interface to remote v8 debugger. See | 6 * @fileoverview Provides communication interface to remote v8 debugger. See |
7 * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol | 7 * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol |
8 */ | 8 */ |
9 goog.provide('devtools.DebuggerAgent'); | 9 goog.provide('devtools.DebuggerAgent'); |
10 | 10 |
11 | 11 |
12 /** | 12 /** |
13 * @constructor | 13 * @constructor |
14 */ | 14 */ |
15 devtools.DebuggerAgent = function() { | 15 devtools.DebuggerAgent = function() { |
16 RemoteDebuggerAgent.DebuggerOutput = | 16 RemoteDebuggerAgent.DebuggerOutput = |
17 goog.bind(this.handleDebuggerOutput_, this); | 17 goog.bind(this.handleDebuggerOutput_, this); |
18 RemoteDebuggerAgent.SetContextId = | 18 RemoteDebuggerAgent.SetContextId = |
19 goog.bind(this.setContextId_, this); | 19 goog.bind(this.setContextId_, this); |
20 RemoteDebuggerAgent.DidGetActiveProfilerModules = | |
21 goog.bind(this.didGetActiveProfilerModules_, this); | |
22 RemoteDebuggerAgent.DidGetNextLogLines = | |
23 goog.bind(this.didGetNextLogLines_, this); | |
24 | 20 |
25 /** | 21 /** |
26 * Id of the inspected page global context. It is used for filtering scripts. | 22 * Id of the inspected page global context. It is used for filtering scripts. |
27 * @type {number} | 23 * @type {number} |
28 */ | 24 */ |
29 this.contextId_ = null; | 25 this.contextId_ = null; |
30 | 26 |
31 /** | 27 /** |
32 * Mapping from script id to script info. | 28 * Mapping from script id to script info. |
33 * @type {Object} | 29 * @type {Object} |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 /** | 79 /** |
84 * If backtrace response is received when initial scripts response | 80 * If backtrace response is received when initial scripts response |
85 * is not yet processed the backtrace handling will be postponed until | 81 * is not yet processed the backtrace handling will be postponed until |
86 * after the scripts response processing. The handler bound to its arguments | 82 * after the scripts response processing. The handler bound to its arguments |
87 * and this agent will be stored in this field then. | 83 * and this agent will be stored in this field then. |
88 * @type {?function()} | 84 * @type {?function()} |
89 */ | 85 */ |
90 this.pendingBacktraceResponseHandler_ = null; | 86 this.pendingBacktraceResponseHandler_ = null; |
91 | 87 |
92 /** | 88 /** |
93 * Active profiler modules flags. | |
94 * @type {number} | |
95 */ | |
96 this.activeProfilerModules_ = | |
97 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE; | |
98 | |
99 /** | |
100 * Interval for polling profiler state. | |
101 * @type {number} | |
102 */ | |
103 this.getActiveProfilerModulesInterval_ = null; | |
104 | |
105 /** | |
106 * Whether log contents retrieval must be forced next time. | |
107 * @type {boolean} | |
108 */ | |
109 this.forceGetLogLines_ = false; | |
110 | |
111 /** | |
112 * Profiler processor instance. | |
113 * @type {devtools.profiler.Processor} | |
114 */ | |
115 this.profilerProcessor_ = new devtools.profiler.Processor(); | |
116 | |
117 /** | |
118 * Container of all breakpoints set using resource URL. These breakpoints | 89 * Container of all breakpoints set using resource URL. These breakpoints |
119 * survive page reload. Breakpoints set by script id(for scripts that don't | 90 * survive page reload. Breakpoints set by script id(for scripts that don't |
120 * have URLs) are stored in ScriptInfo objects. | 91 * have URLs) are stored in ScriptInfo objects. |
121 * @type {Object} | 92 * @type {Object} |
122 */ | 93 */ |
123 this.urlToBreakpoints_ = {}; | 94 this.urlToBreakpoints_ = {}; |
124 | 95 |
125 | 96 |
126 /** | 97 /** |
127 * Exception message that is shown to user while on exception break. | 98 * Exception message that is shown to user while on exception break. |
(...skipping 10 matching lines...) Expand all Loading... |
138 devtools.DebuggerAgent.ScopeType = { | 109 devtools.DebuggerAgent.ScopeType = { |
139 Global: 0, | 110 Global: 0, |
140 Local: 1, | 111 Local: 1, |
141 With: 2, | 112 With: 2, |
142 Closure: 3, | 113 Closure: 3, |
143 Catch: 4 | 114 Catch: 4 |
144 }; | 115 }; |
145 | 116 |
146 | 117 |
147 /** | 118 /** |
148 * A copy of enum from include/v8.h | |
149 * @enum {number} | |
150 */ | |
151 devtools.DebuggerAgent.ProfilerModules = { | |
152 PROFILER_MODULE_NONE: 0, | |
153 PROFILER_MODULE_CPU: 1, | |
154 PROFILER_MODULE_HEAP_STATS: 1 << 1, | |
155 PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2, | |
156 PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16 | |
157 }; | |
158 | |
159 | |
160 /** | |
161 * Resets debugger agent to its initial state. | 119 * Resets debugger agent to its initial state. |
162 */ | 120 */ |
163 devtools.DebuggerAgent.prototype.reset = function() { | 121 devtools.DebuggerAgent.prototype.reset = function() { |
164 this.contextId_ = null; | 122 this.contextId_ = null; |
165 // No need to request scripts since they all will be pushed in AfterCompile | 123 // No need to request scripts since they all will be pushed in AfterCompile |
166 // events. | 124 // events. |
167 this.requestScriptsWhenContextIdSet_ = false; | 125 this.requestScriptsWhenContextIdSet_ = false; |
168 this.waitingForInitialScriptsResponse_ = false; | 126 this.waitingForInitialScriptsResponse_ = false; |
169 | 127 |
170 this.parsedScripts_ = {}; | 128 this.parsedScripts_ = {}; |
171 this.requestNumberToBreakpointInfo_ = {}; | 129 this.requestNumberToBreakpointInfo_ = {}; |
172 this.callFrames_ = []; | 130 this.callFrames_ = []; |
173 this.requestSeqToCallback_ = {}; | 131 this.requestSeqToCallback_ = {}; |
174 | |
175 // Profiler isn't reset because it contains no data that is | |
176 // specific for a particular V8 instance. All such data is | |
177 // managed by an agent on the Render's side. | |
178 }; | 132 }; |
179 | 133 |
180 | 134 |
181 /** | 135 /** |
182 * Initializes scripts UI. This method is called every time Scripts panel | 136 * Initializes scripts UI. This method is called every time Scripts panel |
183 * is shown. It will send request for context id if it's not set yet. | 137 * is shown. It will send request for context id if it's not set yet. |
184 */ | 138 */ |
185 devtools.DebuggerAgent.prototype.initUI = function() { | 139 devtools.DebuggerAgent.prototype.initUI = function() { |
186 // Initialize scripts cache when Scripts panel is shown first time. | 140 // Initialize scripts cache when Scripts panel is shown first time. |
187 if (this.scriptsPanelInitialized_) { | 141 if (this.scriptsPanelInitialized_) { |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 } else { | 615 } else { |
662 this.resolveFrameVariables_(callFrameId, | 616 this.resolveFrameVariables_(callFrameId, |
663 function(result) { | 617 function(result) { |
664 reportCompletions(result, false /* isException */); | 618 reportCompletions(result, false /* isException */); |
665 }); | 619 }); |
666 } | 620 } |
667 }; | 621 }; |
668 | 622 |
669 | 623 |
670 /** | 624 /** |
671 * Sets up callbacks that deal with profiles processing. | |
672 */ | |
673 devtools.DebuggerAgent.prototype.setupProfilerProcessorCallbacks = function() { | |
674 // A temporary icon indicating that the profile is being processed. | |
675 var processingIcon = new WebInspector.SidebarTreeElement( | |
676 'profile-sidebar-tree-item', | |
677 WebInspector.UIString('Processing...'), | |
678 '', null, false); | |
679 var profilesSidebar = WebInspector.panels.profiles.getProfileType( | |
680 WebInspector.CPUProfileType.TypeId).treeElement; | |
681 | |
682 this.profilerProcessor_.setCallbacks( | |
683 function onProfileProcessingStarted() { | |
684 // Set visually empty string. Subtitle hiding is done via styles | |
685 // manipulation which doesn't play well with dynamic append / removal. | |
686 processingIcon.subtitle = ' '; | |
687 profilesSidebar.appendChild(processingIcon); | |
688 }, | |
689 function onProfileProcessingStatus(ticksCount) { | |
690 processingIcon.subtitle = | |
691 WebInspector.UIString('%d ticks processed', ticksCount); | |
692 }, | |
693 function onProfileProcessingFinished(profile) { | |
694 profilesSidebar.removeChild(processingIcon); | |
695 profile.typeId = WebInspector.CPUProfileType.TypeId; | |
696 InspectorBackend.addFullProfile(profile); | |
697 WebInspector.addProfileHeader(profile); | |
698 // If no profile is currently shown, show the new one. | |
699 var profilesPanel = WebInspector.panels.profiles; | |
700 if (!profilesPanel.visibleView) { | |
701 profilesPanel.showProfile(profile); | |
702 } | |
703 } | |
704 ); | |
705 }; | |
706 | |
707 | |
708 /** | |
709 * Initializes profiling state. | |
710 */ | |
711 devtools.DebuggerAgent.prototype.initializeProfiling = function() { | |
712 this.setupProfilerProcessorCallbacks(); | |
713 this.forceGetLogLines_ = true; | |
714 this.getActiveProfilerModulesInterval_ = setInterval( | |
715 function() { RemoteDebuggerAgent.GetActiveProfilerModules(); }, 1000); | |
716 }; | |
717 | |
718 | |
719 /** | |
720 * Starts profiling. | |
721 * @param {number} modules List of modules to enable. | |
722 */ | |
723 devtools.DebuggerAgent.prototype.startProfiling = function(modules) { | |
724 RemoteDebuggerAgent.StartProfiling(modules); | |
725 if (modules & | |
726 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT) { | |
727 // Active modules will not change, instead, a snapshot will be logged. | |
728 RemoteDebuggerAgent.GetNextLogLines(); | |
729 } | |
730 }; | |
731 | |
732 | |
733 /** | |
734 * Stops profiling. | |
735 */ | |
736 devtools.DebuggerAgent.prototype.stopProfiling = function(modules) { | |
737 RemoteDebuggerAgent.StopProfiling(modules); | |
738 }; | |
739 | |
740 | |
741 /** | |
742 * @param{number} scriptId | 625 * @param{number} scriptId |
743 * @return {string} Type of the context of the script with specified id. | 626 * @return {string} Type of the context of the script with specified id. |
744 */ | 627 */ |
745 devtools.DebuggerAgent.prototype.getScriptContextType = function(scriptId) { | 628 devtools.DebuggerAgent.prototype.getScriptContextType = function(scriptId) { |
746 return this.parsedScripts_[scriptId].getContextType(); | 629 return this.parsedScripts_[scriptId].getContextType(); |
747 }; | 630 }; |
748 | 631 |
749 | 632 |
750 /** | 633 /** |
751 * Removes specified breakpoint from the v8 debugger. | 634 * Removes specified breakpoint from the v8 debugger. |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 | 917 |
1035 // Ignore scripts from other tabs. | 918 // Ignore scripts from other tabs. |
1036 if (!this.isScriptFromInspectedContext_(script, msg)) { | 919 if (!this.isScriptFromInspectedContext_(script, msg)) { |
1037 return; | 920 return; |
1038 } | 921 } |
1039 this.addScriptInfo_(script, msg); | 922 this.addScriptInfo_(script, msg); |
1040 }; | 923 }; |
1041 | 924 |
1042 | 925 |
1043 /** | 926 /** |
1044 * Handles current profiler status. | |
1045 * @param {number} modules List of active (started) modules. | |
1046 */ | |
1047 devtools.DebuggerAgent.prototype.didGetActiveProfilerModules_ = function( | |
1048 modules) { | |
1049 var profModules = devtools.DebuggerAgent.ProfilerModules; | |
1050 var profModuleNone = profModules.PROFILER_MODULE_NONE; | |
1051 if (this.forceGetLogLines_ || | |
1052 (modules != profModuleNone && | |
1053 this.activeProfilerModules_ == profModuleNone)) { | |
1054 this.forceGetLogLines_ = false; | |
1055 // Start to query log data. | |
1056 RemoteDebuggerAgent.GetNextLogLines(); | |
1057 } | |
1058 this.activeProfilerModules_ = modules; | |
1059 // Update buttons. | |
1060 WebInspector.setRecordingProfile(modules & profModules.PROFILER_MODULE_CPU); | |
1061 }; | |
1062 | |
1063 | |
1064 /** | |
1065 * Handles a portion of a profiler log retrieved by GetNextLogLines call. | |
1066 * @param {string} log A portion of profiler log. | |
1067 */ | |
1068 devtools.DebuggerAgent.prototype.didGetNextLogLines_ = function(log) { | |
1069 if (log.length > 0) { | |
1070 this.profilerProcessor_.processLogChunk(log); | |
1071 } else if (this.activeProfilerModules_ == | |
1072 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE) { | |
1073 // No new data and profiling is stopped---suspend log reading. | |
1074 return; | |
1075 } | |
1076 setTimeout(function() { RemoteDebuggerAgent.GetNextLogLines(); }, 500); | |
1077 }; | |
1078 | |
1079 | |
1080 /** | |
1081 * Adds the script info to the local cache. This method assumes that the script | 927 * Adds the script info to the local cache. This method assumes that the script |
1082 * is not in the cache yet. | 928 * is not in the cache yet. |
1083 * @param {Object} script Script json object from the debugger message. | 929 * @param {Object} script Script json object from the debugger message. |
1084 * @param {devtools.DebuggerMessage} msg Debugger message containing the script | 930 * @param {devtools.DebuggerMessage} msg Debugger message containing the script |
1085 * data. | 931 * data. |
1086 */ | 932 */ |
1087 devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script, msg) { | 933 devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script, msg) { |
1088 var context = msg.lookup(script.context.ref); | 934 var context = msg.lookup(script.context.ref); |
1089 var contextType; | 935 var contextType; |
1090 if (goog.isString(context.data)) { | 936 if (goog.isString(context.data)) { |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1649 | 1495 |
1650 | 1496 |
1651 /** | 1497 /** |
1652 * @param {number} handle Object handle. | 1498 * @param {number} handle Object handle. |
1653 * @return {?Object} Returns the object with the handle if it was sent in this | 1499 * @return {?Object} Returns the object with the handle if it was sent in this |
1654 * message(some objects referenced by handles may be missing in the message). | 1500 * message(some objects referenced by handles may be missing in the message). |
1655 */ | 1501 */ |
1656 devtools.DebuggerMessage.prototype.lookup = function(handle) { | 1502 devtools.DebuggerMessage.prototype.lookup = function(handle) { |
1657 return this.refs_[handle]; | 1503 return this.refs_[handle]; |
1658 }; | 1504 }; |
OLD | NEW |