| Index: src/objects.cc
 | 
| diff --git a/src/objects.cc b/src/objects.cc
 | 
| index cfd18780795be70e6aa75736cf43e16ba11eb6e5..20fd66b37eb90b1f1523627350edace29096bfa9 100644
 | 
| --- a/src/objects.cc
 | 
| +++ b/src/objects.cc
 | 
| @@ -433,12 +433,19 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
 | 
|  
 | 
|  
 | 
|  static bool FindAllCanReadHolder(LookupIterator* it) {
 | 
| -  for (; it->IsFound(); it->Next()) {
 | 
| +  // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
 | 
| +  // which have already been checked.
 | 
| +  DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
 | 
| +         it->state() == LookupIterator::INTERCEPTOR);
 | 
| +  for (it->Next(); it->IsFound(); it->Next()) {
 | 
|      if (it->state() == LookupIterator::ACCESSOR) {
 | 
| -      Handle<Object> accessors = it->GetAccessors();
 | 
| +      auto accessors = it->GetAccessors();
 | 
|        if (accessors->IsAccessorInfo()) {
 | 
|          if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
 | 
|        }
 | 
| +    } else if (it->state() == LookupIterator::INTERCEPTOR) {
 | 
| +      auto holder = it->GetHolder<JSObject>();
 | 
| +      if (holder->GetNamedInterceptor()->all_can_read()) return true;
 | 
|      }
 | 
|    }
 | 
|    return false;
 | 
| @@ -448,10 +455,18 @@ static bool FindAllCanReadHolder(LookupIterator* it) {
 | 
|  MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
 | 
|      LookupIterator* it) {
 | 
|    Handle<JSObject> checked = it->GetHolder<JSObject>();
 | 
| -  if (FindAllCanReadHolder(it)) {
 | 
| -    return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
 | 
| -                                   it->GetHolder<JSObject>(),
 | 
| -                                   it->GetAccessors());
 | 
| +  while (FindAllCanReadHolder(it)) {
 | 
| +    if (it->state() == LookupIterator::ACCESSOR) {
 | 
| +      return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
 | 
| +                                     it->GetHolder<JSObject>(),
 | 
| +                                     it->GetAccessors());
 | 
| +    }
 | 
| +    DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
 | 
| +    auto receiver = Handle<JSObject>::cast(it->GetReceiver());
 | 
| +    auto result = GetPropertyWithInterceptor(it->GetHolder<JSObject>(),
 | 
| +                                             receiver, it->name());
 | 
| +    if (it->isolate()->has_scheduled_exception()) break;
 | 
| +    if (!result.is_null()) return result;
 | 
|    }
 | 
|    it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
 | 
|    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
 | 
| @@ -462,8 +477,16 @@ MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
 | 
|  Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
 | 
|      LookupIterator* it) {
 | 
|    Handle<JSObject> checked = it->GetHolder<JSObject>();
 | 
| -  if (FindAllCanReadHolder(it))
 | 
| -    return maybe(it->property_details().attributes());
 | 
| +  while (FindAllCanReadHolder(it)) {
 | 
| +    if (it->state() == LookupIterator::ACCESSOR) {
 | 
| +      return maybe(it->property_details().attributes());
 | 
| +    }
 | 
| +    DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
 | 
| +    auto result = GetPropertyAttributesWithInterceptor(
 | 
| +        it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
 | 
| +    if (it->isolate()->has_scheduled_exception()) break;
 | 
| +    if (result.has_value && result.value != ABSENT) return result;
 | 
| +  }
 | 
|    it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
 | 
|    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
 | 
|                                        Maybe<PropertyAttributes>());
 | 
| @@ -550,6 +573,65 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
 | 
|  }
 | 
|  
 | 
|  
 | 
| +static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
 | 
| +    Isolate* isolate, Handle<JSObject> js_object,
 | 
| +    PrototypeIterator::WhereToStart where_to_start) {
 | 
| +  for (PrototypeIterator iter(isolate, js_object, where_to_start);
 | 
| +       !iter.IsAtEnd(); iter.Advance()) {
 | 
| +    auto curr = PrototypeIterator::GetCurrent(iter);
 | 
| +    if (!curr->IsJSObject()) break;
 | 
| +    auto obj = Handle<JSObject>::cast(curr);
 | 
| +    if (!obj->HasIndexedInterceptor()) continue;
 | 
| +    if (obj->GetIndexedInterceptor()->all_can_read()) return obj;
 | 
| +  }
 | 
| +  return MaybeHandle<JSObject>();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
 | 
| +    Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
 | 
| +    uint32_t index) {
 | 
| +  Handle<JSObject> holder = object;
 | 
| +  PrototypeIterator::WhereToStart where_to_start =
 | 
| +      PrototypeIterator::START_AT_RECEIVER;
 | 
| +  while (true) {
 | 
| +    auto all_can_read_holder =
 | 
| +        FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
 | 
| +    if (!all_can_read_holder.ToHandle(&holder)) break;
 | 
| +    auto result =
 | 
| +        JSObject::GetElementWithInterceptor(holder, receiver, index, false);
 | 
| +    if (isolate->has_scheduled_exception()) break;
 | 
| +    if (!result.is_null()) return result;
 | 
| +    where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
 | 
| +  }
 | 
| +  isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
 | 
| +  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
 | 
| +  return isolate->factory()->undefined_value();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
 | 
| +    Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
 | 
| +    uint32_t index) {
 | 
| +  Handle<JSObject> holder = object;
 | 
| +  PrototypeIterator::WhereToStart where_to_start =
 | 
| +      PrototypeIterator::START_AT_RECEIVER;
 | 
| +  while (true) {
 | 
| +    auto all_can_read_holder =
 | 
| +        FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
 | 
| +    if (!all_can_read_holder.ToHandle(&holder)) break;
 | 
| +    auto result =
 | 
| +        JSObject::GetElementAttributeFromInterceptor(object, receiver, index);
 | 
| +    if (isolate->has_scheduled_exception()) break;
 | 
| +    if (result.has_value && result.value != ABSENT) return result;
 | 
| +    where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
 | 
| +  }
 | 
| +  isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
 | 
| +  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
 | 
| +  return maybe(ABSENT);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
 | 
|                                                     Handle<Object> object,
 | 
|                                                     Handle<Object> receiver,
 | 
| @@ -582,14 +664,14 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
 | 
|      // Check access rights if needed.
 | 
|      if (js_object->IsAccessCheckNeeded()) {
 | 
|        if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
 | 
| -        isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
 | 
| -        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
 | 
| -        return isolate->factory()->undefined_value();
 | 
| +        return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
 | 
| +                                                         receiver, index);
 | 
|        }
 | 
|      }
 | 
|  
 | 
|      if (js_object->HasIndexedInterceptor()) {
 | 
| -      return JSObject::GetElementWithInterceptor(js_object, receiver, index);
 | 
| +      return JSObject::GetElementWithInterceptor(js_object, receiver, index,
 | 
| +                                                 true);
 | 
|      }
 | 
|  
 | 
|      if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
 | 
| @@ -4012,9 +4094,8 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
 | 
|    // Check access rights if needed.
 | 
|    if (object->IsAccessCheckNeeded()) {
 | 
|      if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
 | 
| -      isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
 | 
| -      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
 | 
| -      return maybe(ABSENT);
 | 
| +      return GetElementAttributesWithFailedAccessCheck(isolate, object,
 | 
| +                                                       receiver, index);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -13264,10 +13345,10 @@ MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -MaybeHandle<Object> JSObject::GetElementWithInterceptor(
 | 
| -    Handle<JSObject> object,
 | 
| -    Handle<Object> receiver,
 | 
| -    uint32_t index) {
 | 
| +MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
 | 
| +                                                        Handle<Object> receiver,
 | 
| +                                                        uint32_t index,
 | 
| +                                                        bool check_prototype) {
 | 
|    Isolate* isolate = object->GetIsolate();
 | 
|  
 | 
|    // Make sure that the top context does not change when doing
 | 
| @@ -13292,6 +13373,8 @@ MaybeHandle<Object> JSObject::GetElementWithInterceptor(
 | 
|      }
 | 
|    }
 | 
|  
 | 
| +  if (!check_prototype) return MaybeHandle<Object>();
 | 
| +
 | 
|    ElementsAccessor* handler = object->GetElementsAccessor();
 | 
|    Handle<Object> result;
 | 
|    ASSIGN_RETURN_ON_EXCEPTION(
 | 
| 
 |