| 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 | |
| 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) { | |
| 17 "use strict"; | |
| 18 let prologue = "(function outer() { if (false) { "; | |
| 19 let epilogue = " } })();"; | |
| 20 | |
| 21 assertThrows("'use strong'; " + prologue + code + epilogue, ReferenceError); | |
| 22 | |
| 23 // Make sure the error happens only in strong mode (note that we need strict | |
| 24 // mode here because of let). | |
| 25 assertDoesNotThrow("'use strict'; " + prologue + code + epilogue); | |
| 26 } | |
| 27 | |
| 28 (function DeclarationAfterUse() { | |
| 29 // Note that these tests only test cases where the declaration is found but is | |
| 30 // after the use. In particular, we cannot yet detect cases where the use can | |
| 31 // possibly bind to a global variable. | |
| 32 assertThrowsHelper("x; let x = 0;"); | |
| 33 assertThrowsHelper("function f() { x; let x = 0; }"); | |
| 34 assertThrowsHelper("function f() { x; } let x = 0;"); | |
| 35 | |
| 36 assertThrowsHelper("x; const x = 0;"); | |
| 37 assertThrowsHelper("function f() { x; const x = 0; }"); | |
| 38 assertThrowsHelper("function f() { x; } const x = 0;"); | |
| 39 | |
| 40 // These tests needs to be done a bit more manually, since var is not allowed | |
| 41 // in strong mode: | |
| 42 assertThrows( | |
| 43 `(function outer() { | |
| 44 function f() { 'use strong'; if (false) { x; } } var x = 0; f(); | |
| 45 })()`, | |
| 46 ReferenceError); | |
| 47 assertDoesNotThrow( | |
| 48 "(function outer() {\n" + | |
| 49 " function f() { if (false) { x; } } var x = 0; f(); \n" + | |
| 50 "})()"); | |
| 51 | |
| 52 assertThrows( | |
| 53 "(function outer() {\n" + | |
| 54 " function f() { 'use strong'; if (false) { x; } } var x; f(); \n" + | |
| 55 "})()", | |
| 56 ReferenceError); | |
| 57 assertDoesNotThrow( | |
| 58 "(function outer() {\n" + | |
| 59 " function f() { if (false) { x; } } var x; f(); \n" + | |
| 60 "})()"); | |
| 61 | |
| 62 // Use occurring in the initializer of the declaration: | |
| 63 assertThrowsHelper("let x = x + 1;"); | |
| 64 assertThrowsHelper("let x = x;"); | |
| 65 assertThrowsHelper("let x = y, y = 4;"); | |
| 66 assertThrowsHelper("let x = function() { x; }"); | |
| 67 assertThrowsHelper("let x = a => { x; }"); | |
| 68 assertThrowsHelper("function f(x) { return x; }; let x = f(x);"); | |
| 69 assertThrowsHelper("const x = x;"); | |
| 70 assertThrowsHelper("const x = function() { x; }"); | |
| 71 assertThrowsHelper("const x = a => { x; }"); | |
| 72 assertThrowsHelper("function f(x) {return x}; const x = f(x);"); | |
| 73 | |
| 74 assertThrowsHelper("for (let x = x; ; ) { }"); | |
| 75 assertThrowsHelper("for (const x = x; ; ) { }"); | |
| 76 assertThrowsHelper("for (let x = y, y; ; ) { }"); | |
| 77 assertThrowsHelper("for (const x = y, y = 0; ; ) { }"); | |
| 78 | |
| 79 // Computed property names | |
| 80 assertThrowsHelper("let o = { 'a': 'b', [o.a]: 'c'};"); | |
| 81 })(); | |
| 82 | |
| 83 | |
| 84 (function DeclarationAfterUseInClasses() { | |
| 85 // Referring to a variable declared later | |
| 86 assertThrowsHelper("class C { m() { x; } } let x = 0;"); | |
| 87 assertThrowsHelper("class C { static m() { x; } } let x = 0;"); | |
| 88 assertThrowsHelper("class C { [x]() { } } let x = 0;"); | |
| 89 | |
| 90 assertThrowsHelper("class C { m() { x; } } const x = 0;"); | |
| 91 assertThrowsHelper("class C { static m() { x; } } const x = 0;"); | |
| 92 assertThrowsHelper("class C { [x]() { } } const x = 0;"); | |
| 93 | |
| 94 // Referring to the class name. | |
| 95 assertThrowsHelper("class C extends C { }"); | |
| 96 assertThrowsHelper("let C = class C2 extends C { }"); | |
| 97 assertThrowsHelper("let C = class C2 extends C2 { }"); | |
| 98 | |
| 99 assertThrowsHelper("let C = class C2 { constructor() { C; } }"); | |
| 100 assertThrowsHelper("let C = class C2 { method() { C; } }"); | |
| 101 assertThrowsHelper("let C = class C2 { *generator_method() { C; } }"); | |
| 102 | |
| 103 assertThrowsHelper( | |
| 104 `let C = class C2 { | |
| 105 static a() { return 'A'; } | |
| 106 [C.a()]() { return 'B'; } | |
| 107 };`); | |
| 108 | |
| 109 assertThrowsHelper( | |
| 110 `let C = class C2 { | |
| 111 static a() { return 'A'; } | |
| 112 [C2.a()]() { return 'B'; } | |
| 113 };`); | |
| 114 | |
| 115 assertThrowsHelper( | |
| 116 `let C = class C2 { | |
| 117 [(function() { C; return 'A';})()]() { return 'B'; } | |
| 118 };`); | |
| 119 | |
| 120 // The reference to C or C2 is inside a function, but not a method. | |
| 121 assertThrowsHelper( | |
| 122 `let C = class C2 { | |
| 123 [(function() { C2; return 'A';})()]() { return 'B'; } | |
| 124 };`); | |
| 125 | |
| 126 assertThrowsHelper( | |
| 127 `let C = class C2 { | |
| 128 [(function() { C; return 'A';})()]() { return 'B'; } | |
| 129 };`); | |
| 130 | |
| 131 // The reference to C or C2 is inside a method, but it's not a method of the | |
| 132 // relevant class (C2). | |
| 133 assertThrowsHelper( | |
| 134 `let C = class C2 { | |
| 135 [(new (class D { m() { C2; return 'A'; } })).m()]() { | |
| 136 return 'B'; | |
| 137 } | |
| 138 }`); | |
| 139 | |
| 140 assertThrowsHelper( | |
| 141 `let C = class C2 { | |
| 142 [(new (class D { m() { C; return 'A'; } })).m()]() { | |
| 143 return 'B'; | |
| 144 } | |
| 145 }`); | |
| 146 | |
| 147 assertThrowsHelper( | |
| 148 `let C = class C2 { | |
| 149 [({m() { C2; return 'A'; }}).m()]() { return 'B'; } | |
| 150 }`); | |
| 151 | |
| 152 assertThrowsHelper( | |
| 153 `let C = class C2 { | |
| 154 [({m() { C; return 'A'; }}).m()]() { return 'B'; } | |
| 155 }`); | |
| 156 | |
| 157 assertThrowsHelper( | |
| 158 `class COuter { | |
| 159 m() { | |
| 160 class CInner { | |
| 161 [({ m() { CInner; return 'A'; } }).m()]() { | |
| 162 return 'B'; | |
| 163 } | |
| 164 } | |
| 165 } | |
| 166 }`); | |
| 167 })(); | |
| 168 | |
| 169 | |
| 170 (function UsesWhichAreFine() { | |
| 171 "use strong"; | |
| 172 | |
| 173 let var1 = 0; | |
| 174 var1; | |
| 175 | |
| 176 let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b; | |
| 177 | |
| 178 for (let var3 = 0; var3 < 1; var3++) { | |
| 179 var3; | |
| 180 } | |
| 181 | |
| 182 for (let var4a = 0, var4b = var4a; var4a + var4b < 4; var4a++, var4b++) { | |
| 183 var4a; | |
| 184 var4b; | |
| 185 } | |
| 186 | |
| 187 let var5 = 5; | |
| 188 for (; var5 < 10; ++var5) { } | |
| 189 | |
| 190 let arr = [1, 2]; | |
| 191 for (let i of arr) { | |
| 192 i; | |
| 193 } | |
| 194 | |
| 195 try { | |
| 196 throw "error"; | |
| 197 } catch (e) { | |
| 198 e; | |
| 199 } | |
| 200 | |
| 201 function func1() { func1; this; } | |
| 202 func1(); | |
| 203 func1; | |
| 204 | |
| 205 function * func2() { func2; this; } | |
| 206 func2(); | |
| 207 func2; | |
| 208 | |
| 209 function func4(p, ...rest) { p; rest; this; func2; } | |
| 210 // TODO(arv): The arity checking is not correct with rest parameters. | |
| 211 func4(1, 2); | |
| 212 | |
| 213 let func5 = (p1, p2) => { p1; p2; }; | |
| 214 func5(1, 2); | |
| 215 | |
| 216 let func5b = p1 => p1; | |
| 217 func5b(1); | |
| 218 | |
| 219 function func6() { | |
| 220 var1, var2a, var2b, var2c; | |
| 221 } | |
| 222 | |
| 223 class C1 { constructor() { C1; } }; new C1(); | |
| 224 let C2 = class C3 { constructor() { C3; } }; new C2(); | |
| 225 | |
| 226 class C4 { method() { C4; } *generator_method() { C4; } }; new C4(); | |
| 227 let C5 = class C6 { method() { C6; } *generator_method() { C6; } }; new C5(); | |
| 228 | |
| 229 class C7 { static method() { C7; } }; new C7(); | |
| 230 let C8 = class C9 { static method() { C9; } }; new C8(); | |
| 231 | |
| 232 class C10 { get x() { C10; } }; new C10(); | |
| 233 let C11 = class C12 { get x() { C12; } }; new C11(); | |
| 234 | |
| 235 // Regression test for unnamed classes. | |
| 236 let C13 = class { m() { var1; } }; | |
| 237 | |
| 238 class COuter { | |
| 239 m() { | |
| 240 class CInner { | |
| 241 // Here we can refer to COuter but not to CInner (see corresponding | |
| 242 // assertion test): | |
| 243 [({ m() { COuter; return 'A'; } }).m()]() { return 'B'; } | |
| 244 // And here we can refer to both: | |
| 245 n() { COuter; CInner; } | |
| 246 } | |
| 247 return new CInner(); | |
| 248 } | |
| 249 } | |
| 250 (new COuter()).m().n(); | |
| 251 | |
| 252 // Making sure the check which is supposed to prevent "object literal inside | |
| 253 // computed property name references the class name" is not too generic: | |
| 254 class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m(); | |
| 255 })(); | |
| OLD | NEW |