| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Flags: --strong-mode --harmony_rest_parameters --harmony_arrow_functions --ha
rmony_classes --harmony-computed-property-names | 5 // Flags: --strong-mode --harmony_rest_parameters --harmony_arrow_functions --ha
rmony_classes --harmony_computed-property_names --harmony_templates |
| 6 | 6 |
| 7 // Note that it's essential for these tests that the reference is inside dead | 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 | 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 | 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 | 10 // errors should *not* be inside lazy, unexecuted functions, since lazy parsing |
| 11 // doesn't produce strong mode scoping errors). | 11 // doesn't produce strong mode scoping errors). |
| 12 | 12 |
| 13 // In addition, assertThrows will call eval and that changes variable binding | 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 | 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. | 15 // by wrapping the code to be tested inside an outer function. |
| 16 function assertThrowsHelper(code, error) { | 16 function assertThrowsHelper(code) { |
| 17 "use strict"; | 17 "use strict"; |
| 18 let prologue = "(function outer() { "; | 18 let prologue = "(function outer() { if (false) { "; |
| 19 let epilogue = " })();"; | 19 let epilogue = " } })();"; |
| 20 assertThrows(prologue + code + epilogue, error); | 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); |
| 21 } | 26 } |
| 22 | 27 |
| 23 (function DeclarationAfterUse() { | 28 (function DeclarationAfterUse() { |
| 24 // Note that these tests only test cases where the declaration is found but is | 29 // 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 | 30 // after the use. In particular, we cannot yet detect cases where the use can |
| 26 // possibly bind to a global variable. | 31 // possibly bind to a global variable. |
| 27 assertThrowsHelper("'use strong'; if (false) { x; let x = 0; }", | 32 assertThrowsHelper("x; let x = 0;"); |
| 28 ReferenceError); | 33 assertThrowsHelper("function f() { x; let x = 0; }"); |
| 29 assertThrowsHelper( | 34 assertThrowsHelper("function f() { x; } let x = 0;"); |
| 30 "function f() { 'use strong'; if (false) { x; let x = 0; } } f();", | 35 |
| 36 // These tests needs to be done a bit more manually, since var is not allowed |
| 37 // in strong mode: |
| 38 assertThrows( |
| 39 `(function outer() { |
| 40 function f() { 'use strong'; if (false) { x; } } var x = 0; f(); |
| 41 })()`, |
| 31 ReferenceError); | 42 ReferenceError); |
| 32 assertThrowsHelper( | 43 assertDoesNotThrow( |
| 33 "'use strong'; function f() { if (false) { x; } } let x = 0; f();", | 44 "(function outer() {\n" + |
| 45 " function f() { if (false) { x; } } var x = 0; f(); \n" + |
| 46 "})()"); |
| 47 |
| 48 assertThrows( |
| 49 "(function outer() {\n" + |
| 50 " function f() { 'use strong'; if (false) { x; } } var x; f(); \n" + |
| 51 "})()", |
| 34 ReferenceError); | 52 ReferenceError); |
| 53 assertDoesNotThrow( |
| 54 "(function outer() {\n" + |
| 55 " function f() { if (false) { x; } } var x; f(); \n" + |
| 56 "})()"); |
| 35 | 57 |
| 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 | 58 // Errors are also detected when the declaration and the use are in the same |
| 43 // eval scope. | 59 // eval scope. |
| 44 assertThrowsHelper("'use strong'; eval('x; let x = 0;')", ReferenceError); | 60 assertThrows("'use strong'; eval('if (false) { x; let x = 0;}')", |
| 61 ReferenceError); |
| 62 assertDoesNotThrow("'use strict'; eval('if (false) { x; let x = 0; }')"); |
| 45 | 63 |
| 46 // Use occurring in the initializer of the declaration: | 64 // Use occurring in the initializer of the declaration: |
| 47 assertThrowsHelper("'use strong'; if (false) { let x = x + 1; }", | 65 assertThrowsHelper("let x = x + 1;"); |
| 48 ReferenceError); | 66 assertThrowsHelper("let x = x;"); |
| 49 assertThrowsHelper("'use strong'; if (false) { let x = x; }", | 67 assertThrowsHelper("let x = y, y = 4;"); |
| 50 ReferenceError); | 68 assertThrowsHelper("let x = function() { x; }"); |
| 51 assertThrowsHelper("'use strong'; if (false) { let x = y, y = 4; }", | 69 assertThrowsHelper("let x = a => { x; }"); |
| 52 ReferenceError); | 70 assertThrowsHelper("function f(x) { return x; }; let x = f(x);"); |
| 53 assertThrowsHelper("'use strong'; if (false) { let x = function() { x; } }", | 71 assertThrowsHelper("const x = x;"); |
| 54 ReferenceError); | 72 assertThrowsHelper("const x = function() { x; }"); |
| 55 assertThrowsHelper("'use strong'; if (false) { let x = a => { x; } }", | 73 assertThrowsHelper("const x = a => { x; }"); |
| 56 ReferenceError); | 74 assertThrowsHelper("function f(x) {return x}; const x = f(x);"); |
| 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 | 75 |
| 70 assertThrowsHelper( | 76 assertThrowsHelper("for (let x = x; ; ) { }"); |
| 71 "'use strong'; if (false) { for (let x = x; ; ) { } }", | 77 assertThrowsHelper("for (const x = x; ; ) { }"); |
| 72 ReferenceError); | 78 assertThrowsHelper("for (let x = y, y; ; ) { }"); |
| 73 assertThrowsHelper( | 79 assertThrowsHelper("for (const x = y, y = 0; ; ) { }"); |
| 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 | 80 |
| 83 // Computed property names | 81 // Computed property names |
| 84 assertThrowsHelper( | 82 assertThrowsHelper("let o = { 'a': 'b', [o.a]: 'c'};"); |
| 85 "'use strong'; if (false) { let o = { 'a': 'b', [o.a]: 'c'}; }", | |
| 86 ReferenceError); | |
| 87 })(); | 83 })(); |
| 88 | 84 |
| 89 | 85 |
| 90 (function DeclarationAfterUseInClasses() { | 86 (function DeclarationAfterUseInClasses() { |
| 91 assertThrowsHelper("'use strong'; if (false) { class C extends C { } }", | 87 assertThrowsHelper("class C extends C { }"); |
| 92 ReferenceError); | 88 assertThrowsHelper("let C = class C2 extends C { }"); |
| 93 assertThrowsHelper( | 89 assertThrowsHelper("let C = class C2 extends C2 { }"); |
| 94 "'use strong'; if (false) { let C = class C2 extends C { } }", | 90 |
| 95 ReferenceError); | 91 assertThrowsHelper("let C = class C2 { constructor() { C; } }"); |
| 96 assertThrowsHelper( | 92 assertThrowsHelper("let C = class C2 { method() { C; } }"); |
| 97 "'use strong'; if (false) { let C = class C2 extends C2 { } }", | 93 assertThrowsHelper("let C = class C2 { *generator_method() { C; } }"); |
| 98 ReferenceError); | |
| 99 | 94 |
| 100 assertThrowsHelper( | 95 assertThrowsHelper( |
| 101 "'use strong'; if (false) { let C = class C2 { constructor() { C; } } }", | 96 `let C = class C2 { |
| 102 ReferenceError); | 97 static a() { return 'A'; } |
| 98 [C.a()]() { return 'B'; } |
| 99 };`); |
| 103 | 100 |
| 104 assertThrowsHelper( | 101 assertThrowsHelper( |
| 105 "'use strong'; if (false) { let C = class C2 { method() { C; } } }", | 102 `let C = class C2 { |
| 106 ReferenceError); | 103 static a() { return 'A'; } |
| 104 [C2.a()]() { return 'B'; } |
| 105 };`); |
| 107 | 106 |
| 108 assertThrowsHelper( | 107 assertThrowsHelper( |
| 109 "'use strong'; if (false) { " + | 108 `let C = class C2 { |
| 110 "let C = class C2 { *generator_method() { C; } } }", | 109 [(function() { C; return 'A';})()]() { return 'B'; } |
| 111 ReferenceError); | 110 };`); |
| 112 | |
| 113 assertThrowsHelper( | |
| 114 "'use strong'; if (false) { let C = class C2 { " + | |
| 115 "static a() { return 'A'; } [C.a()]() { return 'B'; } }; }", | |
| 116 ReferenceError); | |
| 117 | |
| 118 assertThrowsHelper( | |
| 119 "'use strong'; if (false) { let C = class C2 { " + | |
| 120 "static a() { return 'A'; } [C2.a()]() { return 'B'; } }; }", | |
| 121 ReferenceError); | |
| 122 | |
| 123 assertThrowsHelper( | |
| 124 "'use strong'; if (false) { let C = class C2 { " + | |
| 125 "[(function() { C; return 'A';})()]() { return 'B'; } }; }", | |
| 126 ReferenceError); | |
| 127 | 111 |
| 128 // The reference to C or C2 is inside a function, but not a method. | 112 // The reference to C or C2 is inside a function, but not a method. |
| 129 assertThrowsHelper( | 113 assertThrowsHelper( |
| 130 "'use strong'; if (false) { let C = class C2 { " + | 114 `let C = class C2 { |
| 131 "[(function() { C2; return 'A';})()]() { return 'B'; } }; }", | 115 [(function() { C2; return 'A';})()]() { return 'B'; } |
| 132 ReferenceError); | 116 };`); |
| 133 | 117 |
| 134 assertThrowsHelper( | 118 assertThrowsHelper( |
| 135 "'use strong'; if (false) { let C = class C2 { " + | 119 `let C = class C2 { |
| 136 "[(function() { C; return 'A';})()]() { return 'B'; } }; }", | 120 [(function() { C; return 'A';})()]() { return 'B'; } |
| 137 ReferenceError); | 121 };`); |
| 138 | 122 |
| 139 // The reference to C or C2 is inside a method, but it's not a method of the | 123 // The reference to C or C2 is inside a method, but it's not a method of the |
| 140 // relevant class (C2). | 124 // relevant class (C2). |
| 141 assertThrowsHelper( | 125 assertThrowsHelper( |
| 142 "'use strong'; if (false) { let C = class C2 { " + | 126 `let C = class C2 { |
| 143 "[(new (class D { m() { C2; return 'A'; } })).m()]() " + | 127 [(new (class D { m() { C2; return 'A'; } })).m()]() { |
| 144 "{ return 'B'; } } }", | 128 return 'B'; |
| 145 ReferenceError); | 129 } |
| 130 }`); |
| 146 | 131 |
| 147 assertThrowsHelper( | 132 assertThrowsHelper( |
| 148 "'use strong'; if (false) { let C = class C2 { " + | 133 `let C = class C2 { |
| 149 "[(new (class D { m() { C; return 'A'; } })).m()]() " + | 134 [(new (class D { m() { C; return 'A'; } })).m()]() { |
| 150 "{ return 'B'; } } }", | 135 return 'B'; |
| 151 ReferenceError); | 136 } |
| 137 }`); |
| 152 | 138 |
| 153 assertThrowsHelper( | 139 assertThrowsHelper( |
| 154 "'use strong'; if (false) { let C = class C2 { " + | 140 `let C = class C2 { |
| 155 "[({m() { C2; return 'A'; }}).m()]() " + | 141 [({m() { C2; return 'A'; }}).m()]() { return 'B'; } |
| 156 "{ return 'B'; } } }", | 142 }`); |
| 157 ReferenceError); | |
| 158 | 143 |
| 159 assertThrowsHelper( | 144 assertThrowsHelper( |
| 160 "'use strong'; if (false) { let C = class C2 { " + | 145 `let C = class C2 { |
| 161 "[({m() { C; return 'A'; }}).m()]() " + | 146 [({m() { C; return 'A'; }}).m()]() { return 'B'; } |
| 162 "{ return 'B'; } } }", | 147 }`); |
| 163 ReferenceError); | |
| 164 | 148 |
| 165 assertThrowsHelper( | 149 assertThrowsHelper( |
| 166 "'use strong';\n" + | 150 `class COuter { |
| 167 "if (false) {\n" + | 151 m() { |
| 168 " class COuter {\n" + | 152 class CInner { |
| 169 " m() {\n" + | 153 [({ m() { CInner; return 'A'; } }).m()]() { |
| 170 " class CInner {\n" + | 154 return 'B'; |
| 171 " [({ m() { CInner; return 'A'; } }).m()]() {\n" + | 155 } |
| 172 " return 'B';\n" + | 156 } |
| 173 " }\n" + | 157 } |
| 174 " }\n" + | 158 }`); |
| 175 " }\n" + | |
| 176 " }\n" + | |
| 177 "}", | |
| 178 ReferenceError); | |
| 179 })(); | 159 })(); |
| 180 | 160 |
| 181 | 161 |
| 182 (function UsesWhichAreFine() { | 162 (function UsesWhichAreFine() { |
| 183 "use strong"; | 163 "use strong"; |
| 184 | 164 |
| 185 let var1 = 0; | 165 let var1 = 0; |
| 186 var1; | 166 var1; |
| 187 | 167 |
| 188 let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b; | 168 let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 } | 246 } |
| 267 return new CInner(); | 247 return new CInner(); |
| 268 } | 248 } |
| 269 } | 249 } |
| 270 (new COuter()).m().n(); | 250 (new COuter()).m().n(); |
| 271 | 251 |
| 272 // Making sure the check which is supposed to prevent "object literal inside | 252 // Making sure the check which is supposed to prevent "object literal inside |
| 273 // computed property name references the class name" is not too generic: | 253 // computed property name references the class name" is not too generic: |
| 274 class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m(); | 254 class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m(); |
| 275 })(); | 255 })(); |
| OLD | NEW |