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 52// NOTE: TestGlobal usually only tests the given string in the context 53// of a global object in dictionary mode. This is because we use 54// delete to get rid of any added properties. 55function TestGlobal(s,e) { 56 // Collect the global properties before the call. 57 var properties = []; 58 for (var key in this) properties.push(key); 59 // Compute the result. 60 var result; 61 try { 62 var code = s + (e ? "; $$$result=" + e : ""); 63 if (this.execScript) { 64 execScript(code); 65 } else { 66 this.eval(code); 67 } 68 // Avoid issues if $$$result is not defined by 69 // reading it through this. 70 result = this.$$$result; 71 } catch (x) { 72 result = CheckException(x); 73 } 74 // Get rid of any introduced global properties before 75 // returning the result. 76 for (var key in this) { 77 if (properties.indexOf(key) == -1) delete this[key]; 78 } 79 return result; 80} 81 82 83function TestContext(s,e) { 84 try { 85 // Use a with-statement to force the system to do dynamic 86 // declarations of the introduced variables or constants. 87 with ({}) { 88 return eval(s + ";" + e); 89 } 90 } catch (x) { 91 return CheckException(x); 92 } 93} 94 95 96function TestAll(expected,s,opt_e) { 97 var e = ""; 98 var msg = s; 99 if (opt_e) { e = opt_e; msg += "; " + opt_e; } 100 assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'"); 101 assertEquals(expected, TestGlobal(s,e), "global:'" + msg + "'"); 102 assertEquals(expected, TestContext(s,e), "context:'" + msg + "'"); 103} 104 105 106function TestConflict(def0, def1) { 107 // No eval. 108 TestAll("TypeError", def0 +'; ' + def1); 109 // Eval everything. 110 TestAll("TypeError", 'eval("' + def0 + '; ' + def1 + '")'); 111 // Eval first definition. 112 TestAll("TypeError", 'eval("' + def0 +'"); ' + def1); 113 // Eval second definition. 114 TestAll("TypeError", def0 + '; eval("' + def1 + '")'); 115 // Eval both definitions separately. 116 TestAll("TypeError", 'eval("' + def0 +'"); eval("' + def1 + '")'); 117} 118 119 120// Test conflicting definitions. 121TestConflict("const x", "var x"); 122TestConflict("const x = 0", "var x"); 123TestConflict("const x", "var x = 0"); 124TestConflict("const x = 0", "var x = 0"); 125 126TestConflict("var x", "const x"); 127TestConflict("var x = 0", "const x"); 128TestConflict("var x", "const x = 0"); 129TestConflict("var x = 0", "const x = 0"); 130 131TestConflict("const x = undefined", "var x"); 132TestConflict("const x", "var x = undefined"); 133TestConflict("const x = undefined", "var x = undefined"); 134 135TestConflict("var x = undefined", "const x"); 136TestConflict("var x", "const x = undefined"); 137TestConflict("var x = undefined", "const x = undefined"); 138 139TestConflict("const x = undefined", "var x = 0"); 140TestConflict("const x = 0", "var x = undefined"); 141 142TestConflict("var x = undefined", "const x = 0"); 143TestConflict("var x = 0", "const x = undefined"); 144 145TestConflict("const x", "function x() { }"); 146TestConflict("const x = 0", "function x() { }"); 147TestConflict("const x = undefined", "function x() { }"); 148 149TestConflict("function x() { }", "const x"); 150TestConflict("function x() { }", "const x = 0"); 151TestConflict("function x() { }", "const x = undefined"); 152 153TestConflict("const x, y", "var x"); 154TestConflict("const x, y", "var y"); 155TestConflict("const x = 0, y", "var x"); 156TestConflict("const x = 0, y", "var y"); 157TestConflict("const x, y = 0", "var x"); 158TestConflict("const x, y = 0", "var y"); 159TestConflict("const x = 0, y = 0", "var x"); 160TestConflict("const x = 0, y = 0", "var y"); 161 162TestConflict("var x", "const x, y"); 163TestConflict("var y", "const x, y"); 164TestConflict("var x", "const x = 0, y"); 165TestConflict("var y", "const x = 0, y"); 166TestConflict("var x", "const x, y = 0"); 167TestConflict("var y", "const x, y = 0"); 168TestConflict("var x", "const x = 0, y = 0"); 169TestConflict("var y", "const x = 0, y = 0"); 170 171 172// Test that multiple conflicts do not cause issues. 173TestConflict("var x, y", "const x, y"); 174 175 176// Test that repeated const declarations throw redeclaration errors. 177TestConflict("const x", "const x"); 178TestConflict("const x = 0", "const x"); 179TestConflict("const x", "const x = 0"); 180TestConflict("const x = 0", "const x = 0"); 181 182TestConflict("const x = undefined", "const x"); 183TestConflict("const x", "const x = undefined"); 184TestConflict("const x = undefined", "const x = undefined"); 185 186TestConflict("const x = undefined", "const x = 0"); 187TestConflict("const x = 0", "const x = undefined"); 188 189TestConflict("const x, y", "const x"); 190TestConflict("const x, y", "const y"); 191TestConflict("const x = 0, y", "const x"); 192TestConflict("const x = 0, y", "const y"); 193TestConflict("const x, y = 0", "const x"); 194TestConflict("const x, y = 0", "const y"); 195TestConflict("const x = 0, y = 0", "const x"); 196TestConflict("const x = 0, y = 0", "const y"); 197 198TestConflict("const x", "const x, y"); 199TestConflict("const y", "const x, y"); 200TestConflict("const x", "const x = 0, y"); 201TestConflict("const y", "const x = 0, y"); 202TestConflict("const x", "const x, y = 0"); 203TestConflict("const y", "const x, y = 0"); 204TestConflict("const x", "const x = 0, y = 0"); 205TestConflict("const y", "const x = 0, y = 0"); 206 207 208// Test that multiple const conflicts do not cause issues. 209TestConflict("const x, y", "const x, y"); 210 211 212// Test that const inside loop behaves correctly. 213var loop = "for (var i = 0; i < 3; i++) { const x = i; }"; 214TestAll(0, loop, "x"); 215TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x"); 216 217 218// Test that const inside with behaves correctly. 219TestAll(87, "with ({x:42}) { const x = 87; }", "x"); 220TestAll(undefined, "with ({x:42}) { const x; }", "x"); 221