Handle<Context> target = Top::global_context();
if (caller->global_context() == *target) return *caller;
- // Compute a function closure that captures the calling context. We
- // need a function that has trivial scope info, since it is only
- // used to hold the context chain together.
- Handle<JSFunction> closure = Factory::NewFunction(Factory::empty_symbol(),
- Factory::undefined_value());
- closure->set_context(*caller);
-
- // Create a new adaptor context that has the target environment as
- // the extension object. This enables the evaluated code to see both
- // the current context with locals and everything and to see global
- // variables declared in the target global object. Furthermore, any
- // properties introduced with 'var' will be added to the target
- // global object because it is the extension object.
- Handle<Context> adaptor =
- Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, closure);
- adaptor->set_extension(target->global());
- return *adaptor;
-}
-
-
-static Object* Runtime_EvalReceiver(Arguments args) {
- StackFrameLocator locator;
- return locator.FindJavaScriptFrame(1)->receiver();
+ // Otherwise, use the global context from the other environment.
+ return *target;
}
}
+THREADED_TEST(Eval) {
+ v8::HandleScope scope;
+ LocalContext current;
+
+ // Test that un-aliased eval uses local context.
+ Local<Script> script =
+ Script::Compile(v8_str("foo = 0;"
+ "(function() {"
+ " var foo = 2;"
+ " return eval('foo');"
+ "})();"));
+ Local<Value> foo = script->Run();
+ CHECK_EQ(2, foo->Int32Value());
+}
+
+
THREADED_TEST(CrossEval) {
v8::HandleScope scope;
LocalContext other;
CHECK(!current->Global()->Has(v8_str("foo")));
// Check that writing to non-existing properties introduces them in
- // the current context.
+ // the other context.
script =
Script::Compile(v8_str("other.eval('na = 1234')"));
script->Run();
- CHECK_EQ(1234, current->Global()->Get(v8_str("na"))->Int32Value());
- CHECK(!other->Global()->Has(v8_str("na")));
+ CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
+ CHECK(!current->Global()->Has(v8_str("na")));
- // Check that variables in current context are visible in other
- // context. This must include local variables.
+ // Check that global variables in current context are not visible in other
+ // context.
+ v8::TryCatch try_catch;
script =
- Script::Compile(v8_str("var bar = 42;"
- "(function() { "
- " var baz = 87;"
- " return other.eval('bar + baz');"
- "})();"));
+ Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
Local<Value> result = script->Run();
- CHECK_EQ(42 + 87, result->Int32Value());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
+
+ // Check that local variables in current context are not visible in other
+ // context.
+ script =
+ Script::Compile(v8_str("(function() { "
+ " var baz = 87;"
+ " return other.eval('baz');"
+ "})();"));
+ result = script->Run();
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Check that global variables in the other environment are visible
// when evaluting code.
other->Global()->Set(v8_str("bis"), v8_num(1234));
script = Script::Compile(v8_str("other.eval('bis')"));
CHECK_EQ(1234, script->Run()->Int32Value());
+ CHECK(!try_catch.HasCaught());
- // Check that the 'this' pointer isn't touched as a result of
- // calling eval across environments.
- script =
- Script::Compile(v8_str("var t = this; other.eval('this == t')"));
+ // Check that the 'this' pointer points to the global object evaluating
+ // code.
+ other->Global()->Set(v8_str("t"), other->Global());
+ script = Script::Compile(v8_str("other.eval('this == t')"));
result = script->Run();
- CHECK(result->IsBoolean());
- CHECK(result->BooleanValue());
+ CHECK(result->IsTrue());
+ CHECK(!try_catch.HasCaught());
- // Check that doing a cross eval works from within a global
- // with-statement.
+ // Check that variables introduced in with-statement are not visible in
+ // other context.
script =
- Script::Compile(v8_str("other.y = 1;"
- "with({x:2}){other.eval('x+y')}"));
+ Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
result = script->Run();
- CHECK_EQ(3, result->Int32Value());
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
// Check that you cannot use 'eval.call' with another object than the
// current global object.
- v8::TryCatch try_catch;
script =
Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
result = script->Run();