debug-backtrace.js revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1// Copyright 2008 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Flags: --expose-debug-as debug 29// The functions used for testing backtraces. They are at the top to make the 30// testing of source line/column easier. 31function f(x, y) { 32 a=1; 33}; 34 35var m = function() { 36 new f(1); 37}; 38 39function g() { 40 m(); 41}; 42 43 44// Get the Debug object exposed from the debug context global object. 45Debug = debug.Debug 46 47listenerCalled = false; 48exception = false; 49 50 51function ParsedResponse(json) { 52 this.response_ = eval('(' + json + ')'); 53 this.refs_ = []; 54 if (this.response_.refs) { 55 for (var i = 0; i < this.response_.refs.length; i++) { 56 this.refs_[this.response_.refs[i].handle] = this.response_.refs[i]; 57 } 58 } 59} 60 61 62ParsedResponse.prototype.response = function() { 63 return this.response_; 64} 65 66 67ParsedResponse.prototype.body = function() { 68 return this.response_.body; 69} 70 71 72ParsedResponse.prototype.lookup = function(handle) { 73 return this.refs_[handle]; 74} 75 76 77function listener(event, exec_state, event_data, data) { 78 try { 79 if (event == Debug.DebugEvent.Break) { 80 // The expected backtrace is 81 // 0: f 82 // 1: m 83 // 2: g 84 // 3: [anonymous] 85 86 var response; 87 var backtrace; 88 var frame; 89 var source; 90 91 // Get the debug command processor. 92 var dcp = exec_state.debugCommandProcessor(); 93 94 // Get the backtrace. 95 var json; 96 json = '{"seq":0,"type":"request","command":"backtrace"}' 97 var resp = dcp.processDebugJSONRequest(json); 98 response = new ParsedResponse(resp); 99 backtrace = response.body(); 100 assertEquals(0, backtrace.fromFrame); 101 assertEquals(4, backtrace.toFrame); 102 assertEquals(4, backtrace.totalFrames); 103 var frames = backtrace.frames; 104 assertEquals(4, frames.length); 105 for (var i = 0; i < frames.length; i++) { 106 assertEquals('frame', frames[i].type); 107 } 108 assertEquals(0, frames[0].index); 109 assertEquals("f", response.lookup(frames[0].func.ref).name); 110 assertEquals(1, frames[1].index); 111 assertEquals("", response.lookup(frames[1].func.ref).name); 112 assertEquals("m", response.lookup(frames[1].func.ref).inferredName); 113 assertEquals(2, frames[2].index); 114 assertEquals("g", response.lookup(frames[2].func.ref).name); 115 assertEquals(3, frames[3].index); 116 assertEquals("", response.lookup(frames[3].func.ref).name); 117 118 // Get backtrace with two frames. 119 json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}' 120 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 121 backtrace = response.body(); 122 assertEquals(1, backtrace.fromFrame); 123 assertEquals(3, backtrace.toFrame); 124 assertEquals(4, backtrace.totalFrames); 125 var frames = backtrace.frames; 126 assertEquals(2, frames.length); 127 for (var i = 0; i < frames.length; i++) { 128 assertEquals('frame', frames[i].type); 129 } 130 assertEquals(1, frames[0].index); 131 assertEquals("", response.lookup(frames[0].func.ref).name); 132 assertEquals("m", response.lookup(frames[0].func.ref).inferredName); 133 assertEquals(2, frames[1].index); 134 assertEquals("g", response.lookup(frames[1].func.ref).name); 135 136 // Get backtrace with bottom two frames. 137 json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":0,"toFrame":2, "bottom":true}}' 138 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 139 backtrace = response.body(); 140 assertEquals(2, backtrace.fromFrame); 141 assertEquals(4, backtrace.toFrame); 142 assertEquals(4, backtrace.totalFrames); 143 var frames = backtrace.frames; 144 assertEquals(2, frames.length); 145 for (var i = 0; i < frames.length; i++) { 146 assertEquals('frame', frames[i].type); 147 } 148 assertEquals(2, frames[0].index); 149 assertEquals("g", response.lookup(frames[0].func.ref).name); 150 assertEquals(3, frames[1].index); 151 assertEquals("", response.lookup(frames[1].func.ref).name); 152 153 // Get the individual frames. 154 json = '{"seq":0,"type":"request","command":"frame"}' 155 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 156 frame = response.body(); 157 assertEquals(0, frame.index); 158 assertEquals("f", response.lookup(frame.func.ref).name); 159 assertTrue(frame.constructCall); 160 assertEquals(31, frame.line); 161 assertEquals(3, frame.column); 162 assertEquals(2, frame.arguments.length); 163 assertEquals('x', frame.arguments[0].name); 164 assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); 165 assertEquals(1, response.lookup(frame.arguments[0].value.ref).value); 166 assertEquals('y', frame.arguments[1].name); 167 assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type); 168 169 json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":0}}' 170 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 171 frame = response.body(); 172 assertEquals(0, frame.index); 173 assertEquals("f", response.lookup(frame.func.ref).name); 174 assertEquals(31, frame.line); 175 assertEquals(3, frame.column); 176 assertEquals(2, frame.arguments.length); 177 assertEquals('x', frame.arguments[0].name); 178 assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); 179 assertEquals(1, response.lookup(frame.arguments[0].value.ref).value); 180 assertEquals('y', frame.arguments[1].name); 181 assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type); 182 183 json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":1}}' 184 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 185 frame = response.body(); 186 assertEquals(1, frame.index); 187 assertEquals("", response.lookup(frame.func.ref).name); 188 assertEquals("m", response.lookup(frame.func.ref).inferredName); 189 assertFalse(frame.constructCall); 190 assertEquals(35, frame.line); 191 assertEquals(2, frame.column); 192 assertEquals(0, frame.arguments.length); 193 194 json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":3}}' 195 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 196 frame = response.body(); 197 assertEquals(3, frame.index); 198 assertEquals("", response.lookup(frame.func.ref).name); 199 200 // Source slices for the individual frames (they all refer to this script). 201 json = '{"seq":0,"type":"request","command":"source",' + 202 '"arguments":{"frame":0,"fromLine":30,"toLine":32}}' 203 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 204 source = response.body(); 205 assertEquals("function f(x, y) {", source.source.substring(0, 18)); 206 assertEquals(30, source.fromLine); 207 assertEquals(32, source.toLine); 208 209 json = '{"seq":0,"type":"request","command":"source",' + 210 '"arguments":{"frame":1,"fromLine":31,"toLine":32}}' 211 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 212 source = response.body(); 213 assertEquals(" a=1;", source.source.substring(0, 6)); 214 assertEquals(31, source.fromLine); 215 assertEquals(32, source.toLine); 216 217 json = '{"seq":0,"type":"request","command":"source",' + 218 '"arguments":{"frame":2,"fromLine":35,"toLine":36}}' 219 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 220 source = response.body(); 221 assertEquals(" new f(1);", source.source.substring(0, 11)); 222 assertEquals(35, source.fromLine); 223 assertEquals(36, source.toLine); 224 225 // Test line interval way beyond this script will result in an error. 226 json = '{"seq":0,"type":"request","command":"source",' + 227 '"arguments":{"frame":0,"fromLine":10000,"toLine":20000}}' 228 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 229 assertFalse(response.response().success); 230 231 // Test without arguments. 232 json = '{"seq":0,"type":"request","command":"source"}' 233 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 234 source = response.body(); 235 assertEquals(Debug.findScript(f).source, source.source); 236 237 listenerCalled = true; 238 } 239 } catch (e) { 240 exception = e 241 }; 242}; 243 244// Add the debug event listener. 245Debug.setListener(listener); 246 247// Set a break point and call to invoke the debug event listener. 248Debug.setBreakPoint(f, 0, 0); 249g(); 250 251// Make sure that the debug event listener vas invoked. 252assertFalse(exception, "exception in listener"); 253assertTrue(listenerCalled); 254 255