1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "test/cctest/compiler/function-tester.h" 6 7 namespace v8 { 8 namespace internal { 9 namespace compiler { 10 11 TEST(Throw) { 12 FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})"); 13 14 T.CheckThrows(T.true_value(), T.NewObject("new Error")); 15 T.CheckCall(T.Val(23), T.false_value(), T.Val(23)); 16 } 17 18 19 TEST(ThrowMessagePosition) { 20 static const char* src = 21 "(function(a, b) { \n" 22 " if (a == 1) throw 1; \n" 23 " if (a == 2) {throw 2} \n" 24 " if (a == 3) {0;throw 3}\n" 25 " throw 4; \n" 26 "}) "; 27 FunctionTester T(src); 28 v8::Local<v8::Message> message; 29 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); 30 31 message = T.CheckThrowsReturnMessage(T.Val(1), T.undefined()); 32 CHECK_EQ(2, message->GetLineNumber(context).FromMaybe(-1)); 33 CHECK_EQ(40, message->GetStartPosition()); 34 35 message = T.CheckThrowsReturnMessage(T.Val(2), T.undefined()); 36 CHECK_EQ(3, message->GetLineNumber(context).FromMaybe(-1)); 37 CHECK_EQ(67, message->GetStartPosition()); 38 39 message = T.CheckThrowsReturnMessage(T.Val(3), T.undefined()); 40 CHECK_EQ(4, message->GetLineNumber(context).FromMaybe(-1)); 41 CHECK_EQ(95, message->GetStartPosition()); 42 } 43 44 45 TEST(ThrowMessageDirectly) { 46 static const char* src = 47 "(function(a, b) {" 48 " if (a) { throw b; } else { throw new Error(b); }" 49 "})"; 50 FunctionTester T(src); 51 v8::Local<v8::Message> message; 52 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); 53 v8::Maybe<bool> t = v8::Just(true); 54 55 message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); 56 CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?"))); 57 58 message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); 59 CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!"))); 60 } 61 62 63 TEST(ThrowMessageIndirectly) { 64 i::FLAG_turbo_try_finally = true; 65 static const char* src = 66 "(function(a, b) {" 67 " try {" 68 " if (a) { throw b; } else { throw new Error(b); }" 69 " } finally {" 70 " try { throw 'clobber'; } catch (e) { 'unclobber'; }" 71 " }" 72 "})"; 73 FunctionTester T(src); 74 v8::Local<v8::Message> message; 75 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); 76 v8::Maybe<bool> t = v8::Just(true); 77 78 message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); 79 CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?"))); 80 81 message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); 82 CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!"))); 83 } 84 85 86 TEST(Catch) { 87 const char* src = 88 "(function(a,b) {" 89 " var r = '-';" 90 " try {" 91 " r += 'A-';" 92 " throw 'B-';" 93 " } catch (e) {" 94 " r += e;" 95 " }" 96 " return r;" 97 "})"; 98 FunctionTester T(src); 99 100 T.CheckCall(T.Val("-A-B-")); 101 } 102 103 104 TEST(CatchNested) { 105 const char* src = 106 "(function(a,b) {" 107 " var r = '-';" 108 " try {" 109 " r += 'A-';" 110 " throw 'C-';" 111 " } catch (e) {" 112 " try {" 113 " throw 'B-';" 114 " } catch (e) {" 115 " r += e;" 116 " }" 117 " r += e;" 118 " }" 119 " return r;" 120 "})"; 121 FunctionTester T(src); 122 123 T.CheckCall(T.Val("-A-B-C-")); 124 } 125 126 127 TEST(CatchBreak) { 128 const char* src = 129 "(function(a,b) {" 130 " var r = '-';" 131 " L: try {" 132 " r += 'A-';" 133 " if (a) break L;" 134 " r += 'B-';" 135 " throw 'C-';" 136 " } catch (e) {" 137 " if (b) break L;" 138 " r += e;" 139 " }" 140 " r += 'D-';" 141 " return r;" 142 "})"; 143 FunctionTester T(src); 144 145 T.CheckCall(T.Val("-A-D-"), T.true_value(), T.false_value()); 146 T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value()); 147 T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value()); 148 } 149 150 151 TEST(CatchCall) { 152 const char* src = 153 "(function(fun) {" 154 " var r = '-';" 155 " try {" 156 " r += 'A-';" 157 " return r + 'B-' + fun();" 158 " } catch (e) {" 159 " r += e;" 160 " }" 161 " return r;" 162 "})"; 163 FunctionTester T(src); 164 165 CompileRun("function thrower() { throw 'T-'; }"); 166 T.CheckCall(T.Val("-A-T-"), T.NewFunction("thrower")); 167 CompileRun("function returner() { return 'R-'; }"); 168 T.CheckCall(T.Val("-A-B-R-"), T.NewFunction("returner")); 169 } 170 171 172 TEST(Finally) { 173 i::FLAG_turbo_try_finally = true; 174 const char* src = 175 "(function(a,b) {" 176 " var r = '-';" 177 " try {" 178 " r += 'A-';" 179 " } finally {" 180 " r += 'B-';" 181 " }" 182 " return r;" 183 "})"; 184 FunctionTester T(src); 185 186 T.CheckCall(T.Val("-A-B-")); 187 } 188 189 190 TEST(FinallyBreak) { 191 i::FLAG_turbo_try_finally = true; 192 const char* src = 193 "(function(a,b) {" 194 " var r = '-';" 195 " L: try {" 196 " r += 'A-';" 197 " if (a) return r;" 198 " r += 'B-';" 199 " if (b) break L;" 200 " r += 'C-';" 201 " } finally {" 202 " r += 'D-';" 203 " }" 204 " return r;" 205 "})"; 206 FunctionTester T(src); 207 208 T.CheckCall(T.Val("-A-"), T.true_value(), T.false_value()); 209 T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value()); 210 T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value()); 211 } 212 213 214 TEST(DeoptTry) { 215 const char* src = 216 "(function f(a) {" 217 " try {" 218 " %DeoptimizeFunction(f);" 219 " throw a;" 220 " } catch (e) {" 221 " return e + 1;" 222 " }" 223 "})"; 224 FunctionTester T(src); 225 226 T.CheckCall(T.Val(2), T.Val(1)); 227 } 228 229 230 TEST(DeoptCatch) { 231 const char* src = 232 "(function f(a) {" 233 " try {" 234 " throw a;" 235 " } catch (e) {" 236 " %DeoptimizeFunction(f);" 237 " return e + 1;" 238 " }" 239 "})"; 240 FunctionTester T(src); 241 242 T.CheckCall(T.Val(2), T.Val(1)); 243 } 244 245 246 TEST(DeoptFinallyReturn) { 247 i::FLAG_turbo_try_finally = true; 248 const char* src = 249 "(function f(a) {" 250 " try {" 251 " throw a;" 252 " } finally {" 253 " %DeoptimizeFunction(f);" 254 " return a + 1;" 255 " }" 256 "})"; 257 FunctionTester T(src); 258 259 T.CheckCall(T.Val(2), T.Val(1)); 260 } 261 262 263 TEST(DeoptFinallyReThrow) { 264 i::FLAG_turbo_try_finally = true; 265 const char* src = 266 "(function f(a) {" 267 " try {" 268 " throw a;" 269 " } finally {" 270 " %DeoptimizeFunction(f);" 271 " }" 272 "})"; 273 FunctionTester T(src); 274 275 #if 0 // TODO(mstarzinger): Enable once we can. 276 T.CheckThrows(T.NewObject("new Error"), T.Val(1)); 277 #endif 278 } 279 280 } // namespace compiler 281 } // namespace internal 282 } // namespace v8 283