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