// Copyright 2012 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_KEYS_H_
#define V8_KEYS_H_

#include "src/isolate.h"
#include "src/objects.h"

namespace v8 {
namespace internal {

enum AddKeyConversion { DO_NOT_CONVERT, CONVERT_TO_ARRAY_INDEX };

// This is a helper class for JSReceiver::GetKeys which collects and sorts keys.
// GetKeys needs to sort keys per prototype level, first showing the integer
// indices from elements then the strings from the properties. However, this
// does not apply to proxies which are in full control of how the keys are
// sorted.
//
// For performance reasons the KeyAccumulator internally separates integer keys
// in |elements_| into sorted lists per prototype level. String keys are
// collected in |string_properties_|, a single OrderedHashSet (similar for
// Symbols in |symbol_properties_|. To separate the keys per level later when
// assembling the final list, |levelLengths_| keeps track of the number of
// String and Symbol keys per level.
//
// Only unique keys are kept by the KeyAccumulator, strings are stored in a
// HashSet for inexpensive lookups. Integer keys are kept in sorted lists which
// are more compact and allow for reasonably fast includes check.
class KeyAccumulator final BASE_EMBEDDED {
 public:
  KeyAccumulator(Isolate* isolate, KeyCollectionMode mode,
                 PropertyFilter filter)
      : isolate_(isolate), mode_(mode), filter_(filter) {}
  ~KeyAccumulator();

  static MaybeHandle<FixedArray> GetKeys(
      Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
      GetKeysConversion keys_conversion = GetKeysConversion::kKeepNumbers,
      bool is_for_in = false);

  Handle<FixedArray> GetKeys(
      GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
  Maybe<bool> CollectKeys(Handle<JSReceiver> receiver,
                          Handle<JSReceiver> object);
  Maybe<bool> CollectOwnElementIndices(Handle<JSReceiver> receiver,
                                       Handle<JSObject> object);
  Maybe<bool> CollectOwnPropertyNames(Handle<JSReceiver> receiver,
                                      Handle<JSObject> object);
  Maybe<bool> CollectAccessCheckInterceptorKeys(
      Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver,
      Handle<JSObject> object);

  // Might return directly the object's enum_cache, copy the result before using
  // as an elements backing store for a JSObject.
  static Handle<FixedArray> GetOwnEnumPropertyKeys(Isolate* isolate,
                                                   Handle<JSObject> object);
  void AddKey(Object* key, AddKeyConversion convert = DO_NOT_CONVERT);
  void AddKey(Handle<Object> key, AddKeyConversion convert = DO_NOT_CONVERT);
  void AddKeys(Handle<FixedArray> array, AddKeyConversion convert);
  void AddKeys(Handle<JSObject> array_like, AddKeyConversion convert);

  // Jump to the next level, pushing the current |levelLength_| to
  // |levelLengths_| and adding a new list to |elements_|.
  Isolate* isolate() { return isolate_; }
  // Filter keys based on their property descriptors.
  PropertyFilter filter() { return filter_; }
  // The collection mode defines whether we collect the keys from the prototype
  // chain or only look at the receiver.
  KeyCollectionMode mode() { return mode_; }
  // In case of for-in loops we have to treat JSProxy keys differently and
  // deduplicate them. Additionally we convert JSProxy keys back to array
  // indices.
  void set_is_for_in(bool value) { is_for_in_ = value; }
  void set_skip_indices(bool value) { skip_indices_ = value; }
  // The last_non_empty_prototype is used to limit the prototypes for which
  // we have to keep track of non-enumerable keys that can shadow keys
  // repeated on the prototype chain.
  void set_last_non_empty_prototype(Handle<JSReceiver> object) {
    last_non_empty_prototype_ = object;
  }
  // Shadowing keys are used to filter keys. This happens when non-enumerable
  // keys appear again on the prototype chain.
  void AddShadowingKey(Object* key);
  void AddShadowingKey(Handle<Object> key);

 private:
  Maybe<bool> CollectOwnKeys(Handle<JSReceiver> receiver,
                             Handle<JSObject> object);
  Maybe<bool> CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
                                    Handle<JSProxy> proxy);
  Maybe<bool> CollectOwnJSProxyTargetKeys(Handle<JSProxy> proxy,
                                          Handle<JSReceiver> target);
  Maybe<bool> AddKeysFromJSProxy(Handle<JSProxy> proxy,
                                 Handle<FixedArray> keys);
  bool IsShadowed(Handle<Object> key);
  bool HasShadowingKeys();
  Handle<OrderedHashSet> keys() { return Handle<OrderedHashSet>::cast(keys_); }

  Isolate* isolate_;
  // keys_ is either an Handle<OrderedHashSet> or in the case of own JSProxy
  // keys a Handle<FixedArray>. The OrderedHashSet is in-place converted to the
  // result list, a FixedArray containing all collected keys.
  Handle<FixedArray> keys_;
  Handle<JSReceiver> last_non_empty_prototype_;
  Handle<ObjectHashSet> shadowing_keys_;
  KeyCollectionMode mode_;
  PropertyFilter filter_;
  bool is_for_in_ = false;
  bool skip_indices_ = false;
  // For all the keys on the first receiver adding a shadowing key we can skip
  // the shadow check.
  bool skip_shadow_check_ = true;

  DISALLOW_COPY_AND_ASSIGN(KeyAccumulator);
};

// The FastKeyAccumulator handles the cases where there are no elements on the
// prototype chain and forwords the complex/slow cases to the normal
// KeyAccumulator. This significantly speeds up the cases where the OWN_ONLY
// case where we do not have to walk the prototype chain.
class FastKeyAccumulator {
 public:
  FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver,
                     KeyCollectionMode mode, PropertyFilter filter)
      : isolate_(isolate), receiver_(receiver), mode_(mode), filter_(filter) {
    Prepare();
  }

  bool is_receiver_simple_enum() { return is_receiver_simple_enum_; }
  bool has_empty_prototype() { return has_empty_prototype_; }
  void set_is_for_in(bool value) { is_for_in_ = value; }

  MaybeHandle<FixedArray> GetKeys(
      GetKeysConversion convert = GetKeysConversion::kKeepNumbers);

 private:
  void Prepare();
  MaybeHandle<FixedArray> GetKeysFast(GetKeysConversion convert);
  MaybeHandle<FixedArray> GetKeysSlow(GetKeysConversion convert);

  MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumCache();

  Isolate* isolate_;
  Handle<JSReceiver> receiver_;
  Handle<JSReceiver> last_non_empty_prototype_;
  KeyCollectionMode mode_;
  PropertyFilter filter_;
  bool is_for_in_ = false;
  bool is_receiver_simple_enum_ = false;
  bool has_empty_prototype_ = false;

  DISALLOW_COPY_AND_ASSIGN(FastKeyAccumulator);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_KEYS_H_
