Chromium Code Reviews| Index: test/cctest/test-api.cc |
| diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
| index 8a1e9147369fbde7d20e996c91e45089c0545e67..f2ed02cc0bcc13fcd70ecf0cd1cd2e6e03a265cf 100644 |
| --- a/test/cctest/test-api.cc |
| +++ b/test/cctest/test-api.cc |
| @@ -16593,3 +16593,177 @@ TEST(StringEmpty) { |
| CHECK(v8::String::Empty(isolate).IsEmpty()); |
| CHECK_EQ(3, fatal_error_callback_counter); |
| } |
| + |
| + |
| +static int instance_checked_getter_count = 0; |
| +static Handle<Value> InstanceCheckedGetter(Local<String> name, |
| + const AccessorInfo& info) { |
| + printf("InstanceCheckedGetter!\n"); |
|
Sven Panne
2012/06/04 07:50:32
Hmmm, do we really need printf in unit tests?
Michael Starzinger
2012/06/04 09:11:15
Done. Ooops, forgot to remove that again.
|
| + CHECK_EQ(name, v8_str("foo")); |
| + instance_checked_getter_count++; |
| + return v8_num(11); |
| +} |
| + |
| + |
| +static int instance_checked_setter_count = 0; |
| +static void InstanceCheckedSetter(Local<String> name, |
| + Local<Value> value, |
| + const AccessorInfo& info) { |
| + printf("InstanceCheckedSetter!\n"); |
| + CHECK_EQ(name, v8_str("foo")); |
| + CHECK_EQ(value, v8_num(23)); |
| + instance_checked_setter_count++; |
| +} |
| + |
| + |
| +static void CheckInstanceCheckedResult(int getters, |
| + int setters, |
| + bool expects_callbacks, |
| + TryCatch* try_catch) { |
| + if (expects_callbacks) { |
| + CHECK(!try_catch->HasCaught()); |
| + CHECK_EQ(getters, instance_checked_getter_count); |
| + CHECK_EQ(setters, instance_checked_setter_count); |
| + } else { |
| + CHECK(try_catch->HasCaught()); |
| + CHECK_EQ(0, instance_checked_getter_count); |
| + CHECK_EQ(0, instance_checked_setter_count); |
| + } |
| + try_catch->Reset(); |
| +} |
| + |
| + |
| +static void CheckInstanceCheckedAccessors(bool expects_callbacks) { |
| + instance_checked_getter_count = 0; |
| + instance_checked_setter_count = 0; |
| + TryCatch try_catch; |
| + |
| + // Test path through generic runtime code. |
| + CompileRun("obj.foo"); |
| + CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch); |
| + CompileRun("obj.foo = 23"); |
| + CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch); |
| + |
| + // Test path through generated LoadIC and StoredIC. |
| + CompileRun("function test_get(o) { o.foo; }" |
| + "test_get(obj);"); |
| + CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch); |
| + CompileRun("test_get(obj);"); |
| + CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch); |
| + CompileRun("test_get(obj);"); |
| + CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch); |
| + CompileRun("function test_set(o) { o.foo = 23; }" |
| + "test_set(obj);"); |
| + CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch); |
| + CompileRun("test_set(obj);"); |
| + CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch); |
| + CompileRun("test_set(obj);"); |
| + CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch); |
| + |
| + // Test path through optimized code. |
| + CompileRun("%OptimizeFunctionOnNextCall(test_get);" |
| + "test_get(obj);"); |
| + CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch); |
| + CompileRun("%OptimizeFunctionOnNextCall(test_set);" |
| + "test_set(obj);"); |
| + CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch); |
| + |
| + // Cleanup so that closures start out fresh in next check. |
| + CompileRun("%DeoptimizeFunction(test_get);" |
| + "%ClearFunctionTypeFeedback(test_get);" |
| + "%DeoptimizeFunction(test_set);" |
| + "%ClearFunctionTypeFeedback(test_set);"); |
| +} |
| + |
| + |
| +THREADED_TEST(InstanceCheckOnInstanceAccessor) { |
| + v8::internal::FLAG_allow_natives_syntax = true; |
| + v8::HandleScope scope; |
| + LocalContext context; |
| + |
| + Local<FunctionTemplate> templ = FunctionTemplate::New(); |
| + Local<ObjectTemplate> inst = templ->InstanceTemplate(); |
| + inst->SetAccessor(v8_str("foo"), |
| + InstanceCheckedGetter, InstanceCheckedSetter, |
| + Handle<Value>(), |
| + v8::DEFAULT, |
| + v8::None, |
| + templ); |
| + context->Global()->Set(v8_str("f"), templ->GetFunction()); |
| + |
| + printf("Testing positive ...\n"); |
| + CompileRun("var obj = new f();"); |
| + CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(true); |
| + |
| + printf("Testing negative ...\n"); |
| + CompileRun("var obj = {};" |
| + "obj.__proto__ = new f();"); |
| + CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(false); |
| +} |
| + |
| + |
| +THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) { |
| + v8::internal::FLAG_allow_natives_syntax = true; |
| + v8::HandleScope scope; |
| + LocalContext context; |
| + |
| + Local<FunctionTemplate> templ = FunctionTemplate::New(); |
| + Local<ObjectTemplate> inst = templ->InstanceTemplate(); |
| + AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter); |
| + inst->SetAccessor(v8_str("foo"), |
| + InstanceCheckedGetter, InstanceCheckedSetter, |
| + Handle<Value>(), |
| + v8::DEFAULT, |
| + v8::None, |
| + templ); |
| + context->Global()->Set(v8_str("f"), templ->GetFunction()); |
| + |
| + printf("Testing positive ...\n"); |
| + CompileRun("var obj = new f();"); |
| + CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(true); |
| + |
| + printf("Testing negative ...\n"); |
| + CompileRun("var obj = {};" |
| + "obj.__proto__ = new f();"); |
| + CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(false); |
| +} |
| + |
| + |
| +THREADED_TEST(InstanceCheckOnPrototypeAccessor) { |
| + v8::internal::FLAG_allow_natives_syntax = true; |
| + v8::HandleScope scope; |
| + LocalContext context; |
| + |
| + Local<FunctionTemplate> templ = FunctionTemplate::New(); |
| + Local<ObjectTemplate> proto = templ->PrototypeTemplate(); |
| + proto->SetAccessor(v8_str("foo"), |
| + InstanceCheckedGetter, InstanceCheckedSetter, |
| + Handle<Value>(), |
| + v8::DEFAULT, |
| + v8::None, |
| + templ); |
| + context->Global()->Set(v8_str("f"), templ->GetFunction()); |
| + |
| + printf("Testing positive ...\n"); |
| + CompileRun("var obj = new f();"); |
| + CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(true); |
| + |
| + printf("Testing negative ...\n"); |
| + CompileRun("var obj = {};" |
| + "obj.__proto__ = new f();"); |
| + CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(false); |
| + |
| + printf("Testing positive with modified prototype chain ...\n"); |
| + CompileRun("var obj = new f();" |
| + "var pro = {};" |
| + "pro.__proto__ = obj.__proto__;" |
| + "obj.__proto__ = pro;"); |
| + CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj")))); |
| + CheckInstanceCheckedAccessors(true); |
| +} |