Commit 4c910202 authored by olehougaard's avatar olehougaard

Changing the semantics of cross-frame eval to be compatible with Safari and Firefox.

Review URL: http://codereview.chromium.org/11601

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4a31a4b6
...@@ -3956,29 +3956,8 @@ static Object* EvalContext() { ...@@ -3956,29 +3956,8 @@ static Object* EvalContext() {
Handle<Context> target = Top::global_context(); Handle<Context> target = Top::global_context();
if (caller->global_context() == *target) return *caller; if (caller->global_context() == *target) return *caller;
// Compute a function closure that captures the calling context. We // Otherwise, use the global context from the other environment.
// need a function that has trivial scope info, since it is only return *target;
// 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();
} }
......
...@@ -195,7 +195,6 @@ namespace v8 { namespace internal { ...@@ -195,7 +195,6 @@ namespace v8 { namespace internal {
F(GlobalPrint, 1) \ F(GlobalPrint, 1) \
\ \
/* Eval */ \ /* Eval */ \
F(EvalReceiver, 1) \
F(GlobalReceiver, 1) \ F(GlobalReceiver, 1) \
\ \
F(SetProperty, -1 /* 3 or 4 */) \ F(SetProperty, -1 /* 3 or 4 */) \
......
...@@ -113,7 +113,7 @@ function GlobalEval(x) { ...@@ -113,7 +113,7 @@ function GlobalEval(x) {
var f = %CompileString(x, 0, true); var f = %CompileString(x, 0, true);
if (!IS_FUNCTION(f)) return f; if (!IS_FUNCTION(f)) return f;
return f.call(%EvalReceiver(this)); return f.call(this);
} }
......
...@@ -4018,6 +4018,22 @@ THREADED_TEST(FunctionDescriptorException) { ...@@ -4018,6 +4018,22 @@ THREADED_TEST(FunctionDescriptorException) {
} }
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) { THREADED_TEST(CrossEval) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext other; LocalContext other;
...@@ -4039,49 +4055,58 @@ THREADED_TEST(CrossEval) { ...@@ -4039,49 +4055,58 @@ THREADED_TEST(CrossEval) {
CHECK(!current->Global()->Has(v8_str("foo"))); CHECK(!current->Global()->Has(v8_str("foo")));
// Check that writing to non-existing properties introduces them in // Check that writing to non-existing properties introduces them in
// the current context. // the other context.
script = script =
Script::Compile(v8_str("other.eval('na = 1234')")); Script::Compile(v8_str("other.eval('na = 1234')"));
script->Run(); script->Run();
CHECK_EQ(1234, current->Global()->Get(v8_str("na"))->Int32Value()); CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
CHECK(!other->Global()->Has(v8_str("na"))); CHECK(!current->Global()->Has(v8_str("na")));
// Check that variables in current context are visible in other // Check that global variables in current context are not visible in other
// context. This must include local variables. // context.
v8::TryCatch try_catch;
script = script =
Script::Compile(v8_str("var bar = 42;" Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
"(function() { "
" var baz = 87;"
" return other.eval('bar + baz');"
"})();"));
Local<Value> result = script->Run(); 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 // Check that global variables in the other environment are visible
// when evaluting code. // when evaluting code.
other->Global()->Set(v8_str("bis"), v8_num(1234)); other->Global()->Set(v8_str("bis"), v8_num(1234));
script = Script::Compile(v8_str("other.eval('bis')")); script = Script::Compile(v8_str("other.eval('bis')"));
CHECK_EQ(1234, script->Run()->Int32Value()); CHECK_EQ(1234, script->Run()->Int32Value());
CHECK(!try_catch.HasCaught());
// Check that the 'this' pointer isn't touched as a result of // Check that the 'this' pointer points to the global object evaluating
// calling eval across environments. // code.
script = other->Global()->Set(v8_str("t"), other->Global());
Script::Compile(v8_str("var t = this; other.eval('this == t')")); script = Script::Compile(v8_str("other.eval('this == t')"));
result = script->Run(); result = script->Run();
CHECK(result->IsBoolean()); CHECK(result->IsTrue());
CHECK(result->BooleanValue()); CHECK(!try_catch.HasCaught());
// Check that doing a cross eval works from within a global // Check that variables introduced in with-statement are not visible in
// with-statement. // other context.
script = script =
Script::Compile(v8_str("other.y = 1;" Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
"with({x:2}){other.eval('x+y')}"));
result = script->Run(); 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 // Check that you cannot use 'eval.call' with another object than the
// current global object. // current global object.
v8::TryCatch try_catch;
script = script =
Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')")); Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
result = script->Run(); result = script->Run();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment