Chromium Code Reviews| Index: src/accessors.cc |
| diff --git a/src/accessors.cc b/src/accessors.cc |
| index 1bc9221a20c5c973c020bfea7f90cd0a46ce4316..c1591b7481c1f4889a82efbeea7db5361dbb9896 100644 |
| --- a/src/accessors.cc |
| +++ b/src/accessors.cc |
| @@ -95,6 +95,45 @@ 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)); |
| + for (uint32_t len = old_length; len > new_length; --len) { |
|
rossberg
2012/11/08 14:56:28
If you want to avoid the off-by-one nuisance below
adamk
2012/11/08 15:11:23
Nope: first of all, need to add an if statement no
rossberg
2012/11/08 15:16:12
Note the +1. ;)
|
| + PropertyAttributes attributes = array->GetLocalElementAttribute(len - 1); |
| + 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, len - 1)); |
| + indices.Add(isolate->factory()->Uint32ToString(len - 1)); |
| + } |
| + |
| + MaybeObject* result = array->SetElementsLength(*new_length_handle); |
| + 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 +151,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 +161,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", |