1// 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 6// Flags: --harmony-do-expressions --harmony-async-await 7"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(); } }`, 131 err: ` ^^^^^`, 132 }, 133 { src: `()=>{ function* G() { return continue foo(); } }`, 134 err: ` ^^^^^`, 135 }, 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 }, 241 { src: `async() => continue foo()`, 242 err: ` ^^^^^`, 243 }, 244 ], 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() ; }`, 320 `()=>{ 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})(); 394