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 // Flags: --allow-natives-syntax 29 // Test functionality of block scopes. 30 31 "use strict"; 32 33 // Hoisting of var declarations. 34 function f1() { 35 { 36 var x = 1; 37 var y; 38 } 39 assertEquals(1, x) 40 assertEquals(undefined, y) 41 } 42 for (var j = 0; j < 5; ++j) f1(); 43 %OptimizeFunctionOnNextCall(f1); 44 f1(); 45 assertTrue(%GetOptimizationStatus(f1) != 2); 46 47 // Dynamic lookup in and through block contexts. 48 function f2(one) { 49 var x = one + 1; 50 let y = one + 2; 51 const u = one + 4; 52 class a { static foo() { return one + 6; } } 53 { 54 let z = one + 3; 55 const v = one + 5; 56 class b { static foo() { return one + 7; } } 57 assertEquals(1, eval('one')); 58 assertEquals(2, eval('x')); 59 assertEquals(3, eval('y')); 60 assertEquals(4, eval('z')); 61 assertEquals(5, eval('u')); 62 assertEquals(6, eval('v')); 63 assertEquals(7, eval('a.foo()')); 64 assertEquals(8, eval('b.foo()')); 65 } 66 } 67 68 f2(1); 69 70 // Lookup in and through block contexts. 71 function f3(one) { 72 var x = one + 1; 73 let y = one + 2; 74 const u = one + 4; 75 class a { static foo() { return one + 6; } } 76 { 77 let z = one + 3; 78 const v = one + 5; 79 class b { static foo() { return one + 7; } } 80 assertEquals(1, one); 81 assertEquals(2, x); 82 assertEquals(3, y); 83 assertEquals(4, z); 84 assertEquals(5, u); 85 assertEquals(6, v); 86 assertEquals(7, a.foo()); 87 assertEquals(8, b.foo()); 88 } 89 } 90 for (var j = 0; j < 5; ++j) f3(1); 91 %OptimizeFunctionOnNextCall(f3); 92 f3(1); 93 94 95 96 // Dynamic lookup from closure. 97 function f4(one) { 98 var x = one + 1; 99 let y = one + 2; 100 const u = one + 4; 101 class a { static foo() { return one + 6; } } 102 { 103 let z = one + 3; 104 const v = one + 5; 105 class b { static foo() { return one + 7; } } 106 function f() { 107 assertEquals(1, eval('one')); 108 assertEquals(2, eval('x')); 109 assertEquals(3, eval('y')); 110 assertEquals(4, eval('z')); 111 assertEquals(5, eval('u')); 112 assertEquals(6, eval('v')); 113 assertEquals(7, eval('a.foo()')); 114 assertEquals(8, eval('b.foo()')); 115 } 116 f(); 117 } 118 } 119 f4(1); 120 121 122 // Lookup from closure. 123 function f5(one) { 124 var x = one + 1; 125 let y = one + 2; 126 const u = one + 4; 127 class a { static foo() { return one + 6; } } 128 { 129 let z = one + 3; 130 const v = one + 5; 131 class b { static foo() { return one + 7; } } 132 function f() { 133 assertEquals(1, one); 134 assertEquals(2, x); 135 assertEquals(3, y); 136 assertEquals(4, z); 137 assertEquals(5, u); 138 assertEquals(6, v); 139 assertEquals(7, a.foo()); 140 assertEquals(8, b.foo()); 141 } 142 f(); 143 } 144 } 145 f5(1); 146 147 148 // Return from block. 149 function f6() { 150 let x = 1; 151 const u = 3; 152 { 153 let y = 2; 154 const v = 4; 155 return x + y; 156 } 157 } 158 assertEquals(3, f6(6)); 159 160 161 // Variable shadowing and lookup. 162 function f7(a) { 163 let b = 1; 164 var c = 1; 165 var d = 1; 166 const e = 1; 167 class f { static foo() { return 1; } } 168 { // let variables shadowing argument, let, const, class and var variables 169 let a = 2; 170 let b = 2; 171 let c = 2; 172 let e = 2; 173 let f = 2; 174 assertEquals(2,a); 175 assertEquals(2,b); 176 assertEquals(2,c); 177 assertEquals(2,e); 178 assertEquals(2,f); 179 } 180 { // const variables shadowing argument, let, const and var variables 181 const a = 2; 182 const b = 2; 183 const c = 2; 184 const e = 2; 185 const f = 2; 186 assertEquals(2,a); 187 assertEquals(2,b); 188 assertEquals(2,c); 189 assertEquals(2,e); 190 assertEquals(2,f); 191 } 192 { // class variables shadowing argument, let, const and var variables 193 class a { static foo() { return 2; } } 194 class b { static foo() { return 2; } } 195 class c { static foo() { return 2; } } 196 class d { static foo() { return 2; } } 197 class e { static foo() { return 2; } } 198 class f { static foo() { return 2; } } 199 assertEquals(2,a.foo()); 200 assertEquals(2,b.foo()); 201 assertEquals(2,c.foo()); 202 assertEquals(2,e.foo()); 203 assertEquals(2,f.foo()); 204 } 205 try { 206 throw 'stuff1'; 207 } catch (a) { 208 assertEquals('stuff1',a); 209 // catch variable shadowing argument 210 a = 2; 211 assertEquals(2,a); 212 { 213 // let variable shadowing catch variable 214 let a = 3; 215 assertEquals(3,a); 216 try { 217 throw 'stuff2'; 218 } catch (a) { 219 assertEquals('stuff2',a); 220 // catch variable shadowing let variable 221 a = 4; 222 assertEquals(4,a); 223 } 224 assertEquals(3,a); 225 } 226 assertEquals(2,a); 227 } 228 try { 229 throw 'stuff3'; 230 } catch (c) { 231 // catch variable shadowing var variable 232 assertEquals('stuff3',c); 233 { 234 // const variable shadowing catch variable 235 const c = 3; 236 assertEquals(3,c); 237 } 238 assertEquals('stuff3',c); 239 try { 240 throw 'stuff4'; 241 } catch(c) { 242 assertEquals('stuff4',c); 243 // catch variable shadowing catch variable 244 c = 3; 245 assertEquals(3,c); 246 } 247 (function(c) { 248 // argument shadowing catch variable 249 c = 3; 250 assertEquals(3,c); 251 })(); 252 assertEquals('stuff3', c); 253 (function() { 254 // var variable shadowing catch variable 255 var c = 3; 256 })(); 257 assertEquals('stuff3', c); 258 c = 2; 259 } 260 assertEquals(1,c); 261 (function(a,b,c,e,f) { 262 // arguments shadowing argument, let, const, class and var variable 263 a = 2; 264 b = 2; 265 c = 2; 266 e = 2; 267 f = 2; 268 assertEquals(2,a); 269 assertEquals(2,b); 270 assertEquals(2,c); 271 assertEquals(2,e); 272 assertEquals(2,f); 273 // var variable shadowing var variable 274 var d = 2; 275 })(1,1); 276 assertEquals(1,a); 277 assertEquals(1,b); 278 assertEquals(1,c); 279 assertEquals(1,d); 280 assertEquals(1,e); 281 assertEquals(1,f.foo()); 282 } 283 f7(1); 284 285 286 // Ensure let and const variables are block local 287 // and var variables function local. 288 function f8() { 289 var let_accessors = []; 290 var var_accessors = []; 291 var const_accessors = []; 292 var class_accessors = []; 293 for (var i = 0; i < 10; i++) { 294 let x = i; 295 var y = i; 296 const z = i; 297 class a { static foo() { return x; } } 298 let_accessors[i] = function() { return x; } 299 var_accessors[i] = function() { return y; } 300 const_accessors[i] = function() { return z; } 301 class_accessors[i] = function() { return a; } 302 } 303 for (var j = 0; j < 10; j++) { 304 y = j + 10; 305 assertEquals(j, let_accessors[j]()); 306 assertEquals(y, var_accessors[j]()); 307 assertEquals(j, const_accessors[j]()); 308 assertEquals(j, class_accessors[j]().foo()); 309 } 310 } 311 f8(); 312