Index: test/mjsunit/harmony/block-eval-var-over-let.js |
diff --git a/test/mjsunit/harmony/block-eval-var-over-let.js b/test/mjsunit/harmony/block-eval-var-over-let.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..292d073c81002e5239c525fdceb66a9e5245b392 |
--- /dev/null |
+++ b/test/mjsunit/harmony/block-eval-var-over-let.js |
@@ -0,0 +1,191 @@ |
+// Copyright 2015 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function --no-legacy-const |
+ |
+// Var-let conflict in a function throws, even if the var is in an eval |
+ |
+let caught = false; |
+ |
+// Throws at the top level of a function |
+try { |
+ (function() { |
+ let x = 1; |
+ eval('var x = 2'); |
+ })() |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// If the eval is in its own block scope, throws |
+caught = false; |
+try { |
+ (function() { |
+ let y = 1; |
+ { eval('var y = 2'); } |
+ })() |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// If the let is in its own block scope, with the eval, throws |
+caught = false |
+try { |
+ (function() { |
+ { |
+ let x = 1; |
+ eval('var x = 2'); |
+ } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// Legal if the let is no longer visible |
+caught = false |
+try { |
+ (function() { |
+ { |
+ let x = 1; |
+ } |
+ eval('var x = 2'); |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertFalse(caught); |
+ |
+// All the same works for const: |
+// Throws at the top level of a function |
+try { |
+ (function() { |
+ const x = 1; |
+ eval('var x = 2'); |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// If the eval is in its own block scope, throws |
+caught = false; |
+try { |
+ (function() { |
+ const y = 1; |
+ { eval('var y = 2'); } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// If the const is in its own block scope, with the eval, throws |
+caught = false |
+try { |
+ (function() { |
+ { |
+ const x = 1; |
+ eval('var x = 2'); |
+ } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// Legal if the const is no longer visible |
+caught = false |
+try { |
+ (function() { |
+ { |
+ const x = 1; |
+ } |
+ eval('var x = 2'); |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertFalse(caught); |
+ |
+// In global scope |
+caught = false; |
+try { |
+ let z = 1; |
+ eval('var z = 2'); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// Let declarations beyond a function boundary don't conflict |
+caught = false; |
+try { |
+ let a = 1; |
+ (function() { |
+ eval('var a'); |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertFalse(caught); |
+ |
+// var across with doesn't conflict |
+caught = false; |
+try { |
+ (function() { |
+ with ({x: 1}) { |
+ eval("var x = 2;"); |
+ } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertFalse(caught); |
+ |
+// var can still conflict with let across a with |
+caught = false; |
+try { |
+ (function() { |
+ let x; |
+ with ({x: 1}) { |
+ eval("var x = 2;"); |
+ } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// Functions declared in eval also conflict |
+caught = false |
+try { |
+ (function() { |
+ { |
+ let x = 1; |
+ eval('function x() {}'); |
+ } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+assertTrue(caught); |
+ |
+// TODO(littledan): Hoisting x out of the block should be |
+// prevented in this case BUG(v8:4479) |
+caught = false |
+try { |
+ (function() { |
+ { |
+ let x = 1; |
+ eval('{ function x() {} }'); |
+ } |
+ })(); |
+} catch (e) { |
+ caught = true; |
+} |
+// TODO(littledan): switch to assertTrue when bug is fixed |
+assertTrue(caught); |