1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function --no-legacy-const
6
7// Var-let conflict in a function throws, even if the var is in an eval
8
9// Throws at the top level of a function
10assertThrows(function() {
11  let x = 1;
12  eval('var x');
13}, TypeError);
14
15// If the eval is in its own block scope, throws
16assertThrows(function() {
17  let y = 1;
18  { eval('var y'); }
19}, TypeError);
20
21// If the let is in its own block scope, with the eval, throws
22assertThrows(function() {
23  {
24    let x = 1;
25    eval('var x');
26  }
27}, TypeError);
28
29// Legal if the let is no longer visible
30assertDoesNotThrow(function() {
31  {
32    let x = 1;
33  }
34  eval('var x');
35});
36
37// All the same works for const:
38// Throws at the top level of a function
39assertThrows(function() {
40  const x = 1;
41  eval('var x');
42}, TypeError);
43
44// If the eval is in its own block scope, throws
45assertThrows(function() {
46  const y = 1;
47  { eval('var y'); }
48}, TypeError);
49
50// If the const is in its own block scope, with the eval, throws
51assertThrows(function() {
52  {
53    const x = 1;
54    eval('var x');
55  }
56}, TypeError);
57
58// Legal if the const is no longer visible
59assertDoesNotThrow(function() {
60  {
61    const x = 1;
62  }
63  eval('var x');
64});
65
66// In global scope
67let caught = false;
68try {
69  let z = 1;
70  eval('var z');
71} catch (e) {
72  caught = true;
73}
74assertTrue(caught);
75
76// Let declarations beyond a function boundary don't conflict
77caught = false;
78try {
79  let a = 1;
80  (function() {
81    eval('var a');
82  })();
83} catch (e) {
84  caught = true;
85}
86assertFalse(caught);
87
88// var across with doesn't conflict
89caught = false;
90try {
91  (function() {
92    with ({x: 1}) {
93      eval("var x");
94    }
95  })();
96} catch (e) {
97  caught = true;
98}
99assertFalse(caught);
100
101// var can still conflict with let across a with
102caught = false;
103try {
104  (function() {
105    let x;
106    with ({x: 1}) {
107      eval("var x");
108    }
109  })();
110} catch (e) {
111  caught = true;
112}
113assertTrue(caught);
114
115// Functions declared in eval also conflict
116caught = false
117try {
118  (function() {
119    {
120      let x = 1;
121      eval('function x() {}');
122    }
123  })();
124} catch (e) {
125  caught = true;
126}
127assertTrue(caught);
128
129// TODO(littledan): Hoisting x out of the block should be
130// prevented in this case BUG(v8:4479)
131caught = false
132try {
133  (function() {
134    {
135      let x = 1;
136      eval('{ function x() {} }');
137    }
138  })();
139} catch (e) {
140  caught = true;
141}
142// TODO(littledan): switch to assertTrue when bug is fixed
143assertTrue(caught);
144