Home | History | Annotate | Download | only in js
      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 
     24 description(
     25 "This test checks that the following expressions or statements are valid ECMASCRIPT code or should throw parse error"
     26 );
     27 
     28 function 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 
     52 function valid(_a)
     53 {
     54     // Test both the grammar and the syntax checker
     55     runTest(_a, false);
     56     runTest("function f() { " + _a + " }", false);
     57 }
     58 
     59 function 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 
     76 debug  ("Unary operators and member access");
     77 
     78 valid  ("");
     79 invalid("(a");
     80 invalid("a[5");
     81 invalid("a[5 + 6");
     82 invalid("a.");
     83 invalid("()");
     84 invalid("a.'l'");
     85 valid  ("a: +~!new a");
     86 invalid("new -a");
     87 valid  ("new (-1)")
     88 valid  ("a: b: c: new f(x++)++")
     89 valid  ("(a)++");
     90 valid  ("(1--).x");
     91 invalid("a-- ++");
     92 invalid("(a:) --b");
     93 valid  ("++ -- ++ a");
     94 valid  ("++ new new a ++");
     95 valid  ("delete void 0");
     96 invalid("delete the void");
     97 invalid("(a++");
     98 valid  ("++a--");
     99 valid  ("++((a))--");
    100 valid  ("(a.x++)++");
    101 invalid("1: null");
    102 invalid("+-!~");
    103 invalid("+-!~((");
    104 invalid("a)");
    105 invalid("a]");
    106 invalid(".l");
    107 invalid("1.l");
    108 valid  ("1 .l");
    109 
    110 debug  ("Binary and conditional operators");
    111 
    112 valid  ("a + + typeof this");
    113 invalid("a + * b");
    114 invalid("a ? b");
    115 invalid("a ? b :");
    116 invalid("%a");
    117 invalid("a-");
    118 valid  ("a = b ? b = c : d = e");
    119 valid  ("s: a[1].l ? b.l['s'] ? c++ : d : true");
    120 valid  ("a ? b + 1 ? c + 3 * d.l : d[5][6] : e");
    121 valid  ("a in b instanceof delete -c");
    122 invalid("a in instanceof b.l");
    123 valid  ("- - true % 5");
    124 invalid("- false = 3");
    125 valid  ("a: b: c: (1 + null) = 3");
    126 valid  ("a[2] = b.l += c /= 4 * 7 ^ !6");
    127 invalid("a + typeof b += c in d");
    128 invalid("typeof a &= typeof b");
    129 valid  ("a: ((typeof (a))) >>>= a || b.l && c");
    130 valid  ("a: b: c[a /= f[a %= b]].l[c[x] = 7] -= a ? b <<= f : g");
    131 valid  ("-void+x['y'].l == x.l != 5 - f[7]");
    132 
    133 debug  ("Function calls (and new with arguments)");
    134 
    135 valid  ("a()()()");
    136 valid  ("s: l: a[2](4 == 6, 5 = 6)(f[4], 6)");
    137 valid  ("s: eval(a.apply(), b.call(c[5] - f[7]))");
    138 invalid("a(");
    139 invalid("a(5");
    140 invalid("a(5,");
    141 invalid("a(5,)");
    142 invalid("a(5,6");
    143 valid  ("a(b[7], c <d> e.l, new a() > b)");
    144 invalid("a(b[5)");
    145 invalid("a(b.)");
    146 valid  ("~new new a(1)(i++)(c[l])");
    147 invalid("a(*a)");
    148 valid  ("((((a))((b)()).l))()");
    149 valid  ("(a)[b + (c) / (d())].l--");
    150 valid  ("new (5)");
    151 invalid("new a(5");
    152 valid  ("new (f + 5)(6, (g)() - 'l'() - true(false))");
    153 invalid("a(.length)");
    154 
    155 debug  ("function declaration and expression");
    156 
    157 valid  ("function f() {}");
    158 valid  ("function f(a,b) {}");
    159 invalid("function () {}");
    160 invalid("function f(a b) {}");
    161 invalid("function f(a,) {}");
    162 invalid("function f(a,");
    163 invalid("function f(a, 1) {}");
    164 valid  ("function g(arguments, eval) {}");
    165 valid  ("function f() {} + function g() {}");
    166 invalid("(function a{})");
    167 invalid("(function this(){})");
    168 valid  ("(delete new function f(){} + function(a,b){}(5)(6))");
    169 valid  ("6 - function (m) { function g() {} }");
    170 invalid("function l() {");
    171 invalid("function l++(){}");
    172 
    173 debug  ("Array and object literal, comma operator");
    174 
    175 // Note these are tested elsewhere, no need to repeat those tests here
    176 valid  ("[] in [5,6] * [,5,] / [,,5,,] || [a,] && new [,b] % [,,]");
    177 invalid("[5,");
    178 invalid("[,");
    179 invalid("(a,)");
    180 valid  ("1 + {get get(){}, set set(a){}, get1:4, set1:get-set, }");
    181 invalid("1 + {a");
    182 invalid("1 + {a:");
    183 invalid("1 + {get l(");
    184 invalid(",a");
    185 valid  ("(4,(5,a(3,4))),f[4,a-6]");
    186 invalid("(,f)");
    187 invalid("a,,b");
    188 invalid("a ? b, c : d");
    189 
    190 debug  ("simple statements");
    191 
    192 valid  ("{ }");
    193 invalid("{ { }");
    194 valid  ("{ ; ; ; }");
    195 valid  ("a: { ; }");
    196 invalid("{ a: }");
    197 valid  ("{} f; { 6 + f() }");
    198 valid  ("{ a[5],6; {} ++b-new (-5)() } c().l++");
    199 valid  ("{ l1: l2: l3: { this } a = 32 ; { i++ ; { { { } } ++i } } }");
    200 valid  ("if (a) ;");
    201 invalid("{ if (a) }");
    202 invalid("if a {}");
    203 invalid("if (a");
    204 invalid("if (a { }");
    205 valid  ("x: s: if (a) ; else b");
    206 invalid("else {}");
    207 valid  ("if (a) if (b) y; else {} else ;");
    208 invalid("if (a) {} else x; else");
    209 invalid("if (a) { else }");
    210 valid  ("if (a.l + new b()) 4 + 5 - f()");
    211 valid  ("if (a) with (x) ; else with (y) ;");
    212 invalid("with a.b { }");
    213 valid  ("while (a() - new b) ;");
    214 invalid("while a {}");
    215 valid  ("do ; while(0) i++"); // Is this REALLY valid? (Firefox also accepts this)
    216 valid  ("do if (a) x; else y; while(z)");
    217 invalid("do g; while 4");
    218 invalid("do g; while ((4)");
    219 valid  ("{ { do do do ; while(0) while(0) while(0) } }");
    220 valid  ("do while (0) if (a) {} else y; while(0)");
    221 valid  ("if (a) while (b) if (c) with(d) {} else e; else f");
    222 invalid("break ; break your_limits ; continue ; continue living ; debugger");
    223 invalid("debugger X");
    224 invalid("break 0.2");
    225 invalid("continue a++");
    226 invalid("continue (my_friend)");
    227 valid  ("while (1) break");
    228 valid  ("do if (a) with (b) continue; else debugger; while (false)");
    229 invalid("do if (a) while (false) else debugger");
    230 invalid("while if (a) ;");
    231 valid  ("if (a) function f() {} else function g() {}");
    232 valid  ("if (a()) while(0) function f() {} else function g() {}");
    233 invalid("if (a()) function f() { else function g() }");
    234 invalid("if (a) if (b) ; else function f {}");
    235 invalid("if (a) if (b) ; else function (){}");
    236 valid  ("throw a");
    237 valid  ("throw a + b in void c");
    238 invalid("throw");
    239 
    240 debug  ("var and const statements");
    241 
    242 valid  ("var a, b = null");
    243 valid  ("const a = 5, b, c");
    244 invalid("var");
    245 invalid("var = 7");
    246 invalid("var c (6)");
    247 valid  ("if (a) var a,b; else const b, c");
    248 invalid("var 5 = 6");
    249 valid  ("while (0) var a, b, c=6, d, e, f=5*6, g=f*h, h");
    250 invalid("var a = if (b) { c }");
    251 invalid("var a = var b");
    252 valid  ("const a = b += c, a, a, a = (b - f())");
    253 invalid("var a %= b | 5");
    254 invalid("var (a) = 5");
    255 invalid("var a = (4, b = 6");
    256 invalid("const 'l' = 3");
    257 invalid("var var = 3");
    258 valid  ("var varr = 3 in 1");
    259 valid  ("const a, a, a = void 7 - typeof 8, a = 8");
    260 valid  ("const x_x = 6 /= 7 ? e : f");
    261 invalid("var a = ?");
    262 invalid("const a = *7");
    263 invalid("var a = :)");
    264 valid  ("var a = a in b in c instanceof d");
    265 invalid("var a = b ? c, b");
    266 invalid("const a = b : c");
    267 
    268 debug  ("for statement");
    269 
    270 valid  ("for ( ; ; ) { break }");
    271 valid  ("for ( a ; ; ) { break }");
    272 valid  ("for ( ; a ; ) { break }");
    273 valid  ("for ( ; ; a ) { break }");
    274 valid  ("for ( a ; a ; ) break");
    275 valid  ("for ( a ; ; a ) break");
    276 valid  ("for ( ; a ; a ) break");
    277 invalid("for () { }");
    278 invalid("for ( a ) { }");
    279 invalid("for ( ; ) ;");
    280 invalid("for a ; b ; c { }");
    281 invalid("for (a ; { }");
    282 invalid("for ( a ; ) ;");
    283 invalid("for ( ; a ) break");
    284 valid  ("for (var a, b ; ; ) { break } ");
    285 valid  ("for (var a = b, b = a ; ; ) break");
    286 valid  ("for (var a = b, c, d, b = a ; x in b ; ) { break }");
    287 valid  ("for (var a = b, c, d ; ; 1 in a()) break");
    288 invalid("for ( ; var a ; ) break");
    289 invalid("for (const a; ; ) break");
    290 invalid("for ( %a ; ; ) { }");
    291 valid  ("for (a in b) break");
    292 valid  ("for (a() in b) break");
    293 valid  ("for (a().l[4] in b) break");
    294 valid  ("for (new a in b in c in d) break");
    295 valid  ("for (new new new a in b) break");
    296 invalid("for (delete new a() in b) break");
    297 invalid("for (a * a in b) break");
    298 valid  ("for ((a * a) in b) break");
    299 invalid("for (a++ in b) break");
    300 valid  ("for ((a++) in b) break");
    301 invalid("for (++a in b) break");
    302 valid  ("for ((++a) in b) break");
    303 invalid("for (a, b in c) break");
    304 invalid("for (a,b in c ;;) break");
    305 valid  ("for (a,(b in c) ;;) break");
    306 valid  ("for ((a, b) in c) break");
    307 invalid("for (a ? b : c in c) break");
    308 valid  ("for ((a ? b : c) in c) break");
    309 valid  ("for (var a in b in c) break");
    310 valid  ("for (var a = 5 += 6 in b) break");
    311 invalid("for (var a += 5 in b) break");
    312 invalid("for (var a = in b) break");
    313 invalid("for (var a, b in b) break");
    314 invalid("for (var a = -6, b in b) break");
    315 invalid("for (var a, b = 8 in b) break");
    316 valid  ("for (var a = (b in c) in d) break");
    317 invalid("for (var a = (b in c in d) break");
    318 invalid("for (var (a) in b) { }");
    319 valid  ("for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}");
    320 
    321 debug  ("try statement");
    322 
    323 invalid("try { break } catch(e) {}");
    324 valid  ("try {} finally { c++ }");
    325 valid  ("try { with (x) { } } catch(e) {} finally { if (a) ; }");
    326 invalid("try {}");
    327 invalid("catch(e) {}");
    328 invalid("finally {}");
    329 invalid("try a; catch(e) {}");
    330 invalid("try {} catch(e) a()");
    331 invalid("try {} finally a()");
    332 invalid("try {} catch(e)");
    333 invalid("try {} finally");
    334 invalid("try {} finally {} catch(e) {}");
    335 invalid("try {} catch (...) {}");
    336 invalid("try {} catch {}");
    337 valid  ("if (a) try {} finally {} else b;");
    338 valid  ("if (--a()) do with(1) try {} catch(ke) { f() ; g() } while (a in b) else {}");
    339 invalid("if (a) try {} else b; catch (e) { }");
    340 invalid("try { finally {}");
    341 
    342 debug  ("switch statement");
    343 
    344 valid  ("switch (a) {}");
    345 invalid("switch () {}");
    346 invalid("case 5:");
    347 invalid("default:");
    348 invalid("switch (a) b;");
    349 invalid("switch (a) case 3: b;");
    350 valid  ("switch (f()) { case 5 * f(): default: case '6' - 9: ++i }");
    351 invalid("switch (true) { default: case 6: default: }");
    352 invalid("switch (l) { f(); }");
    353 invalid("switch (l) { case 1: ; a: case 5: }");
    354 valid  ("switch (g() - h[5].l) { case 1 + 6: a: b: c: ++f }");
    355 invalid("switch (g) { case 1: a: }");
    356 invalid("switch (g) { case 1: a: default: }");
    357 invalid("switch g { case 1: l() }");
    358 invalid("switch (g) { case 1:");
    359 valid  ("switch (l) { case a = b ? c : d : }");
    360 valid  ("switch (sw) { case a ? b - 7[1] ? [c,,] : d = 6 : { } : }");
    361 invalid("switch (l) { case b ? c : }");
    362 valid  ("switch (l) { case 1: a: with(g) switch (g) { case 2: default: } default: }");
    363 invalid("switch (4 - ) { }");
    364 invalid("switch (l) { default case: 5; }");
    365 
    366 invalid("L: L: ;");
    367 invalid("L: L1: L: ;");
    368 invalid("L: L1: L2: L3: L4: L: ;");
    369 
    370 invalid("for(var a,b 'this shouldn\'t be allowed' false ; ) ;");
    371 invalid("for(var a,b '");
    372 
    373 valid("function __proto__(){}")
    374 valid("(function __proto__(){})")
    375 valid("'use strict'; function __proto__(){}")
    376 valid("'use strict'; (function __proto__(){})")
    377 
    378 valid("if (0) $foo; ")
    379 valid("if (0) _foo; ")
    380 valid("if (0) foo$; ")
    381 valid("if (0) foo_; ")
    382 valid("if (0) obj.$foo; ")
    383 valid("if (0) obj._foo; ")
    384 valid("if (0) obj.foo$; ")
    385 valid("if (0) obj.foo_; ")
    386 valid("if (0) obj.foo\\u03bb; ")
    387 valid("if (0) new a(b+c).d = 5");
    388 valid("if (0) new a(b+c) = 5");
    389 valid("([1 || 1].a = 1)");
    390 valid("({a: 1 || 1}.a = 1)");
    391 
    392 invalid("var a.b = c");
    393 invalid("var a.b;");
    394 
    395 try { eval("a.b.c = {};"); } catch(e1) { e=e1; shouldBe("e.line", "1") }
    396 foo = 'FAIL';
    397 bar = 'PASS';
    398 try {
    399      eval("foo = 'PASS'; a.b.c = {}; bar  = 'FAIL';");
    400 } catch(e) {
    401      shouldBe("foo", "'PASS'");
    402      shouldBe("bar", "'PASS'");
    403 }
    404