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