| Index: test/cctest/test-api.cc
|
| ===================================================================
|
| --- test/cctest/test-api.cc (revision 8993)
|
| +++ test/cctest/test-api.cc (working copy)
|
| @@ -1318,7 +1318,293 @@
|
| CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
|
| }
|
|
|
| +int do_nothing_call_count = 0;
|
| +int foo_setter_call_count = 0;
|
| +int bar_setter_call_count = 0;
|
|
|
| +static v8::Handle<v8::Value> AccessorGetterFoo(Local<String> property,
|
| + const AccessorInfo& info) {
|
| + return v8::String::New("fooget");
|
| +}
|
| +
|
| +static void AccessorSetterFoo(Local<String> property,
|
| + Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + foo_setter_call_count++;
|
| + String::AsciiValue name(property);
|
| + CHECK_EQ(*name, "foo");
|
| + return;
|
| +}
|
| +
|
| +static v8::Handle<v8::Value> AccessorGetterBar(Local<String> property,
|
| + const AccessorInfo& info) {
|
| + return v8::String::New("barget");
|
| +}
|
| +
|
| +static void AccessorSetterBar(Local<String> property,
|
| + Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + bar_setter_call_count++;
|
| + String::AsciiValue name(property);
|
| + CHECK_EQ(*name, "bar");
|
| + return;
|
| +}
|
| +
|
| +static v8::Handle<Value> DoNothingGetterHandler(Local<String> name,
|
| + const AccessorInfo& info) {
|
| + do_nothing_call_count++;
|
| + return v8::Handle<Value>();
|
| +}
|
| +
|
| +THREADED_TEST(NamedPropertyHandlerWalkingUpPrototypeChain) {
|
| + do_nothing_call_count = 0;
|
| + foo_setter_call_count = 0;
|
| + bar_setter_call_count = 0;
|
| + v8::HandleScope scope;
|
| + v8::Handle<v8::FunctionTemplate> grandparent = v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> parent = v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> child = v8::FunctionTemplate::New();
|
| + parent->Inherit(grandparent);
|
| + child->Inherit(parent);
|
| + child->InstanceTemplate()->SetNamedPropertyHandler(DoNothingGetterHandler,
|
| + 0, 0, 0, 0,
|
| + v8_str("data"));
|
| + grandparent->PrototypeTemplate()->SetAccessor(v8::String::New("foo"),
|
| + AccessorGetterFoo,
|
| + AccessorSetterFoo);
|
| + parent->PrototypeTemplate()->SetAccessor(v8::String::New("bar"),
|
| + AccessorGetterBar,
|
| + AccessorSetterBar);
|
| +
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("obj"),
|
| + child->GetFunction()->NewInstance());
|
| + CHECK_EQ(do_nothing_call_count, 0);
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.foo")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 1);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "fooget");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.bar")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "barget");
|
| + }
|
| + {
|
| + v8::Handle<Value> result = v8_compile("obj.foo = 1")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2); // shoudn't change
|
| + CHECK_EQ(foo_setter_call_count, 1);
|
| + CHECK_EQ(result->Int32Value(), 1);
|
| + }
|
| + {
|
| + v8::Handle<Value> result = v8_compile("obj.bar = 2")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2); // shoudn't change
|
| + CHECK_EQ(bar_setter_call_count, 1);
|
| + CHECK_EQ(result->Int32Value(), 2);
|
| + }
|
| + // The values should not be on the instance (for Accessors)
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.foo")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 3);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "fooget");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.bar")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 4);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "barget");
|
| + }
|
| +}
|
| +
|
| +int catch_all_propety_call_count = 0;
|
| +
|
| +static v8::Handle<Value> CatchAllPropertyHandler(Local<String> name,
|
| + const AccessorInfo& info) {
|
| + catch_all_propety_call_count++;
|
| + CHECK_EQ(v8_str("SOMETHING"), info.Data());
|
| + return v8::String::New("GOTCHA");
|
| +}
|
| +
|
| +int baz_setter_call_count = 0;
|
| +
|
| +static v8::Handle<v8::Value> AccessorGetterBaz(Local<String> property,
|
| + const AccessorInfo& info) {
|
| + return v8::String::New("bazget");
|
| +}
|
| +
|
| +static void AccessorSetterBaz(Local<String> property,
|
| + Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + baz_setter_call_count++;
|
| + String::AsciiValue name(property);
|
| + CHECK_EQ(*name, "baz");
|
| + return;
|
| +}
|
| +
|
| +THREADED_TEST(WalkingUpPrototypeChainWithNamedPropertyHandlerOnPrototype) {
|
| + do_nothing_call_count = 0;
|
| + catch_all_propety_call_count = 0;
|
| + foo_setter_call_count = 0;
|
| + bar_setter_call_count = 0;
|
| + baz_setter_call_count = 0;
|
| + v8::HandleScope scope;
|
| + v8::Handle<v8::FunctionTemplate> grandgrandparent =
|
| + v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> grandparent = v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> parent = v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> child = v8::FunctionTemplate::New();
|
| + grandparent->Inherit(grandgrandparent);
|
| + parent->Inherit(grandparent);
|
| + child->Inherit(parent);
|
| + child->InstanceTemplate()->SetNamedPropertyHandler(DoNothingGetterHandler,
|
| + 0, 0, 0, 0,
|
| + v8_str("data"));
|
| + grandparent->PrototypeTemplate()->SetNamedPropertyHandler(CatchAllPropertyHandler,
|
| + 0, 0, 0, 0,
|
| + v8_str("SOMETHING"));
|
| + grandgrandparent->PrototypeTemplate()->SetAccessor(v8::String::New("baz"),
|
| + AccessorGetterBaz,
|
| + AccessorSetterBaz);
|
| + grandparent->PrototypeTemplate()->SetAccessor(v8::String::New("foo"),
|
| + AccessorGetterFoo,
|
| + AccessorSetterFoo);
|
| + parent->PrototypeTemplate()->SetAccessor(v8::String::New("bar"),
|
| + AccessorGetterBar,
|
| + AccessorSetterBar);
|
| +
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("obj"),
|
| + child->GetFunction()->NewInstance());
|
| + CHECK_EQ(do_nothing_call_count, 0);
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.foo")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 1);
|
| + CHECK_EQ(catch_all_propety_call_count, 1);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "GOTCHA");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.bar")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2);
|
| + CHECK_EQ(catch_all_propety_call_count, 1); // shoudn't get called
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "barget");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.baz")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 3);
|
| + CHECK_EQ(catch_all_propety_call_count, 2);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "GOTCHA");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.foo = 1")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 3); // shoudn't change
|
| + CHECK_EQ(catch_all_propety_call_count, 2);
|
| + CHECK_EQ(foo_setter_call_count, 1);
|
| + CHECK_EQ(result->Int32Value(), 1);
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.bar = 2")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 3);
|
| + CHECK_EQ(catch_all_propety_call_count, 2);
|
| + CHECK_EQ(bar_setter_call_count, 1);
|
| + CHECK_EQ(result->Int32Value(), 2);
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.baz = 3")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 3);
|
| + CHECK_EQ(catch_all_propety_call_count, 2);
|
| + CHECK_EQ(baz_setter_call_count, 1);
|
| + CHECK_EQ(result->Int32Value(), 3);
|
| + }
|
| + // The values should not be on the instance (for Accessors)
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.foo")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 4);
|
| + CHECK_EQ(catch_all_propety_call_count, 3);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "GOTCHA");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.bar")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 5);
|
| + CHECK_EQ(catch_all_propety_call_count, 3);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "barget");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.baz")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 6);
|
| + CHECK_EQ(catch_all_propety_call_count, 4);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "GOTCHA");
|
| + }
|
| +}
|
| +
|
| +THREADED_TEST(NamedPropertyHandlerPropertyNotOnPrototype) {
|
| + do_nothing_call_count = 0;
|
| + foo_setter_call_count = 0;
|
| + bar_setter_call_count = 0;
|
| + v8::HandleScope scope;
|
| + v8::Handle<v8::FunctionTemplate> grandparent = v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> parent = v8::FunctionTemplate::New();
|
| + v8::Handle<v8::FunctionTemplate> child = v8::FunctionTemplate::New();
|
| + parent->Inherit(grandparent);
|
| + child->Inherit(parent);
|
| + child->InstanceTemplate()->SetNamedPropertyHandler(DoNothingGetterHandler,
|
| + 0, 0, 0, 0,
|
| + v8_str("data"));
|
| + grandparent->PrototypeTemplate()->SetAccessor(v8::String::New("foo"),
|
| + AccessorGetterFoo,
|
| + AccessorSetterFoo);
|
| + parent->PrototypeTemplate()->SetAccessor(v8::String::New("bar"),
|
| + AccessorGetterBar,
|
| + AccessorSetterBar);
|
| +
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("obj"),
|
| + child->GetFunction()->NewInstance());
|
| + CHECK_EQ(do_nothing_call_count, 0);
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.a")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 1);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "undefined");
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.b")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2);
|
| + String::AsciiValue Result(result);
|
| + CHECK_EQ(*Result, "undefined");
|
| + }
|
| + {
|
| + v8::Handle<Value> result = v8_compile("obj.a = 1;")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2); // shoudn't change
|
| + CHECK_EQ(result->Int32Value(), 1);
|
| + }
|
| + {
|
| + v8::Handle<Value> result = v8_compile("obj.b = 2;")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 2); // shoudn't change
|
| + CHECK_EQ(result->Int32Value(), 2);
|
| + }
|
| + // The values should be on the instance (not handled by Accessors)
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.a")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 3);
|
| + CHECK_EQ(result->Int32Value(), 1);
|
| + }
|
| + {
|
| + v8::Handle<v8::Value> result = v8_compile("obj.b")->Run();
|
| + CHECK_EQ(do_nothing_call_count, 4);
|
| + CHECK_EQ(result->Int32Value(), 2);
|
| + }
|
| +}
|
| +
|
| +
|
| int echo_indexed_call_count = 0;
|
|
|
|
|
| @@ -1331,6 +1617,7 @@
|
| }
|
|
|
|
|
| +
|
| THREADED_TEST(IndexedPropertyHandlerGetter) {
|
| v8::HandleScope scope;
|
| v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
|
|
|