1// Copyright 2008 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 for const semantics. 29 30 31function CheckException(e) { 32 var string = e.toString(); 33 var index = string.indexOf(':'); 34 assertTrue(index >= 0); 35 var name = string.slice(0, index); 36 assertTrue(string.indexOf("has already been declared") >= 0 || 37 string.indexOf("redeclaration") >= 0); 38 if (name == 'SyntaxError') return 'TypeError'; 39 return name; 40} 41 42 43function TestLocal(s,e) { 44 try { 45 return eval("(function(){" + s + ";return " + e + "})")(); 46 } catch (x) { 47 return CheckException(x); 48 } 49} 50 51 52function TestContext(s,e) { 53 try { 54 // Use a with-statement to force the system to do dynamic 55 // declarations of the introduced variables or constants. 56 with ({}) { 57 return eval(s + ";" + e); 58 } 59 } catch (x) { 60 return CheckException(x); 61 } 62} 63 64 65function TestAll(expected,s,opt_e) { 66 var e = ""; 67 var msg = s; 68 if (opt_e) { e = opt_e; msg += "; " + opt_e; } 69 assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'"); 70 assertEquals(expected, TestContext(s,e), "context:'" + msg + "'"); 71} 72 73 74function TestConflict(def0, def1) { 75 // No eval. 76 TestAll("TypeError", def0 +'; ' + def1); 77 // Eval everything. 78 TestAll("TypeError", 'eval("' + def0 + '; ' + def1 + '")'); 79 // Eval first definition. 80 TestAll("TypeError", 'eval("' + def0 +'"); ' + def1); 81 // Eval second definition. 82 TestAll("TypeError", def0 + '; eval("' + def1 +'")'); 83 // Eval both definitions separately. 84 TestAll("TypeError", 'eval("' + def0 +'"); eval("' + def1 + '")'); 85} 86 87 88// Test conflicting definitions. 89TestConflict("const x", "var x"); 90TestConflict("const x = 0", "var x"); 91TestConflict("const x", "var x = 0"); 92TestConflict("const x = 0", "var x = 0"); 93 94TestConflict("var x", "const x"); 95TestConflict("var x = 0", "const x"); 96TestConflict("var x", "const x = 0"); 97TestConflict("var x = 0", "const x = 0"); 98 99TestConflict("const x = undefined", "var x"); 100TestConflict("const x", "var x = undefined"); 101TestConflict("const x = undefined", "var x = undefined"); 102 103TestConflict("var x = undefined", "const x"); 104TestConflict("var x", "const x = undefined"); 105TestConflict("var x = undefined", "const x = undefined"); 106 107TestConflict("const x = undefined", "var x = 0"); 108TestConflict("const x = 0", "var x = undefined"); 109 110TestConflict("var x = undefined", "const x = 0"); 111TestConflict("var x = 0", "const x = undefined"); 112 113TestConflict("const x", "function x() { }"); 114TestConflict("const x = 0", "function x() { }"); 115TestConflict("const x = undefined", "function x() { }"); 116 117TestConflict("function x() { }", "const x"); 118TestConflict("function x() { }", "const x = 0"); 119TestConflict("function x() { }", "const x = undefined"); 120 121TestConflict("const x, y", "var x"); 122TestConflict("const x, y", "var y"); 123TestConflict("const x = 0, y", "var x"); 124TestConflict("const x = 0, y", "var y"); 125TestConflict("const x, y = 0", "var x"); 126TestConflict("const x, y = 0", "var y"); 127TestConflict("const x = 0, y = 0", "var x"); 128TestConflict("const x = 0, y = 0", "var y"); 129 130TestConflict("var x", "const x, y"); 131TestConflict("var y", "const x, y"); 132TestConflict("var x", "const x = 0, y"); 133TestConflict("var y", "const x = 0, y"); 134TestConflict("var x", "const x, y = 0"); 135TestConflict("var y", "const x, y = 0"); 136TestConflict("var x", "const x = 0, y = 0"); 137TestConflict("var y", "const x = 0, y = 0"); 138 139 140// Test that multiple conflicts do not cause issues. 141TestConflict("var x, y", "const x, y"); 142 143 144// Test that repeated const declarations throw redeclaration errors. 145TestConflict("const x", "const x"); 146TestConflict("const x = 0", "const x"); 147TestConflict("const x", "const x = 0"); 148TestConflict("const x = 0", "const x = 0"); 149 150TestConflict("const x = undefined", "const x"); 151TestConflict("const x", "const x = undefined"); 152TestConflict("const x = undefined", "const x = undefined"); 153 154TestConflict("const x = undefined", "const x = 0"); 155TestConflict("const x = 0", "const x = undefined"); 156 157TestConflict("const x, y", "const x"); 158TestConflict("const x, y", "const y"); 159TestConflict("const x = 0, y", "const x"); 160TestConflict("const x = 0, y", "const y"); 161TestConflict("const x, y = 0", "const x"); 162TestConflict("const x, y = 0", "const y"); 163TestConflict("const x = 0, y = 0", "const x"); 164TestConflict("const x = 0, y = 0", "const y"); 165 166TestConflict("const x", "const x, y"); 167TestConflict("const y", "const x, y"); 168TestConflict("const x", "const x = 0, y"); 169TestConflict("const y", "const x = 0, y"); 170TestConflict("const x", "const x, y = 0"); 171TestConflict("const y", "const x, y = 0"); 172TestConflict("const x", "const x = 0, y = 0"); 173TestConflict("const y", "const x = 0, y = 0"); 174 175 176// Test that multiple const conflicts do not cause issues. 177TestConflict("const x, y", "const x, y"); 178 179 180// Test that const inside loop behaves correctly. 181var loop = "for (var i = 0; i < 3; i++) { const x = i; }"; 182TestAll(0, loop, "x"); 183TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x"); 184 185 186// Test that const inside with behaves correctly. 187TestAll(87, "with ({x:42}) { const x = 87; }", "x"); 188TestAll(undefined, "with ({x:42}) { const x; }", "x"); 189 190 191// Additional tests for how various combinations of re-declarations affect 192// the values of the var/const in question. 193try { 194 eval("var undefined;"); 195} catch (ex) { 196 assertUnreachable("undefined (1) has thrown"); 197} 198 199var original_undef = undefined; 200var undefined = 1; // Should be silently ignored. 201assertEquals(original_undef, undefined, "undefined got overwritten"); 202undefined = original_undef; 203 204const e = 1; eval('var e = 2'); 205assertEquals(1, e, "e has wrong value"); 206 207const h; eval('var h = 1'); 208assertEquals(undefined, h, "h has wrong value"); 209 210eval("Object.defineProperty(this, 'i', { writable: true });" 211 + "const i = 7;" 212 + "assertEquals(7, i, \"i has wrong value\");"); 213 214var global = this; 215Object.defineProperty(global, 'j', { value: 100, writable: true }); 216assertEquals(100, j); 217// The const declaration stays configurable, so the declaration above goes 218// through even though the const declaration is hoisted above. 219const j = 2; 220assertEquals(2, j, "j has wrong value"); 221 222var k = 1; 223try { eval('const k'); } catch(e) { } 224assertEquals(1, k, "k has wrong value"); 225try { eval('const k = 10'); } catch(e) { } 226assertEquals(1, k, "k has wrong value"); 227