Change Has* and Get*Attributes to return Maybe<*>, indicating possible exceptions.

BUG=
R=ishell@chromium.org

Review URL: https://codereview.chromium.org/418383002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22624 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2014-07-25 18:32:11 +00:00
parent 3c873c4305
commit 4a956ab1c2
11 changed files with 464 additions and 316 deletions

View File

@ -895,6 +895,13 @@ struct Maybe {
};
// Convenience wrapper.
template <class T>
inline Maybe<T> maybe(T t) {
return Maybe<T>(t);
}
// --- Special objects ---

View File

@ -1905,7 +1905,11 @@ v8::Local<Value> v8::TryCatch::StackTrace() const {
i::HandleScope scope(isolate_);
i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
i::Handle<i::String> name = isolate_->factory()->stack_string();
if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local<Value>();
EXCEPTION_PREAMBLE(isolate_);
Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
has_pending_exception = !maybe.has_value;
EXCEPTION_BAILOUT_CHECK(isolate_, v8::Local<Value>());
if (!maybe.value) return v8::Local<Value>();
i::Handle<i::Object> value;
if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
return v8::Local<Value>();
@ -3139,10 +3143,13 @@ PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
}
i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
PropertyAttributes result =
EXCEPTION_PREAMBLE(isolate);
Maybe<PropertyAttributes> result =
i::JSReceiver::GetPropertyAttributes(self, key_name);
if (result == ABSENT) return static_cast<PropertyAttribute>(NONE);
return static_cast<PropertyAttribute>(result);
has_pending_exception = !result.has_value;
EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
if (result.value == ABSENT) return static_cast<PropertyAttribute>(NONE);
return static_cast<PropertyAttribute>(result.value);
}
@ -3399,7 +3406,11 @@ bool v8::Object::Has(uint32_t index) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
return i::JSReceiver::HasElement(self, index);
EXCEPTION_PREAMBLE(isolate);
Maybe<bool> maybe = i::JSReceiver::HasElement(self, index);
has_pending_exception = !maybe.has_value;
EXCEPTION_BAILOUT_CHECK(isolate, false);
return maybe.value;
}
@ -3478,8 +3489,12 @@ bool v8::Object::HasOwnProperty(Handle<String> key) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
return false);
return i::JSReceiver::HasOwnProperty(
Utils::OpenHandle(this), Utils::OpenHandle(*key));
EXCEPTION_PREAMBLE(isolate);
Maybe<bool> maybe = i::JSReceiver::HasOwnProperty(Utils::OpenHandle(this),
Utils::OpenHandle(*key));
has_pending_exception = !maybe.has_value;
EXCEPTION_BAILOUT_CHECK(isolate, false);
return maybe.value;
}
@ -3487,8 +3502,12 @@ bool v8::Object::HasRealNamedProperty(Handle<String> key) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
return false);
return i::JSObject::HasRealNamedProperty(Utils::OpenHandle(this),
Utils::OpenHandle(*key));
EXCEPTION_PREAMBLE(isolate);
Maybe<bool> maybe = i::JSObject::HasRealNamedProperty(
Utils::OpenHandle(this), Utils::OpenHandle(*key));
has_pending_exception = !maybe.has_value;
EXCEPTION_BAILOUT_CHECK(isolate, false);
return maybe.value;
}
@ -3496,7 +3515,12 @@ bool v8::Object::HasRealIndexedProperty(uint32_t index) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
return false);
return i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
EXCEPTION_PREAMBLE(isolate);
Maybe<bool> maybe =
i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
has_pending_exception = !maybe.has_value;
EXCEPTION_BAILOUT_CHECK(isolate, false);
return maybe.value;
}
@ -3506,8 +3530,12 @@ bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
"v8::Object::HasRealNamedCallbackProperty()",
return false);
ENTER_V8(isolate);
return i::JSObject::HasRealNamedCallbackProperty(Utils::OpenHandle(this),
Utils::OpenHandle(*key));
EXCEPTION_PREAMBLE(isolate);
Maybe<bool> maybe = i::JSObject::HasRealNamedCallbackProperty(
Utils::OpenHandle(this), Utils::OpenHandle(*key));
has_pending_exception = !maybe.has_value;
EXCEPTION_BAILOUT_CHECK(isolate, false);
return maybe.value;
}

View File

@ -106,15 +106,18 @@ Handle<Object> Context::Lookup(Handle<String> name,
// Context extension objects needs to behave as if they have no
// prototype. So even if we want to follow prototype chains, we need
// to only do a local lookup for context extension objects.
Maybe<PropertyAttributes> maybe;
if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
object->IsJSContextExtensionObject()) {
*attributes = JSReceiver::GetOwnPropertyAttributes(object, name);
maybe = JSReceiver::GetOwnPropertyAttributes(object, name);
} else {
*attributes = JSReceiver::GetPropertyAttributes(object, name);
maybe = JSReceiver::GetPropertyAttributes(object, name);
}
if (isolate->has_pending_exception()) return Handle<Object>();
if (!maybe.has_value) return Handle<Object>();
ASSERT(!isolate->has_pending_exception());
*attributes = maybe.value;
if (*attributes != ABSENT) {
if (maybe.value != ABSENT) {
if (FLAG_trace_contexts) {
PrintF("=> found property in context object %p\n",
reinterpret_cast<void*>(*object));

View File

@ -419,7 +419,9 @@ void SetResolvedNumberSettings(Isolate* isolate,
Handle<String> key =
factory->NewStringFromStaticAscii("minimumSignificantDigits");
if (JSReceiver::HasOwnProperty(resolved, key)) {
Maybe<bool> maybe = JSReceiver::HasOwnProperty(resolved, key);
CHECK(maybe.has_value);
if (maybe.value) {
JSObject::SetProperty(
resolved,
factory->NewStringFromStaticAscii("minimumSignificantDigits"),
@ -428,7 +430,9 @@ void SetResolvedNumberSettings(Isolate* isolate,
}
key = factory->NewStringFromStaticAscii("maximumSignificantDigits");
if (JSReceiver::HasOwnProperty(resolved, key)) {
maybe = JSReceiver::HasOwnProperty(resolved, key);
CHECK(maybe.has_value);
if (maybe.value) {
JSObject::SetProperty(
resolved,
factory->NewStringFromStaticAscii("maximumSignificantDigits"),
@ -783,7 +787,9 @@ icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromStaticAscii("dateFormat");
if (JSReceiver::HasOwnProperty(obj, key)) {
Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, key);
CHECK(maybe.has_value);
if (maybe.value) {
return reinterpret_cast<icu::SimpleDateFormat*>(
obj->GetInternalField(0));
}
@ -857,7 +863,9 @@ icu::DecimalFormat* NumberFormat::UnpackNumberFormat(
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromStaticAscii("numberFormat");
if (JSReceiver::HasOwnProperty(obj, key)) {
Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, key);
CHECK(maybe.has_value);
if (maybe.value) {
return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
}
@ -912,7 +920,9 @@ icu::Collator* Collator::InitializeCollator(
icu::Collator* Collator::UnpackCollator(Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key = isolate->factory()->NewStringFromStaticAscii("collator");
if (JSReceiver::HasOwnProperty(obj, key)) {
Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, key);
CHECK(maybe.has_value);
if (maybe.value) {
return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
}
@ -971,7 +981,9 @@ icu::BreakIterator* BreakIterator::UnpackBreakIterator(Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromStaticAscii("breakIterator");
if (JSReceiver::HasOwnProperty(obj, key)) {
Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, key);
CHECK(maybe.has_value);
if (maybe.value) {
return reinterpret_cast<icu::BreakIterator*>(obj->GetInternalField(0));
}

View File

@ -106,15 +106,18 @@ typedef ZoneList<Handle<Object> > ZoneObjectList;
// Macros for MaybeHandle.
#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T) \
#define RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, value) \
do { \
Isolate* __isolate__ = (isolate); \
if (__isolate__->has_scheduled_exception()) { \
__isolate__->PromoteScheduledException(); \
return MaybeHandle<T>(); \
return value; \
} \
} while (false)
#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T) \
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, MaybeHandle<T>())
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value) \
do { \
if (!(call).ToHandle(&dst)) { \

View File

@ -1166,7 +1166,8 @@ MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
}
bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) {
Maybe<bool> JSProxy::HasElementWithHandler(Handle<JSProxy> proxy,
uint32_t index) {
Isolate* isolate = proxy->GetIsolate();
Handle<String> name = isolate->factory()->Uint32ToString(index);
return HasPropertyWithHandler(proxy, name);
@ -6629,27 +6630,32 @@ Object* JSReceiver::GetConstructor() {
}
bool JSReceiver::HasProperty(Handle<JSReceiver> object,
Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
Handle<Name> name) {
if (object->IsJSProxy()) {
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
return JSProxy::HasPropertyWithHandler(proxy, name);
}
return GetPropertyAttributes(object, name) != ABSENT;
Maybe<PropertyAttributes> result = GetPropertyAttributes(object, name);
if (!result.has_value) return Maybe<bool>();
return maybe(result.value != ABSENT);
}
bool JSReceiver::HasOwnProperty(Handle<JSReceiver> object, Handle<Name> name) {
Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
Handle<Name> name) {
if (object->IsJSProxy()) {
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
return JSProxy::HasPropertyWithHandler(proxy, name);
}
return GetOwnPropertyAttributes(object, name) != ABSENT;
Maybe<PropertyAttributes> result = GetOwnPropertyAttributes(object, name);
if (!result.has_value) return Maybe<bool>();
return maybe(result.value != ABSENT);
}
PropertyAttributes JSReceiver::GetPropertyAttributes(Handle<JSReceiver> object,
Handle<Name> key) {
Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
Handle<JSReceiver> object, Handle<Name> key) {
uint32_t index;
if (object->IsJSObject() && key->AsArrayIndex(&index)) {
return GetElementAttribute(object, index);
@ -6659,8 +6665,8 @@ PropertyAttributes JSReceiver::GetPropertyAttributes(Handle<JSReceiver> object,
}
PropertyAttributes JSReceiver::GetElementAttribute(Handle<JSReceiver> object,
uint32_t index) {
Maybe<PropertyAttributes> JSReceiver::GetElementAttribute(
Handle<JSReceiver> object, uint32_t index) {
if (object->IsJSProxy()) {
return JSProxy::GetElementAttributeWithHandler(
Handle<JSProxy>::cast(object), object, index);
@ -6696,27 +6702,32 @@ Object* JSReceiver::GetIdentityHash() {
}
bool JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
if (object->IsJSProxy()) {
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
return JSProxy::HasElementWithHandler(proxy, index);
}
return JSObject::GetElementAttributeWithReceiver(
Handle<JSObject>::cast(object), object, index, true) != ABSENT;
Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
Handle<JSObject>::cast(object), object, index, true);
if (!result.has_value) return Maybe<bool>();
return maybe(result.value != ABSENT);
}
bool JSReceiver::HasOwnElement(Handle<JSReceiver> object, uint32_t index) {
Maybe<bool> JSReceiver::HasOwnElement(Handle<JSReceiver> object,
uint32_t index) {
if (object->IsJSProxy()) {
Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
return JSProxy::HasElementWithHandler(proxy, index);
}
return JSObject::GetElementAttributeWithReceiver(
Handle<JSObject>::cast(object), object, index, false) != ABSENT;
Maybe<PropertyAttributes> result = JSObject::GetElementAttributeWithReceiver(
Handle<JSObject>::cast(object), object, index, false);
if (!result.has_value) return Maybe<bool>();
return maybe(result.value != ABSENT);
}
PropertyAttributes JSReceiver::GetOwnElementAttribute(
Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttribute(
Handle<JSReceiver> object, uint32_t index) {
if (object->IsJSProxy()) {
return JSProxy::GetElementAttributeWithHandler(

View File

@ -594,13 +594,15 @@ MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
}
PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck(
Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
LookupIterator* it) {
Handle<JSObject> checked = it->GetHolder<JSObject>();
if (FindAllCanReadHolder(it)) return it->property_details().attributes();
if (FindAllCanReadHolder(it))
return maybe(it->property_details().attributes());
it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
// TODO(yangguo): Issue 3269, check for scheduled exception missing?
return ABSENT;
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
Maybe<PropertyAttributes>());
return maybe(ABSENT);
}
@ -3019,8 +3021,8 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
Maybe<PropertyAttributes> maybe_attributes =
JSObject::GetPropertyAttributesWithInterceptor(
it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
done = maybe_attributes.has_value;
if (!maybe_attributes.has_value) return MaybeHandle<Object>();
done = maybe_attributes.value != ABSENT;
if (done && (maybe_attributes.value & READ_ONLY) != 0) {
return WriteToReadOnlyProperty(it, value, strict_mode);
}
@ -3594,24 +3596,21 @@ void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
}
bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
Handle<Name> name) {
Isolate* isolate = proxy->GetIsolate();
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (name->IsSymbol()) return false;
if (name->IsSymbol()) return maybe(false);
Handle<Object> args[] = { name };
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, result,
CallTrap(proxy,
"has",
isolate->derived_has_trap(),
ARRAY_SIZE(args),
args),
false);
isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
ARRAY_SIZE(args), args),
Maybe<bool>());
return result->BooleanValue();
return maybe(result->BooleanValue());
}
@ -3779,62 +3778,58 @@ MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
}
PropertyAttributes JSProxy::GetPropertyAttributesWithHandler(
Handle<JSProxy> proxy,
Handle<Object> receiver,
Handle<Name> name) {
Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
Isolate* isolate = proxy->GetIsolate();
HandleScope scope(isolate);
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (name->IsSymbol()) return ABSENT;
if (name->IsSymbol()) return maybe(ABSENT);
Handle<Object> args[] = { name };
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, result,
proxy->CallTrap(proxy,
"getPropertyDescriptor",
Handle<Object>(),
ARRAY_SIZE(args),
args),
NONE);
proxy->CallTrap(proxy, "getPropertyDescriptor", Handle<Object>(),
ARRAY_SIZE(args), args),
Maybe<PropertyAttributes>());
if (result->IsUndefined()) return ABSENT;
if (result->IsUndefined()) return maybe(ABSENT);
Handle<Object> argv[] = { result };
Handle<Object> desc;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, desc,
Execution::Call(isolate,
isolate->to_complete_property_descriptor(),
result,
ARRAY_SIZE(argv),
argv),
NONE);
Execution::Call(isolate, isolate->to_complete_property_descriptor(),
result, ARRAY_SIZE(argv), argv),
Maybe<PropertyAttributes>());
// Convert result to PropertyAttributes.
Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("enumerable_"));
Handle<Object> enumerable;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, enumerable, Object::GetProperty(desc, enum_n), NONE);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
Object::GetProperty(desc, enum_n),
Maybe<PropertyAttributes>());
Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("configurable_"));
Handle<Object> configurable;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, configurable, Object::GetProperty(desc, conf_n), NONE);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
Object::GetProperty(desc, conf_n),
Maybe<PropertyAttributes>());
Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("writable_"));
Handle<Object> writable;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, writable, Object::GetProperty(desc, writ_n), NONE);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
Object::GetProperty(desc, writ_n),
Maybe<PropertyAttributes>());
if (!writable->BooleanValue()) {
Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("set_"));
Handle<Object> setter;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, setter, Object::GetProperty(desc, set_n), NONE);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
Object::GetProperty(desc, set_n),
Maybe<PropertyAttributes>());
writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
}
@ -3846,21 +3841,19 @@ PropertyAttributes JSProxy::GetPropertyAttributesWithHandler(
Handle<Object> error = isolate->factory()->NewTypeError(
"proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
isolate->Throw(*error);
return NONE;
return maybe(NONE);
}
int attributes = NONE;
if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
if (!writable->BooleanValue()) attributes |= READ_ONLY;
return static_cast<PropertyAttributes>(attributes);
return maybe(static_cast<PropertyAttributes>(attributes));
}
PropertyAttributes JSProxy::GetElementAttributeWithHandler(
Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
uint32_t index) {
Maybe<PropertyAttributes> JSProxy::GetElementAttributeWithHandler(
Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) {
Isolate* isolate = proxy->GetIsolate();
Handle<String> name = isolate->factory()->Uint32ToString(index);
return GetPropertyAttributesWithHandler(proxy, receiver, name);
@ -4278,7 +4271,7 @@ Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
Handle<Object> receiver,
Handle<Name> name) {
// TODO(rossberg): Support symbols in the API.
if (name->IsSymbol()) return Maybe<PropertyAttributes>();
if (name->IsSymbol()) return maybe(ABSENT);
Isolate* isolate = holder->GetIsolate();
HandleScope scope(isolate);
@ -4299,8 +4292,7 @@ Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
if (!result.IsEmpty()) {
ASSERT(result->IsInt32());
return Maybe<PropertyAttributes>(
static_cast<PropertyAttributes>(result->Int32Value()));
return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
}
} else if (!interceptor->getter()->IsUndefined()) {
v8::NamedPropertyGetterCallback getter =
@ -4309,13 +4301,15 @@ Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
v8::Handle<v8::Value> result =
args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
if (!result.IsEmpty()) return Maybe<PropertyAttributes>(DONT_ENUM);
if (!result.IsEmpty()) return maybe(DONT_ENUM);
}
return Maybe<PropertyAttributes>();
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
return maybe(ABSENT);
}
PropertyAttributes JSReceiver::GetOwnPropertyAttributes(
Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
Handle<JSReceiver> object, Handle<Name> name) {
// Check whether the name is an array index.
uint32_t index = 0;
@ -4327,7 +4321,8 @@ PropertyAttributes JSReceiver::GetOwnPropertyAttributes(
}
PropertyAttributes JSReceiver::GetPropertyAttributes(LookupIterator* it) {
Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
LookupIterator* it) {
for (; it->IsFound(); it->Next()) {
switch (it->state()) {
case LookupIterator::NOT_FOUND:
@ -4339,25 +4334,26 @@ PropertyAttributes JSReceiver::GetPropertyAttributes(LookupIterator* it) {
Maybe<PropertyAttributes> result =
JSObject::GetPropertyAttributesWithInterceptor(
it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
if (result.has_value) return result.value;
if (!result.has_value) return result;
if (result.value != ABSENT) return result;
break;
}
case LookupIterator::ACCESS_CHECK:
if (it->HasAccess(v8::ACCESS_HAS)) break;
return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
case LookupIterator::PROPERTY:
if (it->HasProperty()) return it->property_details().attributes();
if (it->HasProperty()) {
return maybe(it->property_details().attributes());
}
break;
}
}
return ABSENT;
return maybe(ABSENT);
}
PropertyAttributes JSObject::GetElementAttributeWithReceiver(
Handle<JSObject> object,
Handle<JSReceiver> receiver,
uint32_t index,
Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
bool check_prototype) {
Isolate* isolate = object->GetIsolate();
@ -4365,14 +4361,14 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
// TODO(yangguo): Issue 3269, check for scheduled exception missing?
return ABSENT;
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
return maybe(ABSENT);
}
}
if (object->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate, object);
if (iter.IsAtEnd()) return ABSENT;
if (iter.IsAtEnd()) return maybe(ABSENT);
ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
return JSObject::GetElementAttributeWithReceiver(
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
@ -4390,10 +4386,8 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
}
PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
Handle<JSObject> object,
Handle<JSReceiver> receiver,
uint32_t index,
Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
bool check_prototype) {
Isolate* isolate = object->GetIsolate();
HandleScope scope(isolate);
@ -4412,7 +4406,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
v8::Handle<v8::Integer> result = args.Call(query, index);
if (!result.IsEmpty())
return static_cast<PropertyAttributes>(result->Int32Value());
return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
} else if (!interceptor->getter()->IsUndefined()) {
v8::IndexedPropertyGetterCallback getter =
v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
@ -4420,7 +4414,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
ApiIndexedPropertyAccess(
"interceptor-indexed-get-has", *object, index));
v8::Handle<v8::Value> result = args.Call(getter, index);
if (!result.IsEmpty()) return NONE;
if (!result.IsEmpty()) return maybe(NONE);
}
return GetElementAttributeWithoutInterceptor(
@ -4428,21 +4422,19 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
}
PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
Handle<JSObject> object,
Handle<JSReceiver> receiver,
uint32_t index,
Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor(
Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
bool check_prototype) {
PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
receiver, object, index);
if (attr != ABSENT) return attr;
if (attr != ABSENT) return maybe(attr);
// Handle [] on String objects.
if (object->IsStringObjectWithCharacterAt(index)) {
return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
return maybe(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE));
}
if (!check_prototype) return ABSENT;
if (!check_prototype) return maybe(ABSENT);
PrototypeIterator iter(object->GetIsolate(), object);
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
@ -4451,7 +4443,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
index);
}
if (iter.IsAtEnd()) return ABSENT;
if (iter.IsAtEnd()) return maybe(ABSENT);
return GetElementAttributeWithReceiver(
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
index, true);
@ -5031,7 +5023,10 @@ void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL);
return GetPropertyAttributes(&it) != ABSENT;
Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
// Cannot get an exception since the hidden_string isn't accessible to JS.
ASSERT(maybe.has_value);
return maybe.value != ABSENT;
}
@ -5254,7 +5249,9 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
Handle<Object> old_value;
bool should_enqueue_change_record = false;
if (object->map()->is_observed()) {
should_enqueue_change_record = HasOwnElement(object, index);
Maybe<bool> maybe = HasOwnElement(object, index);
if (!maybe.has_value) return MaybeHandle<Object>();
should_enqueue_change_record = maybe.value;
if (should_enqueue_change_record) {
if (!GetOwnElementAccessorPair(object, index).is_null()) {
old_value = Handle<Object>::cast(factory->the_hole_value());
@ -5275,10 +5272,14 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
if (should_enqueue_change_record && !HasOwnElement(object, index)) {
if (should_enqueue_change_record) {
Maybe<bool> maybe = HasOwnElement(object, index);
if (!maybe.has_value) return MaybeHandle<Object>();
if (!maybe.value) {
Handle<String> name = factory->Uint32ToString(index);
EnqueueChangeRecord(object, "delete", name, old_value);
}
}
return result;
}
@ -5355,9 +5356,13 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
result = DeleteNormalizedProperty(object, name, mode);
}
if (is_observed && !HasOwnProperty(object, name)) {
if (is_observed) {
Maybe<bool> maybe = HasOwnProperty(object, name);
if (!maybe.has_value) return MaybeHandle<Object>();
if (!maybe.value) {
EnqueueChangeRecord(object, "delete", name, old_value);
}
}
return result;
}
@ -5839,8 +5844,10 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
for (int i = 0; i < names->length(); i++) {
ASSERT(names->get(i)->IsString());
Handle<String> key_string(String::cast(names->get(i)));
PropertyAttributes attributes =
Maybe<PropertyAttributes> maybe =
JSReceiver::GetOwnPropertyAttributes(copy, key_string);
ASSERT(maybe.has_value);
PropertyAttributes attributes = maybe.value;
// Only deep copy fields from the object literal expression.
// In particular, don't try to copy the length attribute of
// an array.
@ -6588,7 +6595,7 @@ void JSObject::SetPropertyCallback(Handle<JSObject> object,
}
void JSObject::DefineAccessor(Handle<JSObject> object,
MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
Handle<Name> name,
Handle<Object> getter,
Handle<Object> setter,
@ -6598,17 +6605,17 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
if (object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
// TODO(yangguo): Issue 3269, check for scheduled exception missing?
return;
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
if (object->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate, object);
if (iter.IsAtEnd()) return;
if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
name, getter, setter, attributes);
return;
return isolate->factory()->undefined_value();
}
// Make sure that the top context does not change when doing callbacks or
@ -6627,7 +6634,9 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
bool preexists = false;
if (is_observed) {
if (is_element) {
preexists = HasOwnElement(object, index);
Maybe<bool> maybe = HasOwnElement(object, index);
ASSERT(maybe.has_value);
preexists = maybe.value;
if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
old_value =
Object::GetElement(isolate, object, index).ToHandleChecked();
@ -6653,6 +6662,8 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
const char* type = preexists ? "reconfigure" : "add";
EnqueueChangeRecord(object, type, name, old_value);
}
return isolate->factory()->undefined_value();
}
@ -11655,10 +11666,11 @@ static bool GetOldValue(Isolate* isolate,
uint32_t index,
List<Handle<Object> >* old_values,
List<uint32_t>* indices) {
PropertyAttributes attributes =
Maybe<PropertyAttributes> maybe =
JSReceiver::GetOwnElementAttribute(object, index);
ASSERT(attributes != ABSENT);
if (attributes == DONT_DELETE) return false;
ASSERT(maybe.has_value);
ASSERT(maybe.value != ABSENT);
if (maybe.value == DONT_DELETE) return false;
Handle<Object> value;
if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
value = Handle<Object>::cast(isolate->factory()->the_hole_value());
@ -12891,8 +12903,11 @@ MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
strict_mode, check_prototype, set_mode);
}
PropertyAttributes old_attributes =
Maybe<PropertyAttributes> maybe =
JSReceiver::GetOwnElementAttribute(object, index);
if (!maybe.has_value) return MaybeHandle<Object>();
PropertyAttributes old_attributes = maybe.value;
Handle<Object> old_value = isolate->factory()->the_hole_value();
Handle<Object> old_length_handle;
Handle<Object> new_length_handle;
@ -12921,7 +12936,10 @@ MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
Object);
Handle<String> name = isolate->factory()->Uint32ToString(index);
PropertyAttributes new_attributes = GetOwnElementAttribute(object, index);
maybe = GetOwnElementAttribute(object, index);
if (!maybe.has_value) return MaybeHandle<Object>();
PropertyAttributes new_attributes = maybe.value;
if (old_attributes == ABSENT) {
if (object->IsJSArray() &&
!old_length_handle->SameValue(
@ -13691,7 +13709,7 @@ MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
}
bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
Handle<Name> key) {
Isolate* isolate = object->GetIsolate();
SealHandleScope shs(isolate);
@ -13699,44 +13717,47 @@ bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
// TODO(yangguo): Issue 3269, check for scheduled exception missing?
return false;
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
return maybe(false);
}
}
LookupResult result(isolate);
object->LookupOwnRealNamedProperty(key, &result);
return result.IsFound() && !result.IsInterceptor();
return maybe(result.IsFound() && !result.IsInterceptor());
}
bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) {
Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
uint32_t index) {
Isolate* isolate = object->GetIsolate();
HandleScope scope(isolate);
// Check access rights if needed.
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
// TODO(yangguo): Issue 3269, check for scheduled exception missing?
return false;
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
return maybe(false);
}
}
if (object->IsJSGlobalProxy()) {
HandleScope scope(isolate);
PrototypeIterator iter(isolate, object);
if (iter.IsAtEnd()) return false;
if (iter.IsAtEnd()) return maybe(false);
ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
return HasRealElementProperty(
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
}
return GetElementAttributeWithoutInterceptor(
object, object, index, false) != ABSENT;
Maybe<PropertyAttributes> result =
GetElementAttributeWithoutInterceptor(object, object, index, false);
if (!result.has_value) return Maybe<bool>();
return maybe(result.value != ABSENT);
}
bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
Handle<Name> key) {
Isolate* isolate = object->GetIsolate();
SealHandleScope shs(isolate);
@ -13744,14 +13765,14 @@ bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
// TODO(yangguo): Issue 3269, check for scheduled exception missing?
return false;
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
return maybe(false);
}
}
LookupResult result(isolate);
object->LookupOwnRealNamedProperty(key, &result);
return result.IsPropertyCallbacks();
return maybe(result.IsPropertyCallbacks());
}

View File

@ -1960,10 +1960,14 @@ class JSReceiver: public HeapObject {
StrictMode strict_mode);
// Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
static inline bool HasProperty(Handle<JSReceiver> object, Handle<Name> name);
static inline bool HasOwnProperty(Handle<JSReceiver>, Handle<Name> name);
static inline bool HasElement(Handle<JSReceiver> object, uint32_t index);
static inline bool HasOwnElement(Handle<JSReceiver> object, uint32_t index);
MUST_USE_RESULT static inline Maybe<bool> HasProperty(
Handle<JSReceiver> object, Handle<Name> name);
MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(Handle<JSReceiver>,
Handle<Name> name);
MUST_USE_RESULT static inline Maybe<bool> HasElement(
Handle<JSReceiver> object, uint32_t index);
MUST_USE_RESULT static inline Maybe<bool> HasOwnElement(
Handle<JSReceiver> object, uint32_t index);
// Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7.
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
@ -1985,20 +1989,17 @@ class JSReceiver: public HeapObject {
// function that was used to instantiate the object).
String* constructor_name();
static inline PropertyAttributes GetPropertyAttributes(
Handle<JSReceiver> object,
Handle<Name> name);
static PropertyAttributes GetPropertyAttributes(LookupIterator* it);
static PropertyAttributes GetOwnPropertyAttributes(
Handle<JSReceiver> object,
Handle<Name> name);
MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetPropertyAttributes(
Handle<JSReceiver> object, Handle<Name> name);
MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes(
LookupIterator* it);
MUST_USE_RESULT static Maybe<PropertyAttributes> GetOwnPropertyAttributes(
Handle<JSReceiver> object, Handle<Name> name);
static inline PropertyAttributes GetElementAttribute(
Handle<JSReceiver> object,
uint32_t index);
static inline PropertyAttributes GetOwnElementAttribute(
Handle<JSReceiver> object,
uint32_t index);
MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetElementAttribute(
Handle<JSReceiver> object, uint32_t index);
MUST_USE_RESULT static inline Maybe<PropertyAttributes>
GetOwnElementAttribute(Handle<JSReceiver> object, uint32_t index);
// Return the constructor function (may be Heap::null_value()).
inline Object* GetConstructor();
@ -2198,17 +2199,16 @@ class JSObject: public JSReceiver {
InterceptorInfo* GetIndexedInterceptor();
// Used from JSReceiver.
static Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptor(
Handle<JSObject> holder,
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetPropertyAttributesWithInterceptor(Handle<JSObject> holder,
Handle<Object> receiver,
Handle<Name> name);
static PropertyAttributes GetPropertyAttributesWithFailedAccessCheck(
LookupIterator* it);
static PropertyAttributes GetElementAttributeWithReceiver(
Handle<JSObject> object,
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetPropertyAttributesWithFailedAccessCheck(LookupIterator* it);
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetElementAttributeWithReceiver(Handle<JSObject> object,
Handle<JSReceiver> receiver,
uint32_t index,
bool check_prototype);
uint32_t index, bool check_prototype);
// Retrieves an AccessorPair property from the given object. Might return
// undefined if the property doesn't exist or is of a different kind.
@ -2218,9 +2218,8 @@ class JSObject: public JSReceiver {
AccessorComponent component);
// Defines an AccessorPair property on the given object.
// TODO(mstarzinger): Rename to SetAccessor() and return empty handle on
// exception instead of letting callers check for scheduled exception.
static void DefineAccessor(Handle<JSObject> object,
// TODO(mstarzinger): Rename to SetAccessor().
static MaybeHandle<Object> DefineAccessor(Handle<JSObject> object,
Handle<Name> name,
Handle<Object> getter,
Handle<Object> setter,
@ -2381,11 +2380,12 @@ class JSObject: public JSReceiver {
Handle<JSReceiver> receiver);
// Support functions for v8 api (needed for correct interceptor behavior).
static bool HasRealNamedProperty(Handle<JSObject> object,
Handle<Name> key);
static bool HasRealElementProperty(Handle<JSObject> object, uint32_t index);
static bool HasRealNamedCallbackProperty(Handle<JSObject> object,
Handle<Name> key);
MUST_USE_RESULT static Maybe<bool> HasRealNamedProperty(
Handle<JSObject> object, Handle<Name> key);
MUST_USE_RESULT static Maybe<bool> HasRealElementProperty(
Handle<JSObject> object, uint32_t index);
MUST_USE_RESULT static Maybe<bool> HasRealNamedCallbackProperty(
Handle<JSObject> object, Handle<Name> key);
// Get the header size for a JSObject. Used to compute the index of
// internal fields as well as the number of internal fields.
@ -2658,13 +2658,12 @@ class JSObject: public JSReceiver {
uint32_t index,
Handle<Object> holder);
static PropertyAttributes GetElementAttributeWithInterceptor(
Handle<JSObject> object,
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetElementAttributeWithInterceptor(Handle<JSObject> object,
Handle<JSReceiver> receiver,
uint32_t index,
bool continue_search);
static PropertyAttributes GetElementAttributeWithoutInterceptor(
Handle<JSObject> object,
uint32_t index, bool continue_search);
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetElementAttributeWithoutInterceptor(Handle<JSObject> object,
Handle<JSReceiver> receiver,
uint32_t index,
bool continue_search);
@ -9947,12 +9946,12 @@ class JSProxy: public JSReceiver {
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
Handle<Object> value, StrictMode strict_mode, bool* done);
static PropertyAttributes GetPropertyAttributesWithHandler(
Handle<JSProxy> proxy,
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetPropertyAttributesWithHandler(Handle<JSProxy> proxy,
Handle<Object> receiver,
Handle<Name> name);
static PropertyAttributes GetElementAttributeWithHandler(
Handle<JSProxy> proxy,
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetElementAttributeWithHandler(Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
uint32_t index);
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler(
@ -10004,9 +10003,10 @@ class JSProxy: public JSReceiver {
Handle<Object> value,
StrictMode strict_mode);
static bool HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name);
static inline bool HasElementWithHandler(Handle<JSProxy> proxy,
uint32_t index);
MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler(
Handle<JSProxy> proxy, Handle<Name> name);
MUST_USE_RESULT static inline Maybe<bool> HasElementWithHandler(
Handle<JSProxy> proxy, uint32_t index);
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler(
Handle<JSProxy> proxy,

View File

@ -1946,11 +1946,11 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
// LookupIterator.
if (name->AsArrayIndex(&index)) {
// Get attributes.
attrs = JSReceiver::GetOwnElementAttribute(obj, index);
if (attrs == ABSENT) {
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->undefined_value();
}
Maybe<PropertyAttributes> maybe =
JSReceiver::GetOwnElementAttribute(obj, index);
if (!maybe.has_value) return MaybeHandle<Object>();
attrs = maybe.value;
if (attrs == ABSENT) return factory->undefined_value();
// Get AccessorPair if present.
maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index);
@ -1963,11 +1963,10 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
} else {
// Get attributes.
LookupIterator it(obj, name, LookupIterator::CHECK_OWN);
attrs = JSObject::GetPropertyAttributes(&it);
if (attrs == ABSENT) {
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->undefined_value();
}
Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
if (!maybe.has_value) return MaybeHandle<Object>();
attrs = maybe.value;
if (attrs == ABSENT) return factory->undefined_value();
// Get AccessorPair if present.
if (it.state() == LookupIterator::PROPERTY &&
@ -1982,7 +1981,7 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
isolate, value, Object::GetProperty(&it), Object);
}
}
ASSERT(!isolate->has_scheduled_exception());
ASSERT(!isolate->has_pending_exception());
Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
@ -2143,7 +2142,9 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global,
bool is_const, bool is_function) {
// Do the lookup own properties only, see ES5 erratum.
LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN);
PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
ASSERT(maybe.has_value);
PropertyAttributes old_attributes = maybe.value;
if (old_attributes != ABSENT) {
// The name was declared before; check for conflicting re-declarations.
@ -2271,7 +2272,9 @@ RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
// Lookup the property as own on the global object.
LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN);
PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
ASSERT(maybe.has_value);
PropertyAttributes old_attributes = maybe.value;
PropertyAttributes attr =
static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
@ -2419,7 +2422,9 @@ RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
ASSERT(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
LookupIterator it(holder, name, LookupIterator::CHECK_HIDDEN);
PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
if (!maybe.has_value) return isolate->heap()->exception();
PropertyAttributes old_attributes = maybe.value;
// Ignore if we can't reconfigure the value.
if ((old_attributes & DONT_DELETE) != 0) {
@ -4747,17 +4752,21 @@ static MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> key) {
MaybeHandle<Object> Runtime::HasObjectProperty(Isolate* isolate,
Handle<JSReceiver> object,
Handle<Object> key) {
Maybe<bool> maybe;
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
return isolate->factory()->ToBoolean(JSReceiver::HasElement(object, index));
}
maybe = JSReceiver::HasElement(object, index);
} else {
// Convert the key to a name - possibly by calling back into JavaScript.
Handle<Name> name;
ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
return isolate->factory()->ToBoolean(JSReceiver::HasProperty(object, name));
maybe = JSReceiver::HasProperty(object, name);
}
if (!maybe.has_value) return MaybeHandle<Object>();
return isolate->factory()->ToBoolean(maybe.value);
}
@ -4939,9 +4948,8 @@ RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
bool fast = obj->HasFastProperties();
// DefineAccessor checks access rights.
JSObject::DefineAccessor(obj, name, getter, setter, attr);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::DefineAccessor(obj, name, getter, setter, attr));
if (fast) JSObject::MigrateSlowToFast(obj, 0);
return isolate->heap()->undefined_value();
}
@ -5279,7 +5287,9 @@ RUNTIME_FUNCTION(Runtime_AddPropertyForTemplate) {
} else {
uint32_t index = 0;
RUNTIME_ASSERT(key->ToArrayIndex(&index));
duplicate = JSReceiver::HasOwnElement(object, index);
Maybe<bool> maybe = JSReceiver::HasOwnElement(object, index);
if (!maybe.has_value) return isolate->heap()->exception();
duplicate = maybe.value;
}
if (duplicate) {
Handle<Object> args[1] = { key };
@ -5501,9 +5511,9 @@ RUNTIME_FUNCTION(Runtime_DeleteProperty) {
static Object* HasOwnPropertyImplementation(Isolate* isolate,
Handle<JSObject> object,
Handle<Name> key) {
if (JSReceiver::HasOwnProperty(object, key)) {
return isolate->heap()->true_value();
}
Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key);
if (!maybe.has_value) return isolate->heap()->exception();
if (maybe.value) return isolate->heap()->true_value();
// Handle hidden prototypes. If there's a hidden prototype above this thing
// then we have to check it for properties, because they are supposed to
// look like they are on this object.
@ -5513,7 +5523,7 @@ static Object* HasOwnPropertyImplementation(Isolate* isolate,
->map()
->is_hidden_prototype()) {
// TODO(verwaest): The recursion is not necessary for keys that are array
// indicies. Removing this.
// indices. Removing this.
return HasOwnPropertyImplementation(
isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
key);
@ -5538,11 +5548,11 @@ RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
// Fast case: either the key is a real named property or it is not
// an array index and there are no interceptors or hidden
// prototypes.
if (JSObject::HasRealNamedProperty(js_obj, key)) {
ASSERT(!isolate->has_scheduled_exception());
Maybe<bool> maybe = JSObject::HasRealNamedProperty(js_obj, key);
if (!maybe.has_value) return isolate->heap()->exception();
ASSERT(!isolate->has_pending_exception());
if (maybe.value) {
return isolate->heap()->true_value();
} else {
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
Map* map = js_obj->map();
if (!key_is_array_index &&
@ -5571,10 +5581,9 @@ RUNTIME_FUNCTION(Runtime_HasProperty) {
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
bool result = JSReceiver::HasProperty(receiver, key);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
if (isolate->has_pending_exception()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result);
Maybe<bool> maybe = JSReceiver::HasProperty(receiver, key);
if (!maybe.has_value) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(maybe.value);
}
@ -5584,9 +5593,9 @@ RUNTIME_FUNCTION(Runtime_HasElement) {
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
bool result = JSReceiver::HasElement(receiver, index);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->ToBoolean(result);
Maybe<bool> maybe = JSReceiver::HasElement(receiver, index);
if (!maybe.has_value) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(maybe.value);
}
@ -5597,13 +5606,11 @@ RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
PropertyAttributes att = JSReceiver::GetOwnPropertyAttributes(object, key);
if (att == ABSENT || (att & DONT_ENUM) != 0) {
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->false_value();
}
ASSERT(!isolate->has_scheduled_exception());
return isolate->heap()->true_value();
Maybe<PropertyAttributes> maybe =
JSReceiver::GetOwnPropertyAttributes(object, key);
if (!maybe.has_value) return isolate->heap()->exception();
if (maybe.value == ABSENT) maybe.value = DONT_ENUM;
return isolate->heap()->ToBoolean((maybe.value & DONT_ENUM) == 0);
}
@ -9196,7 +9203,13 @@ static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate,
// property from it.
if (!holder.is_null()) {
Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name));
#ifdef DEBUG
if (!object->IsJSProxy()) {
Maybe<bool> maybe = JSReceiver::HasProperty(object, name);
ASSERT(maybe.has_value);
ASSERT(maybe.value);
}
#endif
// GetProperty below can cause GC.
Handle<Object> receiver_handle(
object->IsGlobalObject()
@ -10183,16 +10196,19 @@ static bool IterateElements(Isolate* isolate,
Handle<Object> element_value(elements->get(j), isolate);
if (!element_value->IsTheHole()) {
visitor->visit(j, element_value);
} else if (JSReceiver::HasElement(receiver, j)) {
} else {
Maybe<bool> maybe = JSReceiver::HasElement(receiver, j);
if (!maybe.has_value) return false;
if (maybe.value) {
// Call GetElement on receiver, not its prototype, or getters won't
// have the correct receiver.
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, element_value,
Object::GetElement(isolate, receiver, j),
false);
Object::GetElement(isolate, receiver, j), false);
visitor->visit(j, element_value);
}
}
}
break;
}
case FAST_HOLEY_DOUBLE_ELEMENTS:
@ -10216,17 +10232,20 @@ static bool IterateElements(Isolate* isolate,
Handle<Object> element_value =
isolate->factory()->NewNumber(double_value);
visitor->visit(j, element_value);
} else if (JSReceiver::HasElement(receiver, j)) {
} else {
Maybe<bool> maybe = JSReceiver::HasElement(receiver, j);
if (!maybe.has_value) return false;
if (maybe.value) {
// Call GetElement on receiver, not its prototype, or getters won't
// have the correct receiver.
Handle<Object> element_value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, element_value,
Object::GetElement(isolate, receiver, j),
false);
Object::GetElement(isolate, receiver, j), false);
visitor->visit(j, element_value);
}
}
}
break;
}
case DICTIONARY_ELEMENTS: {
@ -11539,7 +11558,9 @@ static bool SetLocalVariableValue(Isolate* isolate,
!function_context->IsNativeContext()) {
Handle<JSObject> ext(JSObject::cast(function_context->extension()));
if (JSReceiver::HasProperty(ext, variable_name)) {
Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
ASSERT(maybe.has_value);
if (maybe.value) {
// We don't expect this to do anything except replacing
// property value.
Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
@ -11623,7 +11644,9 @@ static bool SetClosureVariableValue(Isolate* isolate,
// be variables introduced by eval.
if (context->has_extension()) {
Handle<JSObject> ext(JSObject::cast(context->extension()));
if (JSReceiver::HasProperty(ext, variable_name)) {
Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
ASSERT(maybe.has_value);
if (maybe.value) {
// We don't expect this to do anything except replacing property value.
Runtime::DefineObjectProperty(
ext, variable_name, new_value, NONE).Assert();
@ -12700,11 +12723,11 @@ MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject(
Handle<JSFunction> function) {
// Do not materialize the arguments object for eval or top-level code.
// Skip if "arguments" is already taken.
if (!function->shared()->is_function() ||
JSReceiver::HasOwnProperty(
target, isolate->factory()->arguments_string())) {
return target;
}
if (!function->shared()->is_function()) return target;
Maybe<bool> maybe = JSReceiver::HasOwnProperty(
target, isolate->factory()->arguments_string());
if (!maybe.has_value) return MaybeHandle<JSObject>();
if (maybe.value) return target;
// FunctionGetArguments can't throw an exception.
Handle<JSObject> arguments = Handle<JSObject>::cast(

View File

@ -210,7 +210,9 @@ TEST(HeapObjects) {
Handle<String> object_string = Handle<String>::cast(factory->Object_string());
Handle<GlobalObject> global(CcTest::i_isolate()->context()->global_object());
CHECK(JSReceiver::HasOwnProperty(global, object_string));
v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, object_string);
CHECK(maybe.has_value);
CHECK(maybe.value);
// Check ToString for oddballs
CheckOddball(isolate, heap->true_value(), "true");
@ -277,7 +279,9 @@ TEST(GarbageCollection) {
heap->CollectGarbage(NEW_SPACE);
// Function should be alive.
CHECK(JSReceiver::HasOwnProperty(global, name));
v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, name);
CHECK(maybe.has_value);
CHECK(maybe.value);
// Check function is retained.
Handle<Object> func_value =
Object::GetProperty(global, name).ToHandleChecked();
@ -295,7 +299,9 @@ TEST(GarbageCollection) {
// After gc, it should survive.
heap->CollectGarbage(NEW_SPACE);
CHECK(JSReceiver::HasOwnProperty(global, obj_name));
maybe = JSReceiver::HasOwnProperty(global, obj_name);
CHECK(maybe.has_value);
CHECK(maybe.value);
Handle<Object> obj =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(obj->IsJSObject());
@ -652,55 +658,85 @@ TEST(ObjectProperties) {
Handle<Smi> two(Smi::FromInt(2), isolate);
// check for empty
CHECK(!JSReceiver::HasOwnProperty(obj, first));
v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);
// add first
JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
CHECK(JSReceiver::HasOwnProperty(obj, first));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(maybe.value);
// delete first
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
CHECK(!JSReceiver::HasOwnProperty(obj, first));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);
// add first and then second
JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
CHECK(JSReceiver::HasOwnProperty(obj, first));
CHECK(JSReceiver::HasOwnProperty(obj, second));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(maybe.value);
maybe = JSReceiver::HasOwnProperty(obj, second);
CHECK(maybe.has_value);
CHECK(maybe.value);
// delete first and then second
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
CHECK(JSReceiver::HasOwnProperty(obj, second));
maybe = JSReceiver::HasOwnProperty(obj, second);
CHECK(maybe.has_value);
CHECK(maybe.value);
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
CHECK(!JSReceiver::HasOwnProperty(obj, first));
CHECK(!JSReceiver::HasOwnProperty(obj, second));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);
maybe = JSReceiver::HasOwnProperty(obj, second);
CHECK(maybe.has_value);
CHECK(!maybe.value);
// add first and then second
JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
CHECK(JSReceiver::HasOwnProperty(obj, first));
CHECK(JSReceiver::HasOwnProperty(obj, second));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(maybe.value);
maybe = JSReceiver::HasOwnProperty(obj, second);
CHECK(maybe.has_value);
CHECK(maybe.value);
// delete second and then first
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
CHECK(JSReceiver::HasOwnProperty(obj, first));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(maybe.value);
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
CHECK(!JSReceiver::HasOwnProperty(obj, first));
CHECK(!JSReceiver::HasOwnProperty(obj, second));
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);
maybe = JSReceiver::HasOwnProperty(obj, second);
CHECK(maybe.has_value);
CHECK(!maybe.value);
// check string and internalized string match
const char* string1 = "fisk";
Handle<String> s1 = factory->NewStringFromAsciiChecked(string1);
JSReceiver::SetProperty(obj, s1, one, SLOPPY).Check();
Handle<String> s1_string = factory->InternalizeUtf8String(string1);
CHECK(JSReceiver::HasOwnProperty(obj, s1_string));
maybe = JSReceiver::HasOwnProperty(obj, s1_string);
CHECK(maybe.has_value);
CHECK(maybe.value);
// check internalized string and string match
const char* string2 = "fugl";
Handle<String> s2_string = factory->InternalizeUtf8String(string2);
JSReceiver::SetProperty(obj, s2_string, one, SLOPPY).Check();
Handle<String> s2 = factory->NewStringFromAsciiChecked(string2);
CHECK(JSReceiver::HasOwnProperty(obj, s2));
maybe = JSReceiver::HasOwnProperty(obj, s2);
CHECK(maybe.has_value);
CHECK(maybe.value);
}

View File

@ -167,7 +167,9 @@ TEST(MarkCompactCollector) {
{ HandleScope scope(isolate);
Handle<String> func_name = factory->InternalizeUtf8String("theFunction");
CHECK(JSReceiver::HasOwnProperty(global, func_name));
v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, func_name);
CHECK(maybe.has_value);
CHECK(maybe.value);
Handle<Object> func_value =
Object::GetProperty(global, func_name).ToHandleChecked();
CHECK(func_value->IsJSFunction());
@ -185,7 +187,9 @@ TEST(MarkCompactCollector) {
{ HandleScope scope(isolate);
Handle<String> obj_name = factory->InternalizeUtf8String("theObject");
CHECK(JSReceiver::HasOwnProperty(global, obj_name));
v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, obj_name);
CHECK(maybe.has_value);
CHECK(maybe.value);
Handle<Object> object =
Object::GetProperty(global, obj_name).ToHandleChecked();
CHECK(object->IsJSObject());