| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2012 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. |
| 30 |
| 31 Debug = debug.Debug |
| 32 |
| 33 function TestCase(fun, restart_fun_name, break_type) |
| 34 { |
| 35 function FindCallFrame(exec_state, function_name) { |
| 36 for (var i = 0; i < exec_state.frameCount(); i++) { |
| 37 var frame = exec_state.frame(i); |
| 38 var func_mirror = frame.func(); |
| 39 if (function_name== func_mirror.name()) { |
| 40 return frame; |
| 41 } |
| 42 } |
| 43 throw new Error("Failed to find function name " + function_name); |
| 44 } |
| 45 |
| 46 function DebuggerStatementHandler(exec_state) { |
| 47 var frame = FindCallFrame(exec_state, restart_fun_name); |
| 48 // Throws if fails. |
| 49 Debug.LiveEdit.RestartFrame(frame); |
| 50 } |
| 51 |
| 52 var saved_exception = null; |
| 53 |
| 54 function listener(event, exec_state, event_data, data) { |
| 55 if (saved_exception != null) { |
| 56 return; |
| 57 } |
| 58 if (event == Debug.DebugEvent.BeforeCompile || |
| 59 event == Debug.DebugEvent.AfterCompile) { |
| 60 // Ignore. |
| 61 } else if (event == break_type) { |
| 62 try { |
| 63 DebuggerStatementHandler(exec_state); |
| 64 } catch (e) { |
| 65 saved_exception = e; |
| 66 } |
| 67 } else { |
| 68 var name = event; |
| 69 for (var k in Debug.DebugEvent) { |
| 70 if (Debug.DebugEvent[k] == event) { |
| 71 name = "Debug.DebugEvent." + k; |
| 72 } |
| 73 } |
| 74 print("Other: " + name); |
| 75 } |
| 76 } |
| 77 |
| 78 var fun_name = /function ?(.*)\(/.exec(String(fun))[1]; |
| 79 print("Test function " + fun_name); |
| 80 |
| 81 Debug.setListener(listener); |
| 82 |
| 83 var result; |
| 84 try { |
| 85 result = fun(); |
| 86 } catch (e) { |
| 87 result = "Exception caught: " + e; |
| 88 } |
| 89 |
| 90 Debug.setListener(null); |
| 91 |
| 92 if (saved_exception) { |
| 93 print("Exception: " + saved_exception); |
| 94 print("Stack: " + saved_exception.stack); |
| 95 assertUnreachable(); |
| 96 } |
| 97 print("Done, result " + result); |
| 98 assertEquals("Capybara", result); |
| 99 print("\n"); |
| 100 } |
| 101 |
| 102 |
| 103 |
| 104 // Test cases. |
| 105 |
| 106 |
| 107 // Restart when throwing exception in eval. |
| 108 function RestartWhenThrowingInEval() { |
| 109 var input = [ "}", "'Capybara'" ]; |
| 110 var pos = 0; |
| 111 |
| 112 function Inner(p) { |
| 113 return eval(p); |
| 114 } |
| 115 |
| 116 function Helper() { |
| 117 var p = input[pos++]; |
| 118 return Inner(p); |
| 119 } |
| 120 |
| 121 return Helper(); |
| 122 } |
| 123 |
| 124 Debug.setBreakOnException(); |
| 125 TestCase(RestartWhenThrowingInEval, "Helper", Debug.DebugEvent.Exception) |
| 126 Debug.clearBreakOnException(); |
| 127 |
| 128 |
| 129 // Restart when throwing exception. |
| 130 function RestartWhenThrowing() { |
| 131 var input = [ undefined, "Capybara" ]; |
| 132 var pos = 0; |
| 133 |
| 134 function Inner(p) { |
| 135 return p.toString(); |
| 136 } |
| 137 |
| 138 function Helper() { |
| 139 var p = input[pos++]; |
| 140 return Inner(p); |
| 141 } |
| 142 |
| 143 return Helper(); |
| 144 } |
| 145 |
| 146 Debug.setBreakOnException(); |
| 147 TestCase(RestartWhenThrowing, "Helper", Debug.DebugEvent.Exception) |
| 148 Debug.clearBreakOnException(); |
| 149 |
| 150 |
| 151 // Restart when catching an exception. |
| 152 function RestartWhenCatching() { |
| 153 var input = [ undefined, "Capybara" ]; |
| 154 var pos = 0; |
| 155 |
| 156 function Inner() { |
| 157 var p = input[pos++]; |
| 158 try { |
| 159 return p.toString(); |
| 160 } catch (e) { |
| 161 debugger; |
| 162 return "Not capybara"; |
| 163 } |
| 164 } |
| 165 |
| 166 return Inner(); |
| 167 } |
| 168 |
| 169 TestCase(RestartWhenCatching, "Inner", Debug.DebugEvent.Break) |
| 170 |
| 171 |
| 172 // Restart on throwing while catching an exception. |
| 173 function RestartWhenThrowingInCatch() { |
| 174 var input = [ undefined, "Capybara" ]; |
| 175 var pos = 0; |
| 176 |
| 177 function Inner() { |
| 178 var p = input[pos++]; |
| 179 Debug.clearBreakOnException(); |
| 180 try { |
| 181 return p.toString(); |
| 182 } catch (e) { |
| 183 Debug.setBreakOnException(); |
| 184 (3).changeValue(); |
| 185 } |
| 186 return "Something"; |
| 187 } |
| 188 |
| 189 return Inner(); |
| 190 } |
| 191 |
| 192 TestCase(RestartWhenThrowingInCatch, "Inner", Debug.DebugEvent.Exception) |
| 193 Debug.clearBreakOnException(); |
| 194 |
| 195 |
| 196 // Restart on throwing while catching an exception, not touching catch. |
| 197 function RestartWhenThrowingInCatchKeepCatch() { |
| 198 var input = [ undefined, "Cat" ]; |
| 199 var pos = 0; |
| 200 |
| 201 function Inner() { |
| 202 var p = input[pos++]; |
| 203 Debug.setBreakOnException(); |
| 204 return p.toString(); |
| 205 } |
| 206 |
| 207 function Middle() { |
| 208 Debug.clearBreakOnException(); |
| 209 try { |
| 210 throw new Error("Capybara"); |
| 211 } catch (e) { |
| 212 Inner(); |
| 213 return e.message; |
| 214 } |
| 215 } |
| 216 |
| 217 return Middle(); |
| 218 } |
| 219 |
| 220 TestCase(RestartWhenThrowingInCatchKeepCatch, "Inner", |
| 221 Debug.DebugEvent.Exception) |
| 222 Debug.clearBreakOnException(); |
| 223 |
| 224 |
| 225 // Restart while in finally, not touching finally. |
| 226 function RestartWhenThrowingInFinally() { |
| 227 var input = [ |
| 228 function() { debugger; }, |
| 229 function() {} |
| 230 ]; |
| 231 var pos = 0; |
| 232 |
| 233 function Inner() { |
| 234 try { |
| 235 throw new Error("Cat"); |
| 236 } catch (e) { |
| 237 input[pos++](); |
| 238 } |
| 239 } |
| 240 |
| 241 function Middle() { |
| 242 try { |
| 243 try { |
| 244 throw new Error("Capybara"); |
| 245 } finally { |
| 246 Inner(); |
| 247 } |
| 248 } catch (e) { |
| 249 return e.message; |
| 250 } |
| 251 } |
| 252 |
| 253 return Middle(); |
| 254 } |
| 255 |
| 256 TestCase(RestartWhenThrowingInFinally, "Inner", Debug.DebugEvent.Break) |
| 257 |
| OLD | NEW |