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 31 function props(x) { 32 var array = []; 33 for (let p in x) array.push(p); 34 return array.sort(); 35 } 36 37 assertEquals(0, props({}).length); 38 assertEquals(1, props({x:1}).length); 39 assertEquals(2, props({x:1, y:2}).length); 40 41 assertArrayEquals(["x"], props({x:1})); 42 assertArrayEquals(["x", "y"], props({x:1, y:2})); 43 assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3})); 44 45 assertEquals(0, props([]).length); 46 assertEquals(1, props([1]).length); 47 assertEquals(2, props([1,2]).length); 48 49 assertArrayEquals(["0"], props([1])); 50 assertArrayEquals(["0", "1"], props([1,2])); 51 assertArrayEquals(["0", "1", "2"], props([1,2,3])); 52 53 var o = {}; 54 var a = []; 55 let i = "outer_i"; 56 let s = "outer_s"; 57 for (let i = 0x0020; i < 0x01ff; i+=2) { 58 let s = 'char:' + String.fromCharCode(i); 59 a.push(s); 60 o[s] = i; 61 } 62 assertArrayEquals(a, props(o)); 63 assertEquals(i, "outer_i"); 64 assertEquals(s, "outer_s"); 65 66 var a = []; 67 assertEquals(0, props(a).length); 68 a[Math.pow(2,30)-1] = 0; 69 assertEquals(1, props(a).length); 70 a[Math.pow(2,31)-1] = 0; 71 assertEquals(2, props(a).length); 72 a[1] = 0; 73 assertEquals(3, props(a).length); 74 75 var result = ''; 76 for (let p in {a : [0], b : 1}) { result += p; } 77 assertEquals('ab', result); 78 79 var result = ''; 80 for (let p in {a : {v:1}, b : 1}) { result += p; } 81 assertEquals('ab', result); 82 83 var result = ''; 84 for (let p in { get a() {}, b : 1}) { result += p; } 85 assertEquals('ab', result); 86 87 var result = ''; 88 for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; } 89 assertEquals('ab', result); 90 91 92 // Check that there is exactly one variable without initializer 93 // in a for-in statement with let variables. 94 assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError); 95 assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError); 96 assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError); 97 assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError); 98 assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError); 99 assertThrows("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. 104 function 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 } 113 closures1(); 114 115 116 function 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 } 127 closures2(); 128 129 130 function 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 } 139 closure_in_for_init(); 140 141 142 function 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 } 149 closure_in_for_cond(); 150 151 152 function 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 } 159 closure_in_for_next(); 160 161 162 // In a for-in statement the iteration variable is fresh 163 // for each iteration. 164 function 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 } 175 closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}}); 176 177 // Check normal for statement completion values. 178 assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }")); 179 assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }")); 180 assertEquals(undefined, eval("for (let i = 0; false;) { }")); 181 assertEquals(undefined, eval("for (const i = 0; false;) { }")); 182 assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }")); 183 assertEquals(undefined, eval("for (let i = 0; false;) { i; }")); 184 assertEquals(undefined, eval("for (const i = 0; false;) { i; }")); 185 assertEquals(undefined, eval("for (let i = 0; true;) { break; }")); 186 assertEquals(undefined, eval("for (const i = 0; true;) { break; }")); 187 assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }")); 188 assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }")); 189 assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }")); 190 assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }")); 191 assertEquals(0, eval("for (let i = 0; true;) { i; break; }")); 192 assertEquals(0, eval("for (const i = 0; true;) { i; break; }")); 193 assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }")); 194 assertEquals( 195 undefined, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }")); 196 assertEquals( 197 undefined, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }")); 198 assertEquals( 199 undefined, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }")); 200 assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }")); 201 assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }")); 202 assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }")); 203