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 28function props(x) { 29 var array = []; 30 for (let p in x) array.push(p); 31 return array.sort(); 32} 33 34assertEquals(0, props({}).length); 35assertEquals(1, props({x:1}).length); 36assertEquals(2, props({x:1, y:2}).length); 37 38assertArrayEquals(["x"], props({x:1})); 39assertArrayEquals(["x", "y"], props({x:1, y:2})); 40assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3})); 41 42assertEquals(0, props([]).length); 43assertEquals(1, props([1]).length); 44assertEquals(2, props([1,2]).length); 45 46assertArrayEquals(["0"], props([1])); 47assertArrayEquals(["0", "1"], props([1,2])); 48assertArrayEquals(["0", "1", "2"], props([1,2,3])); 49 50var o = {}; 51var a = []; 52let i = "outer_i"; 53let s = "outer_s"; 54for (let i = 0x0020; i < 0x01ff; i+=2) { 55 let s = 'char:' + String.fromCharCode(i); 56 a.push(s); 57 o[s] = i; 58} 59assertArrayEquals(a, props(o)); 60assertEquals(i, "outer_i"); 61assertEquals(s, "outer_s"); 62 63var a = []; 64assertEquals(0, props(a).length); 65a[Math.pow(2,30)-1] = 0; 66assertEquals(1, props(a).length); 67a[Math.pow(2,31)-1] = 0; 68assertEquals(2, props(a).length); 69a[1] = 0; 70assertEquals(3, props(a).length); 71 72var result = ''; 73for (let p in {a : [0], b : 1}) { result += p; } 74assertEquals('ab', result); 75 76var result = ''; 77for (let p in {a : {v:1}, b : 1}) { result += p; } 78assertEquals('ab', result); 79 80var result = ''; 81for (let p in { get a() {}, b : 1}) { result += p; } 82assertEquals('ab', result); 83 84var result = ''; 85for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; } 86assertEquals('ab', result); 87 88 89// Check that there is exactly one variable without initializer 90// in a for-in statement with let variables. 91assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError); 92assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError); 93assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError); 94assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError); 95assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError); 96assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError); 97 98 99// In a normal for statement the iteration variable is 100// freshly allocated for each iteration. 101function closures1() { 102 let a = []; 103 for (let i = 0; i < 5; ++i) { 104 a.push(function () { return i; }); 105 } 106 for (let j = 0; j < 5; ++j) { 107 assertEquals(j, a[j]()); 108 } 109} 110closures1(); 111 112 113function closures2() { 114 let a = [], b = []; 115 for (let i = 0, j = 10; i < 5; ++i, ++j) { 116 a.push(function () { return i; }); 117 b.push(function () { return j; }); 118 } 119 for (let k = 0; k < 5; ++k) { 120 assertEquals(k, a[k]()); 121 assertEquals(k + 10, b[k]()); 122 } 123} 124closures2(); 125 126 127function closure_in_for_init() { 128 let a = []; 129 for (let i = 0, f = function() { return i }; i < 5; ++i) { 130 a.push(f); 131 } 132 for (let k = 0; k < 5; ++k) { 133 assertEquals(0, a[k]()); 134 } 135} 136closure_in_for_init(); 137 138 139function closure_in_for_cond() { 140 let a = []; 141 for (let i = 0; a.push(function () { return i; }), i < 5; ++i) { } 142 for (let k = 0; k < 5; ++k) { 143 assertEquals(k, a[k]()); 144 } 145} 146closure_in_for_cond(); 147 148 149function closure_in_for_next() { 150 let a = []; 151 for (let i = 0; i < 5; a.push(function () { return i; }), ++i) { } 152 for (let k = 0; k < 5; ++k) { 153 assertEquals(k + 1, a[k]()); 154 } 155} 156closure_in_for_next(); 157 158 159// In a for-in statement the iteration variable is fresh 160// for each iteration. 161function closures3(x) { 162 let a = []; 163 for (let p in x) { 164 a.push(function () { return p; }); 165 } 166 let k = 0; 167 for (let q in x) { 168 assertEquals(q, a[k]()); 169 ++k; 170 } 171} 172closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}}); 173 174// Check normal for statement completion values. 175assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }")); 176assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }")); 177assertEquals(undefined, eval("for (let i = 0; false;) { }")); 178assertEquals(undefined, eval("for (const i = 0; false;) { }")); 179assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }")); 180assertEquals(undefined, eval("for (let i = 0; false;) { i; }")); 181assertEquals(undefined, eval("for (const i = 0; false;) { i; }")); 182assertEquals(undefined, eval("for (let i = 0; true;) { break; }")); 183assertEquals(undefined, eval("for (const i = 0; true;) { break; }")); 184assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }")); 185assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }")); 186assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }")); 187assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }")); 188assertEquals(0, eval("for (let i = 0; true;) { i; break; }")); 189assertEquals(0, eval("for (const i = 0; true;) { i; break; }")); 190assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }")); 191assertEquals( 192 undefined, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }")); 193assertEquals( 194 undefined, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }")); 195assertEquals( 196 undefined, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }")); 197assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }")); 198assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }")); 199assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }")); 200