Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index a03054653aa16cf014d8ffd83783a7ccd4d7c223..23ff2e274ae5e9abd9e3c721e1065d45006632c0 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -9378,7 +9378,51 @@ void JSArray::Expand(int required_size) { |
MaybeObject* JSArray::SetElementsLength(Object* len) { |
// We should never end in here with a pixel or external array. |
ASSERT(AllowsSetElementsLength()); |
- return GetElementsAccessor()->SetLength(this, len); |
+ if (!(FLAG_harmony_observation && map()->is_observed())) |
+ return GetElementsAccessor()->SetLength(this, len); |
+ |
+ Isolate* isolate = GetIsolate(); |
+ HandleScope scope(isolate); |
+ Handle<JSArray> self(this); |
+ List<Handle<String> > indices; |
+ List<Handle<Object> > old_values; |
+ Handle<Object> old_length_handle(self->length()); |
+ Handle<Object> new_length_handle(len); |
+ uint32_t old_length = 0; |
+ CHECK(old_length_handle->ToArrayIndex(&old_length)); |
+ uint32_t new_length = 0; |
+ if (!new_length_handle->ToArrayIndex(&new_length)) |
+ return Failure::InternalError(); |
+ |
+ // TODO(adamk): This loop can be very slow for arrays in dictionary mode. |
+ // Find another way to iterate over arrays with dictionary elements. |
+ for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { |
+ PropertyAttributes attributes = self->GetLocalElementAttribute(i); |
+ if (attributes == ABSENT) continue; |
+ // A non-configurable property will cause the truncation operation to |
+ // stop at this index. |
+ if (attributes == DONT_DELETE) break; |
+ // TODO(adamk): Don't fetch the old value if it's an accessor. |
+ old_values.Add(Object::GetElement(self, i)); |
+ indices.Add(isolate->factory()->Uint32ToString(i)); |
+ } |
+ |
+ MaybeObject* result = |
+ self->GetElementsAccessor()->SetLength(*self, *new_length_handle); |
+ Handle<Object> hresult; |
+ if (!result->ToHandle(&hresult)) return result; |
+ |
+ CHECK(self->length()->ToArrayIndex(&new_length)); |
+ if (old_length != new_length) { |
+ for (int i = 0; i < indices.length(); ++i) { |
+ JSObject::EnqueueChangeRecord( |
+ self, "deleted", indices[i], old_values[i]); |
+ } |
+ JSObject::EnqueueChangeRecord( |
+ self, "updated", isolate->factory()->length_symbol(), |
+ old_length_handle); |
+ } |
+ return *hresult; |
} |