Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index ea9e6e122a24e811ea71874e1fb138c3b03a714e..54dc656f8bebb95938d4d30824b4b7d12c2a9b8d 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -76,6 +76,11 @@ static void ExpectBoolean(const char* code, bool expected) { |
} |
+static void ExpectTrue(const char* code) { |
+ ExpectBoolean(code, true); |
+} |
+ |
+ |
static void ExpectObject(const char* code, Local<Value> expected) { |
Local<Value> result = CompileRun(code); |
CHECK(result->Equals(expected)); |
@@ -2506,7 +2511,7 @@ THREADED_TEST(DefinePropertyOnAPIAccessor) { |
// Uses getOwnPropertyDescriptor to check the configurable status |
Local<Script> script_desc |
- = Script::Compile(v8_str("var prop =Object.getOwnPropertyDescriptor( " |
+ = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( " |
"obj, 'x');" |
"prop.configurable;")); |
Local<Value> result = script_desc->Run(); |
@@ -2592,7 +2597,166 @@ THREADED_TEST(DefinePropertyOnDefineGetterSetter) { |
} |
+static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context, |
+ char const* name) { |
+ return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name))); |
+} |
+ |
+ |
+THREADED_TEST(DefineAPIAccessorOnObject) { |
+ v8::HandleScope scope; |
+ Local<ObjectTemplate> templ = ObjectTemplate::New(); |
+ LocalContext context; |
+ |
+ context->Global()->Set(v8_str("obj1"), templ->NewInstance()); |
+ CompileRun("var obj2 = {};"); |
+ |
+ CHECK(CompileRun("obj1.x")->IsUndefined()); |
+ CHECK(CompileRun("obj2.x")->IsUndefined()); |
+ |
+ CHECK(GetGlobalProperty(&context, "obj1")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ |
+ ExpectString("obj1.x", "x"); |
+ CHECK(CompileRun("obj2.x")->IsUndefined()); |
+ |
+ CHECK(GetGlobalProperty(&context, "obj2")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ |
+ ExpectString("obj1.x", "x"); |
+ ExpectString("obj2.x", "x"); |
+ |
+ ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable"); |
+ ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable"); |
+ |
+ CompileRun("Object.defineProperty(obj1, 'x'," |
+ "{ get: function() { return 'y'; }, configurable: true })"); |
+ ExpectString("obj1.x", "y"); |
+ ExpectString("obj2.x", "x"); |
+ |
+ CompileRun("Object.defineProperty(obj2, 'x'," |
+ "{ get: function() { return 'y'; }, configurable: true })"); |
+ |
+ ExpectString("obj1.x", "y"); |
+ ExpectString("obj2.x", "y"); |
+ |
+ ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable"); |
+ ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable"); |
+ |
+ CHECK(GetGlobalProperty(&context, "obj1")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ CHECK(GetGlobalProperty(&context, "obj2")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ |
+ ExpectString("obj1.x", "x"); |
+ ExpectString("obj2.x", "x"); |
+ |
+ ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable"); |
+ ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable"); |
+ |
+ // Define getters/setters, but now make them not configurable. |
+ CompileRun("Object.defineProperty(obj1, 'x'," |
+ "{ get: function() { return 'z'; }, configurable: false })"); |
+ CompileRun("Object.defineProperty(obj2, 'x'," |
+ "{ get: function() { return 'z'; }, configurable: false })"); |
+ |
+ ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable"); |
+ ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable"); |
+ |
+ ExpectString("obj1.x", "z"); |
+ ExpectString("obj2.x", "z"); |
+ |
+ CHECK(!GetGlobalProperty(&context, "obj1")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ CHECK(!GetGlobalProperty(&context, "obj2")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ |
+ ExpectString("obj1.x", "z"); |
+ ExpectString("obj2.x", "z"); |
+} |
+ |
+ |
+THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) { |
+ v8::HandleScope scope; |
+ Local<ObjectTemplate> templ = ObjectTemplate::New(); |
+ LocalContext context; |
+ |
+ context->Global()->Set(v8_str("obj1"), templ->NewInstance()); |
+ CompileRun("var obj2 = {};"); |
+ |
+ CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor( |
+ v8_str("x"), |
+ GetXValue, NULL, |
+ v8_str("donut"), v8::DEFAULT, v8::DontDelete)); |
+ CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor( |
+ v8_str("x"), |
+ GetXValue, NULL, |
+ v8_str("donut"), v8::DEFAULT, v8::DontDelete)); |
+ |
+ ExpectString("obj1.x", "x"); |
+ ExpectString("obj2.x", "x"); |
+ |
+ ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable"); |
+ ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable"); |
+ |
+ CHECK(!GetGlobalProperty(&context, "obj1")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ CHECK(!GetGlobalProperty(&context, "obj2")-> |
+ SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); |
+ |
+ { |
+ v8::TryCatch try_catch; |
+ CompileRun("Object.defineProperty(obj1, 'x'," |
+ "{get: function() { return 'func'; }})"); |
+ CHECK(try_catch.HasCaught()); |
+ String::AsciiValue exception_value(try_catch.Exception()); |
+ CHECK_EQ(*exception_value, |
+ "TypeError: Cannot redefine property: defineProperty"); |
+ } |
+ { |
+ v8::TryCatch try_catch; |
+ CompileRun("Object.defineProperty(obj2, 'x'," |
+ "{get: function() { return 'func'; }})"); |
+ CHECK(try_catch.HasCaught()); |
+ String::AsciiValue exception_value(try_catch.Exception()); |
+ CHECK_EQ(*exception_value, |
+ "TypeError: Cannot redefine property: defineProperty"); |
+ } |
+} |
+ |
+ |
+static v8::Handle<Value> Get239Value(Local<String> name, |
+ const AccessorInfo& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ CHECK_EQ(info.Data(), v8_str("donut")); |
+ CHECK_EQ(name, v8_str("239")); |
+ return name; |
+} |
+ |
+ |
+THREADED_TEST(ElementAPIAccessor) { |
+ v8::HandleScope scope; |
+ Local<ObjectTemplate> templ = ObjectTemplate::New(); |
+ LocalContext context; |
+ |
+ context->Global()->Set(v8_str("obj1"), templ->NewInstance()); |
+ CompileRun("var obj2 = {};"); |
+ |
+ CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor( |
+ v8_str("239"), |
+ Get239Value, NULL, |
+ v8_str("donut"))); |
+ CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor( |
+ v8_str("239"), |
+ Get239Value, NULL, |
+ v8_str("donut"))); |
+ |
+ ExpectString("obj1[239]", "239"); |
+ ExpectString("obj2[239]", "239"); |
+ ExpectString("obj1['239']", "239"); |
+ ExpectString("obj2['239']", "239"); |
+} |
v8::Persistent<Value> xValue; |