1// Copyright 2013 the V8 project authors. All rights reserved. 2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions 6// are met: 7// 1. Redistributions of source code must retain the above copyright 8// notice, this list of conditions and the following disclaimer. 9// 2. Redistributions in binary form must reproduce the above copyright 10// notice, this list of conditions and the following disclaimer in the 11// documentation and/or other materials provided with the distribution. 12// 13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24description( 25"This test checks that the following expressions or statements are valid ECMASCRIPT code or should throw parse error" 26); 27 28function runTest(_a, errorType) 29{ 30 var success; 31 if (typeof _a != "string") 32 testFailed("runTest expects string argument: " + _a); 33 try { 34 eval(_a); 35 success = true; 36 } catch (e) { 37 success = !(e instanceof SyntaxError); 38 } 39 if ((!!errorType) == !success) { 40 if (errorType) 41 testPassed('Invalid: "' + _a + '"'); 42 else 43 testPassed('Valid: "' + _a + '"'); 44 } else { 45 if (errorType) 46 testFailed('Invalid: "' + _a + '" should throw ' + errorType.name); 47 else 48 testFailed('Valid: "' + _a + '" should NOT throw '); 49 } 50} 51 52function valid(_a) 53{ 54 // Test both the grammar and the syntax checker 55 runTest(_a, false); 56 runTest("function f() { " + _a + " }", false); 57} 58 59function invalid(_a, _type) 60{ 61 _type = _type || SyntaxError; 62 // Test both the grammar and the syntax checker 63 runTest(_a, true); 64 runTest("function f() { " + _a + " }", true); 65} 66 67// known issue: 68// some statements requires statement as argument, and 69// it seems the End-Of-File terminator is converted to semicolon 70// "a:[EOF]" is not parse error, while "{ a: }" is parse error 71// "if (a)[EOF]" is not parse error, while "{ if (a) }" is parse error 72// known issues of bison parser: 73// accepts: 'function f() { return 6 + }' (only inside a function declaration) 74// some comma expressions: see reparsing-semicolon-insertion.js 75 76debug ("Unary operators and member access"); 77 78valid (""); 79invalid("(a"); 80invalid("a[5"); 81invalid("a[5 + 6"); 82invalid("a."); 83invalid("()"); 84invalid("a.'l'"); 85valid ("a: +~!new a"); 86invalid("new -a"); 87valid ("new (-1)") 88valid ("a: b: c: new f(x++)++") 89valid ("(a)++"); 90valid ("(1--).x"); 91invalid("a-- ++"); 92invalid("(a:) --b"); 93valid ("++ -- ++ a"); 94valid ("++ new new a ++"); 95valid ("delete void 0"); 96invalid("delete the void"); 97invalid("(a++"); 98valid ("++a--"); 99valid ("++((a))--"); 100valid ("(a.x++)++"); 101invalid("1: null"); 102invalid("+-!~"); 103invalid("+-!~(("); 104invalid("a)"); 105invalid("a]"); 106invalid(".l"); 107invalid("1.l"); 108valid ("1 .l"); 109 110debug ("Binary and conditional operators"); 111 112valid ("a + + typeof this"); 113invalid("a + * b"); 114invalid("a ? b"); 115invalid("a ? b :"); 116invalid("%a"); 117invalid("a-"); 118valid ("a = b ? b = c : d = e"); 119valid ("s: a[1].l ? b.l['s'] ? c++ : d : true"); 120valid ("a ? b + 1 ? c + 3 * d.l : d[5][6] : e"); 121valid ("a in b instanceof delete -c"); 122invalid("a in instanceof b.l"); 123valid ("- - true % 5"); 124invalid("- false = 3"); 125valid ("a: b: c: (1 + null) = 3"); 126valid ("a[2] = b.l += c /= 4 * 7 ^ !6"); 127invalid("a + typeof b += c in d"); 128invalid("typeof a &= typeof b"); 129valid ("a: ((typeof (a))) >>>= a || b.l && c"); 130valid ("a: b: c[a /= f[a %= b]].l[c[x] = 7] -= a ? b <<= f : g"); 131valid ("-void+x['y'].l == x.l != 5 - f[7]"); 132 133debug ("Function calls (and new with arguments)"); 134 135valid ("a()()()"); 136valid ("s: l: a[2](4 == 6, 5 = 6)(f[4], 6)"); 137valid ("s: eval(a.apply(), b.call(c[5] - f[7]))"); 138invalid("a("); 139invalid("a(5"); 140invalid("a(5,"); 141invalid("a(5,)"); 142invalid("a(5,6"); 143valid ("a(b[7], c <d> e.l, new a() > b)"); 144invalid("a(b[5)"); 145invalid("a(b.)"); 146valid ("~new new a(1)(i++)(c[l])"); 147invalid("a(*a)"); 148valid ("((((a))((b)()).l))()"); 149valid ("(a)[b + (c) / (d())].l--"); 150valid ("new (5)"); 151invalid("new a(5"); 152valid ("new (f + 5)(6, (g)() - 'l'() - true(false))"); 153invalid("a(.length)"); 154 155debug ("function declaration and expression"); 156 157valid ("function f() {}"); 158valid ("function f(a,b) {}"); 159invalid("function () {}"); 160invalid("function f(a b) {}"); 161invalid("function f(a,) {}"); 162invalid("function f(a,"); 163invalid("function f(a, 1) {}"); 164valid ("function g(arguments, eval) {}"); 165valid ("function f() {} + function g() {}"); 166invalid("(function a{})"); 167invalid("(function this(){})"); 168valid ("(delete new function f(){} + function(a,b){}(5)(6))"); 169valid ("6 - function (m) { function g() {} }"); 170invalid("function l() {"); 171invalid("function l++(){}"); 172 173debug ("Array and object literal, comma operator"); 174 175// Note these are tested elsewhere, no need to repeat those tests here 176valid ("[] in [5,6] * [,5,] / [,,5,,] || [a,] && new [,b] % [,,]"); 177invalid("[5,"); 178invalid("[,"); 179invalid("(a,)"); 180valid ("1 + {get get(){}, set set(a){}, get1:4, set1:get-set, }"); 181invalid("1 + {a"); 182invalid("1 + {a:"); 183invalid("1 + {get l("); 184invalid(",a"); 185valid ("(4,(5,a(3,4))),f[4,a-6]"); 186invalid("(,f)"); 187invalid("a,,b"); 188invalid("a ? b, c : d"); 189 190debug ("simple statements"); 191 192valid ("{ }"); 193invalid("{ { }"); 194valid ("{ ; ; ; }"); 195valid ("a: { ; }"); 196invalid("{ a: }"); 197valid ("{} f; { 6 + f() }"); 198valid ("{ a[5],6; {} ++b-new (-5)() } c().l++"); 199valid ("{ l1: l2: l3: { this } a = 32 ; { i++ ; { { { } } ++i } } }"); 200valid ("if (a) ;"); 201invalid("{ if (a) }"); 202invalid("if a {}"); 203invalid("if (a"); 204invalid("if (a { }"); 205valid ("x: s: if (a) ; else b"); 206invalid("else {}"); 207valid ("if (a) if (b) y; else {} else ;"); 208invalid("if (a) {} else x; else"); 209invalid("if (a) { else }"); 210valid ("if (a.l + new b()) 4 + 5 - f()"); 211valid ("if (a) with (x) ; else with (y) ;"); 212invalid("with a.b { }"); 213valid ("while (a() - new b) ;"); 214invalid("while a {}"); 215valid ("do ; while(0) i++"); // Is this REALLY valid? (Firefox also accepts this) 216valid ("do if (a) x; else y; while(z)"); 217invalid("do g; while 4"); 218invalid("do g; while ((4)"); 219valid ("{ { do do do ; while(0) while(0) while(0) } }"); 220valid ("do while (0) if (a) {} else y; while(0)"); 221valid ("if (a) while (b) if (c) with(d) {} else e; else f"); 222invalid("break ; break your_limits ; continue ; continue living ; debugger"); 223invalid("debugger X"); 224invalid("break 0.2"); 225invalid("continue a++"); 226invalid("continue (my_friend)"); 227valid ("while (1) break"); 228valid ("do if (a) with (b) continue; else debugger; while (false)"); 229invalid("do if (a) while (false) else debugger"); 230invalid("while if (a) ;"); 231valid ("if (a) function f() {} else function g() {}"); 232valid ("if (a()) while(0) function f() {} else function g() {}"); 233invalid("if (a()) function f() { else function g() }"); 234invalid("if (a) if (b) ; else function f {}"); 235invalid("if (a) if (b) ; else function (){}"); 236valid ("throw a"); 237valid ("throw a + b in void c"); 238invalid("throw"); 239 240debug ("var and const statements"); 241 242valid ("var a, b = null"); 243valid ("const a = 5, b, c"); 244invalid("var"); 245invalid("var = 7"); 246invalid("var c (6)"); 247valid ("if (a) var a,b; else const b, c"); 248invalid("var 5 = 6"); 249valid ("while (0) var a, b, c=6, d, e, f=5*6, g=f*h, h"); 250invalid("var a = if (b) { c }"); 251invalid("var a = var b"); 252valid ("const a = b += c, a, a, a = (b - f())"); 253invalid("var a %= b | 5"); 254invalid("var (a) = 5"); 255invalid("var a = (4, b = 6"); 256invalid("const 'l' = 3"); 257invalid("var var = 3"); 258valid ("var varr = 3 in 1"); 259valid ("const a, a, a = void 7 - typeof 8, a = 8"); 260valid ("const x_x = 6 /= 7 ? e : f"); 261invalid("var a = ?"); 262invalid("const a = *7"); 263invalid("var a = :)"); 264valid ("var a = a in b in c instanceof d"); 265invalid("var a = b ? c, b"); 266invalid("const a = b : c"); 267 268debug ("for statement"); 269 270valid ("for ( ; ; ) { break }"); 271valid ("for ( a ; ; ) { break }"); 272valid ("for ( ; a ; ) { break }"); 273valid ("for ( ; ; a ) { break }"); 274valid ("for ( a ; a ; ) break"); 275valid ("for ( a ; ; a ) break"); 276valid ("for ( ; a ; a ) break"); 277invalid("for () { }"); 278invalid("for ( a ) { }"); 279invalid("for ( ; ) ;"); 280invalid("for a ; b ; c { }"); 281invalid("for (a ; { }"); 282invalid("for ( a ; ) ;"); 283invalid("for ( ; a ) break"); 284valid ("for (var a, b ; ; ) { break } "); 285valid ("for (var a = b, b = a ; ; ) break"); 286valid ("for (var a = b, c, d, b = a ; x in b ; ) { break }"); 287valid ("for (var a = b, c, d ; ; 1 in a()) break"); 288invalid("for ( ; var a ; ) break"); 289invalid("for (const a; ; ) break"); 290invalid("for ( %a ; ; ) { }"); 291valid ("for (a in b) break"); 292valid ("for (a() in b) break"); 293valid ("for (a().l[4] in b) break"); 294valid ("for (new a in b in c in d) break"); 295valid ("for (new new new a in b) break"); 296invalid("for (delete new a() in b) break"); 297invalid("for (a * a in b) break"); 298valid ("for ((a * a) in b) break"); 299invalid("for (a++ in b) break"); 300valid ("for ((a++) in b) break"); 301invalid("for (++a in b) break"); 302valid ("for ((++a) in b) break"); 303invalid("for (a, b in c) break"); 304invalid("for (a,b in c ;;) break"); 305valid ("for (a,(b in c) ;;) break"); 306valid ("for ((a, b) in c) break"); 307invalid("for (a ? b : c in c) break"); 308valid ("for ((a ? b : c) in c) break"); 309valid ("for (var a in b in c) break"); 310valid ("for (var a = 5 += 6 in b) break"); 311invalid("for (var a += 5 in b) break"); 312invalid("for (var a = in b) break"); 313invalid("for (var a, b in b) break"); 314invalid("for (var a = -6, b in b) break"); 315invalid("for (var a, b = 8 in b) break"); 316valid ("for (var a = (b in c) in d) break"); 317invalid("for (var a = (b in c in d) break"); 318invalid("for (var (a) in b) { }"); 319valid ("for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}"); 320 321debug ("try statement"); 322 323invalid("try { break } catch(e) {}"); 324valid ("try {} finally { c++ }"); 325valid ("try { with (x) { } } catch(e) {} finally { if (a) ; }"); 326invalid("try {}"); 327invalid("catch(e) {}"); 328invalid("finally {}"); 329invalid("try a; catch(e) {}"); 330invalid("try {} catch(e) a()"); 331invalid("try {} finally a()"); 332invalid("try {} catch(e)"); 333invalid("try {} finally"); 334invalid("try {} finally {} catch(e) {}"); 335invalid("try {} catch (...) {}"); 336invalid("try {} catch {}"); 337valid ("if (a) try {} finally {} else b;"); 338valid ("if (--a()) do with(1) try {} catch(ke) { f() ; g() } while (a in b) else {}"); 339invalid("if (a) try {} else b; catch (e) { }"); 340invalid("try { finally {}"); 341 342debug ("switch statement"); 343 344valid ("switch (a) {}"); 345invalid("switch () {}"); 346invalid("case 5:"); 347invalid("default:"); 348invalid("switch (a) b;"); 349invalid("switch (a) case 3: b;"); 350valid ("switch (f()) { case 5 * f(): default: case '6' - 9: ++i }"); 351invalid("switch (true) { default: case 6: default: }"); 352invalid("switch (l) { f(); }"); 353invalid("switch (l) { case 1: ; a: case 5: }"); 354valid ("switch (g() - h[5].l) { case 1 + 6: a: b: c: ++f }"); 355invalid("switch (g) { case 1: a: }"); 356invalid("switch (g) { case 1: a: default: }"); 357invalid("switch g { case 1: l() }"); 358invalid("switch (g) { case 1:"); 359valid ("switch (l) { case a = b ? c : d : }"); 360valid ("switch (sw) { case a ? b - 7[1] ? [c,,] : d = 6 : { } : }"); 361invalid("switch (l) { case b ? c : }"); 362valid ("switch (l) { case 1: a: with(g) switch (g) { case 2: default: } default: }"); 363invalid("switch (4 - ) { }"); 364invalid("switch (l) { default case: 5; }"); 365 366invalid("L: L: ;"); 367invalid("L: L1: L: ;"); 368invalid("L: L1: L2: L3: L4: L: ;"); 369 370invalid("for(var a,b 'this shouldn\'t be allowed' false ; ) ;"); 371invalid("for(var a,b '"); 372 373valid("function __proto__(){}") 374valid("(function __proto__(){})") 375valid("'use strict'; function __proto__(){}") 376valid("'use strict'; (function __proto__(){})") 377 378valid("if (0) $foo; ") 379valid("if (0) _foo; ") 380valid("if (0) foo$; ") 381valid("if (0) foo_; ") 382valid("if (0) obj.$foo; ") 383valid("if (0) obj._foo; ") 384valid("if (0) obj.foo$; ") 385valid("if (0) obj.foo_; ") 386valid("if (0) obj.foo\\u03bb; ") 387valid("if (0) new a(b+c).d = 5"); 388valid("if (0) new a(b+c) = 5"); 389valid("([1 || 1].a = 1)"); 390valid("({a: 1 || 1}.a = 1)"); 391 392invalid("var a.b = c"); 393invalid("var a.b;"); 394 395try { eval("a.b.c = {};"); } catch(e1) { e=e1; shouldBe("e.line", "1") } 396foo = 'FAIL'; 397bar = 'PASS'; 398try { 399 eval("foo = 'PASS'; a.b.c = {}; bar = 'FAIL';"); 400} catch(e) { 401 shouldBe("foo", "'PASS'"); 402 shouldBe("bar", "'PASS'"); 403} 404