Reviewers: rossberg,

Message:
PTAL.

Description:
Fix load of potentially eval-shadowed let bindings.


BUG=
TEST=test/mjsunit/harmony/block-let-semantics.js


Please review this at http://codereview.chromium.org/8118032/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/ia32/full-codegen-ia32.cc
  M test/mjsunit/harmony/block-let-semantics.js


Index: src/ia32/full-codegen-ia32.cc
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index d45a9cdaeea3ab3725152056bb3a87ecde43e77d..b66711fb7693fa82cd8dd33c01e67380092dee90 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1207,10 +1207,16 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
   } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == Variable::CONST) {
+    if (local->mode() == Variable::CONST ||
+        local->mode() == Variable::LET) {
       __ cmp(eax, isolate()->factory()->the_hole_value());
       __ j(not_equal, done);
-      __ mov(eax, isolate()->factory()->undefined_value());
+      if (local->mode() == Variable::CONST) {
+        __ mov(eax, isolate()->factory()->undefined_value());
+      } else {  // Variable::LET
+        __ push(Immediate(var->name()));
+        __ CallRuntime(Runtime::kThrowReferenceError, 1);
+      }
     }
     __ jmp(done);
   }
Index: test/mjsunit/harmony/block-let-semantics.js
diff --git a/test/mjsunit/harmony/block-let-semantics.js b/test/mjsunit/harmony/block-let-semantics.js index 198c3b4fb96803b415fdc65e0c69d3573eb23465..f50c3ed03f140eb47831a2b3992e9bdfb8067d6a 100644
--- a/test/mjsunit/harmony/block-let-semantics.js
+++ b/test/mjsunit/harmony/block-let-semantics.js
@@ -81,13 +81,20 @@ TestAll('f()(); let x; function f() { return function() { x += 1; } }');
 TestAll('f()(); let x; function f() { return function() { ++x; } }');
 TestAll('f()(); let x; function f() { return function() { x++; } }');

-// Use in before initialization with a dynamic lookup.
+// Use before initialization with a dynamic lookup.
 TestAll('eval("x + 1;"); let x;');
 TestAll('eval("x = 1;"); let x;');
 TestAll('eval("x += 1;"); let x;');
 TestAll('eval("++x;"); let x;');
 TestAll('eval("x++;"); let x;');

+// Use before initialization with check for eval-shadowed bindings.
+TestAll('function f() { eval("var y = 2;"); x + 1; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); x = 1; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); x += 1; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); ++x; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); x++; }; f(); let x;');
+
 // Test that variables introduced by function declarations are created and
 // initialized upon entering a function / block scope.
 function f() {
@@ -136,3 +143,19 @@ function f2() {
   }
   assertEquals(5, n());
 }
+
+// Test that resolution of let bound variables works with scopes that call eval.
+function outer() {
+  function middle() {
+    function inner() {
+      return x;
+    }
+    eval("1 + 1");
+    return x + inner();
+  }
+
+  let x = 1;
+  middle();
+}
+
+assertEquals(2, outer());


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to