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:
parent
9756397b76
commit
40fa4a761b
@ -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);
|
||||
|
@ -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")));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user