// 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_BUILTINS_ACCESSORS_H_
#define V8_BUILTINS_ACCESSORS_H_

#include "include/v8.h"
#include "src/base/bit-field.h"
#include "src/common/globals.h"
#include "src/objects/property-details.h"
#include "src/utils/allocation.h"

namespace v8 {
namespace internal {

// Forward declarations.
class AccessorInfo;
template <typename T>
class Handle;
class FieldIndex;
class JavaScriptFrame;

// The list of accessor descriptors. This is a second-order macro
// taking a macro to be applied to all accessor descriptor names.
// V(accessor_name, AccessorName, GetterSideEffectType, SetterSideEffectType)
#define ACCESSOR_INFO_LIST_GENERATOR(V, _)                                    \
  V(_, arguments_iterator, ArgumentsIterator, kHasNoSideEffect,               \
    kHasSideEffectToReceiver)                                                 \
  V(_, array_length, ArrayLength, kHasNoSideEffect, kHasSideEffectToReceiver) \
  V(_, bound_function_length, BoundFunctionLength, kHasNoSideEffect,          \
    kHasSideEffectToReceiver)                                                 \
  V(_, bound_function_name, BoundFunctionName, kHasNoSideEffect,              \
    kHasSideEffectToReceiver)                                                 \
  V(_, error_stack, ErrorStack, kHasSideEffectToReceiver,                     \
    kHasSideEffectToReceiver)                                                 \
  V(_, function_arguments, FunctionArguments, kHasNoSideEffect,               \
    kHasSideEffectToReceiver)                                                 \
  V(_, function_caller, FunctionCaller, kHasNoSideEffect,                     \
    kHasSideEffectToReceiver)                                                 \
  V(_, function_name, FunctionName, kHasNoSideEffect,                         \
    kHasSideEffectToReceiver)                                                 \
  V(_, function_length, FunctionLength, kHasNoSideEffect,                     \
    kHasSideEffectToReceiver)                                                 \
  V(_, function_prototype, FunctionPrototype, kHasNoSideEffect,               \
    kHasSideEffectToReceiver)                                                 \
  V(_, regexp_result_indices, RegExpResultIndices, kHasSideEffectToReceiver,  \
    kHasSideEffectToReceiver)                                                 \
  V(_, string_length, StringLength, kHasNoSideEffect, kHasSideEffectToReceiver)

#define ACCESSOR_SETTER_LIST(V) \
  V(ArrayLengthSetter)          \
  V(ErrorStackSetter)           \
  V(FunctionPrototypeSetter)    \
  V(ModuleNamespaceEntrySetter) \
  V(ReconfigureToDataProperty)

// Accessors contains all predefined proxy accessors.

class Accessors : public AllStatic {
 public:
#define ACCESSOR_GETTER_DECLARATION(_, accessor_name, AccessorName, ...) \
  static void AccessorName##Getter(                                      \
      v8::Local<v8::Name> name,                                          \
      const v8::PropertyCallbackInfo<v8::Value>& info);
  ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_GETTER_DECLARATION, /* not used */)
#undef ACCESSOR_GETTER_DECLARATION

#define ACCESSOR_SETTER_DECLARATION(accessor_name)          \
  static void accessor_name(                                \
      v8::Local<v8::Name> name, v8::Local<v8::Value> value, \
      const v8::PropertyCallbackInfo<v8::Boolean>& info);
  ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION)
#undef ACCESSOR_SETTER_DECLARATION

  static constexpr int kAccessorInfoCount =
#define COUNT_ACCESSOR(...) +1
      ACCESSOR_INFO_LIST_GENERATOR(COUNT_ACCESSOR, /* not used */);
#undef COUNT_ACCESSOR

  static constexpr int kAccessorSetterCount =
#define COUNT_ACCESSOR(...) +1
      ACCESSOR_SETTER_LIST(COUNT_ACCESSOR);
#undef COUNT_ACCESSOR

  static void ModuleNamespaceEntryGetter(
      v8::Local<v8::Name> name,
      const v8::PropertyCallbackInfo<v8::Value>& info);
  static Handle<AccessorInfo> MakeModuleNamespaceEntryInfo(Isolate* isolate,
                                                           Handle<String> name);

  // Accessor function called directly from the runtime system. Returns the
  // newly materialized arguments object for the given {frame}. Note that for
  // optimized frames it is possible to specify an {inlined_jsframe_index}.
  static Handle<JSObject> FunctionGetArguments(JavaScriptFrame* frame,
                                               int inlined_jsframe_index);

  // Returns true for properties that are accessors to object fields.
  // If true, the matching FieldIndex is returned through |field_index|.
  static bool IsJSObjectFieldAccessor(Isolate* isolate, Handle<Map> map,
                                      Handle<Name> name,
                                      FieldIndex* field_index);

  static MaybeHandle<Object> ReplaceAccessorWithDataProperty(
      Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder,
      Handle<Name> name, Handle<Object> value);

  // Create an AccessorInfo. The setter is optional (can be nullptr).
  //
  // Note that the type of setter is AccessorNameBooleanSetterCallback instead
  // of v8::AccessorNameSetterCallback.  The difference is that the former can
  // set a (boolean) return value. The setter should roughly follow the same
  // conventions as many of the internal methods in objects.cc:
  // - The return value is unset iff there was an exception.
  // - If the ShouldThrow argument is true, the return value must not be false.
  using AccessorNameBooleanSetterCallback =
      void (*)(Local<v8::Name> property, Local<v8::Value> value,
               const PropertyCallbackInfo<v8::Boolean>& info);

  V8_EXPORT_PRIVATE static Handle<AccessorInfo> MakeAccessor(
      Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
      AccessorNameBooleanSetterCallback setter);

 private:
#define ACCESSOR_INFO_DECLARATION(_, accessor_name, AccessorName, ...) \
  static Handle<AccessorInfo> Make##AccessorName##Info(Isolate* isolate);
  ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_INFO_DECLARATION, /* not used */)
#undef ACCESSOR_INFO_DECLARATION

  friend class Heap;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_BUILTINS_ACCESSORS_H_
