• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(Throw)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 
TEST(ThrowMessagePosition)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 
TEST(ThrowMessageDirectly)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 
TEST(ThrowMessageIndirectly)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 
TEST(Catch)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 
TEST(CatchNested)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 
TEST(CatchBreak)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 
TEST(CatchCall)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 
TEST(Finally)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 
TEST(FinallyBreak)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 
TEST(DeoptTry)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 
TEST(DeoptCatch)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 
TEST(DeoptFinallyReturn)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 
TEST(DeoptFinallyReThrow)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