1// Copyright 2009 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// Get the Debug object exposed from the debug context global object. 30Debug = debug.Debug 31 32listenerComplete = false; 33exception = false; 34 35function safeEval(code) { 36 try { 37 return eval('(' + code + ')'); 38 } catch (e) { 39 assertEquals(void 0, e); 40 return undefined; 41 } 42} 43 44 45// Send an evaluation request and return the handle of the result. 46function evaluateRequest(exec_state, arguments) { 47 // Get the debug command processor. 48 var dcp = exec_state.debugCommandProcessor("unspecified_running_state"); 49 50 // The base part of all evaluate requests. 51 var base_request = '"seq":0,"type":"request","command":"evaluate"' 52 53 // Generate request with the supplied arguments. 54 var request; 55 if (arguments) { 56 request = '{' + base_request + ',"arguments":' + arguments + '}'; 57 } else { 58 request = '{' + base_request + '}' 59 } 60 61 var response = safeEval(dcp.processDebugJSONRequest(request)); 62 assertTrue(response.success, request + ' -> ' + response.message); 63 64 return response.body.handle; 65} 66 67 68// Send a lookup request and return the evaluated JSON response. 69function lookupRequest(exec_state, arguments, success) { 70 // Get the debug command processor. 71 var dcp = exec_state.debugCommandProcessor("unspecified_running_state"); 72 73 // The base part of all lookup requests. 74 var base_request = '"seq":0,"type":"request","command":"lookup"' 75 76 // Generate request with the supplied arguments. 77 var request; 78 if (arguments) { 79 request = '{' + base_request + ',"arguments":' + arguments + '}'; 80 } else { 81 request = '{' + base_request + '}' 82 } 83 84 var response = safeEval(dcp.processDebugJSONRequest(request)); 85 if (success) { 86 assertTrue(response.success, request + ' -> ' + response.message); 87 } else { 88 assertFalse(response.success, request + ' -> ' + response.message); 89 } 90 assertEquals(response.running, dcp.isRunning(), request + ' -> expected not running'); 91 92 return response; 93} 94 95 96function listener(event, exec_state, event_data, data) { 97 try { 98 if (event == Debug.DebugEvent.Break) { 99 // Test some illegal lookup requests. 100 lookupRequest(exec_state, void 0, false); 101 lookupRequest(exec_state, '{"handles":["a"]}', false); 102 lookupRequest(exec_state, '{"handles":[-1]}', false); 103 104 // Evaluate and get some handles. 105 var handle_o = evaluateRequest(exec_state, '{"expression":"o"}'); 106 var handle_p = evaluateRequest(exec_state, '{"expression":"p"}'); 107 var handle_b = evaluateRequest(exec_state, '{"expression":"a"}'); 108 var handle_a = evaluateRequest(exec_state, '{"expression":"b","frame":1}'); 109 assertEquals(handle_o, handle_a); 110 assertEquals(handle_a, handle_b); 111 assertFalse(handle_o == handle_p, "o and p have he same handle"); 112 113 var response; 114 var count; 115 response = lookupRequest(exec_state, '{"handles":[' + handle_o + ']}', true); 116 var obj = response.body[handle_o]; 117 assertTrue(!!obj, 'Object not found: ' + handle_o); 118 assertEquals(handle_o, obj.handle); 119 count = 0; 120 for (i in obj.properties) { 121 switch (obj.properties[i].name) { 122 case 'o': 123 obj.properties[i].ref = handle_o; 124 count++; 125 break; 126 case 'p': 127 obj.properties[i].ref = handle_p; 128 count++; 129 break; 130 } 131 } 132 assertEquals(2, count, 'Either "o" or "p" not found'); 133 response = lookupRequest(exec_state, '{"handles":[' + handle_p + ']}', true); 134 obj = response.body[handle_p]; 135 assertTrue(!!obj, 'Object not found: ' + handle_p); 136 assertEquals(handle_p, obj.handle); 137 138 // Check handles for functions on the stack. 139 var handle_f = evaluateRequest(exec_state, '{"expression":"f"}'); 140 var handle_g = evaluateRequest(exec_state, '{"expression":"g"}'); 141 var handle_caller = evaluateRequest(exec_state, '{"expression":"f.caller"}'); 142 143 assertFalse(handle_f == handle_g, "f and g have he same handle"); 144 assertEquals(handle_g, handle_caller, "caller for f should be g"); 145 146 response = lookupRequest(exec_state, '{"handles":[' + handle_f + ']}', true); 147 obj = response.body[handle_f]; 148 assertEquals(handle_f, obj.handle); 149 150 count = 0; 151 for (i in obj.properties) { 152 var ref = obj.properties[i].ref; 153 var arguments = '{"handles":[' + ref + ']}'; 154 switch (obj.properties[i].name) { 155 case 'name': 156 var response_name; 157 response_name = lookupRequest(exec_state, arguments, true); 158 assertEquals('string', response_name.body[ref].type); 159 assertEquals("f", response_name.body[ref].value); 160 count++; 161 break; 162 case 'length': 163 var response_length; 164 response_length = lookupRequest(exec_state, arguments, true); 165 assertEquals('number', response_length.body[ref].type); 166 assertEquals(1, response_length.body[ref].value); 167 count++; 168 break; 169 case 'caller': 170 assertEquals(handle_g, obj.properties[i].ref); 171 count++; 172 break; 173 } 174 } 175 assertEquals(3, count, 'Either "name", "length" or "caller" not found'); 176 177 178 // Resolve all at once. 179 var refs = []; 180 for (i in obj.properties) { 181 refs.push(obj.properties[i].ref); 182 } 183 184 var arguments = '{"handles":[' + refs.join(',') + ']}'; 185 response = lookupRequest(exec_state, arguments, true); 186 count = 0; 187 for (i in obj.properties) { 188 var ref = obj.properties[i].ref; 189 var val = response.body[ref]; 190 assertTrue(!!val, 'Failed to lookup "' + obj.properties[i].name + '"'); 191 switch (obj.properties[i].name) { 192 case 'name': 193 assertEquals('string', val.type); 194 assertEquals("f", val.value); 195 count++; 196 break; 197 case 'length': 198 assertEquals('number', val.type); 199 assertEquals(1, val.value); 200 count++; 201 break; 202 case 'caller': 203 assertEquals('function', val.type); 204 assertEquals(handle_g, ref); 205 count++; 206 break; 207 } 208 } 209 assertEquals(3, count, 'Either "name", "length" or "caller" not found'); 210 211 count = 0; 212 for (var handle in response.body) { 213 assertTrue(refs.indexOf(parseInt(handle)) != -1, 214 'Handle not in the request: ' + handle); 215 count++; 216 } 217 assertEquals(count, obj.properties.length, 218 'Unexpected number of resolved objects'); 219 220 221 // Indicate that all was processed. 222 listenerComplete = true; 223 } 224 } catch (e) { 225 exception = e 226 }; 227}; 228 229// Add the debug event listener. 230Debug.setListener(listener); 231 232function f(a) { 233 debugger; 234}; 235 236function g(b) { 237 f(b); 238}; 239 240// Set a break point at return in f and invoke g to hit the breakpoint. 241Debug.setBreakPoint(f, 2, 0); 242o = {}; 243p = {} 244o.o = o; 245o.p = p; 246p.o = o; 247p.p = p; 248g(o); 249 250assertFalse(exception, "exception in listener") 251// Make sure that the debug event listener vas invoked. 252assertTrue(listenerComplete, "listener did not run to completion: " + exception); 253