Index: test/cctest/test-accessors.cc |
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc |
index ba71600cd68a918460768f55df8561c4de0aefc4..963379ce97f6fafe341e2643386e72822af8dfdd 100644 |
--- a/test/cctest/test-accessors.cc |
+++ b/test/cctest/test-accessors.cc |
@@ -585,3 +585,72 @@ THREADED_TEST(AccessorPropertyCrossContext) { |
"for (var i = 0; i < 10; i++) o.n;"); |
CHECK(!try_catch.HasCaught()); |
} |
+ |
+ |
+using namespace v8::internal; |
+ |
+ |
+static MaybeObject* ZeroAccessorGet(Isolate*, Object*, void*) { |
+ return Smi::FromInt(0); |
+} |
+ |
+ |
+static MaybeObject* ReadOnlySetAccessor(Isolate* isolate, |
+ JSObject*, |
+ Object* value, |
+ void*) { |
+ return value; |
+} |
+ |
+ |
+const AccessorDescriptor kCallbackDescriptor = { |
+ ZeroAccessorGet, |
+ ReadOnlySetAccessor, |
+ 0 |
+}; |
+ |
+ |
+THREADED_TEST(RedefineReadOnlyConfigurableForeignCallbackAccessor) { |
+ // Verify that property redefinition over foreign callbacks-backed |
+ // properties works as expected if the property is non-writable, |
+ // but writable. Such a property can be redefined without first |
+ // making the property writable (ES5.1 - 8.12.9.10.b) |
+ // (bug 3045.) |
+ LocalContext env; |
+ v8::Isolate* isolate = env->GetIsolate(); |
+ Factory* factory = CcTest::i_isolate()->factory(); |
+ |
+ v8::HandleScope scope(isolate); |
+ |
+ Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
+ Handle<DescriptorArray> instance_descriptors( |
+ map->instance_descriptors()); |
+ ASSERT(instance_descriptors->IsEmpty()); |
+ |
+ Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 1); |
+ DescriptorArray::WhitenessWitness witness(*descriptors); |
+ map->set_instance_descriptors(*descriptors); |
+ |
+ Handle<Foreign> foreign = factory->NewForeign(&kCallbackDescriptor); |
+ Handle<v8::internal::String> name = |
+ factory->InternalizeUtf8String(Vector<const char>("prop", 4)); |
+ |
+ // Want a non-writable and configurable property. |
+ PropertyAttributes attribs = |
+ static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY); |
+ CallbacksDescriptor d(*name, *foreign, attribs); |
+ map->AppendDescriptor(&d, witness); |
+ |
+ Handle<Object> object = factory->NewJSObjectFromMap(map); |
+ |
+ // Put the object on the global object. |
+ env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "Foreign"), |
+ v8::Utils::ToLocal(object)); |
+ |
+ // ..and redefine the property through JavaScript, returning its value. |
+ const char* script = |
+ "Object.defineProperty(Foreign, 'prop', {value: 2}); Foreign.prop"; |
+ v8::Handle<v8::Value> result = v8::Script::Compile( |
+ v8::String::NewFromUtf8(CcTest::isolate(), script))->Run(); |
+ CHECK_EQ(2, result->Int32Value()); |
+} |