Index: src/accessors.cc |
diff --git a/src/accessors.cc b/src/accessors.cc |
index 7c6d344ec0b9f1b86e8fd251f109eee6ae7a6d85..a8a117821d6499f0bc810348b802da2c4227c51d 100644 |
--- a/src/accessors.cc |
+++ b/src/accessors.cc |
@@ -171,12 +171,39 @@ void Accessors::ArrayLengthSetter( |
Handle<JSArray> array = Handle<JSArray>::cast(object); |
Handle<Object> length_obj = Utils::OpenHandle(*val); |
+ bool was_readonly; |
+ { |
+ LookupIterator it(object, Utils::OpenHandle(*name), LookupIterator::OWN); |
+ DCHECK(it.IsFound()); |
+ was_readonly = it.property_details().IsReadOnly(); |
+ } |
+ |
uint32_t length = 0; |
if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) { |
isolate->OptionalRescheduleException(false); |
return; |
} |
+ // 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(). |
+ LookupIterator it(object, Utils::OpenHandle(*name), LookupIterator::OWN); |
Camillo Bruni
2016/11/30 12:08:27
I think you want to delay the LookupIterator creat
caitp
2016/11/30 13:17:58
Done, but I think with that condition, it gets cre
|
+ DCHECK(it.IsFound()); |
+ if (!was_readonly && V8_UNLIKELY(it.property_details().IsReadOnly()) && |
+ length != array->length()->Number()) { |
+ 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; |