Index: src/accessors.cc |
diff --git a/src/accessors.cc b/src/accessors.cc |
index 7c6d344ec0b9f1b86e8fd251f109eee6ae7a6d85..085e00cd44e0320555d3c2d8e16b95b61d96e215 100644 |
--- a/src/accessors.cc |
+++ b/src/accessors.cc |
@@ -167,16 +167,38 @@ void Accessors::ArrayLengthSetter( |
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); |
HandleScope scope(isolate); |
+ DCHECK(Utils::OpenHandle(*name)->SameValue(isolate->heap()->length_string())); |
+ |
Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder()); |
Handle<JSArray> array = Handle<JSArray>::cast(object); |
Handle<Object> length_obj = Utils::OpenHandle(*val); |
+ bool was_readonly = JSArray::HasReadOnlyLength(array); |
+ |
uint32_t length = 0; |
if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) { |
isolate->OptionalRescheduleException(false); |
return; |
} |
+ if (!was_readonly && V8_UNLIKELY(JSArray::HasReadOnlyLength(array)) && |
+ length != array->length()->Number()) { |
+ // AnythingToArrayLength() may have called setter re-entrantly and modified |
+ // its property descriptor. Don't perform this check if "length" was |
+ // previously readonly, as this may have been called during |
+ // DefineOwnPropertyIgnoreAttributes(). |
+ if (info.ShouldThrowOnError()) { |
+ Factory* factory = isolate->factory(); |
+ isolate->Throw(*factory->NewTypeError( |
+ MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name), |
+ i::Object::TypeOf(isolate, object), object)); |
+ isolate->OptionalRescheduleException(false); |
+ } else { |
+ info.GetReturnValue().Set(false); |
+ } |
+ return; |
+ } |
+ |
JSArray::SetLength(array, length); |
uint32_t actual_new_len = 0; |