Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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. |
| 31 | function f(x, y) { |
| 32 | a=1; |
| 33 | }; |
| 34 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 35 | var m = (0, function() { |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 36 | new f(1); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 37 | }); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 38 | |
| 39 | function g() { |
| 40 | m(); |
| 41 | }; |
| 42 | |
| 43 | |
| 44 | // Get the Debug object exposed from the debug context global object. |
| 45 | Debug = debug.Debug |
| 46 | |
| 47 | listenerCalled = false; |
| 48 | exception = false; |
| 49 | |
| 50 | |
| 51 | function 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 | |
| 62 | ParsedResponse.prototype.response = function() { |
| 63 | return this.response_; |
| 64 | } |
| 65 | |
| 66 | |
| 67 | ParsedResponse.prototype.body = function() { |
| 68 | return this.response_.body; |
| 69 | } |
| 70 | |
| 71 | |
Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 72 | ParsedResponse.prototype.running = function() { |
| 73 | return this.response_.running; |
| 74 | } |
| 75 | |
| 76 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 77 | ParsedResponse.prototype.lookup = function(handle) { |
| 78 | return this.refs_[handle]; |
| 79 | } |
| 80 | |
| 81 | |
| 82 | function 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 | |
Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 96 | var dcp; |
| 97 | // New copy of debug command processor paused state. |
| 98 | dcp = exec_state.debugCommandProcessor(false); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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); |
Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 123 | assertFalse(response.running(), "expected not running"); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 168 | assertEquals(2, frame.column); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 182 | assertEquals(2, frame.column); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 198 | assertEquals(2, frame.column); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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 | |
Steve Block | 3ce2e20 | 2009-11-05 08:53:23 +0000 | [diff] [blame] | 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 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 255 | listenerCalled = true; |
| 256 | } |
| 257 | } catch (e) { |
| 258 | exception = e |
| 259 | }; |
| 260 | }; |
| 261 | |
| 262 | // Add the debug event listener. |
| 263 | Debug.setListener(listener); |
| 264 | |
| 265 | // Set a break point and call to invoke the debug event listener. |
| 266 | Debug.setBreakPoint(f, 0, 0); |
| 267 | g(); |
| 268 | |
| 269 | // Make sure that the debug event listener vas invoked. |
| 270 | assertFalse(exception, "exception in listener"); |
| 271 | assertTrue(listenerCalled); |