1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Test let declarations in various settings. 29 30"use strict"; 31 32// Global 33let x; 34let y = 2; 35const z = 4; 36class c { static foo() { return 1; } } 37 38// Block local 39{ 40 let y; 41 let x = 3; 42 const z = 5; 43 class c { static foo() { return 2; } } 44} 45 46assertEquals(undefined, x); 47assertEquals(2,y); 48assertEquals(4,z); 49assertEquals(1, c.foo()); 50 51if (true) { 52 let y; 53 assertEquals(undefined, y); 54} 55 56// Invalid declarations are early errors in harmony mode and thus should trigger 57// an exception in eval code during parsing, before even compiling or executing 58// the code. Thus the generated function is not called here. 59function TestLocalThrows(str, expect) { 60 assertThrows("(function(arg){ 'use strict'; " + str + "})", expect); 61} 62 63function TestLocalDoesNotThrow(str) { 64 assertDoesNotThrow("(function(arg){ 'use strict'; " + str + "})()"); 65} 66 67// Test let declarations in statement positions. 68TestLocalThrows("if (true) let x;", SyntaxError); 69TestLocalThrows("if (true) {} else let x;", SyntaxError); 70TestLocalThrows("do let x; while (false)", SyntaxError); 71TestLocalThrows("while (false) let x;", SyntaxError); 72TestLocalThrows("label: let x;", SyntaxError); 73TestLocalThrows("for (;false;) let x;", SyntaxError); 74TestLocalDoesNotThrow("switch (true) { case true: let x; }"); 75TestLocalDoesNotThrow("switch (true) { default: let x; }"); 76 77// Test const declarations with initialisers in statement positions. 78TestLocalThrows("if (true) const x = 1;", SyntaxError); 79TestLocalThrows("if (true) {} else const x = 1;", SyntaxError); 80TestLocalThrows("do const x = 1; while (false)", SyntaxError); 81TestLocalThrows("while (false) const x = 1;", SyntaxError); 82TestLocalThrows("label: const x = 1;", SyntaxError); 83TestLocalThrows("for (;false;) const x = 1;", SyntaxError); 84TestLocalDoesNotThrow("switch (true) { case true: const x = 1; }"); 85TestLocalDoesNotThrow("switch (true) { default: const x = 1; }"); 86 87// Test const declarations without initialisers. 88TestLocalThrows("const x;", SyntaxError); 89TestLocalThrows("const x = 1, y;", SyntaxError); 90TestLocalThrows("const x, y = 1;", SyntaxError); 91 92// Test const declarations without initialisers in statement positions. 93TestLocalThrows("if (true) const x;", SyntaxError); 94TestLocalThrows("if (true) {} else const x;", SyntaxError); 95TestLocalThrows("do const x; while (false)", SyntaxError); 96TestLocalThrows("while (false) const x;", SyntaxError); 97TestLocalThrows("label: const x;", SyntaxError); 98TestLocalThrows("for (;false;) const x;", SyntaxError); 99TestLocalThrows("switch (true) { case true: const x; }", SyntaxError); 100TestLocalThrows("switch (true) { default: const x; }", SyntaxError); 101 102// Test var declarations in statement positions. 103TestLocalDoesNotThrow("if (true) var x;"); 104TestLocalDoesNotThrow("if (true) {} else var x;"); 105TestLocalDoesNotThrow("do var x; while (false)"); 106TestLocalDoesNotThrow("while (false) var x;"); 107TestLocalDoesNotThrow("label: var x;"); 108TestLocalDoesNotThrow("for (;false;) var x;"); 109TestLocalDoesNotThrow("switch (true) { case true: var x; }"); 110TestLocalDoesNotThrow("switch (true) { default: var x; }"); 111 112// Test class declarations with initialisers in statement positions. 113TestLocalThrows("if (true) class x { };", SyntaxError); 114TestLocalThrows("if (true) {} else class x { };", SyntaxError); 115TestLocalThrows("do class x { }; while (false)", SyntaxError); 116TestLocalThrows("while (false) class x { };", SyntaxError); 117TestLocalThrows("label: class x { };", SyntaxError); 118TestLocalThrows("for (;false;) class x { };", SyntaxError); 119TestLocalDoesNotThrow("switch (true) { case true: class x { }; }"); 120TestLocalDoesNotThrow("switch (true) { default: class x { }; }"); 121 122// Test that redeclarations of functions are only allowed in outermost scope. 123TestLocalThrows("{ let f; var f; }"); 124TestLocalThrows("{ var f; let f; }"); 125TestLocalThrows("{ function f() {} let f; }"); 126TestLocalThrows("{ let f; function f() {} }"); 127TestLocalThrows("{ function f() {} var f; }"); 128TestLocalThrows("{ var f; function f() {} }"); 129TestLocalThrows("{ function f() {} class f {} }"); 130TestLocalThrows("{ class f {}; function f() {} }"); 131TestLocalThrows("{ function f() {} function f() {} }"); 132TestLocalThrows("function f() {} let f;"); 133TestLocalThrows("let f; function f() {}"); 134TestLocalThrows("function f() {} class f {}"); 135TestLocalThrows("class f {}; function f() {}"); 136TestLocalDoesNotThrow("function arg() {}"); 137TestLocalDoesNotThrow("function f() {} var f;"); 138TestLocalDoesNotThrow("var f; function f() {}"); 139TestLocalDoesNotThrow("function f() {} function f() {}"); 140 141function g(f) { 142 function f() { return 1 } 143 return f() 144} 145assertEquals(1, g(function() { return 2 })) 146 147 148// Test function declarations in source element and 149// sloppy statement positions. 150function f() { 151 // Sloppy source element positions. 152 function g0() { 153 "use strict"; 154 // Strict source element positions. 155 function h() { } 156 { 157 function h1() { } 158 } 159 } 160 { 161 function g1() { } 162 } 163} 164f(); 165 166// Test function declarations in statement position in strict mode. 167TestLocalThrows("function f() { if (true) function g() {} }", SyntaxError); 168TestLocalThrows("function f() { if (true) {} else function g() {} }", SyntaxError); 169TestLocalThrows("function f() { do function g() {} while (false) }", SyntaxError); 170TestLocalThrows("function f() { while (false) function g() {} }", SyntaxError); 171TestLocalThrows("function f() { label: function g() {} }", SyntaxError); 172TestLocalThrows("function f() { for (;false;) function g() {} }", SyntaxError); 173TestLocalDoesNotThrow("function f() { switch (true) { case true: function g() {} } }"); 174TestLocalDoesNotThrow("function f() { switch (true) { default: function g() {} } }"); 175