blob: 486c3e1da6e29a62e94cbd20e8230a9b09111f4f [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// Copyright 2016 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// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
Ben Murdoch61f157c2016-09-16 13:49:30 +01006// Flags: --harmony-do-expressions --harmony-async-await
Ben Murdochc5610432016-08-08 18:44:38 +01007"use strict";
8
9var SyntaxErrorTests = [
10 { msg: "Unexpected expression inside tail call",
11 tests: [
12 { src: `()=>{ return continue foo ; }`,
13 err: ` ^^^`,
14 },
15 { src: `()=>{ return continue 42 ; }`,
16 err: ` ^^`,
17 },
18 { src: `()=>{ return continue new foo () ; }`,
19 err: ` ^^^^^^^^^^`,
20 },
21 { src: `()=>{ loop: return continue loop ; }`,
22 err: ` ^^^^`,
23 },
24 { src: `class A { foo() { return continue super.x ; } }`,
25 err: ` ^^^^^^^`,
26 },
27 { src: `()=>{ return continue this ; }`,
28 err: ` ^^^^`,
29 },
30 { src: `()=>{ return continue class A {} ; }`,
31 err: ` ^^^^^^^^^^`,
32 },
33 { src: `()=>{ return continue class A extends B {} ; }`,
34 err: ` ^^^^^^^^^^^^^^^^^^^^`,
35 },
36 { src: `()=>{ return continue function A() { } ; }`,
37 err: ` ^^^^^^^^^^^^^^^^`,
38 },
39 { src: `()=>{ return continue { a: b, c: d} ; }`,
40 err: ` ^^^^^^^^^^^^^`,
41 },
42 { src: `()=>{ return continue function* Gen() { yield 1; } ; }`,
43 err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
44 },
45 { src: `function A() { return continue new.target ; }`,
46 err: ` ^^^^^^^^^^`,
47 },
48 { src: `()=>{ return continue () ; }`,
49 err: ` ^^`,
50 },
51 { src: `()=>{ return continue ( 42 ) ; }`,
52 err: ` ^^^^^^`,
53 },
54 { src: "()=>{ return continue `123 ${foo} 34lk` ; }",
55 err: ` ^^^^^^^^^^^^^^^^^`,
56 },
57 { src: `()=>{ return continue do { x ? foo() : bar() ; } }`,
58 err: ` ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
59 },
60 ],
61 },
62 { msg: "Tail call expression is not allowed here",
63 tests: [
64 { src: `()=>{ return continue continue continue b() ; }`,
65 err: ` ^^^^^^^^^^^^`,
66 },
67 { src: `()=>{ return continue ( continue b() ) ; }`,
68 err: ` ^^^^^^^^^^^^`,
69 },
70 { src: `()=>{ return continue f() - a ; }`,
71 err: ` ^^^^^^^^^^^^^`,
72 },
73 { src: `()=>{ return b + continue f() ; }`,
74 err: ` ^^^^^^^^^^^^^^`,
75 },
76 { src: `()=>{ return 1, 2, 3, continue f() , 4 ; }`,
77 err: ` ^^^^^^^^^^^^^`,
78 },
79 { src: `()=>{ var x = continue f ( ) ; }`,
80 err: ` ^^^^^^^^^^^^^^^`,
81 },
82 { src: `()=>{ return continue f () ? 1 : 2 ; }`,
83 err: ` ^^^^^^^^^^^^^`,
84 },
85 { src: `()=>{ return (1, 2, 3, continue f()), 4; }`,
86 err: ` ^^^^^^^^^^^^`,
87 },
88 { src: `()=>{ return [1, 2, continue f() ] ; }`,
89 err: ` ^^^^^^^^^^^^`,
90 },
91 { src: `()=>{ return [1, 2, ... continue f() ] ; }`,
92 err: ` ^^^^^^^^^^^^`,
93 },
94 { src: `()=>{ return [1, 2, continue f(), 3 ] ; }`,
95 err: ` ^^^^^^^^^^^^`,
96 },
97 { src: "()=>{ return `123 ${a} ${ continue foo ( ) } 34lk` ; }",
98 err: ` ^^^^^^^^^^^^^^^^`,
99 },
100 { src: `()=>{ return g( 1, 2, continue f() ); }`,
101 err: ` ^^^^^^^^^^^^`,
102 },
103 { src: `()=>{ return continue f() || a; }`,
104 err: ` ^^^^^^^^^^^^`,
105 },
106 { src: `()=>{ return a || b || c || continue f() || d; }`,
107 err: ` ^^^^^^^^^^^^`,
108 },
109 { src: `()=>{ return a && b && c && continue f() && d; }`,
110 err: ` ^^^^^^^^^^^^`,
111 },
112 { src: `()=>{ return a && b || c && continue f() ? d : e; }`,
113 err: ` ^^^^^^^^^^^^`,
114 },
115 { src: `()=>{ return a ? b : c && continue f() && d || e; }`,
116 err: ` ^^^^^^^^^^^^`,
117 },
118 { src: `()=>{ return continue foo() instanceof bar ; }`,
119 err: ` ^^^^^^^^^^^^^^`,
120 },
121 { src: `()=>{ return bar instanceof continue foo() ; }`,
122 err: ` ^^^^^^^^^^^^^^`,
123 },
124 { src: `()=>{ return continue foo() in bar ; }`,
125 err: ` ^^^^^^^^^^^^^^`,
126 },
127 { src: `()=>{ return bar in continue foo() ; }`,
128 err: ` ^^^^^^^^^^^^^^`,
129 },
130 { src: `()=>{ function* G() { yield continue foo(); } }`,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100131 err: ` ^^^^^`,
132 },
133 { src: `()=>{ function* G() { return continue foo(); } }`,
134 err: ` ^^^^^`,
Ben Murdochc5610432016-08-08 18:44:38 +0100135 },
136 { src: `()=>{ (1, 2, 3, continue f() ) => {} }`,
137 err: ` ^^^^^^^^^^^^`,
138 },
139 { src: `()=>{ (... continue f()) => {} }`,
140 err: ` ^^^^^^^^^^^^`,
141 },
142 { src: `()=>{ (a, b, c, ... continue f() ) => {} }`,
143 err: ` ^^^^^^^^^^^^`,
144 },
145 { src: `()=>{ return a <= continue f(); }`,
146 err: ` ^^^^^^^^^^^^`,
147 },
148 { src: `()=>{ return b > continue f(); }`,
149 err: ` ^^^^^^^^^^^^`,
150 },
151 { src: `()=>{ return a << continue f(); }`,
152 err: ` ^^^^^^^^^^^^`,
153 },
154 { src: `()=>{ return b >> continue f(); }`,
155 err: ` ^^^^^^^^^^^^`,
156 },
157 { src: `()=>{ return c >>> continue f(); }`,
158 err: ` ^^^^^^^^^^^^`,
159 },
160 { src: `()=>{ return continue f() = a ; }`,
161 err: ` ^^^^^^^^^^^^`,
162 },
163 { src: `()=>{ return a = continue f() ; }`,
164 err: ` ^^^^^^^^^^^^`,
165 },
166 { src: `()=>{ return a += continue f(); }`,
167 err: ` ^^^^^^^^^^^^`,
168 },
169 { src: `()=>{ return a ** continue f() ; }`,
170 err: ` ^^^^^^^^^^^^`,
171 },
172 { src: `()=>{ return delete continue foo() ; }`,
173 err: ` ^^^^^^^^^^^^^^`,
174 },
175 { src: `()=>{ typeof continue foo() ; }`,
176 err: ` ^^^^^^^^^^^^^^`,
177 },
178 { src: `()=>{ return ~ continue foo() ; }`,
179 err: ` ^^^^^^^^^^^^^^`,
180 },
181 { src: `()=>{ return void continue foo() ; }`,
182 err: ` ^^^^^^^^^^^^^^`,
183 },
184 { src: `()=>{ return !continue foo() ; }`,
185 err: ` ^^^^^^^^^^^^^^`,
186 },
187 { src: `()=>{ return -continue foo() ; }`,
188 err: ` ^^^^^^^^^^^^^^`,
189 },
190 { src: `()=>{ return +continue foo() ; }`,
191 err: ` ^^^^^^^^^^^^^^`,
192 },
193 { src: `()=>{ return ++ continue f( ) ; }`,
194 err: ` ^^^^^^^^^^^^^`,
195 },
196 { src: `()=>{ return continue f() ++; }`,
197 err: ` ^^^^^^^^^^^^`,
198 },
199 { src: `()=>{ return continue f() --; }`,
200 err: ` ^^^^^^^^^^^^`,
201 },
202 { src: `()=>{ return (continue foo()) () ; }`,
203 err: ` ^^^^^^^^^^^^^^`,
204 },
205 { src: `()=>{ for (var i = continue foo(); i < 10; i++) bar(); }`,
206 err: ` ^^^^^^^^^^^^^^`,
207 },
208 { src: `()=>{ for (var i = 0; i < continue foo(); i++) bar(); }`,
209 err: ` ^^^^^^^^^^^^^^`,
210 },
211 { src: `()=>{ for (var i = 0; i < 10; continue foo()) bar(); }`,
212 err: ` ^^^^^^^^^^^^^^`,
213 },
214 { src: `()=>{ if (continue foo()) bar(); }`,
215 err: ` ^^^^^^^^^^^^^^`,
216 },
217 { src: `()=>{ while (continue foo()) bar(); }`,
218 err: ` ^^^^^^^^^^^^^^`,
219 },
220 { src: `()=>{ do { smth; } while (continue foo()) ; }`,
221 err: ` ^^^^^^^^^^^^^^`,
222 },
223 { src: `()=>{ throw continue foo() ; }`,
224 err: ` ^^^^^^^^^^^^^^`,
225 },
226 { src: `()=>{ switch (continue foo()) { case 1: break; } ; }`,
227 err: ` ^^^^^^^^^^^^^^`,
228 },
229 { src: `()=>{ let x = continue foo() }`,
230 err: ` ^^^^^^^^^^^^^^`,
231 },
232 { src: `()=>{ const c = continue foo() }`,
233 err: ` ^^^^^^^^^^^^^^^`,
234 },
235 { src: `class A {}; class B extends A { constructor() { return continue foo () ; } }`,
236 err: ` ^^^^^^^^^^^^^^^`,
237 },
238 { src: `class A extends continue f () {}; }`,
239 err: ` ^^^^^^^^^^^^^`,
240 },
Ben Murdoch61f157c2016-09-16 13:49:30 +0100241 { src: `async() => continue foo()`,
242 err: ` ^^^^^`,
243 },
Ben Murdochc5610432016-08-08 18:44:38 +0100244 ],
245 },
246 { msg: "Tail call expression in try block",
247 tests: [
248 { src: `()=>{ try { return continue f ( ) ; } catch(e) {} }`,
249 err: ` ^^^^^^^^^^^^^^^^`,
250 },
251 { src: `()=>{ try { try { smth; } catch(e) { return continue f( ) ; } }`,
252 err: ` ^^^^^^^^^^^^^^`,
253 },
254 { src: `()=>{ try { try { smth; } catch(e) { return continue f( ) ; } } finally { bla; } }`,
255 err: ` ^^^^^^^^^^^^^^`,
256 },
257 ],
258 },
259 { msg: "Tail call expression in catch block when finally block is also present",
260 tests: [
261 { src: `()=>{ try { smth; } catch(e) { return continue f ( ) ; } finally { blah; } }`,
262 err: ` ^^^^^^^^^^^^^^^^`,
263 },
264 { src: `()=>{ try { smth; } catch(e) { try { smth; } catch (e) { return continue f ( ) ; } } finally { blah; } }`,
265 err: ` ^^^^^^^^^^^^^^^^`,
266 },
267 ],
268 },
269 { msg: "Tail call expression in for-in/of body",
270 tests: [
271 { src: `()=>{ for (var v in {a:0}) { return continue foo () ; } }`,
272 err: ` ^^^^^^^^^^^^^^^^`,
273 },
274 { src: `()=>{ for (var v of [1, 2, 3]) { return continue foo () ; } }`,
275 err: ` ^^^^^^^^^^^^^^^^`,
276 },
277 ],
278 },
279 { msg: "Tail call of a direct eval is not allowed",
280 tests: [
281 { src: `()=>{ return continue eval(" foo () " ) ; }`,
282 err: ` ^^^^^^^^^^^^^^^^^`,
283 },
284 { src: `()=>{ return a || continue eval("", 1, 2) ; }`,
285 err: ` ^^^^^^^^^^^^^^`,
286 },
287 { src: `()=>{ return a, continue eval ( ) ; }`,
288 err: ` ^^^^^^^^^`,
289 },
290 { src: `()=> a, continue eval ( ) ; `,
291 err: ` ^^^^^^^^^`,
292 },
293 { src: `()=> a || continue eval (' ' ) ; `,
294 err: ` ^^^^^^^^^^^^`,
295 },
296 ],
297 },
298 { msg: "Undefined label 'foo'",
299 tests: [
300 { src: `()=>{ continue foo () ; }`,
301 err: ` ^^^`,
302 },
303 ],
304 },
305];
306
307
308// Should parse successfully.
309var NoErrorTests = [
310 `()=>{ return continue a.b.c.foo () ; }`,
311 `()=>{ return continue a().b.c().d.foo () ; }`,
312 `()=>{ return continue foo (1)(2)(3, 4) ; }`,
313 `()=>{ return continue (0, eval)(); }`,
314 `()=>{ return ( continue b() ) ; }`,
315 "()=>{ return continue bar`ab cd ef` ; }",
316 "()=>{ return continue bar`ab ${cd} ef` ; }",
317 `()=>{ return a || continue f() ; }`,
318 `()=>{ return a && continue f() ; }`,
319 `()=>{ return a , continue f() ; }`,
Ben Murdochc5610432016-08-08 18:44:38 +0100320 `()=>{ class A { foo() { return continue super.f() ; } } }`,
321 `()=>{ function B() { return continue new.target() ; } }`,
322 `()=>{ return continue do { x ? foo() : bar() ; }() }`,
323 `()=>{ return continue (do { x ? foo() : bar() ; })() }`,
324 `()=>{ return do { 1, continue foo() } }`,
325 `()=>{ return do { x ? continue foo() : y } }`,
326 `()=>{ return a || (b && continue c()); }`,
327 `()=>{ return a && (b || continue c()); }`,
328 `()=>{ return a || (b ? c : continue d()); }`,
329 `()=>{ return 1, 2, 3, a || (b ? c : continue d()); }`,
330 `()=> continue (foo ()) ;`,
331 `()=> a || continue foo () ;`,
332 `()=> a && continue foo () ;`,
333 `()=> a ? continue foo () : b;`,
334];
335
336
337(function() {
338 for (var test_set of SyntaxErrorTests) {
339 var expected_message = "SyntaxError: " + test_set.msg;
340 for (var test of test_set.tests) {
341 var passed = true;
342 var e = null;
343 try {
344 eval(test.src);
345 } catch (ee) {
346 e = ee;
347 }
348 print("=======================================");
349 print("Expected | " + expected_message);
350 print("Source | " + test.src);
351 print(" | " + test.err);
352
353 if (e === null) {
354 print("FAILED");
355 throw new Error("SyntaxError was not thrown");
356 }
357
358 var details = %GetExceptionDetails(e);
359 if (details.start_pos == undefined ||
360 details.end_pos == undefined) {
361 throw new Error("Bad message object returned");
362 }
363 var underline = " ".repeat(details.start_pos) +
364 "^".repeat(details.end_pos - details.start_pos);
365 var passed = expected_message === e.toString() &&
366 test.err === underline;
367
368 if (passed) {
369 print("PASSED");
370 print();
371 } else {
372 print("---------------------------------------");
373 print("Actual | " + e);
374 print("Source | " + test.src);
375 print(" | " + underline);
376 print("FAILED");
377 throw new Error("Test failed");
378 }
379 }
380 }
381})();
382
383
384(function() {
385 for (var src of NoErrorTests) {
386 print("=======================================");
387 print("Source | " + src);
388 src = `"use strict"; ` + src;
389 Realm.eval(0, src);
390 print("PASSED");
391 print();
392 }
393})();