Chromium Code Reviews| Index: src/accessors.cc |
| diff --git a/src/accessors.cc b/src/accessors.cc |
| index 58db0024ea1b2f824e15fa634e07befa10aa5bc7..5743c7552f1ae7539dec267a87b3bdd6b5c705f5 100644 |
| --- a/src/accessors.cc |
| +++ b/src/accessors.cc |
| @@ -173,21 +173,6 @@ Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo( |
| // |
| -// The helper function will 'flatten' Number objects. |
| -Handle<Object> Accessors::FlattenNumber(Isolate* isolate, |
| - Handle<Object> value) { |
| - if (value->IsNumber() || !value->IsJSValue()) return value; |
| - Handle<JSValue> wrapper = Handle<JSValue>::cast(value); |
| - DCHECK(wrapper->GetIsolate()->native_context()->number_function()-> |
| - has_initial_map()); |
| - if (wrapper->map() == isolate->number_function()->initial_map()) { |
| - return handle(wrapper->value(), isolate); |
| - } |
| - |
| - return value; |
| -} |
| - |
| - |
| void Accessors::ArrayLengthGetter( |
| v8::Local<v8::Name> name, |
| const v8::PropertyCallbackInfo<v8::Value>& info) { |
| @@ -200,44 +185,64 @@ void Accessors::ArrayLengthGetter( |
| } |
| +// Tries to non-observably convert |value| to a valid array length. |
| +// Returns false if it fails. |
| +static bool FastAsArrayLength(Isolate* isolate, Handle<Object> value, |
| + uint32_t* length) { |
| + if (value->ToArrayLength(length)) return true; |
| + // We don't support AsArrayLength, so use AsArrayIndex for now. This just |
| + // misses out on kMaxUInt32. |
| + if (value->IsString()) return String::cast(*value)->AsArrayIndex(length); |
| + if (!value->IsJSValue()) return false; |
| + Handle<JSValue> wrapper = Handle<JSValue>::cast(value); |
| + DCHECK(wrapper->GetIsolate() |
| + ->native_context() |
| + ->number_function() |
| + ->has_initial_map()); |
| + // Only support fast unwrapping for the initial map. Otherwise valueOf might |
| + // have been overwritten, in which case unwrapping is invalid. |
| + if (wrapper->map() != isolate->number_function()->initial_map()) return false; |
| + return wrapper->value()->ToArrayIndex(length); |
|
Toon Verwaest
2015/06/19 20:48:57
I think this is actually wrong...
Number.prototyp
Jakob Kummerow
2015/06/20 11:26:38
Good point, in addition to checking the wrapper's
|
| +} |
| + |
| + |
| void Accessors::ArrayLengthSetter( |
| v8::Local<v8::Name> name, |
| v8::Local<v8::Value> val, |
| const v8::PropertyCallbackInfo<void>& info) { |
| - // TODO(verwaest): Speed up. |
| i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); |
| HandleScope scope(isolate); |
| + |
| Handle<JSObject> object = Utils::OpenHandle(*info.This()); |
| - Handle<Object> value = Utils::OpenHandle(*val); |
| + Handle<JSArray> array = Handle<JSArray>::cast(object); |
| + Handle<Object> length_obj = Utils::OpenHandle(*val); |
| + |
| + uint32_t length = 0; |
| + if (!FastAsArrayLength(isolate, length_obj, &length)) { |
| + Handle<Object> uint32_v; |
| + if (!Execution::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) { |
| + isolate->OptionalRescheduleException(false); |
| + return; |
| + } |
| - value = FlattenNumber(isolate, value); |
| + Handle<Object> number_v; |
| + if (!Execution::ToNumber(isolate, length_obj).ToHandle(&number_v)) { |
| + isolate->OptionalRescheduleException(false); |
| + return; |
| + } |
| - Handle<JSArray> array_handle = Handle<JSArray>::cast(object); |
| - MaybeHandle<Object> maybe; |
| - Handle<Object> uint32_v; |
| - maybe = Execution::ToUint32(isolate, value); |
| - if (!maybe.ToHandle(&uint32_v)) { |
| - isolate->OptionalRescheduleException(false); |
| - return; |
| - } |
| - Handle<Object> number_v; |
| - maybe = Execution::ToNumber(isolate, value); |
| - if (!maybe.ToHandle(&number_v)) { |
| - isolate->OptionalRescheduleException(false); |
| - return; |
| - } |
| + if (uint32_v->Number() != number_v->Number()) { |
| + Handle<Object> exception = isolate->factory()->NewRangeError( |
| + MessageTemplate::kInvalidArrayLength); |
| + return isolate->ScheduleThrow(*exception); |
| + } |
| - if (uint32_v->Number() == number_v->Number()) { |
| - uint32_t new_length = 0; |
| - CHECK(uint32_v->ToArrayLength(&new_length)); |
| - maybe = JSArray::ObservableSetLength(array_handle, new_length); |
| - if (maybe.is_null()) isolate->OptionalRescheduleException(false); |
| - return; |
| + CHECK(uint32_v->ToArrayLength(&length)); |
| } |
| - Handle<Object> exception = |
| - isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength); |
| - isolate->ScheduleThrow(*exception); |
| + if (JSArray::ObservableSetLength(array, length).is_null()) { |
| + isolate->OptionalRescheduleException(false); |
| + } |
| } |