#ifndef V8_API_API_ARGUMENTS_H_
#define V8_API_API_ARGUMENTS_H_
#include "include/v8-template.h"
#include "src/builtins/builtins-utils.h"
#include "src/execution/isolate.h"
#include "src/objects/slots.h"
#include "src/objects/visitors.h"
namespace v8 {
namespace internal {
class CustomArgumentsBase : public Relocatable {
protected:
explicit inline CustomArgumentsBase(Isolate* isolate);
};
template <typename T>
class CustomArguments : public CustomArgumentsBase {
public:
static constexpr int kReturnValueIndex = T::kReturnValueIndex;
static_assert(T::kSize == sizeof(T));
~CustomArguments() override;
inline void IterateInstance(RootVisitor* v) override {
v->VisitRootPointers(Root::kRelocatable, nullptr, slot_at(0),
slot_at(T::kArgsLength));
}
protected:
explicit inline CustomArguments(Isolate* isolate)
: CustomArgumentsBase(isolate) {}
template <typename V>
Handle<V> GetReturnValue(Isolate* isolate) const;
inline Isolate* isolate() const {
return reinterpret_cast<Isolate*>((*slot_at(T::kIsolateIndex)).ptr());
}
inline FullObjectSlot slot_at(int index) const {
DCHECK_LE(static_cast<unsigned>(index),
static_cast<unsigned>(T::kArgsLength));
return FullObjectSlot(values_ + index);
}
Address values_[T::kArgsLength];
};
class PropertyCallbackArguments final
: public CustomArguments<PropertyCallbackInfo<Value> > {
public:
using T = PropertyCallbackInfo<Value>;
using Super = CustomArguments<T>;
static constexpr int kArgsLength = T::kArgsLength;
static constexpr int kThisIndex = T::kThisIndex;
static constexpr int kCallbackInfoIndex = T::kCallbackInfoIndex;
static constexpr int kUnusedIndex = T::kUnusedIndex;
static constexpr int kHolderIndex = T::kHolderIndex;
static constexpr int kIsolateIndex = T::kIsolateIndex;
static constexpr int kShouldThrowOnErrorIndex = T::kShouldThrowOnErrorIndex;
static constexpr int kPropertyKeyIndex = T::kPropertyKeyIndex;
inline PropertyCallbackArguments(Isolate* isolate, Tagged<Object> self,
Tagged<JSObject> holder,
Maybe<ShouldThrow> should_throw);
inline ~PropertyCallbackArguments();
PropertyCallbackArguments(const PropertyCallbackArguments&) = delete;
PropertyCallbackArguments& operator=(const PropertyCallbackArguments&) =
delete;
inline DirectHandle<JSAny> CallAccessorGetter(DirectHandle<AccessorInfo> info,
DirectHandle<Name> name);
V8_WARN_UNUSED_RESULT
inline bool CallAccessorSetter(DirectHandle<AccessorInfo> info,
DirectHandle<Name> name,
DirectHandle<Object> value);
inline DirectHandle<Object> CallNamedQuery(
DirectHandle<InterceptorInfo> interceptor, DirectHandle<Name> name);
inline DirectHandle<JSAny> CallNamedGetter(
DirectHandle<InterceptorInfo> interceptor, DirectHandle<Name> name);
inline v8::Intercepted CallNamedSetter(
DirectHandle<InterceptorInfo> interceptor, DirectHandle<Name> name,
DirectHandle<Object> value);
inline v8::Intercepted CallNamedDefiner(
DirectHandle<InterceptorInfo> interceptor, DirectHandle<Name> name,
const v8::PropertyDescriptor& desc);
inline v8::Intercepted CallNamedDeleter(
DirectHandle<InterceptorInfo> interceptor, DirectHandle<Name> name);
inline Handle<JSAny> CallNamedDescriptor(
DirectHandle<InterceptorInfo> interceptor, DirectHandle<Name> name);
inline DirectHandle<JSObjectOrUndefined> CallNamedEnumerator(
DirectHandle<InterceptorInfo> interceptor);
inline DirectHandle<Object> CallIndexedQuery(
DirectHandle<InterceptorInfo> interceptor, uint32_t index);
inline DirectHandle<JSAny> CallIndexedGetter(
DirectHandle<InterceptorInfo> interceptor, uint32_t index);
inline v8::Intercepted CallIndexedSetter(
DirectHandle<InterceptorInfo> interceptor, uint32_t index,
DirectHandle<Object> value);
inline v8::Intercepted CallIndexedDefiner(
DirectHandle<InterceptorInfo> interceptor, uint32_t index,
const v8::PropertyDescriptor& desc);
inline v8::Intercepted CallIndexedDeleter(
DirectHandle<InterceptorInfo> interceptor, uint32_t index);
inline Handle<JSAny> CallIndexedDescriptor(
DirectHandle<InterceptorInfo> interceptor, uint32_t index);
inline DirectHandle<JSObjectOrUndefined> CallIndexedEnumerator(
DirectHandle<InterceptorInfo> interceptor);
inline void AcceptSideEffects() {
#ifdef DEBUG
javascript_execution_counter_ = 0;
#endif
}
inline Maybe<InterceptorResult> GetBooleanReturnValue(
v8::Intercepted intercepted, const char* callback_kind_for_error_message,
bool ignore_return_value = false);
template <typename T>
const v8::PropertyCallbackInfo<T>& GetPropertyCallbackInfo() {
return *(reinterpret_cast<PropertyCallbackInfo<T>*>(&values_[0]));
}
bool ShouldThrowOnError() {
return GetPropertyCallbackInfo<Value>().ShouldThrowOnError();
}
template <typename T>
static Tagged<Object> GetPropertyKey(const PropertyCallbackInfo<T>& info) {
return Tagged<Object>(info.args_[kPropertyKeyIndex]);
}
template <typename T>
static Handle<Object> GetPropertyKeyHandle(
const PropertyCallbackInfo<T>& info) {
return Handle<Object>(&info.args_[kPropertyKeyIndex]);
}
template <typename T>
static uint32_t GetPropertyIndex(const PropertyCallbackInfo<T>& info) {
Address ptr = reinterpret_cast<Address>(&info.args_) -
offsetof(PropertyCallbackArguments, values_);
auto pca = reinterpret_cast<const PropertyCallbackArguments*>(ptr);
return pca->index_;
}
inline DirectHandle<JSObject> holder() const;
private:
inline DirectHandle<JSObjectOrUndefined> CallPropertyEnumerator(
DirectHandle<InterceptorInfo> interceptor);
inline DirectHandle<Object> receiver() const;
uint32_t index_ = kMaxUInt32;
#ifdef DEBUG
uint32_t javascript_execution_counter_;
#endif
};
class FunctionCallbackArguments
: public CustomArguments<FunctionCallbackInfo<Value> > {
public:
using T = FunctionCallbackInfo<Value>;
using Super = CustomArguments<T>;
static constexpr int kArgsLength = T::kArgsLength;
static constexpr int kArgsLengthWithReceiver = T::kArgsLengthWithReceiver;
static constexpr int kUnusedIndex = T::kUnusedIndex;
static constexpr int kIsolateIndex = T::kIsolateIndex;
static constexpr int kContextIndex = T::kContextIndex;
static constexpr int kTargetIndex = T::kTargetIndex;
static constexpr int kNewTargetIndex = T::kNewTargetIndex;
static_assert(T::kThisValuesIndex == BuiltinArguments::kReceiverArgsIndex);
static constexpr int kSize = T::kSize;
static constexpr int kImplicitArgsOffset = T::kImplicitArgsOffset;
static constexpr int kValuesOffset = T::kValuesOffset;
static constexpr int kLengthOffset = T::kLengthOffset;
static_assert(T::kSize == sizeof(T));
static_assert(T::kImplicitArgsOffset == offsetof(T, implicit_args_));
static_assert(T::kValuesOffset == offsetof(T, values_));
static_assert(T::kLengthOffset == offsetof(T, length_));
inline FunctionCallbackArguments(Isolate* isolate,
Tagged<FunctionTemplateInfo> target,
Tagged<HeapObject> new_target, Address* argv,
int argc);
* The following Call function wraps the calling of all callbacks to handle
* calling either the old or the new style callbacks depending on which one
* has been registered.
* For old callbacks which return an empty handle, the ReturnValue is checked
* and used if it's been set to anything inside the callback.
* New style callbacks always use the return value.
*/
inline DirectHandle<Object> CallOrConstruct(
Tagged<FunctionTemplateInfo> function, bool is_construct);
template <typename T>
static Tagged<Object> GetTarget(const FunctionCallbackInfo<T>& info) {
return Tagged<Object>(info.implicit_args_[kTargetIndex]);
}
private:
Address* argv_;
int const argc_;
};
static_assert(BuiltinArguments::kNumExtraArgs ==
BuiltinExitFrameConstants::kNumExtraArgs);
static_assert(BuiltinArguments::kNumExtraArgsWithReceiver ==
BuiltinExitFrameConstants::kNumExtraArgsWithReceiver);
}
}
#endif