OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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: --strong-mode --harmony_rest_parameters --harmony_arrow_functions --ha
rmony_classes --harmony-computed-property-names |
| 6 |
| 7 // Note that it's essential for these tests that the reference is inside dead |
| 8 // code (because we already produce ReferenceErrors for run-time unresolved |
| 9 // variables and don't want to confuse those with strong mode errors). But the |
| 10 // errors should *not* be inside lazy, unexecuted functions, since lazy parsing |
| 11 // doesn't produce strong mode scoping errors). |
| 12 |
| 13 // In addition, assertThrows will call eval and that changes variable binding |
| 14 // types (see e.g., UNBOUND_EVAL_SHADOWED). We can avoid unwanted side effects |
| 15 // by wrapping the code to be tested inside an outer function. |
| 16 function assertThrowsHelper(code, error) { |
| 17 "use strict"; |
| 18 let prologue = "(function outer() { "; |
| 19 let epilogue = " })();"; |
| 20 assertThrows(prologue + code + epilogue, error); |
| 21 } |
| 22 |
| 23 (function DeclarationAfterUse() { |
| 24 // Note that these tests only test cases where the declaration is found but is |
| 25 // after the use. In particular, we cannot yet detect cases where the use can |
| 26 // possibly bind to a global variable. |
| 27 assertThrowsHelper("'use strong'; if (false) { x; let x = 0; }", |
| 28 ReferenceError); |
| 29 assertThrowsHelper( |
| 30 "function f() { 'use strong'; if (false) { x; let x = 0; } } f();", |
| 31 ReferenceError); |
| 32 assertThrowsHelper( |
| 33 "'use strong'; function f() { if (false) { x; } } let x = 0; f();", |
| 34 ReferenceError); |
| 35 |
| 36 assertThrowsHelper( |
| 37 "function f() { 'use strong'; if (false) { x; } } var x = 0; f();", |
| 38 ReferenceError); |
| 39 assertThrowsHelper( |
| 40 "function f() { 'use strong'; if (false) { x; } } var x; f();", |
| 41 ReferenceError); |
| 42 // Errors are also detected when the declaration and the use are in the same |
| 43 // eval scope. |
| 44 assertThrowsHelper("'use strong'; eval('x; let x = 0;')", ReferenceError); |
| 45 |
| 46 // Use occurring in the initializer of the declaration: |
| 47 assertThrowsHelper("'use strong'; if (false) { let x = x + 1; }", |
| 48 ReferenceError); |
| 49 assertThrowsHelper("'use strong'; if (false) { let x = x; }", |
| 50 ReferenceError); |
| 51 assertThrowsHelper("'use strong'; if (false) { let x = y, y = 4; }", |
| 52 ReferenceError); |
| 53 assertThrowsHelper("'use strong'; if (false) { let x = function() { x; } }", |
| 54 ReferenceError); |
| 55 assertThrowsHelper("'use strong'; if (false) { let x = a => { x; } }", |
| 56 ReferenceError); |
| 57 assertThrowsHelper( |
| 58 "'use strong'; if (false) { function f() {}; let x = f(x); }", |
| 59 ReferenceError); |
| 60 assertThrowsHelper("'use strong'; if (false) { const x = x; }", |
| 61 ReferenceError); |
| 62 assertThrowsHelper("'use strong'; if (false) { const x = function() { x; } }", |
| 63 ReferenceError); |
| 64 assertThrowsHelper("'use strong'; if (false) { const x = a => { x; } }", |
| 65 ReferenceError); |
| 66 assertThrowsHelper( |
| 67 "'use strong'; if (false) { function f() {}; const x = f(x); }", |
| 68 ReferenceError); |
| 69 |
| 70 assertThrowsHelper( |
| 71 "'use strong'; if (false) { for (let x = x; ; ) { } }", |
| 72 ReferenceError); |
| 73 assertThrowsHelper( |
| 74 "'use strong'; if (false) { for (const x = x; ; ) { } }", |
| 75 ReferenceError); |
| 76 assertThrowsHelper( |
| 77 "'use strong'; if (false) { for (let x = y, y; ; ) { } }", |
| 78 ReferenceError); |
| 79 assertThrowsHelper( |
| 80 "'use strong'; if (false) { for (const x = y, y = 0; ; ) { } }", |
| 81 ReferenceError); |
| 82 |
| 83 // Computed property names |
| 84 assertThrowsHelper( |
| 85 "'use strong'; if (false) { let o = { 'a': 'b', [o.a]: 'c'}; }", |
| 86 ReferenceError); |
| 87 })(); |
| 88 |
| 89 |
| 90 (function DeclarationAfterUseInClasses() { |
| 91 assertThrowsHelper("'use strong'; if (false) { class C extends C { } }", |
| 92 ReferenceError); |
| 93 assertThrowsHelper( |
| 94 "'use strong'; if (false) { let C = class C2 extends C { } }", |
| 95 ReferenceError); |
| 96 assertThrowsHelper( |
| 97 "'use strong'; if (false) { let C = class C2 extends C2 { } }", |
| 98 ReferenceError); |
| 99 |
| 100 assertThrowsHelper( |
| 101 "'use strong'; if (false) { let C = class C2 { constructor() { C; } } }", |
| 102 ReferenceError); |
| 103 |
| 104 assertThrowsHelper( |
| 105 "'use strong'; if (false) { let C = class C2 { method() { C; } } }", |
| 106 ReferenceError); |
| 107 |
| 108 assertThrowsHelper( |
| 109 "'use strong'; if (false) { let C = class C2 { " + |
| 110 "static a() { return 'A'; } [C.a()]() { return 'B'; } }; }", |
| 111 ReferenceError); |
| 112 |
| 113 // TODO(marja, rossberg): More tests related to computed property names in |
| 114 // classes + recognize more errors. This one is not recognized as an error |
| 115 // yet: |
| 116 // let C = class C2 { |
| 117 // static a() { return 'A'; } |
| 118 // [C2.a()]() { return 'B'; } << C2 should not be allowed here |
| 119 // }; |
| 120 })(); |
| 121 |
| 122 |
| 123 (function UsesWhichAreFine() { |
| 124 "use strong"; |
| 125 |
| 126 let var1 = 0; |
| 127 var1; |
| 128 |
| 129 let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b; |
| 130 |
| 131 for (let var3 = 0; var3 < 1; var3++) { |
| 132 var3; |
| 133 } |
| 134 |
| 135 for (let var4a = 0, var4b = var4a; var4a + var4b < 4; var4a++, var4b++) { |
| 136 var4a; |
| 137 var4b; |
| 138 } |
| 139 |
| 140 let var5 = 5; |
| 141 for (; var5 < 10; ++var5) { } |
| 142 |
| 143 let arr = [1, 2]; |
| 144 for (let i of arr) { |
| 145 i; |
| 146 } |
| 147 |
| 148 let var6 = [1, 2]; |
| 149 // The second var6 resolves to outside (not to the first var6). |
| 150 for (let var6 of var6) { var6; } |
| 151 |
| 152 try { |
| 153 throw "error"; |
| 154 } catch (e) { |
| 155 e; |
| 156 } |
| 157 |
| 158 function func1() { func1; this; } |
| 159 func1(); |
| 160 func1; |
| 161 |
| 162 function * func2() { func2; this; } |
| 163 func2(); |
| 164 func2; |
| 165 |
| 166 function func4(p, ...rest) { p; rest; this; func2; } |
| 167 func4(); |
| 168 |
| 169 let func5 = (p1, p2) => { p1; p2; }; |
| 170 func5(); |
| 171 |
| 172 function func6() { |
| 173 var1, var2a, var2b, var2c; |
| 174 } |
| 175 |
| 176 (function eval1() { |
| 177 let var7 = 0; // Declaration position will be something large. |
| 178 // But use position will be something small, however, this is not an error, |
| 179 // since the use is inside an eval scope. |
| 180 eval("var7;"); |
| 181 })(); |
| 182 |
| 183 class C1 { constructor() { C1; } }; new C1(); |
| 184 let C2 = class C3 { constructor() { C3; } }; new C2(); |
| 185 |
| 186 class C4 { method() { C4; method; } }; new C4(); |
| 187 let C5 = class C6 { method() { C6; method; } }; new C5(); |
| 188 })(); |
OLD | NEW |