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 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
TEST(Catch)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
TEST(CatchNested)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
TEST(CatchBreak)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
TEST(CatchCall)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
TEST(Finally)171 TEST(Finally) {
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
TEST(FinallyBreak)188 TEST(FinallyBreak) {
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
TEST(DeoptTry)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
TEST(DeoptCatch)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
TEST(DeoptFinallyReturn)243 TEST(DeoptFinallyReturn) {
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
TEST(DeoptFinallyReThrow)259 TEST(DeoptFinallyReThrow) {
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
270 T.CheckThrows(T.NewObject("new Error"), T.Val(1));
271 }
272
273 } // namespace compiler
274 } // namespace internal
275 } // namespace v8
276