// 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_API_CALLBACKS_H_
#define V8_OBJECTS_API_CALLBACKS_H_

#include "src/objects/struct.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

// An accessor must have a getter, but can have no setter.
//
// When setting a property, V8 searches accessors in prototypes.
// If an accessor was found and it does not have a setter,
// the request is ignored.
//
// If the accessor in the prototype has the READ_ONLY property attribute, then
// a new value is added to the derived object when the property is set.
// This shadows the accessor in the prototype.
class AccessorInfo : public StructPtr {
 public:
  DECL_ACCESSORS2(name, Name)
  DECL_INT_ACCESSORS(flags)
  DECL_ACCESSORS(expected_receiver_type, Object)
  // This directly points at a foreign C function to be used from the runtime.
  DECL_ACCESSORS(getter, Object)
  inline bool has_getter();
  DECL_ACCESSORS(setter, Object)
  inline bool has_setter();
  // This either points at the same as above, or a trampoline in case we are
  // running with the simulator. Use these entries from generated code.
  DECL_ACCESSORS(js_getter, Object)
  DECL_ACCESSORS(data, Object)

  static Address redirect(Address address, AccessorComponent component);
  Address redirected_getter() const;

  // Dispatched behavior.
  DECL_PRINTER(AccessorInfo)

  DECL_BOOLEAN_ACCESSORS(all_can_read)
  DECL_BOOLEAN_ACCESSORS(all_can_write)
  DECL_BOOLEAN_ACCESSORS(is_special_data_property)
  DECL_BOOLEAN_ACCESSORS(replace_on_access)
  DECL_BOOLEAN_ACCESSORS(is_sloppy)

  inline SideEffectType getter_side_effect_type() const;
  inline void set_getter_side_effect_type(SideEffectType type);

  inline SideEffectType setter_side_effect_type() const;
  inline void set_setter_side_effect_type(SideEffectType type);

  // The property attributes used when an API object template is instantiated
  // for the first time. Changing of this value afterwards does not affect
  // the actual attributes of a property.
  inline PropertyAttributes initial_property_attributes() const;
  inline void set_initial_property_attributes(PropertyAttributes attributes);

  // Checks whether the given receiver is compatible with this accessor.
  static bool IsCompatibleReceiverMap(Handle<AccessorInfo> info,
                                      Handle<Map> map);
  inline bool IsCompatibleReceiver(Object* receiver);

  DECL_CAST2(AccessorInfo)

  // Dispatched behavior.
  DECL_VERIFIER(AccessorInfo)

  // Append all descriptors to the array that are not already there.
  // Return number added.
  static int AppendUnique(Isolate* isolate, Handle<Object> descriptors,
                          Handle<FixedArray> array, int valid_descriptors);

// Layout description.
#define ACCESSOR_INFO_FIELDS(V)               \
  V(kNameOffset, kTaggedSize)                 \
  V(kFlagsOffset, kTaggedSize)                \
  V(kExpectedReceiverTypeOffset, kTaggedSize) \
  V(kSetterOffset, kTaggedSize)               \
  V(kGetterOffset, kTaggedSize)               \
  V(kJsGetterOffset, kTaggedSize)             \
  V(kDataOffset, kTaggedSize)                 \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, ACCESSOR_INFO_FIELDS)
#undef ACCESSOR_INFO_FIELDS

 private:
  inline bool HasExpectedReceiverType();

// Bit positions in |flags|.
#define ACCESSOR_INFO_FLAGS_BIT_FIELDS(V, _)                           \
  V(AllCanReadBit, bool, 1, _)                                         \
  V(AllCanWriteBit, bool, 1, _)                                        \
  V(IsSpecialDataPropertyBit, bool, 1, _)                              \
  V(IsSloppyBit, bool, 1, _)                                           \
  V(ReplaceOnAccessBit, bool, 1, _)                                    \
  V(GetterSideEffectTypeBits, SideEffectType, 2, _)                    \
  /* We could save a bit from setter side-effect type, if necessary */ \
  V(SetterSideEffectTypeBits, SideEffectType, 2, _)                    \
  V(InitialAttributesBits, PropertyAttributes, 3, _)

  DEFINE_BIT_FIELDS(ACCESSOR_INFO_FLAGS_BIT_FIELDS)
#undef ACCESSOR_INFO_FLAGS_BIT_FIELDS

  OBJECT_CONSTRUCTORS(AccessorInfo, StructPtr);
};

class AccessCheckInfo : public StructPtr {
 public:
  DECL_ACCESSORS(callback, Object)
  DECL_ACCESSORS(named_interceptor, Object)
  DECL_ACCESSORS(indexed_interceptor, Object)
  DECL_ACCESSORS(data, Object)

  DECL_CAST2(AccessCheckInfo)

  // Dispatched behavior.
  DECL_PRINTER(AccessCheckInfo)
  DECL_VERIFIER(AccessCheckInfo)

  static AccessCheckInfo Get(Isolate* isolate, Handle<JSObject> receiver);

// Layout description.
#define ACCESS_CHECK_INFO_FIELDS(V)         \
  V(kCallbackOffset, kTaggedSize)           \
  V(kNamedInterceptorOffset, kTaggedSize)   \
  V(kIndexedInterceptorOffset, kTaggedSize) \
  V(kDataOffset, kTaggedSize)               \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
                                ACCESS_CHECK_INFO_FIELDS)
#undef ACCESS_CHECK_INFO_FIELDS

  OBJECT_CONSTRUCTORS(AccessCheckInfo, StructPtr);
};

class InterceptorInfo : public StructPtr {
 public:
  DECL_ACCESSORS(getter, Object)
  DECL_ACCESSORS(setter, Object)
  DECL_ACCESSORS(query, Object)
  DECL_ACCESSORS(descriptor, Object)
  DECL_ACCESSORS(deleter, Object)
  DECL_ACCESSORS(enumerator, Object)
  DECL_ACCESSORS(definer, Object)
  DECL_ACCESSORS(data, Object)
  DECL_BOOLEAN_ACCESSORS(can_intercept_symbols)
  DECL_BOOLEAN_ACCESSORS(all_can_read)
  DECL_BOOLEAN_ACCESSORS(non_masking)
  DECL_BOOLEAN_ACCESSORS(is_named)
  DECL_BOOLEAN_ACCESSORS(has_no_side_effect)

  inline int flags() const;
  inline void set_flags(int flags);

  DECL_CAST2(InterceptorInfo)

  // Dispatched behavior.
  DECL_PRINTER(InterceptorInfo)
  DECL_VERIFIER(InterceptorInfo)

// Layout description.
#define INTERCEPTOR_INFO_FIELDS(V)  \
  V(kGetterOffset, kTaggedSize)     \
  V(kSetterOffset, kTaggedSize)     \
  V(kQueryOffset, kTaggedSize)      \
  V(kDescriptorOffset, kTaggedSize) \
  V(kDeleterOffset, kTaggedSize)    \
  V(kEnumeratorOffset, kTaggedSize) \
  V(kDefinerOffset, kTaggedSize)    \
  V(kDataOffset, kTaggedSize)       \
  V(kFlagsOffset, kTaggedSize)      \
  V(kSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
                                INTERCEPTOR_INFO_FIELDS)
#undef INTERCEPTOR_INFO_FIELDS

  static const int kCanInterceptSymbolsBit = 0;
  static const int kAllCanReadBit = 1;
  static const int kNonMasking = 2;
  static const int kNamed = 3;
  static const int kHasNoSideEffect = 4;

  OBJECT_CONSTRUCTORS(InterceptorInfo, StructPtr);
};

class CallHandlerInfo : public Tuple3 {
 public:
  DECL_ACCESSORS(callback, Object)
  DECL_ACCESSORS(js_callback, Object)
  DECL_ACCESSORS(data, Object)

  DECL_CAST2(CallHandlerInfo)

  inline bool IsSideEffectFreeCallHandlerInfo() const;
  inline bool IsSideEffectCallHandlerInfo() const;
  inline void SetNextCallHasNoSideEffect();
  // Returns whether or not the next call can be side effect free.
  // Calling this will change the state back to having a side effect.
  inline bool NextCallHasNoSideEffect();

  // Dispatched behavior.
  DECL_PRINTER(CallHandlerInfo)
  DECL_VERIFIER(CallHandlerInfo)

  Address redirected_callback() const;

  static const int kCallbackOffset = kValue1Offset;
  static const int kJsCallbackOffset = kValue2Offset;
  static const int kDataOffset = kValue3Offset;

  OBJECT_CONSTRUCTORS(CallHandlerInfo, Tuple3);
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_API_CALLBACKS_H_
