Correctly set ReadOnly flag on indexed properties when using the API Set method (fixes issue 1470)

Review URL: http://codereview.chromium.org/7149015

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8286 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ricow@chromium.org 2011-06-15 06:44:57 +00:00
parent 9756397b76
commit 40fa4a761b
2 changed files with 56 additions and 0 deletions

View File

@ -3936,6 +3936,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
}
// Special case for elements if any of the flags are true.
// If elements are in fast case we always implicitly assume that:
// DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false.
static MaybeObject* NormalizeObjectSetElement(Isolate* isolate,
Handle<JSObject> js_object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attr) {
// Normalize the elements to enable attributes on the property.
NormalizeElements(js_object);
Handle<NumberDictionary> dictionary(js_object->element_dictionary());
// Make sure that we never go back to fast case.
dictionary->set_requires_slow_elements();
PropertyDetails details = PropertyDetails(attr, NORMAL);
Handle<NumberDictionary> extended_dictionary =
NumberDictionarySet(dictionary, index, value, details);
if (*extended_dictionary != *dictionary) {
js_object->set_elements(*extended_dictionary);
}
return *value;
}
MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
Handle<Object> object,
Handle<Object> key,
@ -3971,6 +3994,10 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
return *value;
}
if (((attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0)) {
return NormalizeObjectSetElement(isolate, js_object, index, value, attr);
}
Handle<Object> result = SetElement(js_object, index, value, strict_mode);
if (result.is_null()) return Failure::Exception();
return *value;
@ -3979,6 +4006,13 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
if (key->IsString()) {
Handle<Object> result;
if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
if (((attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0)) {
return NormalizeObjectSetElement(isolate,
js_object,
index,
value,
attr);
}
result = SetElement(js_object, index, value, strict_mode);
} else {
Handle<String> key_string = Handle<String>::cast(key);

View File

@ -14480,3 +14480,25 @@ THREADED_TEST(CallAPIFunctionOnNonObject) {
TryCatch try_catch;
CompileRun("f.call(2)");
}
// Regression test for issue 1470.
THREADED_TEST(ReadOnlyIndexedProperties) {
v8::HandleScope scope;
Local<ObjectTemplate> templ = ObjectTemplate::New();
LocalContext context;
Local<v8::Object> obj = templ->NewInstance();
context->Global()->Set(v8_str("obj"), obj);
obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
obj->Set(v8_str("1"), v8_str("foobar"));
CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
obj->Set(v8_num(2), v8_str("foobar"));
CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
// Test non-smi case.
obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
obj->Set(v8_str("2000000000"), v8_str("foobar"));
CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
}