Restructure Object::SetProperty and related functions.
This is in preparation of implementing Reflect.set. R=rossberg BUG= Review URL: https://codereview.chromium.org/1394983005 Cr-Commit-Position: refs/heads/master@{#31501}
This commit is contained in:
parent
1c50fc1162
commit
d91e9e4f1d
@ -300,7 +300,7 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
|
||||
isolate->factory()->prototype_string()),
|
||||
JSFunction);
|
||||
MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false,
|
||||
THROW_ON_ERROR),
|
||||
Object::THROW_ON_ERROR),
|
||||
MaybeHandle<JSFunction>());
|
||||
}
|
||||
}
|
||||
|
@ -3709,8 +3709,8 @@ Maybe<bool> v8::Object::SetPrototype(Local<Context> context,
|
||||
// We do not allow exceptions thrown while setting the prototype
|
||||
// to propagate outside.
|
||||
TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
|
||||
auto result =
|
||||
i::JSObject::SetPrototype(self, value_obj, false, i::THROW_ON_ERROR);
|
||||
auto result = i::JSObject::SetPrototype(self, value_obj, false,
|
||||
i::Object::THROW_ON_ERROR);
|
||||
has_pending_exception = result.IsNothing();
|
||||
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
|
||||
return Just(true);
|
||||
|
@ -701,7 +701,7 @@ Handle<JSFunction> Genesis::GetThrowTypeErrorIntrinsic(
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY))
|
||||
.Assert();
|
||||
|
||||
if (JSObject::PreventExtensions(function, THROW_ON_ERROR).IsNothing())
|
||||
if (JSObject::PreventExtensions(function, Object::THROW_ON_ERROR).IsNothing())
|
||||
DCHECK(false);
|
||||
|
||||
return function;
|
||||
|
@ -1585,7 +1585,7 @@ BUILTIN(ReflectPreventExtensions) {
|
||||
}
|
||||
|
||||
Maybe<bool> result = JSReceiver::PreventExtensions(
|
||||
Handle<JSReceiver>::cast(target), DONT_THROW);
|
||||
Handle<JSReceiver>::cast(target), Object::DONT_THROW);
|
||||
return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
|
||||
: isolate->heap()->exception();
|
||||
}
|
||||
@ -1611,7 +1611,7 @@ BUILTIN(ReflectSetPrototypeOf) {
|
||||
}
|
||||
|
||||
Maybe<bool> result = JSReceiver::SetPrototype(
|
||||
Handle<JSReceiver>::cast(target), proto, true, DONT_THROW);
|
||||
Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
|
||||
MAYBE_RETURN(result, isolate->heap()->exception());
|
||||
return *isolate->factory()->ToBoolean(result.FromJust());
|
||||
}
|
||||
|
473
src/objects.cc
473
src/objects.cc
@ -866,8 +866,10 @@ bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::SetPropertyWithAccessor(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
|
||||
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();
|
||||
@ -883,21 +885,24 @@ 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);
|
||||
// TODO(verwaest): Shouldn't this case be unreachable (at least in the
|
||||
// long run?) Should we have ExecutableAccessorPairs with missing setter
|
||||
// that are "writable"? If they aren't writable, shouldn't we have bailed
|
||||
// out already earlier?
|
||||
|
||||
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.
|
||||
@ -905,15 +910,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>()));
|
||||
}
|
||||
|
||||
|
||||
@ -945,10 +948,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();
|
||||
@ -957,10 +960,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);
|
||||
}
|
||||
|
||||
|
||||
@ -1045,17 +1048,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>();
|
||||
}
|
||||
|
||||
|
||||
@ -3514,8 +3520,8 @@ 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) {
|
||||
Isolate* isolate = it->isolate();
|
||||
// Make sure that the top context does not change when doing callbacks or
|
||||
// interceptor calls.
|
||||
@ -3523,7 +3529,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 Just(false);
|
||||
|
||||
Handle<JSObject> holder = it->GetHolder<JSObject>();
|
||||
v8::Local<v8::Value> result;
|
||||
@ -3541,7 +3547,7 @@ MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
|
||||
Handle<Name> name = it->name();
|
||||
|
||||
if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
|
||||
return MaybeHandle<Object>();
|
||||
return Just(false);
|
||||
}
|
||||
|
||||
v8::GenericNamedPropertySetterCallback setter =
|
||||
@ -3553,13 +3559,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 Just(false);
|
||||
#ifdef DEBUG
|
||||
Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
|
||||
result_internal->VerifyApiCallResultType();
|
||||
#endif
|
||||
return value;
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
|
||||
@ -3572,11 +3578,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());
|
||||
@ -3593,20 +3597,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;
|
||||
}
|
||||
@ -3614,24 +3619,26 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
|
||||
|
||||
case LookupIterator::INTERCEPTOR:
|
||||
if (it->HolderIsReceiverOrHiddenPrototype()) {
|
||||
MaybeHandle<Object> maybe_result =
|
||||
Maybe<bool> maybe_result =
|
||||
JSObject::SetPropertyWithInterceptor(it, value);
|
||||
if (!maybe_result.is_null()) return maybe_result;
|
||||
if (it->isolate()->has_pending_exception()) return maybe_result;
|
||||
if (maybe_result.IsNothing()) return Nothing<bool>();
|
||||
if (maybe_result.FromJust()) return Just(true);
|
||||
} 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() &&
|
||||
@ -3640,18 +3647,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;
|
||||
@ -3668,13 +3676,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>();
|
||||
}
|
||||
|
||||
|
||||
@ -3682,11 +3689,22 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
|
||||
Handle<Object> value,
|
||||
LanguageMode language_mode,
|
||||
StoreFromKeyed store_mode) {
|
||||
MAYBE_RETURN_NULL(
|
||||
SetProperty(it, value, language_mode, THROW_ON_ERROR, store_mode));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -3695,12 +3713,17 @@ 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) {
|
||||
MAYBE_RETURN_NULL(result);
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!it->GetReceiver()->IsJSReceiver()) {
|
||||
return WriteToReadOnlyProperty(it, value, language_mode);
|
||||
MAYBE_RETURN_NULL(
|
||||
WriteToReadOnlyProperty(it, value, language_mode, THROW_ON_ERROR));
|
||||
return value;
|
||||
}
|
||||
|
||||
LookupIterator::Configuration c = LookupIterator::OWN;
|
||||
@ -3713,7 +3736,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_RETURN_NULL(JSObject::SetPropertyWithFailedAccessCheck(
|
||||
&own_lookup, value, THROW_ON_ERROR));
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3727,7 +3752,9 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
|
||||
return JSObject::DefineOwnPropertyIgnoreAttributes(
|
||||
&own_lookup, value, details.attributes());
|
||||
}
|
||||
return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
|
||||
MAYBE_RETURN_NULL(WriteToReadOnlyProperty(
|
||||
&own_lookup, value, language_mode, THROW_ON_ERROR));
|
||||
return value;
|
||||
}
|
||||
|
||||
case LookupIterator::ACCESSOR: {
|
||||
@ -3744,9 +3771,13 @@ 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) {
|
||||
MAYBE_RETURN_NULL(result);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3786,44 +3817,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);
|
||||
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::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);
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@ -3837,8 +3864,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());
|
||||
@ -3859,8 +3886,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
|
||||
@ -3871,7 +3898,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.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3885,10 +3913,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
|
||||
@ -3896,7 +3925,7 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
|
||||
receiver->JSObjectVerify();
|
||||
}
|
||||
#endif
|
||||
return value;
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
|
||||
@ -3946,9 +3975,21 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
|
||||
PropertyAttributes attributes,
|
||||
LanguageMode language_mode,
|
||||
StoreFromKeyed store_mode) {
|
||||
MAYBE_RETURN_NULL(AddDataProperty(it, value, attributes, language_mode,
|
||||
THROW_ON_ERROR, store_mode));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
@ -3957,24 +3998,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 &&
|
||||
@ -3987,8 +4031,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 {
|
||||
@ -4012,10 +4056,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) {
|
||||
@ -4024,7 +4068,7 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
|
||||
#endif
|
||||
}
|
||||
|
||||
return value;
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
|
||||
@ -4376,68 +4420,63 @@ 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(true);
|
||||
|
||||
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(true);
|
||||
// TODO(neis): This needs to be made spec-conformant by throwing a TypeError
|
||||
// if the trap's result is falsish.
|
||||
}
|
||||
|
||||
|
||||
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 =
|
||||
@ -4447,12 +4486,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());
|
||||
|
||||
@ -4470,9 +4508,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.
|
||||
@ -4482,13 +4520,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));
|
||||
}
|
||||
|
||||
|
||||
@ -4768,10 +4806,9 @@ 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);
|
||||
if (result.IsNothing()) return MaybeHandle<Object>();
|
||||
if (result.FromJust()) return value;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4786,11 +4823,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;
|
||||
|
||||
@ -4829,7 +4864,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_RETURN_NULL(SetDataProperty(it, value, THROW_ON_ERROR));
|
||||
return value;
|
||||
}
|
||||
|
||||
// Special case: properties of typed arrays cannot be reconfigured to
|
||||
@ -6962,18 +6998,16 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
|
||||
|
||||
|
||||
MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
|
||||
return PreventExtensionsWithTransition<FROZEN>(object, THROW_ON_ERROR)
|
||||
.IsJust()
|
||||
? object
|
||||
: MaybeHandle<Object>();
|
||||
MAYBE_RETURN_NULL(
|
||||
PreventExtensionsWithTransition<FROZEN>(object, THROW_ON_ERROR));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) {
|
||||
return PreventExtensionsWithTransition<SEALED>(object, THROW_ON_ERROR)
|
||||
.IsJust()
|
||||
? object
|
||||
: MaybeHandle<Object>();
|
||||
MAYBE_RETURN_NULL(
|
||||
PreventExtensionsWithTransition<SEALED>(object, THROW_ON_ERROR));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
@ -14160,6 +14194,17 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
|
||||
uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) {
|
||||
MAYBE_RETURN_NULL(
|
||||
AddDataElement(object, index, value, attributes, THROW_ON_ERROR));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// 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();
|
||||
@ -14220,30 +14265,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);
|
||||
}
|
||||
|
||||
|
||||
@ -14446,17 +14494,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()
|
||||
|
123
src/objects.h
123
src/objects.h
@ -1033,6 +1033,25 @@ class Object {
|
||||
CERTAINLY_NOT_STORE_FROM_KEYED
|
||||
};
|
||||
|
||||
enum ShouldThrow { THROW_ON_ERROR, DONT_THROW };
|
||||
|
||||
#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)
|
||||
|
||||
#define MAYBE_RETURN(call, value) \
|
||||
do { \
|
||||
if ((call).IsNothing()) return value; \
|
||||
} while (false)
|
||||
|
||||
#define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>())
|
||||
|
||||
INLINE(bool IsFixedArrayBase() const);
|
||||
INLINE(bool IsExternal() const);
|
||||
INLINE(bool IsAccessorInfo() const);
|
||||
@ -1219,12 +1238,22 @@ class Object {
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetProperty(
|
||||
LookupIterator* it, LanguageMode language_mode = SLOPPY);
|
||||
|
||||
// Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5.
|
||||
// ES6 [[Set]] (when passed DONT_THROW)
|
||||
// Invariants for this and related functions (unless stated otherwise):
|
||||
// 1) When the result is Nothing, an exception is pending.
|
||||
// 2) When passed THROW_ON_ERROR, the result is never Just(false).
|
||||
// In some cases, an exception is thrown regardless of the ShouldThrow
|
||||
// argument. These cases are either in accordance with the spec or not
|
||||
// covered by it (eg., concerning API callbacks).
|
||||
MUST_USE_RESULT static Maybe<bool> SetProperty(LookupIterator* it,
|
||||
Handle<Object> value,
|
||||
LanguageMode language_mode,
|
||||
ShouldThrow should_throw,
|
||||
StoreFromKeyed store_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
|
||||
Handle<Object> object, Handle<Name> name, Handle<Object> value,
|
||||
LanguageMode language_mode,
|
||||
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode,
|
||||
StoreFromKeyed store_mode);
|
||||
@ -1238,24 +1267,30 @@ class Object {
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ReadAbsentProperty(
|
||||
Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
|
||||
LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> CannotCreateProperty(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> CannotCreateProperty(
|
||||
MUST_USE_RESULT static Maybe<bool> CannotCreateProperty(
|
||||
Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
|
||||
Handle<Object> value, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
|
||||
Handle<Object> value, LanguageMode language_mode,
|
||||
ShouldThrow should_throw);
|
||||
MUST_USE_RESULT static Maybe<bool> WriteToReadOnlyProperty(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode,
|
||||
ShouldThrow should_throw);
|
||||
MUST_USE_RESULT static Maybe<bool> WriteToReadOnlyProperty(
|
||||
Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
|
||||
Handle<Object> value, LanguageMode language_mode);
|
||||
Handle<Object> value, LanguageMode language_mode,
|
||||
ShouldThrow should_throw);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> RedefineNonconfigurableProperty(
|
||||
Isolate* isolate, Handle<Object> name, Handle<Object> value,
|
||||
LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
|
||||
LookupIterator* it, Handle<Object> value);
|
||||
MUST_USE_RESULT static Maybe<bool> SetDataProperty(LookupIterator* it,
|
||||
Handle<Object> value,
|
||||
ShouldThrow should_throw);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
|
||||
LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
|
||||
LanguageMode language_mode, StoreFromKeyed store_mode);
|
||||
MUST_USE_RESULT static Maybe<bool> AddDataProperty(
|
||||
LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
|
||||
LanguageMode language_mode, ShouldThrow should_throw,
|
||||
StoreFromKeyed store_mode);
|
||||
MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
|
||||
Handle<Object> object, Handle<Name> name,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
@ -1271,16 +1306,16 @@ class Object {
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor(
|
||||
LookupIterator* it, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static Maybe<bool> SetPropertyWithAccessor(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode,
|
||||
ShouldThrow should_throw);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
|
||||
Handle<Object> receiver,
|
||||
Handle<JSReceiver> getter);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithDefinedSetter(
|
||||
Handle<Object> receiver,
|
||||
Handle<JSReceiver> setter,
|
||||
Handle<Object> value);
|
||||
MUST_USE_RESULT static Maybe<bool> SetPropertyWithDefinedSetter(
|
||||
Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value,
|
||||
ShouldThrow should_throw);
|
||||
|
||||
MUST_USE_RESULT static inline MaybeHandle<Object> GetElement(
|
||||
Isolate* isolate, Handle<Object> object, uint32_t index,
|
||||
@ -1374,9 +1409,10 @@ class Object {
|
||||
Map* GetRootMap(Isolate* isolate);
|
||||
|
||||
// Helper for SetProperty and SetSuperProperty.
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyInternal(
|
||||
// Return value is only meaningful if [found] is set to true on return.
|
||||
MUST_USE_RESULT static Maybe<bool> SetPropertyInternal(
|
||||
LookupIterator* it, Handle<Object> value, LanguageMode language_mode,
|
||||
StoreFromKeyed store_mode, bool* found);
|
||||
ShouldThrow should_throw, StoreFromKeyed store_mode, bool* found);
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
|
||||
};
|
||||
@ -1798,28 +1834,6 @@ enum KeyFilter { SKIP_SYMBOLS, INCLUDE_SYMBOLS };
|
||||
enum GetKeysConversion { KEEP_NUMBERS, CONVERT_TO_STRING };
|
||||
|
||||
|
||||
enum ShouldThrow { THROW_ON_ERROR, DONT_THROW };
|
||||
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
#define MAYBE_RETURN(call, value) \
|
||||
do { \
|
||||
if ((call).IsNothing()) return value; \
|
||||
} while (false)
|
||||
|
||||
#define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>())
|
||||
|
||||
|
||||
// JSReceiver includes types on which properties can be defined, i.e.,
|
||||
// JSObject and JSProxy.
|
||||
class JSReceiver: public HeapObject {
|
||||
@ -2040,7 +2054,7 @@ class JSObject: public JSReceiver {
|
||||
static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object,
|
||||
uint32_t limit);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor(
|
||||
MUST_USE_RESULT static Maybe<bool> SetPropertyWithInterceptor(
|
||||
LookupIterator* it, Handle<Object> value);
|
||||
|
||||
// SetLocalPropertyIgnoreAttributes converts callbacks to fields. We need to
|
||||
@ -2077,6 +2091,9 @@ class JSObject: public JSReceiver {
|
||||
static void AddProperty(Handle<JSObject> object, Handle<Name> name,
|
||||
Handle<Object> value, PropertyAttributes attributes);
|
||||
|
||||
MUST_USE_RESULT static Maybe<bool> AddDataElement(
|
||||
Handle<JSObject> receiver, uint32_t index, Handle<Object> value,
|
||||
PropertyAttributes attributes, ShouldThrow should_throw);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> AddDataElement(
|
||||
Handle<JSObject> receiver, uint32_t index, Handle<Object> value,
|
||||
PropertyAttributes attributes);
|
||||
@ -2505,8 +2522,8 @@ class JSObject: public JSReceiver {
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it, Handle<Object> value);
|
||||
MUST_USE_RESULT static Maybe<bool> SetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it, Handle<Object> value, ShouldThrow should_throw);
|
||||
|
||||
// Add a property to a slow-case object.
|
||||
static void AddSlowProperty(Handle<JSObject> object,
|
||||
@ -9546,20 +9563,23 @@ class JSProxy: public JSReceiver {
|
||||
|
||||
// If the handler defines an accessor property with a setter, invoke it.
|
||||
// If it defines an accessor property without a setter, or a data property
|
||||
// that is read-only, throw. In all these cases set '*done' to true,
|
||||
// otherwise set it to false.
|
||||
// that is read-only, fail. In all these cases set '*done' to true.
|
||||
// Otherwise set it to false, in which case the return value is not
|
||||
// meaningful.
|
||||
MUST_USE_RESULT
|
||||
static MaybeHandle<Object> SetPropertyViaPrototypesWithHandler(
|
||||
static Maybe<bool> 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);
|
||||
|
||||
MUST_USE_RESULT static Maybe<PropertyAttributes>
|
||||
GetPropertyAttributesWithHandler(Handle<JSProxy> proxy,
|
||||
Handle<Object> receiver,
|
||||
Handle<Name> name);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler(
|
||||
MUST_USE_RESULT static Maybe<bool> SetPropertyWithHandler(
|
||||
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
|
||||
Handle<Object> value, LanguageMode language_mode);
|
||||
Handle<Object> value, LanguageMode language_mode,
|
||||
ShouldThrow should_throw);
|
||||
|
||||
// Turn the proxy into an (empty) JSObject.
|
||||
static void Fix(Handle<JSProxy> proxy);
|
||||
@ -10093,7 +10113,6 @@ class JSArray: public JSObject {
|
||||
|
||||
static bool HasReadOnlyLength(Handle<JSArray> array);
|
||||
static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index);
|
||||
static MaybeHandle<Object> ReadOnlyLengthError(Handle<JSArray> array);
|
||||
|
||||
// Initialize the array with the given capacity. The function may
|
||||
// fail due to out-of-memory situations, but only if the requested
|
||||
|
@ -320,9 +320,9 @@ static Object* ArrayConstructorCommon(Isolate* isolate,
|
||||
if (original_constructor->has_instance_prototype()) {
|
||||
Handle<Object> prototype =
|
||||
handle(original_constructor->instance_prototype(), isolate);
|
||||
MAYBE_RETURN(
|
||||
JSObject::SetPrototype(array, prototype, false, THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
MAYBE_RETURN(JSObject::SetPrototype(array, prototype, false,
|
||||
Object::THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
|
||||
|
||||
if (!constructor_parent.is_null()) {
|
||||
MAYBE_RETURN_NULL(JSObject::SetPrototype(constructor, constructor_parent,
|
||||
false, THROW_ON_ERROR));
|
||||
false, Object::THROW_ON_ERROR));
|
||||
}
|
||||
|
||||
JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
|
||||
|
@ -166,8 +166,9 @@ RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
|
||||
DCHECK(args.length() == 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
||||
MAYBE_RETURN(JSReceiver::SetPrototype(obj, prototype, false, THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
MAYBE_RETURN(
|
||||
JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
return *obj;
|
||||
}
|
||||
|
||||
@ -177,8 +178,9 @@ RUNTIME_FUNCTION(Runtime_SetPrototype) {
|
||||
DCHECK(args.length() == 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
|
||||
MAYBE_RETURN(JSReceiver::SetPrototype(obj, prototype, true, THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
MAYBE_RETURN(
|
||||
JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
return *obj;
|
||||
}
|
||||
|
||||
@ -263,7 +265,7 @@ RUNTIME_FUNCTION(Runtime_PreventExtensions) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
|
||||
if (JSReceiver::PreventExtensions(obj, THROW_ON_ERROR).IsNothing())
|
||||
if (JSReceiver::PreventExtensions(obj, Object::THROW_ON_ERROR).IsNothing())
|
||||
return isolate->heap()->exception();
|
||||
return *obj;
|
||||
}
|
||||
@ -1025,9 +1027,9 @@ static Object* Runtime_NewObjectHelper(Isolate* isolate,
|
||||
if (original_function->has_instance_prototype()) {
|
||||
Handle<Object> prototype =
|
||||
handle(original_function->instance_prototype(), isolate);
|
||||
MAYBE_RETURN(
|
||||
JSObject::SetPrototype(result, prototype, false, THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
MAYBE_RETURN(JSObject::SetPrototype(result, prototype, false,
|
||||
Object::THROW_ON_ERROR),
|
||||
isolate->heap()->exception());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -864,7 +864,7 @@ RUNTIME_FUNCTION(Runtime_DeclareModules) {
|
||||
}
|
||||
}
|
||||
|
||||
if (JSObject::PreventExtensions(module, THROW_ON_ERROR).IsNothing())
|
||||
if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR).IsNothing())
|
||||
DCHECK(false);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user