Fixing wrong reference to this in eval.
authorolehougaard <olehougaard@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Nov 2008 10:02:37 +0000 (10:02 +0000)
committerolehougaard <olehougaard@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 18 Nov 2008 10:02:37 +0000 (10:02 +0000)
Review URL: http://codereview.chromium.org/11227

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@784 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/runtime.cc
src/runtime.h
src/v8natives.js
test/cctest/test-api.cc

index f2b102d..5e60c0d 100644 (file)
@@ -3961,6 +3961,26 @@ static Object* EvalContext() {
 }
 
 
+static Object* Runtime_EvalReceiver(Arguments args) {
+  ASSERT(args.length() == 1);
+  StackFrameLocator locator;
+  JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
+  // Fetch the caller context from the frame.
+  Context* caller = Context::cast(frame->context());
+
+  // Check for eval() invocations that cross environments. Use the
+  // top frames receiver if evaluating in current environment.
+  Context* global_context = Top::context()->global()->global_context();
+  if (caller->global_context() == global_context) {
+    return frame->receiver();
+  }
+
+  // Otherwise use the given argument (the global object of the
+  // receiving context).
+  return args[0];
+}
+
+
 static Object* Runtime_GlobalReceiver(Arguments args) {
   ASSERT(args.length() == 1);
   Object* global = args[0];
index f0fdf1f..36a7180 100644 (file)
@@ -195,6 +195,7 @@ namespace v8 { namespace internal {
   F(GlobalPrint, 1) \
   \
   /* Eval */ \
+  F(EvalReceiver, 1) \
   F(GlobalReceiver, 1) \
   \
   F(SetProperty, -1 /* 3 or 4 */) \
index 21e3c93..f3c98a5 100644 (file)
@@ -113,7 +113,7 @@ function GlobalEval(x) {
   var f = %CompileString(x, 0, true);
   if (!IS_FUNCTION(f)) return f;
 
-  return f.call(this);
+  return f.call(%EvalReceiver(this));
 }
 
 
index 7fba4f3..3c91294 100644 (file)
@@ -4029,8 +4029,16 @@ THREADED_TEST(Eval) {
                              "  var foo = 2;"
                              "  return eval('foo');"
                              "})();"));
-  Local<Value> foo = script->Run();
-  CHECK_EQ(2, foo->Int32Value());
+  Local<Value> result = script->Run();
+  CHECK_EQ(2, result->Int32Value());
+
+  // Test that un-aliased eval has right this.
+  script =
+      Script::Compile(v8_str("function MyObject() { this.self = eval('this'); }"
+                             "var o = new MyObject();"
+                             "o === o.self"));
+  result = script->Run();
+  CHECK(result->IsTrue());
 }