// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_PROTOTYPE_INL_H_
#define V8_OBJECTS_PROTOTYPE_INL_H_

#include "src/objects/prototype.h"

#include "src/handles/handles-inl.h"
#include "src/objects/js-proxy.h"
#include "src/objects/map-inl.h"

namespace v8 {
namespace internal {

PrototypeIterator::PrototypeIterator(Isolate* isolate,
                                     Handle<JSReceiver> receiver,
                                     WhereToStart where_to_start,
                                     WhereToEnd where_to_end)
    : isolate_(isolate),
      handle_(receiver),
      where_to_end_(where_to_end),
      is_at_end_(false),
      seen_proxies_(0) {
  CHECK(!handle_.is_null());
  if (where_to_start == kStartAtPrototype) Advance();
}

PrototypeIterator::PrototypeIterator(Isolate* isolate, JSReceiver receiver,
                                     WhereToStart where_to_start,
                                     WhereToEnd where_to_end)
    : isolate_(isolate),
      object_(receiver),
      where_to_end_(where_to_end),
      is_at_end_(false),
      seen_proxies_(0) {
  if (where_to_start == kStartAtPrototype) Advance();
}

PrototypeIterator::PrototypeIterator(Isolate* isolate, Map receiver_map,
                                     WhereToEnd where_to_end)
    : isolate_(isolate),
      object_(receiver_map.GetPrototypeChainRootMap(isolate_).prototype()),
      where_to_end_(where_to_end),
      is_at_end_(object_.IsNull(isolate_)),
      seen_proxies_(0) {
  if (!is_at_end_ && where_to_end_ == END_AT_NON_HIDDEN) {
    DCHECK(object_.IsJSReceiver());
    Map map = JSReceiver::cast(object_).map();
    is_at_end_ = !map.IsJSGlobalProxyMap();
  }
}

PrototypeIterator::PrototypeIterator(Isolate* isolate, Handle<Map> receiver_map,
                                     WhereToEnd where_to_end)
    : isolate_(isolate),
      handle_(receiver_map->GetPrototypeChainRootMap(isolate_).prototype(),
              isolate_),
      where_to_end_(where_to_end),
      is_at_end_(handle_->IsNull(isolate_)),
      seen_proxies_(0) {
  if (!is_at_end_ && where_to_end_ == END_AT_NON_HIDDEN) {
    DCHECK(handle_->IsJSReceiver());
    Map map = JSReceiver::cast(*handle_).map();
    is_at_end_ = !map.IsJSGlobalProxyMap();
  }
}

bool PrototypeIterator::HasAccess() const {
  // We can only perform access check in the handlified version of the
  // PrototypeIterator.
  DCHECK(!handle_.is_null());
  if (handle_->IsAccessCheckNeeded()) {
    return isolate_->MayAccess(handle(isolate_->context(), isolate_),
                               Handle<JSObject>::cast(handle_));
  }
  return true;
}

void PrototypeIterator::Advance() {
  if (handle_.is_null() && object_.IsJSProxy()) {
    is_at_end_ = true;
    object_ = ReadOnlyRoots(isolate_).null_value();
    return;
  } else if (!handle_.is_null() && handle_->IsJSProxy()) {
    is_at_end_ = true;
    handle_ = isolate_->factory()->null_value();
    return;
  }
  AdvanceIgnoringProxies();
}

void PrototypeIterator::AdvanceIgnoringProxies() {
  Object object = handle_.is_null() ? object_ : *handle_;
  Map map = HeapObject::cast(object).map();

  HeapObject prototype = map.prototype();
  is_at_end_ =
      prototype.IsNull(isolate_) ||
      (where_to_end_ == END_AT_NON_HIDDEN && !map.IsJSGlobalProxyMap());

  if (handle_.is_null()) {
    object_ = prototype;
  } else {
    handle_ = handle(prototype, isolate_);
  }
}

V8_WARN_UNUSED_RESULT bool PrototypeIterator::AdvanceFollowingProxies() {
  DCHECK(!(handle_.is_null() && object_.IsJSProxy()));
  if (!HasAccess()) {
    // Abort the lookup if we do not have access to the current object.
    handle_ = isolate_->factory()->null_value();
    is_at_end_ = true;
    return true;
  }
  return AdvanceFollowingProxiesIgnoringAccessChecks();
}

V8_WARN_UNUSED_RESULT bool
PrototypeIterator::AdvanceFollowingProxiesIgnoringAccessChecks() {
  if (handle_.is_null() || !handle_->IsJSProxy()) {
    AdvanceIgnoringProxies();
    return true;
  }

  // Due to possible __proto__ recursion limit the number of Proxies
  // we visit to an arbitrarily chosen large number.
  seen_proxies_++;
  if (seen_proxies_ > JSProxy::kMaxIterationLimit) {
    isolate_->StackOverflow();
    return false;
  }
  MaybeHandle<HeapObject> proto =
      JSProxy::GetPrototype(Handle<JSProxy>::cast(handle_));
  if (!proto.ToHandle(&handle_)) return false;
  is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN || handle_->IsNull(isolate_);
  return true;
}

}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_PROTOTYPE_INL_H_
