| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 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 |  | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 5 | #include "test/cctest/compiler/function-tester.h" | 
 | 6 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 7 | namespace v8 { | 
 | 8 | namespace internal { | 
 | 9 | namespace compiler { | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 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 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 19 | TEST(ThrowMessagePosition) { | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 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); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 28 |   v8::Local<v8::Message> message; | 
 | 29 |   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 30 |  | 
 | 31 |   message = T.CheckThrowsReturnMessage(T.Val(1), T.undefined()); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 32 |   CHECK_EQ(2, message->GetLineNumber(context).FromMaybe(-1)); | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 33 |   CHECK_EQ(40, message->GetStartPosition()); | 
 | 34 |  | 
 | 35 |   message = T.CheckThrowsReturnMessage(T.Val(2), T.undefined()); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 36 |   CHECK_EQ(3, message->GetLineNumber(context).FromMaybe(-1)); | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 37 |   CHECK_EQ(67, message->GetStartPosition()); | 
 | 38 |  | 
 | 39 |   message = T.CheckThrowsReturnMessage(T.Val(3), T.undefined()); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 40 |   CHECK_EQ(4, message->GetLineNumber(context).FromMaybe(-1)); | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 41 |   CHECK_EQ(95, message->GetStartPosition()); | 
 | 42 | } | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 64 |   static const char* src = | 
 | 65 |       "(function(a, b) {" | 
 | 66 |       "  try {" | 
 | 67 |       "    if (a) { throw b; } else { throw new Error(b); }" | 
 | 68 |       "  } finally {" | 
 | 69 |       "    try { throw 'clobber'; } catch (e) { 'unclobber'; }" | 
 | 70 |       "  }" | 
 | 71 |       "})"; | 
 | 72 |   FunctionTester T(src); | 
 | 73 |   v8::Local<v8::Message> message; | 
 | 74 |   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); | 
 | 75 |   v8::Maybe<bool> t = v8::Just(true); | 
 | 76 |  | 
 | 77 |   message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); | 
 | 78 |   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?"))); | 
 | 79 |  | 
 | 80 |   message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); | 
 | 81 |   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!"))); | 
 | 82 | } | 
 | 83 |  | 
 | 84 |  | 
 | 85 | TEST(Catch) { | 
 | 86 |   const char* src = | 
 | 87 |       "(function(a,b) {" | 
 | 88 |       "  var r = '-';" | 
 | 89 |       "  try {" | 
 | 90 |       "    r += 'A-';" | 
 | 91 |       "    throw 'B-';" | 
 | 92 |       "  } catch (e) {" | 
 | 93 |       "    r += e;" | 
 | 94 |       "  }" | 
 | 95 |       "  return r;" | 
 | 96 |       "})"; | 
 | 97 |   FunctionTester T(src); | 
 | 98 |  | 
 | 99 |   T.CheckCall(T.Val("-A-B-")); | 
 | 100 | } | 
 | 101 |  | 
 | 102 |  | 
 | 103 | TEST(CatchNested) { | 
 | 104 |   const char* src = | 
 | 105 |       "(function(a,b) {" | 
 | 106 |       "  var r = '-';" | 
 | 107 |       "  try {" | 
 | 108 |       "    r += 'A-';" | 
 | 109 |       "    throw 'C-';" | 
 | 110 |       "  } catch (e) {" | 
 | 111 |       "    try {" | 
 | 112 |       "      throw 'B-';" | 
 | 113 |       "    } catch (e) {" | 
 | 114 |       "      r += e;" | 
 | 115 |       "    }" | 
 | 116 |       "    r += e;" | 
 | 117 |       "  }" | 
 | 118 |       "  return r;" | 
 | 119 |       "})"; | 
 | 120 |   FunctionTester T(src); | 
 | 121 |  | 
 | 122 |   T.CheckCall(T.Val("-A-B-C-")); | 
 | 123 | } | 
 | 124 |  | 
 | 125 |  | 
 | 126 | TEST(CatchBreak) { | 
 | 127 |   const char* src = | 
 | 128 |       "(function(a,b) {" | 
 | 129 |       "  var r = '-';" | 
 | 130 |       "  L: try {" | 
 | 131 |       "    r += 'A-';" | 
 | 132 |       "    if (a) break L;" | 
 | 133 |       "    r += 'B-';" | 
 | 134 |       "    throw 'C-';" | 
 | 135 |       "  } catch (e) {" | 
 | 136 |       "    if (b) break L;" | 
 | 137 |       "    r += e;" | 
 | 138 |       "  }" | 
 | 139 |       "  r += 'D-';" | 
 | 140 |       "  return r;" | 
 | 141 |       "})"; | 
 | 142 |   FunctionTester T(src); | 
 | 143 |  | 
 | 144 |   T.CheckCall(T.Val("-A-D-"), T.true_value(), T.false_value()); | 
 | 145 |   T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value()); | 
 | 146 |   T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value()); | 
 | 147 | } | 
 | 148 |  | 
 | 149 |  | 
 | 150 | TEST(CatchCall) { | 
 | 151 |   const char* src = | 
 | 152 |       "(function(fun) {" | 
 | 153 |       "  var r = '-';" | 
 | 154 |       "  try {" | 
 | 155 |       "    r += 'A-';" | 
 | 156 |       "    return r + 'B-' + fun();" | 
 | 157 |       "  } catch (e) {" | 
 | 158 |       "    r += e;" | 
 | 159 |       "  }" | 
 | 160 |       "  return r;" | 
 | 161 |       "})"; | 
 | 162 |   FunctionTester T(src); | 
 | 163 |  | 
 | 164 |   CompileRun("function thrower() { throw 'T-'; }"); | 
 | 165 |   T.CheckCall(T.Val("-A-T-"), T.NewFunction("thrower")); | 
 | 166 |   CompileRun("function returner() { return 'R-'; }"); | 
 | 167 |   T.CheckCall(T.Val("-A-B-R-"), T.NewFunction("returner")); | 
 | 168 | } | 
 | 169 |  | 
 | 170 |  | 
 | 171 | TEST(Finally) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 172 |   const char* src = | 
 | 173 |       "(function(a,b) {" | 
 | 174 |       "  var r = '-';" | 
 | 175 |       "  try {" | 
 | 176 |       "    r += 'A-';" | 
 | 177 |       "  } finally {" | 
 | 178 |       "    r += 'B-';" | 
 | 179 |       "  }" | 
 | 180 |       "  return r;" | 
 | 181 |       "})"; | 
 | 182 |   FunctionTester T(src); | 
 | 183 |  | 
 | 184 |   T.CheckCall(T.Val("-A-B-")); | 
 | 185 | } | 
 | 186 |  | 
 | 187 |  | 
 | 188 | TEST(FinallyBreak) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 189 |   const char* src = | 
 | 190 |       "(function(a,b) {" | 
 | 191 |       "  var r = '-';" | 
 | 192 |       "  L: try {" | 
 | 193 |       "    r += 'A-';" | 
 | 194 |       "    if (a) return r;" | 
 | 195 |       "    r += 'B-';" | 
 | 196 |       "    if (b) break L;" | 
 | 197 |       "    r += 'C-';" | 
 | 198 |       "  } finally {" | 
 | 199 |       "    r += 'D-';" | 
 | 200 |       "  }" | 
 | 201 |       "  return r;" | 
 | 202 |       "})"; | 
 | 203 |   FunctionTester T(src); | 
 | 204 |  | 
 | 205 |   T.CheckCall(T.Val("-A-"), T.true_value(), T.false_value()); | 
 | 206 |   T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value()); | 
 | 207 |   T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value()); | 
 | 208 | } | 
 | 209 |  | 
 | 210 |  | 
 | 211 | TEST(DeoptTry) { | 
 | 212 |   const char* src = | 
 | 213 |       "(function f(a) {" | 
 | 214 |       "  try {" | 
 | 215 |       "    %DeoptimizeFunction(f);" | 
 | 216 |       "    throw a;" | 
 | 217 |       "  } catch (e) {" | 
 | 218 |       "    return e + 1;" | 
 | 219 |       "  }" | 
 | 220 |       "})"; | 
 | 221 |   FunctionTester T(src); | 
 | 222 |  | 
 | 223 |   T.CheckCall(T.Val(2), T.Val(1)); | 
 | 224 | } | 
 | 225 |  | 
 | 226 |  | 
 | 227 | TEST(DeoptCatch) { | 
 | 228 |   const char* src = | 
 | 229 |       "(function f(a) {" | 
 | 230 |       "  try {" | 
 | 231 |       "    throw a;" | 
 | 232 |       "  } catch (e) {" | 
 | 233 |       "    %DeoptimizeFunction(f);" | 
 | 234 |       "    return e + 1;" | 
 | 235 |       "  }" | 
 | 236 |       "})"; | 
 | 237 |   FunctionTester T(src); | 
 | 238 |  | 
 | 239 |   T.CheckCall(T.Val(2), T.Val(1)); | 
 | 240 | } | 
 | 241 |  | 
 | 242 |  | 
 | 243 | TEST(DeoptFinallyReturn) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 244 |   const char* src = | 
 | 245 |       "(function f(a) {" | 
 | 246 |       "  try {" | 
 | 247 |       "    throw a;" | 
 | 248 |       "  } finally {" | 
 | 249 |       "    %DeoptimizeFunction(f);" | 
 | 250 |       "    return a + 1;" | 
 | 251 |       "  }" | 
 | 252 |       "})"; | 
 | 253 |   FunctionTester T(src); | 
 | 254 |  | 
 | 255 |   T.CheckCall(T.Val(2), T.Val(1)); | 
 | 256 | } | 
 | 257 |  | 
 | 258 |  | 
 | 259 | TEST(DeoptFinallyReThrow) { | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 260 |   const char* src = | 
 | 261 |       "(function f(a) {" | 
 | 262 |       "  try {" | 
 | 263 |       "    throw a;" | 
 | 264 |       "  } finally {" | 
 | 265 |       "    %DeoptimizeFunction(f);" | 
 | 266 |       "  }" | 
 | 267 |       "})"; | 
 | 268 |   FunctionTester T(src); | 
 | 269 |  | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 270 |   T.CheckThrows(T.NewObject("new Error"), T.Val(1)); | 
| Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 271 | } | 
 | 272 |  | 
 | 273 | }  // namespace compiler | 
 | 274 | }  // namespace internal | 
 | 275 | }  // namespace v8 |