Chromium Code Reviews| Index: src/accessors.cc | 
| diff --git a/src/accessors.cc b/src/accessors.cc | 
| index 1bc9221a20c5c973c020bfea7f90cd0a46ce4316..8d02b0ceb4ebc8a183e7cbbc29e745b96b250b53 100644 | 
| --- a/src/accessors.cc | 
| +++ b/src/accessors.cc | 
| @@ -95,6 +95,46 @@ Object* Accessors::FlattenNumber(Object* value) { | 
| } | 
| +static MaybeObject* ArraySetLengthObserved(Isolate* isolate, | 
| + Handle<JSArray> array, | 
| + Handle<Object> new_length_handle) { | 
| + List<Handle<String> > indices; | 
| + List<Handle<Object> > old_values; | 
| + Handle<Object> old_length_handle(array->length(), isolate); | 
| + uint32_t old_length; | 
| + CHECK(old_length_handle->ToArrayIndex(&old_length)); | 
| + uint32_t new_length; | 
| + CHECK(new_length_handle->ToArrayIndex(&new_length)); | 
| + uint32_t end_index = old_length; | 
| + while (end_index && end_index-- > new_length) { | 
| 
 
rossberg
2012/11/08 14:26:22
Can we make this a for loop?
 
adamk
2012/11/08 14:48:01
Done, but I'm not sure it looks better (have to de
 
 | 
| + PropertyAttributes attributes = array->GetLocalElementAttribute(end_index); | 
| + 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(array, end_index)); | 
| + indices.Add(isolate->factory()->Uint32ToString(end_index)); | 
| + } | 
| + | 
| + MaybeObject* result = array->SetElementsLength(*new_length_handle); | 
| + | 
| 
 
rossberg
2012/11/08 14:26:22
Nit: move the empty line down by 2.
 
adamk
2012/11/08 14:48:01
Done.
 
 | 
| + Handle<Object> hresult; | 
| + if (!result->ToHandle(&hresult)) return result; | 
| + CHECK(array->length()->ToArrayIndex(&new_length)); | 
| + if (old_length != new_length) { | 
| + for (int i = 0; i < indices.length(); ++i) { | 
| + JSObject::EnqueueChangeRecord( | 
| + array, "deleted", indices[i], old_values[i]); | 
| + } | 
| + JSObject::EnqueueChangeRecord( | 
| + array, "updated", isolate->factory()->length_symbol(), | 
| + old_length_handle); | 
| + } | 
| + return *hresult; | 
| +} | 
| + | 
| + | 
| MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) { | 
| Isolate* isolate = object->GetIsolate(); | 
| @@ -112,7 +152,7 @@ MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) { | 
| HandleScope scope(isolate); | 
| // Protect raw pointers. | 
| - Handle<JSObject> object_handle(object, isolate); | 
| + Handle<JSArray> array_handle(JSArray::cast(object), isolate); | 
| Handle<Object> value_handle(value, isolate); | 
| bool has_exception; | 
| @@ -122,7 +162,11 @@ MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) { | 
| if (has_exception) return Failure::Exception(); | 
| if (uint32_v->Number() == number_v->Number()) { | 
| - return Handle<JSArray>::cast(object_handle)->SetElementsLength(*uint32_v); | 
| + if (FLAG_harmony_observation && array_handle->map()->is_observed()) { | 
| + return ArraySetLengthObserved(isolate, array_handle, uint32_v); | 
| + } else { | 
| + return array_handle->SetElementsLength(*uint32_v); | 
| + } | 
| } | 
| return isolate->Throw( | 
| *isolate->factory()->NewRangeError("invalid_array_length", |