| 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 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 */ | 61 */ |
| 62 this.requestSeqToCallback_ = null; | 62 this.requestSeqToCallback_ = null; |
| 63 | 63 |
| 64 /** | 64 /** |
| 65 * Whether the scripts list has been requested. | 65 * Whether the scripts list has been requested. |
| 66 * @type {boolean} | 66 * @type {boolean} |
| 67 */ | 67 */ |
| 68 this.scriptsCacheInitialized_ = false; | 68 this.scriptsCacheInitialized_ = false; |
| 69 | 69 |
| 70 /** | 70 /** |
| 71 * Whether the scripts list should be requested next time when context id is |
| 72 * set. |
| 73 * @type {boolean} |
| 74 */ |
| 75 this.requestScriptsWhenContextIdSet_ = false; |
| 76 |
| 77 /** |
| 71 * Active profiler modules flags. | 78 * Active profiler modules flags. |
| 72 * @type {number} | 79 * @type {number} |
| 73 */ | 80 */ |
| 74 this.activeProfilerModules_ = | 81 this.activeProfilerModules_ = |
| 75 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE; | 82 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE; |
| 76 | 83 |
| 77 /** | 84 /** |
| 78 * Profiler processor instance. | 85 * Profiler processor instance. |
| 79 * @type {devtools.profiler.Processor} | 86 * @type {devtools.profiler.Processor} |
| 80 */ | 87 */ |
| (...skipping 24 matching lines...) Expand all Loading... |
| 105 Global: 0, | 112 Global: 0, |
| 106 Local: 1, | 113 Local: 1, |
| 107 With: 2, | 114 With: 2, |
| 108 Closure: 3 | 115 Closure: 3 |
| 109 }; | 116 }; |
| 110 | 117 |
| 111 | 118 |
| 112 /** | 119 /** |
| 113 * A no-op JS expression that is sent to the inspected page in order to force v8 | 120 * A no-op JS expression that is sent to the inspected page in order to force v8 |
| 114 * execution. | 121 * execution. |
| 122 * @type {string} |
| 115 */ | 123 */ |
| 116 devtools.DebuggerAgent.VOID_SCRIPT = 'javascript:void(0)'; | 124 devtools.DebuggerAgent.VOID_SCRIPT = 'javascript:void(0)'; |
| 117 | 125 |
| 126 /** |
| 127 * AfterCompile event source for devtools.DebuggerAgent.VOID_SCRIPT. |
| 128 * @type {string} |
| 129 */ |
| 130 devtools.DebuggerAgent.VOID_SCRIPT_EVAL_SOURCE = |
| 131 'with (window._inspectorCommandLineAPI) { with (window) { ' + |
| 132 devtools.DebuggerAgent.VOID_SCRIPT + |
| 133 ' } }'; |
| 118 | 134 |
| 119 /** | 135 /** |
| 120 * A copy of enum from include/v8.h | 136 * A copy of enum from include/v8.h |
| 121 * @enum {number} | 137 * @enum {number} |
| 122 */ | 138 */ |
| 123 devtools.DebuggerAgent.ProfilerModules = { | 139 devtools.DebuggerAgent.ProfilerModules = { |
| 124 PROFILER_MODULE_NONE: 0, | 140 PROFILER_MODULE_NONE: 0, |
| 125 PROFILER_MODULE_CPU: 1, | 141 PROFILER_MODULE_CPU: 1, |
| 126 PROFILER_MODULE_HEAP_STATS: 1 << 1, | 142 PROFILER_MODULE_HEAP_STATS: 1 << 1, |
| 127 PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2, | 143 PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2, |
| 128 PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16 | 144 PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16 |
| 129 }; | 145 }; |
| 130 | 146 |
| 131 | 147 |
| 132 /** | 148 /** |
| 133 * Resets debugger agent to its initial state. | 149 * Resets debugger agent to its initial state. |
| 134 */ | 150 */ |
| 135 devtools.DebuggerAgent.prototype.reset = function() { | 151 devtools.DebuggerAgent.prototype.reset = function() { |
| 136 this.contextId_ = null; | 152 this.contextId_ = null; |
| 153 // No need to request scripts since they all will be pushed in AfterCompile |
| 154 // events. |
| 155 this.requestScriptsWhenContextIdSet_ = false; |
| 137 this.parsedScripts_ = {}; | 156 this.parsedScripts_ = {}; |
| 138 this.requestNumberToBreakpointInfo_ = {}; | 157 this.requestNumberToBreakpointInfo_ = {}; |
| 139 this.callFrames_ = []; | 158 this.callFrames_ = []; |
| 140 this.requestSeqToCallback_ = {}; | 159 this.requestSeqToCallback_ = {}; |
| 141 | 160 |
| 142 // Profiler isn't reset because it contains no data that is | 161 // Profiler isn't reset because it contains no data that is |
| 143 // specific for a particular V8 instance. All such data is | 162 // specific for a particular V8 instance. All such data is |
| 144 // managed by an agent on the Render's side. | 163 // managed by an agent on the Render's side. |
| 145 }; | 164 }; |
| 146 | 165 |
| 147 | 166 |
| 148 /** | 167 /** |
| 149 * Initializes scripts UI. Asynchronously requests for all parsed scripts | 168 * Initializes scripts UI. This method is called every time Scripts panel |
| 150 * if necessary. Response will be processed in handleScriptsResponse_. | 169 * is shown. It will send request for context id if it's not set yet. |
| 151 */ | 170 */ |
| 152 devtools.DebuggerAgent.prototype.initUI = function() { | 171 devtools.DebuggerAgent.prototype.initUI = function() { |
| 153 // There can be a number of scripts from after-compile events that are | 172 // There can be a number of scripts from after-compile events that are |
| 154 // pending addition into the UI. | 173 // pending addition into the UI. |
| 155 for (var scriptId in this.parsedScripts_) { | 174 for (var scriptId in this.parsedScripts_) { |
| 156 var script = this.parsedScripts_[scriptId]; | 175 var script = this.parsedScripts_[scriptId]; |
| 157 WebInspector.parsedScriptSource(scriptId, script.getUrl(), | 176 WebInspector.parsedScriptSource(scriptId, script.getUrl(), |
| 158 undefined /* script source */, script.getLineOffset()); | 177 undefined /* script source */, script.getLineOffset()); |
| 159 } | 178 } |
| 160 | 179 |
| 180 // Initialize scripts cache when Scripts panel is shown first time. |
| 181 if (this.scriptsCacheInitialized_) { |
| 182 return; |
| 183 } |
| 184 this.scriptsCacheInitialized_ = true; |
| 161 if (this.contextId_) { | 185 if (this.contextId_) { |
| 162 // We already have context id. This means that we are here from the | 186 // We already have context id. This means that we are here from the |
| 163 // very beginning of the page load cycle and hence will get all scripts | 187 // very beginning of the page load cycle and hence will get all scripts |
| 164 // via after-compile events. No need to request scripts for this session. | 188 // via after-compile events. No need to request scripts for this session. |
| 165 return; | 189 return; |
| 166 } | 190 } |
| 167 | 191 // Script list should be requested only when current context id is known. |
| 168 RemoteDebuggerAgent.GetContextId(); | 192 RemoteDebuggerAgent.GetContextId(); |
| 169 var cmd = new devtools.DebugCommand('scripts', { | 193 this.requestScriptsWhenContextIdSet_ = true; |
| 170 'includeSource': false | |
| 171 }); | |
| 172 devtools.DebuggerAgent.sendCommand_(cmd); | |
| 173 // Force v8 execution so that it gets to processing the requested command. | |
| 174 devtools.tools.evaluateJavaScript(devtools.DebuggerAgent.VOID_SCRIPT); | |
| 175 }; | 194 }; |
| 176 | 195 |
| 177 | 196 |
| 178 /** | 197 /** |
| 179 * Asynchronously requests the debugger for the script source. | 198 * Asynchronously requests the debugger for the script source. |
| 180 * @param {number} scriptId Id of the script whose source should be resolved. | 199 * @param {number} scriptId Id of the script whose source should be resolved. |
| 181 * @param {function(source:?string):void} callback Function that will be called | 200 * @param {function(source:?string):void} callback Function that will be called |
| 182 * when the source resolution is completed. 'source' parameter will be null | 201 * when the source resolution is completed. 'source' parameter will be null |
| 183 * if the resolution fails. | 202 * if the resolution fails. |
| 184 */ | 203 */ |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; | 716 this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; |
| 698 }; | 717 }; |
| 699 | 718 |
| 700 | 719 |
| 701 /** | 720 /** |
| 702 * Sets debugger context id for scripts filtering. | 721 * Sets debugger context id for scripts filtering. |
| 703 * @param {number} contextId Id of the inspected page global context. | 722 * @param {number} contextId Id of the inspected page global context. |
| 704 */ | 723 */ |
| 705 devtools.DebuggerAgent.prototype.setContextId_ = function(contextId) { | 724 devtools.DebuggerAgent.prototype.setContextId_ = function(contextId) { |
| 706 this.contextId_ = contextId; | 725 this.contextId_ = contextId; |
| 726 |
| 727 // If it's the first time context id is set request scripts list. |
| 728 if (this.requestScriptsWhenContextIdSet_) { |
| 729 this.requestScriptsWhenContextIdSet_ = false; |
| 730 var cmd = new devtools.DebugCommand('scripts', { |
| 731 'includeSource': false |
| 732 }); |
| 733 devtools.DebuggerAgent.sendCommand_(cmd); |
| 734 // Force v8 execution so that it gets to processing the requested command. |
| 735 devtools.tools.evaluateJavaScript(devtools.DebuggerAgent.VOID_SCRIPT); |
| 736 |
| 737 var debuggerAgent = this; |
| 738 this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { |
| 739 // Handle the response iff the context id hasn't changed since the request |
| 740 // was issued. Otherwise if the context id did change all up-to-date |
| 741 // scripts will be pushed in after compile events and there is no need to |
| 742 // handle the response. |
| 743 if (contextId == debuggerAgent.contextId_) { |
| 744 debuggerAgent.handleScriptsResponse_(msg); |
| 745 } |
| 746 }; |
| 747 } |
| 707 }; | 748 }; |
| 708 | 749 |
| 709 | 750 |
| 710 /** | 751 /** |
| 711 * Handles output sent by v8 debugger. The output is either asynchronous event | 752 * Handles output sent by v8 debugger. The output is either asynchronous event |
| 712 * or response to a previously sent request. See protocol definitioun for more | 753 * or response to a previously sent request. See protocol definitioun for more |
| 713 * details on the output format. | 754 * details on the output format. |
| 714 * @param {string} output | 755 * @param {string} output |
| 715 */ | 756 */ |
| 716 devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) { | 757 devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) { |
| 717 var msg; | 758 var msg; |
| 718 try { | 759 try { |
| 719 msg = new devtools.DebuggerMessage(output); | 760 msg = new devtools.DebuggerMessage(output); |
| 720 } catch(e) { | 761 } catch(e) { |
| 721 debugPrint('Failed to handle debugger reponse:\n' + e); | 762 debugPrint('Failed to handle debugger reponse:\n' + e); |
| 722 throw e; | 763 throw e; |
| 723 } | 764 } |
| 724 | 765 |
| 725 if (msg.getType() == 'event') { | 766 if (msg.getType() == 'event') { |
| 726 if (msg.getEvent() == 'break') { | 767 if (msg.getEvent() == 'break') { |
| 727 this.handleBreakEvent_(msg); | 768 this.handleBreakEvent_(msg); |
| 728 } else if (msg.getEvent() == 'exception') { | 769 } else if (msg.getEvent() == 'exception') { |
| 729 this.handleExceptionEvent_(msg); | 770 this.handleExceptionEvent_(msg); |
| 730 } else if (msg.getEvent() == 'afterCompile') { | 771 } else if (msg.getEvent() == 'afterCompile') { |
| 731 this.handleAfterCompileEvent_(msg); | 772 this.handleAfterCompileEvent_(msg); |
| 732 } | 773 } |
| 733 } else if (msg.getType() == 'response') { | 774 } else if (msg.getType() == 'response') { |
| 734 if (msg.getCommand() == 'scripts') { | 775 if (msg.getCommand() == 'scripts') { |
| 735 this.handleScriptsResponse_(msg); | 776 this.invokeCallbackForResponse_(msg); |
| 736 } else if (msg.getCommand() == 'setbreakpoint') { | 777 } else if (msg.getCommand() == 'setbreakpoint') { |
| 737 this.handleSetBreakpointResponse_(msg); | 778 this.handleSetBreakpointResponse_(msg); |
| 738 } else if (msg.getCommand() == 'clearbreakpoint') { | 779 } else if (msg.getCommand() == 'clearbreakpoint') { |
| 739 this.handleClearBreakpointResponse_(msg); | 780 this.handleClearBreakpointResponse_(msg); |
| 740 } else if (msg.getCommand() == 'backtrace') { | 781 } else if (msg.getCommand() == 'backtrace') { |
| 741 this.handleBacktraceResponse_(msg); | 782 this.handleBacktraceResponse_(msg); |
| 742 } else if (msg.getCommand() == 'lookup') { | 783 } else if (msg.getCommand() == 'lookup') { |
| 743 this.invokeCallbackForResponse_(msg); | 784 this.invokeCallbackForResponse_(msg); |
| 744 } else if (msg.getCommand() == 'evaluate') { | 785 } else if (msg.getCommand() == 'evaluate') { |
| 745 this.invokeCallbackForResponse_(msg); | 786 this.invokeCallbackForResponse_(msg); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 } else { | 821 } else { |
| 781 this.resumeExecution(); | 822 this.resumeExecution(); |
| 782 } | 823 } |
| 783 }; | 824 }; |
| 784 | 825 |
| 785 | 826 |
| 786 /** | 827 /** |
| 787 * @param {devtools.DebuggerMessage} msg | 828 * @param {devtools.DebuggerMessage} msg |
| 788 */ | 829 */ |
| 789 devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) { | 830 devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) { |
| 790 if (this.invokeCallbackForResponse_(msg)) { | |
| 791 return; | |
| 792 } | |
| 793 | |
| 794 var scripts = msg.getBody(); | 831 var scripts = msg.getBody(); |
| 795 for (var i = 0; i < scripts.length; i++) { | 832 for (var i = 0; i < scripts.length; i++) { |
| 796 var script = scripts[i]; | 833 var script = scripts[i]; |
| 797 | 834 |
| 798 // Skip scripts from other tabs. | 835 // Skip scripts from other tabs. |
| 799 if (!this.isScriptFromInspectedContext_(script, msg)) { | 836 if (!this.isScriptFromInspectedContext_(script, msg)) { |
| 800 continue; | 837 continue; |
| 801 } | 838 } |
| 802 | 839 |
| 803 // There is no script source | 840 // There is no script source |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 this.addScriptInfo_(script, msg); | 918 this.addScriptInfo_(script, msg); |
| 882 }; | 919 }; |
| 883 | 920 |
| 884 | 921 |
| 885 /** | 922 /** |
| 886 * @param {Object} script Parsed JSON object representing script. | 923 * @param {Object} script Parsed JSON object representing script. |
| 887 * @return {boolean} Whether the script is a result of the void script | 924 * @return {boolean} Whether the script is a result of the void script |
| 888 * evaluation and should not appear in the UI. | 925 * evaluation and should not appear in the UI. |
| 889 */ | 926 */ |
| 890 devtools.DebuggerAgent.prototype.isVoidScript_ = function(script) { | 927 devtools.DebuggerAgent.prototype.isVoidScript_ = function(script) { |
| 928 var voidScript = devtools.DebuggerAgent.VOID_SCRIPT_EVAL_SOURCE; |
| 891 return !script.name && | 929 return !script.name && |
| 892 (script.sourceStart == devtools.DebuggerAgent.VOID_SCRIPT || | 930 (script.sourceStart == voidScript || |
| 893 script.source == devtools.DebuggerAgent.VOID_SCRIPT); | 931 script.source == voidScript); |
| 894 }; | 932 }; |
| 895 | 933 |
| 896 | 934 |
| 897 /** | 935 /** |
| 898 * Handles current profiler status. | 936 * Handles current profiler status. |
| 899 * @param {number} modules List of active (started) modules. | 937 * @param {number} modules List of active (started) modules. |
| 900 */ | 938 */ |
| 901 devtools.DebuggerAgent.prototype.didGetActiveProfilerModules_ = function( | 939 devtools.DebuggerAgent.prototype.didGetActiveProfilerModules_ = function( |
| 902 modules) { | 940 modules) { |
| 903 var profModules = devtools.DebuggerAgent.ProfilerModules; | 941 var profModules = devtools.DebuggerAgent.ProfilerModules; |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1477 | 1515 |
| 1478 | 1516 |
| 1479 /** | 1517 /** |
| 1480 * @param {number} handle Object handle. | 1518 * @param {number} handle Object handle. |
| 1481 * @return {?Object} Returns the object with the handle if it was sent in this | 1519 * @return {?Object} Returns the object with the handle if it was sent in this |
| 1482 * message(some objects referenced by handles may be missing in the message). | 1520 * message(some objects referenced by handles may be missing in the message). |
| 1483 */ | 1521 */ |
| 1484 devtools.DebuggerMessage.prototype.lookup = function(handle) { | 1522 devtools.DebuggerMessage.prototype.lookup = function(handle) { |
| 1485 return this.refs_[handle]; | 1523 return this.refs_[handle]; |
| 1486 }; | 1524 }; |
| OLD | NEW |