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.running = function() { 73 return this.response_.running; 74} 75 76 77ParsedResponse.prototype.lookup = function(handle) { 78 return this.refs_[handle]; 79} 80 81 82function listener(event, exec_state, event_data, data) { 83 try { 84 if (event == Debug.DebugEvent.Break) { 85 // The expected backtrace is 86 // 0: f 87 // 1: m 88 // 2: g 89 // 3: [anonymous] 90 91 var response; 92 var backtrace; 93 var frame; 94 var source; 95 96 var dcp; 97 // New copy of debug command processor paused state. 98 dcp = exec_state.debugCommandProcessor(false); 99 100 // Get the backtrace. 101 var json; 102 json = '{"seq":0,"type":"request","command":"backtrace"}' 103 var resp = dcp.processDebugJSONRequest(json); 104 response = new ParsedResponse(resp); 105 backtrace = response.body(); 106 assertEquals(0, backtrace.fromFrame); 107 assertEquals(4, backtrace.toFrame); 108 assertEquals(4, backtrace.totalFrames); 109 var frames = backtrace.frames; 110 assertEquals(4, frames.length); 111 for (var i = 0; i < frames.length; i++) { 112 assertEquals('frame', frames[i].type); 113 } 114 assertEquals(0, frames[0].index); 115 assertEquals("f", response.lookup(frames[0].func.ref).name); 116 assertEquals(1, frames[1].index); 117 assertEquals("", response.lookup(frames[1].func.ref).name); 118 assertEquals("m", response.lookup(frames[1].func.ref).inferredName); 119 assertEquals(2, frames[2].index); 120 assertEquals("g", response.lookup(frames[2].func.ref).name); 121 assertEquals(3, frames[3].index); 122 assertEquals("", response.lookup(frames[3].func.ref).name); 123 assertFalse(response.running(), "expected not running"); 124 125 // Get backtrace with two frames. 126 json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}' 127 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 128 backtrace = response.body(); 129 assertEquals(1, backtrace.fromFrame); 130 assertEquals(3, backtrace.toFrame); 131 assertEquals(4, backtrace.totalFrames); 132 var frames = backtrace.frames; 133 assertEquals(2, frames.length); 134 for (var i = 0; i < frames.length; i++) { 135 assertEquals('frame', frames[i].type); 136 } 137 assertEquals(1, frames[0].index); 138 assertEquals("", response.lookup(frames[0].func.ref).name); 139 assertEquals("m", response.lookup(frames[0].func.ref).inferredName); 140 assertEquals(2, frames[1].index); 141 assertEquals("g", response.lookup(frames[1].func.ref).name); 142 143 // Get backtrace with bottom two frames. 144 json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":0,"toFrame":2, "bottom":true}}' 145 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 146 backtrace = response.body(); 147 assertEquals(2, backtrace.fromFrame); 148 assertEquals(4, backtrace.toFrame); 149 assertEquals(4, backtrace.totalFrames); 150 var frames = backtrace.frames; 151 assertEquals(2, frames.length); 152 for (var i = 0; i < frames.length; i++) { 153 assertEquals('frame', frames[i].type); 154 } 155 assertEquals(2, frames[0].index); 156 assertEquals("g", response.lookup(frames[0].func.ref).name); 157 assertEquals(3, frames[1].index); 158 assertEquals("", response.lookup(frames[1].func.ref).name); 159 160 // Get the individual frames. 161 json = '{"seq":0,"type":"request","command":"frame"}' 162 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 163 frame = response.body(); 164 assertEquals(0, frame.index); 165 assertEquals("f", response.lookup(frame.func.ref).name); 166 assertTrue(frame.constructCall); 167 assertEquals(31, frame.line); 168 assertEquals(3, frame.column); 169 assertEquals(2, frame.arguments.length); 170 assertEquals('x', frame.arguments[0].name); 171 assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); 172 assertEquals(1, response.lookup(frame.arguments[0].value.ref).value); 173 assertEquals('y', frame.arguments[1].name); 174 assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type); 175 176 json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":0}}' 177 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 178 frame = response.body(); 179 assertEquals(0, frame.index); 180 assertEquals("f", response.lookup(frame.func.ref).name); 181 assertEquals(31, frame.line); 182 assertEquals(3, frame.column); 183 assertEquals(2, frame.arguments.length); 184 assertEquals('x', frame.arguments[0].name); 185 assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); 186 assertEquals(1, response.lookup(frame.arguments[0].value.ref).value); 187 assertEquals('y', frame.arguments[1].name); 188 assertEquals('undefined', response.lookup(frame.arguments[1].value.ref).type); 189 190 json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":1}}' 191 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 192 frame = response.body(); 193 assertEquals(1, frame.index); 194 assertEquals("", response.lookup(frame.func.ref).name); 195 assertEquals("m", response.lookup(frame.func.ref).inferredName); 196 assertFalse(frame.constructCall); 197 assertEquals(35, frame.line); 198 assertEquals(6, frame.column); 199 assertEquals(0, frame.arguments.length); 200 201 json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":3}}' 202 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 203 frame = response.body(); 204 assertEquals(3, frame.index); 205 assertEquals("", response.lookup(frame.func.ref).name); 206 207 // Source slices for the individual frames (they all refer to this script). 208 json = '{"seq":0,"type":"request","command":"source",' + 209 '"arguments":{"frame":0,"fromLine":30,"toLine":32}}' 210 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 211 source = response.body(); 212 assertEquals("function f(x, y) {", source.source.substring(0, 18)); 213 assertEquals(30, source.fromLine); 214 assertEquals(32, source.toLine); 215 216 json = '{"seq":0,"type":"request","command":"source",' + 217 '"arguments":{"frame":1,"fromLine":31,"toLine":32}}' 218 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 219 source = response.body(); 220 assertEquals(" a=1;", source.source.substring(0, 6)); 221 assertEquals(31, source.fromLine); 222 assertEquals(32, source.toLine); 223 224 json = '{"seq":0,"type":"request","command":"source",' + 225 '"arguments":{"frame":2,"fromLine":35,"toLine":36}}' 226 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 227 source = response.body(); 228 assertEquals(" new f(1);", source.source.substring(0, 11)); 229 assertEquals(35, source.fromLine); 230 assertEquals(36, source.toLine); 231 232 // Test line interval way beyond this script will result in an error. 233 json = '{"seq":0,"type":"request","command":"source",' + 234 '"arguments":{"frame":0,"fromLine":10000,"toLine":20000}}' 235 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 236 assertFalse(response.response().success); 237 238 // Test without arguments. 239 json = '{"seq":0,"type":"request","command":"source"}' 240 response = new ParsedResponse(dcp.processDebugJSONRequest(json)); 241 source = response.body(); 242 assertEquals(Debug.findScript(f).source, source.source); 243 244 // New copy of debug command processor in running state. 245 dcp = exec_state.debugCommandProcessor(true); 246 // Get the backtrace. 247 json = '{"seq":0,"type":"request","command":"backtrace"}' 248 resp = dcp.processDebugJSONRequest(json); 249 response = new ParsedResponse(resp); 250 // It might be argueable, but we expect response to have body when 251 // not suspended 252 assertTrue(!!response.body(), "response should be null"); 253 assertTrue(response.running(), "expected running"); 254 255 listenerCalled = true; 256 } 257 } catch (e) { 258 exception = e 259 }; 260}; 261 262// Add the debug event listener. 263Debug.setListener(listener); 264 265// Set a break point and call to invoke the debug event listener. 266Debug.setBreakPoint(f, 0, 0); 267g(); 268 269// Make sure that the debug event listener vas invoked. 270assertFalse(exception, "exception in listener"); 271assertTrue(listenerCalled); 272