| Index: test/cctest/test-api.cc
|
| ===================================================================
|
| --- test/cctest/test-api.cc (revision 2114)
|
| +++ test/cctest/test-api.cc (working copy)
|
| @@ -4515,10 +4515,6 @@
|
| v8::HandleScope scope;
|
| LocalContext current;
|
|
|
| - // This sets 'global' to the real global object (as opposed to the
|
| - // proxy). It is highly implementation dependent, so take care.
|
| - current->Global()->Set(v8_str("global"), current->Global()->GetPrototype());
|
| -
|
| // Tests where aliased eval can only be resolved dynamically.
|
| Local<Script> script =
|
| Script::Compile(v8_str("function f(x) { "
|
| @@ -4527,7 +4523,7 @@
|
| "}"
|
| "foo = 0;"
|
| "result1 = f(new Object());"
|
| - "result2 = f(global);"
|
| + "result2 = f(this);"
|
| "var x = new Object();"
|
| "x.eval = function(x) { return 1; };"
|
| "result3 = f(x);"));
|
| @@ -4542,7 +4538,7 @@
|
| " var bar = 2;"
|
| " with (x) { return eval('bar'); }"
|
| "}"
|
| - "f(global)"));
|
| + "f(this)"));
|
| script->Run();
|
| CHECK(try_catch.HasCaught());
|
| try_catch.Reset();
|
| @@ -4629,6 +4625,44 @@
|
| }
|
|
|
|
|
| +// Test that calling eval in a context which has been detached from
|
| +// its global throws an exception. This behavior is consistent with
|
| +// other JavaScript implementations.
|
| +THREADED_TEST(EvalInDetachedGlobal) {
|
| + v8::HandleScope scope;
|
| +
|
| + v8::Persistent<Context> context0 = Context::New();
|
| + v8::Persistent<Context> context1 = Context::New();
|
| +
|
| + // Setup function in context0 that uses eval from context0.
|
| + context0->Enter();
|
| + v8::Handle<v8::Value> fun =
|
| + CompileRun("var x = 42;"
|
| + "(function() {"
|
| + " var e = eval;"
|
| + " return function(s) { return e(s); }"
|
| + "})()");
|
| + context0->Exit();
|
| +
|
| + // Put the function into context1 and call it before and after
|
| + // detaching the global. Before detaching, the call succeeds and
|
| + // after detaching and exception is thrown.
|
| + context1->Enter();
|
| + context1->Global()->Set(v8_str("fun"), fun);
|
| + v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
|
| + CHECK_EQ(42, x_value->Int32Value());
|
| + context0->DetachGlobal();
|
| + v8::TryCatch catcher;
|
| + x_value = CompileRun("fun('x')");
|
| + CHECK(x_value.IsEmpty());
|
| + CHECK(catcher.HasCaught());
|
| + context1->Exit();
|
| +
|
| + context1.Dispose();
|
| + context0.Dispose();
|
| +}
|
| +
|
| +
|
| THREADED_TEST(CrossLazyLoad) {
|
| v8::HandleScope scope;
|
| LocalContext other;
|
| @@ -6723,6 +6757,74 @@
|
| }
|
|
|
|
|
| +THREADED_TEST(ForceDelete) {
|
| + v8::HandleScope scope;
|
| + v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
|
| + LocalContext context(NULL, templ);
|
| + v8::Handle<v8::Object> global = context->Global();
|
| +
|
| + // Ordinary properties
|
| + v8::Handle<v8::String> simple_property = v8::String::New("p");
|
| + global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
|
| + CHECK_EQ(4, global->Get(simple_property)->Int32Value());
|
| + // This should fail because the property is dont-delete.
|
| + CHECK(!global->Delete(simple_property));
|
| + CHECK_EQ(4, global->Get(simple_property)->Int32Value());
|
| + // This should succeed even though the property is dont-delete.
|
| + CHECK(global->ForceDelete(simple_property));
|
| + CHECK(global->Get(simple_property)->IsUndefined());
|
| +}
|
| +
|
| +
|
| +static int force_delete_interceptor_count = 0;
|
| +static bool pass_on_delete = false;
|
| +
|
| +
|
| +static v8::Handle<v8::Boolean> ForceDeleteDeleter(
|
| + v8::Local<v8::String> name,
|
| + const v8::AccessorInfo& info) {
|
| + force_delete_interceptor_count++;
|
| + if (pass_on_delete) {
|
| + return v8::Handle<v8::Boolean>();
|
| + } else {
|
| + return v8::True();
|
| + }
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(ForceDeleteWithInterceptor) {
|
| + force_delete_interceptor_count = 0;
|
| + pass_on_delete = false;
|
| +
|
| + v8::HandleScope scope;
|
| + v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
|
| + templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
|
| + LocalContext context(NULL, templ);
|
| + v8::Handle<v8::Object> global = context->Global();
|
| +
|
| + v8::Handle<v8::String> some_property = v8::String::New("a");
|
| + global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
|
| +
|
| + // Deleting a property should get intercepted and nothing should
|
| + // happen.
|
| + CHECK_EQ(0, force_delete_interceptor_count);
|
| + CHECK(global->Delete(some_property));
|
| + CHECK_EQ(1, force_delete_interceptor_count);
|
| + CHECK_EQ(42, global->Get(some_property)->Int32Value());
|
| + // Deleting the property when the interceptor returns an empty
|
| + // handle should not delete the property since it is DontDelete.
|
| + pass_on_delete = true;
|
| + CHECK(!global->Delete(some_property));
|
| + CHECK_EQ(2, force_delete_interceptor_count);
|
| + CHECK_EQ(42, global->Get(some_property)->Int32Value());
|
| + // Forcing the property to be deleted should delete the value
|
| + // without calling the interceptor.
|
| + CHECK(global->ForceDelete(some_property));
|
| + CHECK(global->Get(some_property)->IsUndefined());
|
| + CHECK_EQ(2, force_delete_interceptor_count);
|
| +}
|
| +
|
| +
|
| v8::Persistent<Context> calling_context0;
|
| v8::Persistent<Context> calling_context1;
|
| v8::Persistent<Context> calling_context2;
|
|
|