Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 2b6feb5c828b139d3ada33c35e9dcefe94d64883..9a114c0c5e728684a5993c2c1294b0d032ded601 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -865,8 +865,21 @@ bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, |
| } |
| -MaybeHandle<Object> Object::SetPropertyWithAccessor( |
| - LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { |
| +#define RETURN_FAILURE(isolate, should_throw, call) \ |
| + do { \ |
| + if ((should_throw) == DONT_THROW) { \ |
| + return Just(false); \ |
| + } else { \ |
| + isolate->Throw(*isolate->factory()->call); \ |
| + return Nothing<bool>(); \ |
| + } \ |
| + } while (false) |
| + |
| + |
| +Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, |
| + Handle<Object> value, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw) { |
| Isolate* isolate = it->isolate(); |
| Handle<Object> structure = it->GetAccessors(); |
| Handle<Object> receiver = it->GetReceiver(); |
| @@ -882,21 +895,20 @@ MaybeHandle<Object> Object::SetPropertyWithAccessor( |
| Handle<ExecutableAccessorInfo> info = |
| Handle<ExecutableAccessorInfo>::cast(structure); |
| if (!info->IsCompatibleReceiver(*receiver)) { |
| - THROW_NEW_ERROR(isolate, |
| - NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, |
| - name, receiver), |
| - Object); |
| + isolate->Throw(*isolate->factory()->NewTypeError( |
| + MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); |
| + return Nothing<bool>(); |
| } |
| v8::AccessorNameSetterCallback call_fun = |
| v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); |
| - if (call_fun == nullptr) return value; |
| + if (call_fun == nullptr) return Just(true); |
|
Toon Verwaest
2015/10/20 15:25:06
Shouldn't this case be unreachable (at least in th
neis
2015/10/21 14:42:25
Done.
|
| LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); |
| PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); |
| args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| - return value; |
| + RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
| + return Just(true); |
| } |
| // Regular accessor. |
| @@ -904,15 +916,13 @@ MaybeHandle<Object> Object::SetPropertyWithAccessor( |
| if (setter->IsCallable()) { |
| // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| return SetPropertyWithDefinedSetter( |
| - receiver, Handle<JSReceiver>::cast(setter), value); |
| + receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
| } |
| - if (is_sloppy(language_mode)) return value; |
| - |
| - THROW_NEW_ERROR(isolate, |
| - NewTypeError(MessageTemplate::kNoSetterInCallback, |
| - it->GetName(), it->GetHolder<JSObject>()), |
| - Object); |
| + if (is_sloppy(language_mode)) return Just(true); |
| + RETURN_FAILURE(isolate, should_throw, |
| + NewTypeError(MessageTemplate::kNoSetterInCallback, |
| + it->GetName(), it->GetHolder<JSObject>())); |
| } |
| @@ -944,10 +954,10 @@ MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( |
| } |
| -MaybeHandle<Object> Object::SetPropertyWithDefinedSetter( |
| - Handle<Object> receiver, |
| - Handle<JSReceiver> setter, |
| - Handle<Object> value) { |
| +Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver, |
| + Handle<JSReceiver> setter, |
| + Handle<Object> value, |
| + ShouldThrow should_throw) { |
| Isolate* isolate = setter->GetIsolate(); |
| Debug* debug = isolate->debug(); |
| @@ -956,10 +966,10 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter( |
| if (debug->is_active()) debug->HandleStepIn(setter, false); |
| Handle<Object> argv[] = { value }; |
| - RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, |
| - arraysize(argv), argv), |
| - Object); |
| - return value; |
| + RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver, |
| + arraysize(argv), argv), |
| + Nothing<bool>()); |
| + return Just(true); |
| } |
| @@ -1044,17 +1054,20 @@ bool JSObject::AllCanWrite(LookupIterator* it) { |
| } |
| -MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( |
| - LookupIterator* it, Handle<Object> value) { |
| +Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck( |
| + LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) { |
| Handle<JSObject> checked = it->GetHolder<JSObject>(); |
| if (AllCanWrite(it)) { |
| // The supplied language-mode is ignored by SetPropertyWithAccessor. |
| - return SetPropertyWithAccessor(it, value, SLOPPY); |
| + return SetPropertyWithAccessor(it, value, SLOPPY, should_throw); |
| } |
| it->isolate()->ReportFailedAccessCheck(checked); |
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
| - return value; |
| + RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
| + UNREACHABLE(); |
| + it->isolate()->Throw( |
| + *it->isolate()->factory()->NewTypeError(MessageTemplate::kNoAccess)); |
| + return Nothing<bool>(); |
|
Toon Verwaest
2015/10/20 15:25:06
Nice. Wouldn't it be helpful to extract this to a
neis
2015/10/21 14:42:25
Yes, and this should probably be used in many othe
|
| } |
| @@ -3513,8 +3526,9 @@ Handle<Map> Map::Update(Handle<Map> map) { |
| } |
| -MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| - Handle<Object> value) { |
| +Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| + Handle<Object> value, |
| + ShouldThrow should_throw) { |
| Isolate* isolate = it->isolate(); |
| // Make sure that the top context does not change when doing callbacks or |
| // interceptor calls. |
| @@ -3522,7 +3536,7 @@ MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
| Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
| - if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>(); |
| + if (interceptor->setter()->IsUndefined()) return Nothing<bool>(); |
| Handle<JSObject> holder = it->GetHolder<JSObject>(); |
| v8::Local<v8::Value> result; |
| @@ -3540,7 +3554,7 @@ MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| Handle<Name> name = it->name(); |
| if (name->IsSymbol() && !interceptor->can_intercept_symbols()) { |
| - return MaybeHandle<Object>(); |
| + return Nothing<bool>(); |
| } |
| v8::GenericNamedPropertySetterCallback setter = |
| @@ -3552,13 +3566,13 @@ MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
| } |
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
| - if (result.IsEmpty()) return MaybeHandle<Object>(); |
| + RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
| + if (result.IsEmpty()) return Nothing<bool>(); |
| #ifdef DEBUG |
| Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| result_internal->VerifyApiCallResultType(); |
| #endif |
| - return value; |
| + return Just(true); |
| } |
| @@ -3571,11 +3585,9 @@ MaybeHandle<Object> Object::SetProperty(Handle<Object> object, |
| } |
| -MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, |
| - Handle<Object> value, |
| - LanguageMode language_mode, |
| - StoreFromKeyed store_mode, |
| - bool* found) { |
| +Maybe<bool> Object::SetPropertyInternal( |
| + LookupIterator* it, Handle<Object> value, LanguageMode language_mode, |
| + ShouldThrow should_throw, StoreFromKeyed store_mode, bool* found) { |
| // Make sure that the top context does not change when doing callbacks or |
| // interceptor calls. |
| AssertNoContextChange ncc(it->isolate()); |
| @@ -3592,20 +3604,21 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, |
| if (it->HasAccess()) break; |
| // Check whether it makes sense to reuse the lookup iterator. Here it |
| // might still call into setters up the prototype chain. |
| - return JSObject::SetPropertyWithFailedAccessCheck(it, value); |
| + return JSObject::SetPropertyWithFailedAccessCheck(it, value, |
| + should_throw); |
| case LookupIterator::JSPROXY: |
| if (it->HolderIsReceiverOrHiddenPrototype()) { |
| return JSProxy::SetPropertyWithHandler( |
| it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, |
| - language_mode); |
| + language_mode, should_throw); |
| } else { |
| // TODO(verwaest): Use the MaybeHandle to indicate result. |
| bool has_result = false; |
| - MaybeHandle<Object> maybe_result = |
| + Maybe<bool> maybe_result = |
| JSProxy::SetPropertyViaPrototypesWithHandler( |
| it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), |
| - value, language_mode, &has_result); |
| + value, language_mode, should_throw, &has_result); |
| if (has_result) return maybe_result; |
| done = true; |
| } |
| @@ -3613,24 +3626,26 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, |
| case LookupIterator::INTERCEPTOR: |
| if (it->HolderIsReceiverOrHiddenPrototype()) { |
| - MaybeHandle<Object> maybe_result = |
| - JSObject::SetPropertyWithInterceptor(it, value); |
| - if (!maybe_result.is_null()) return maybe_result; |
| + Maybe<bool> maybe_result = |
| + JSObject::SetPropertyWithInterceptor(it, value, should_throw); |
| + if (maybe_result.IsJust()) return maybe_result; |
| if (it->isolate()->has_pending_exception()) return maybe_result; |
| } else { |
| Maybe<PropertyAttributes> maybe_attributes = |
| JSObject::GetPropertyAttributesWithInterceptor(it); |
| - if (!maybe_attributes.IsJust()) return MaybeHandle<Object>(); |
| + if (!maybe_attributes.IsJust()) return Nothing<bool>(); |
| done = maybe_attributes.FromJust() != ABSENT; |
| if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { |
| - return WriteToReadOnlyProperty(it, value, language_mode); |
| + return WriteToReadOnlyProperty(it, value, language_mode, |
| + should_throw); |
| } |
| } |
| break; |
| case LookupIterator::ACCESSOR: { |
| if (it->IsReadOnly()) { |
| - return WriteToReadOnlyProperty(it, value, language_mode); |
| + return WriteToReadOnlyProperty(it, value, language_mode, |
| + should_throw); |
| } |
| Handle<Object> accessors = it->GetAccessors(); |
| if (accessors->IsAccessorInfo() && |
| @@ -3639,18 +3654,19 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, |
| done = true; |
| break; |
| } |
| - return SetPropertyWithAccessor(it, value, language_mode); |
| + return SetPropertyWithAccessor(it, value, language_mode, should_throw); |
| } |
| case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| // TODO(verwaest): We should throw an exception. |
| - return value; |
| + return Just(true); |
| case LookupIterator::DATA: |
| if (it->IsReadOnly()) { |
| - return WriteToReadOnlyProperty(it, value, language_mode); |
| + return WriteToReadOnlyProperty(it, value, language_mode, |
| + should_throw); |
| } |
| if (it->HolderIsReceiverOrHiddenPrototype()) { |
| - return SetDataProperty(it, value); |
| + return SetDataProperty(it, value, should_throw); |
| } |
| done = true; |
| break; |
| @@ -3667,13 +3683,12 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, |
| // the property did not exist yet on the global object itself, we have to |
| // throw a reference error in strict mode. |
| if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { |
| - THROW_NEW_ERROR(it->isolate(), |
| - NewReferenceError(MessageTemplate::kNotDefined, it->name()), |
| - Object); |
| + RETURN_FAILURE(it->isolate(), should_throw, |
| + NewReferenceError(MessageTemplate::kNotDefined, it->name())); |
| } |
| *found = false; |
| - return MaybeHandle<Object>(); |
| + return Nothing<bool>(); |
| } |
| @@ -3681,11 +3696,22 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it, |
| Handle<Object> value, |
| LanguageMode language_mode, |
| StoreFromKeyed store_mode) { |
| + Maybe<bool> result = |
| + SetProperty(it, value, language_mode, THROW_ON_ERROR, store_mode); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
|
rossberg
2015/10/14 15:59:06
This pattern occurs several times, maybe introduce
|
| +} |
| + |
| + |
| +Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw, |
| + StoreFromKeyed store_mode) { |
| bool found = false; |
| - MaybeHandle<Object> result = |
| - SetPropertyInternal(it, value, language_mode, store_mode, &found); |
| + Maybe<bool> result = SetPropertyInternal(it, value, language_mode, |
| + should_throw, store_mode, &found); |
| if (found) return result; |
| - return AddDataProperty(it, value, NONE, language_mode, store_mode); |
| + return AddDataProperty(it, value, NONE, language_mode, should_throw, |
| + store_mode); |
| } |
| @@ -3694,12 +3720,14 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, |
| LanguageMode language_mode, |
| StoreFromKeyed store_mode) { |
| bool found = false; |
| - MaybeHandle<Object> result = |
| - SetPropertyInternal(it, value, language_mode, store_mode, &found); |
| - if (found) return result; |
| + Maybe<bool> result = SetPropertyInternal(it, value, language_mode, |
| + THROW_ON_ERROR, store_mode, &found); |
| + if (found) return result.IsJust() ? value : MaybeHandle<Object>(); |
| if (!it->GetReceiver()->IsJSReceiver()) { |
| - return WriteToReadOnlyProperty(it, value, language_mode); |
| + Maybe<bool> result = |
| + WriteToReadOnlyProperty(it, value, language_mode, THROW_ON_ERROR); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
| } |
| LookupIterator::Configuration c = LookupIterator::OWN; |
| @@ -3712,7 +3740,9 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, |
| switch (own_lookup.state()) { |
| case LookupIterator::ACCESS_CHECK: |
| if (!own_lookup.HasAccess()) { |
| - return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value); |
| + Maybe<bool> result = JSObject::SetPropertyWithFailedAccessCheck( |
| + &own_lookup, value, THROW_ON_ERROR); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
| } |
| break; |
| @@ -3726,7 +3756,9 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, |
| return JSObject::DefineOwnPropertyIgnoreAttributes( |
| &own_lookup, value, details.attributes()); |
| } |
| - return WriteToReadOnlyProperty(&own_lookup, value, language_mode); |
| + Maybe<bool> result = WriteToReadOnlyProperty( |
| + &own_lookup, value, language_mode, THROW_ON_ERROR); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
| } |
| case LookupIterator::ACCESSOR: { |
| @@ -3743,9 +3775,10 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, |
| case LookupIterator::INTERCEPTOR: |
| case LookupIterator::JSPROXY: { |
| bool found = false; |
| - MaybeHandle<Object> result = SetPropertyInternal( |
| - &own_lookup, value, language_mode, store_mode, &found); |
| - if (found) return result; |
| + Maybe<bool> result = |
| + SetPropertyInternal(&own_lookup, value, language_mode, |
| + THROW_ON_ERROR, store_mode, &found); |
| + if (found) return result.IsJust() ? value : MaybeHandle<Object>(); |
| break; |
| } |
| @@ -3785,44 +3818,40 @@ MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate, |
| } |
| -MaybeHandle<Object> Object::CannotCreateProperty(LookupIterator* it, |
| - Handle<Object> value, |
| - LanguageMode language_mode) { |
| - return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), |
| - value, language_mode); |
| -} |
| - |
| - |
| -MaybeHandle<Object> Object::CannotCreateProperty(Isolate* isolate, |
| - Handle<Object> receiver, |
| - Handle<Object> name, |
| - Handle<Object> value, |
| - LanguageMode language_mode) { |
| - if (is_sloppy(language_mode)) return value; |
| - Handle<String> typeof_string = Object::TypeOf(isolate, receiver); |
| - THROW_NEW_ERROR(isolate, |
| - NewTypeError(MessageTemplate::kStrictCannotCreateProperty, |
| - name, typeof_string, receiver), |
| - Object); |
| +Maybe<bool> Object::CannotCreateProperty(Isolate* isolate, |
| + Handle<Object> receiver, |
| + Handle<Object> name, |
| + Handle<Object> value, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw) { |
| + if (is_sloppy(language_mode)) return Just(true); |
| + RETURN_FAILURE( |
| + isolate, should_throw, |
| + NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name, |
| + Object::TypeOf(isolate, receiver), receiver)); |
| } |
| -MaybeHandle<Object> Object::WriteToReadOnlyProperty( |
| - LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { |
| +Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it, |
| + Handle<Object> value, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw) { |
| return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), |
| - it->GetName(), value, language_mode); |
| + it->GetName(), value, language_mode, |
| + should_throw); |
| } |
| -MaybeHandle<Object> Object::WriteToReadOnlyProperty( |
| - Isolate* isolate, Handle<Object> receiver, Handle<Object> name, |
| - Handle<Object> value, LanguageMode language_mode) { |
| - if (is_sloppy(language_mode)) return value; |
| - Handle<String> typeof_string = Object::TypeOf(isolate, receiver); |
| - THROW_NEW_ERROR(isolate, |
| - NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, |
| - typeof_string, receiver), |
| - Object); |
| +Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate, |
| + Handle<Object> receiver, |
| + Handle<Object> name, |
| + Handle<Object> value, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw) { |
| + if (is_sloppy(language_mode)) return Just(true); |
| + RETURN_FAILURE(isolate, should_throw, |
| + NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, |
| + Object::TypeOf(isolate, receiver), receiver)); |
| } |
| @@ -3836,8 +3865,8 @@ MaybeHandle<Object> Object::RedefineNonconfigurableProperty( |
| } |
| -MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
| - Handle<Object> value) { |
| +Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value, |
| + ShouldThrow should_throw) { |
| // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
| // have own properties. |
| Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
| @@ -3858,8 +3887,8 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
| // Convert the incoming value to a number for storing into typed arrays. |
| if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { |
| if (!value->IsNumber() && !value->IsUndefined()) { |
| - ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign, |
| - Object::ToNumber(value), Object); |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| + it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>()); |
| // ToNumber above might modify the receiver, causing the cached |
| // holder_map to mismatch the actual holder->map() after this point. |
| // Reload the map to be in consistent state. Other cached state cannot |
| @@ -3870,7 +3899,8 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
| // We have to recheck the length. However, it can only change if the |
| // underlying buffer was neutered, so just check that. |
| if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) { |
| - return value; |
| + return Just(true); |
| + // TODO(neis): According to the spec, this should throw a TypeError. |
| } |
| } |
| } |
| @@ -3884,10 +3914,11 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
| // Send the change record if there are observers. |
| if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { |
| - RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( |
| - receiver, "update", it->GetName(), |
| - maybe_old.ToHandleChecked()), |
| - Object); |
| + RETURN_ON_EXCEPTION_VALUE( |
| + it->isolate(), |
| + JSObject::EnqueueChangeRecord(receiver, "update", it->GetName(), |
| + maybe_old.ToHandleChecked()), |
| + Nothing<bool>()); |
| } |
| #if VERIFY_HEAP |
| @@ -3895,7 +3926,7 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
| receiver->JSObjectVerify(); |
| } |
| #endif |
| - return value; |
| + return Just(true); |
| } |
| @@ -3945,9 +3976,21 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
| PropertyAttributes attributes, |
| LanguageMode language_mode, |
| StoreFromKeyed store_mode) { |
| + Maybe<bool> result = AddDataProperty(it, value, attributes, language_mode, |
| + THROW_ON_ERROR, store_mode); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
| +} |
| + |
| + |
| +Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, |
| + PropertyAttributes attributes, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw, |
| + StoreFromKeyed store_mode) { |
| DCHECK(!it->GetReceiver()->IsJSProxy()); |
| if (!it->GetReceiver()->IsJSObject()) { |
| - return CannotCreateProperty(it, value, language_mode); |
| + return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), |
| + value, language_mode, should_throw); |
| } |
| DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); |
| @@ -3956,24 +3999,27 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
| // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
| // instead. If the prototype is Null, the proxy is detached. |
| - if (receiver->IsJSGlobalProxy()) return value; |
| + if (receiver->IsJSGlobalProxy()) return Just(true); |
| Isolate* isolate = it->isolate(); |
| if (!receiver->map()->is_extensible() && |
| (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { |
| - if (is_sloppy(language_mode)) return value; |
| - THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible, |
| - it->GetName()), |
| - Object); |
| + if (is_sloppy(language_mode)) return Just(true); |
| + RETURN_FAILURE( |
| + isolate, should_throw, |
| + NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); |
| } |
| if (it->IsElement()) { |
| if (receiver->IsJSArray()) { |
| Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { |
| - if (is_sloppy(language_mode)) return value; |
| - return JSArray::ReadOnlyLengthError(array); |
| + if (is_sloppy(language_mode)) return Just(true); |
| + RETURN_FAILURE(array->GetIsolate(), should_throw, |
| + NewTypeError(MessageTemplate::kStrictReadOnlyProperty, |
| + isolate->factory()->length_string(), |
| + Object::TypeOf(isolate, array), array)); |
| } |
| if (FLAG_trace_external_array_abuse && |
| @@ -3986,8 +4032,8 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
| } |
| } |
| - MaybeHandle<Object> result = |
| - JSObject::AddDataElement(receiver, it->index(), value, attributes); |
| + Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value, |
| + attributes, should_throw); |
| JSObject::ValidateElements(receiver); |
| return result; |
| } else { |
| @@ -4011,10 +4057,10 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
| // Send the change record if there are observers. |
| if (receiver->map()->is_observed() && |
| !isolate->IsInternallyUsedPropertyName(it->name())) { |
| - RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord( |
| - receiver, "add", it->name(), |
| - it->factory()->the_hole_value()), |
| - Object); |
| + RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord( |
| + receiver, "add", it->name(), |
| + it->factory()->the_hole_value()), |
| + Nothing<bool>()); |
| } |
| #if VERIFY_HEAP |
| if (FLAG_verify_heap) { |
| @@ -4023,7 +4069,7 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
| #endif |
| } |
| - return value; |
| + return Just(true); |
| } |
| @@ -4375,68 +4421,76 @@ Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, |
| } |
| -MaybeHandle<Object> JSProxy::SetPropertyWithHandler( |
| - Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, |
| - Handle<Object> value, LanguageMode language_mode) { |
| +Maybe<bool> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
| + Handle<Object> receiver, |
| + Handle<Name> name, |
| + Handle<Object> value, |
| + LanguageMode language_mode, |
| + ShouldThrow should_throw) { |
| Isolate* isolate = proxy->GetIsolate(); |
| // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| - if (name->IsSymbol()) return value; |
| + if (name->IsSymbol()) return Just(false); |
| Handle<Object> args[] = { receiver, name, value }; |
| - RETURN_ON_EXCEPTION( |
| - isolate, |
| - CallTrap(proxy, |
| - "set", |
| - isolate->derived_set_trap(), |
| - arraysize(args), |
| - args), |
| - Object); |
| + RETURN_ON_EXCEPTION_VALUE(isolate, |
| + CallTrap(proxy, "set", isolate->derived_set_trap(), |
| + arraysize(args), args), |
| + Nothing<bool>()); |
| - return value; |
| + return Just(false); |
| + |
| + // TODO(neis): This needs to be made spec-conformant, eg as follows: |
| + /* |
|
Toon Verwaest
2015/10/20 15:25:06
I wouldn't add this commented out code. Open an is
neis
2015/10/21 14:42:25
Done.
|
| + Handle<Object> result; |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, result, |
| + CallTrap(proxy, "set", |
| + isolate->derived_set_trap(), |
| + arraysize(args), args), |
| + Nothing<bool>()); |
| + Handle<Object> handler(proxy->handler(), isolate); |
| + if (result->BooleanValue()) return Just(true); |
| + RETURN_FAILURE(isolate, should_throw, NewTypeError( |
| + MessageTemplate::kProxyHandlerReturned, handler, result, |
| + isolate->factory()->InternalizeUtf8String("set"))); |
| + */ |
| } |
| -MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| +Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( |
| Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, |
| - Handle<Object> value, LanguageMode language_mode, bool* done) { |
| + Handle<Object> value, LanguageMode language_mode, ShouldThrow should_throw, |
| + bool* done) { |
| Isolate* isolate = proxy->GetIsolate(); |
| Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
| // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| if (name->IsSymbol()) { |
| - *done = false; |
| - return isolate->factory()->the_hole_value(); |
| + *done = false; // Return value will be ignored. |
| + return Nothing<bool>(); |
| } |
| *done = true; // except where redefined... |
| Handle<Object> args[] = { name }; |
| Handle<Object> result; |
| - ASSIGN_RETURN_ON_EXCEPTION( |
| - isolate, result, |
| - CallTrap(proxy, |
| - "getPropertyDescriptor", |
| - Handle<Object>(), |
| - arraysize(args), |
| - args), |
| - Object); |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| + isolate, result, CallTrap(proxy, "getPropertyDescriptor", |
| + Handle<Object>(), arraysize(args), args), |
| + Nothing<bool>()); |
| if (result->IsUndefined()) { |
| - *done = false; |
| - return isolate->factory()->the_hole_value(); |
| + *done = false; // Return value will be ignored. |
| + return Nothing<bool>(); |
| } |
| // Emulate [[GetProperty]] semantics for proxies. |
| Handle<Object> argv[] = { result }; |
| Handle<Object> desc; |
| - ASSIGN_RETURN_ON_EXCEPTION( |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| isolate, desc, |
| - Execution::Call(isolate, |
| - isolate->to_complete_property_descriptor(), |
| - result, |
| - arraysize(argv), |
| - argv), |
| - Object); |
| + Execution::Call(isolate, isolate->to_complete_property_descriptor(), |
| + result, arraysize(argv), argv), |
| + Nothing<bool>()); |
| // [[GetProperty]] requires to check that all properties are configurable. |
| Handle<String> configurable_name = |
| @@ -4446,12 +4500,11 @@ MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| Object::GetProperty(desc, configurable_name).ToHandleChecked(); |
| DCHECK(configurable->IsBoolean()); |
| if (configurable->IsFalse()) { |
| - Handle<String> trap = isolate->factory()->InternalizeOneByteString( |
| - STATIC_CHAR_VECTOR("getPropertyDescriptor")); |
| - THROW_NEW_ERROR(isolate, |
| - NewTypeError(MessageTemplate::kProxyPropNotConfigurable, |
| - handler, name, trap), |
| - Object); |
| + RETURN_FAILURE( |
| + isolate, should_throw, |
| + NewTypeError(MessageTemplate::kProxyPropNotConfigurable, handler, name, |
| + isolate->factory()->NewStringFromAsciiChecked( |
| + "getPropertyDescriptor"))); |
| } |
| DCHECK(configurable->IsTrue()); |
| @@ -4469,9 +4522,9 @@ MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| Object::GetProperty(desc, writable_name).ToHandleChecked(); |
| DCHECK(writable->IsBoolean()); |
| *done = writable->IsFalse(); |
| - if (!*done) return isolate->factory()->the_hole_value(); |
| + if (!*done) return Nothing<bool>(); // Return value will be ignored. |
| return WriteToReadOnlyProperty(isolate, receiver, name, value, |
| - language_mode); |
| + language_mode, should_throw); |
| } |
| // We have an AccessorDescriptor. |
| @@ -4481,13 +4534,13 @@ MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| if (!setter->IsUndefined()) { |
| // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| return SetPropertyWithDefinedSetter( |
| - receiver, Handle<JSReceiver>::cast(setter), value); |
| + receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
| } |
| - if (is_sloppy(language_mode)) return value; |
| - THROW_NEW_ERROR( |
| - isolate, NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy), |
| - Object); |
| + if (is_sloppy(language_mode)) return Just(true); |
| + RETURN_FAILURE( |
| + isolate, should_throw, |
| + NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); |
| } |
| @@ -4767,10 +4820,11 @@ MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( |
| // they throw. Here we should do the same. |
| case LookupIterator::INTERCEPTOR: |
| if (handling == DONT_FORCE_FIELD) { |
| - MaybeHandle<Object> maybe_result = |
| - JSObject::SetPropertyWithInterceptor(it, value); |
| - if (!maybe_result.is_null()) return maybe_result; |
| - if (it->isolate()->has_pending_exception()) return maybe_result; |
| + Maybe<bool> result = |
| + JSObject::SetPropertyWithInterceptor(it, value, THROW_ON_ERROR); |
| + if (result.IsJust()) return value; |
| + if (it->isolate()->has_pending_exception()) |
| + return MaybeHandle<Object>(); |
| } |
| break; |
| @@ -4785,11 +4839,9 @@ MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( |
| // Ensure the context isn't changed after calling into accessors. |
| AssertNoContextChange ncc(it->isolate()); |
| - Handle<Object> result; |
| - ASSIGN_RETURN_ON_EXCEPTION( |
| - it->isolate(), result, |
| - JSObject::SetPropertyWithAccessor(it, value, STRICT), Object); |
| - DCHECK(result->SameValue(*value)); |
| + Maybe<bool> result = JSObject::SetPropertyWithAccessor( |
| + it, value, STRICT, THROW_ON_ERROR); |
| + if (result.IsNothing()) return MaybeHandle<Object>(); |
| if (details.attributes() == attributes) return value; |
| @@ -4828,7 +4880,8 @@ MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( |
| Handle<Object> old_value = it->factory()->the_hole_value(); |
| // Regular property update if the attributes match. |
| if (details.attributes() == attributes) { |
| - return SetDataProperty(it, value); |
| + Maybe<bool> result = SetDataProperty(it, value, THROW_ON_ERROR); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
| } |
| // Special case: properties of typed arrays cannot be reconfigured to |
| @@ -6718,6 +6771,15 @@ bool JSObject::ReferencesObject(Object* obj) { |
| } |
| +static MaybeHandle<Object> ReturnObjectOrThrowTypeError( |
| + Handle<JSObject> object, Maybe<bool> maybe, MessageTemplate::Template msg) { |
| + if (!maybe.IsJust()) return MaybeHandle<Object>(); |
| + if (maybe.FromJust()) return object; |
| + Isolate* isolate = object->GetIsolate(); |
| + THROW_NEW_ERROR(isolate, NewTypeError(msg), Object); |
| +} |
| + |
| + |
| Maybe<bool> JSObject::PreventExtensionsInternal(Handle<JSObject> object) { |
| Isolate* isolate = object->GetIsolate(); |
| @@ -6777,15 +6839,6 @@ Maybe<bool> JSObject::PreventExtensionsInternal(Handle<JSObject> object) { |
| } |
| -static MaybeHandle<Object> ReturnObjectOrThrowTypeError( |
| - Handle<JSObject> object, Maybe<bool> maybe, MessageTemplate::Template msg) { |
| - if (!maybe.IsJust()) return MaybeHandle<Object>(); |
| - if (maybe.FromJust()) return object; |
| - Isolate* isolate = object->GetIsolate(); |
| - THROW_NEW_ERROR(isolate, NewTypeError(msg), Object); |
| -} |
| - |
| - |
| MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
| return ReturnObjectOrThrowTypeError(object, PreventExtensionsInternal(object), |
| MessageTemplate::kCannotPreventExt); |
| @@ -14003,6 +14056,17 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, |
| uint32_t index, |
| Handle<Object> value, |
| PropertyAttributes attributes) { |
| + Maybe<bool> result = |
| + AddDataElement(object, index, value, attributes, THROW_ON_ERROR); |
| + return result.IsJust() ? value : MaybeHandle<Object>(); |
| +} |
| + |
| + |
| +// static |
| +Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index, |
| + Handle<Object> value, |
| + PropertyAttributes attributes, |
| + ShouldThrow should_throw) { |
| DCHECK(object->map()->is_extensible()); |
| Isolate* isolate = object->GetIsolate(); |
| @@ -14063,30 +14127,33 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, |
| Handle<JSArray> array = Handle<JSArray>::cast(object); |
| Handle<String> name = isolate->factory()->Uint32ToString(index); |
| - RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); |
| - RETURN_ON_EXCEPTION( |
| + RETURN_ON_EXCEPTION_VALUE(isolate, BeginPerformSplice(array), |
| + Nothing<bool>()); |
| + RETURN_ON_EXCEPTION_VALUE( |
| isolate, EnqueueChangeRecord(array, "add", name, |
| isolate->factory()->the_hole_value()), |
| - Object); |
| - RETURN_ON_EXCEPTION(isolate, |
| - EnqueueChangeRecord(array, "update", |
| - isolate->factory()->length_string(), |
| - old_length_handle), |
| - Object); |
| - RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object); |
| + Nothing<bool>()); |
| + RETURN_ON_EXCEPTION_VALUE( |
| + isolate, EnqueueChangeRecord(array, "update", |
| + isolate->factory()->length_string(), |
| + old_length_handle), |
| + Nothing<bool>()); |
| + RETURN_ON_EXCEPTION_VALUE(isolate, EndPerformSplice(array), |
| + Nothing<bool>()); |
| Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
| - RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted, |
| - new_length - old_length), |
| - Object); |
| + RETURN_ON_EXCEPTION_VALUE(isolate, |
| + EnqueueSpliceRecord(array, old_length, deleted, |
| + new_length - old_length), |
| + Nothing<bool>()); |
| } else if (object->map()->is_observed()) { |
| Handle<String> name = isolate->factory()->Uint32ToString(index); |
| - RETURN_ON_EXCEPTION( |
| + RETURN_ON_EXCEPTION_VALUE( |
| isolate, EnqueueChangeRecord(object, "add", name, |
| isolate->factory()->the_hole_value()), |
| - Object); |
| + Nothing<bool>()); |
| } |
| - return value; |
| + return Just(true); |
| } |
| @@ -14289,17 +14356,6 @@ bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, |
| } |
| -MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { |
| - Isolate* isolate = array->GetIsolate(); |
| - Handle<Name> length = isolate->factory()->length_string(); |
| - Handle<String> typeof_string = Object::TypeOf(isolate, array); |
| - THROW_NEW_ERROR(isolate, |
| - NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, |
| - typeof_string, array), |
| - Object); |
| -} |
| - |
| - |
| template <typename BackingStore> |
| static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) { |
| int limit = object->IsJSArray() |