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