| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef GIN_ARGUMENTS_H_ |
| #define GIN_ARGUMENTS_H_ |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/raw_ptr_exclusion.h" |
| #include "gin/converter.h" |
| #include "gin/gin_export.h" |
| |
| namespace gin { |
| |
| // Arguments is a wrapper around v8::FunctionCallbackInfo that integrates |
| // with Converter to make it easier to marshall arguments and return values |
| // between V8 and C++. |
| // |
| // If constructed instead with a v8::PropertyCallbackInfo, behaves as though a |
| // function with no arguments had been called. |
| class GIN_EXPORT Arguments { |
| public: |
| Arguments(); |
| explicit Arguments(const v8::FunctionCallbackInfo<v8::Value>& info); |
| explicit Arguments(const v8::PropertyCallbackInfo<v8::Value>& info); |
| ~Arguments(); |
| |
| template <typename T> |
| bool GetHolder(T* out) const { |
| v8::Local<v8::Object> holder = is_for_property_ |
| ? info_for_property_->Holder() |
| : info_for_function_->This(); |
| return ConvertFromV8(isolate_, holder, out); |
| } |
| |
| template<typename T> |
| bool GetData(T* out) { |
| v8::Local<v8::Value> data = is_for_property_ ? info_for_property_->Data() |
| : info_for_function_->Data(); |
| return ConvertFromV8(isolate_, data, out); |
| } |
| |
| template<typename T> |
| bool GetNext(T* out) { |
| if (is_for_property_ || next_ >= info_for_function_->Length()) { |
| insufficient_arguments_ = true; |
| return false; |
| } |
| v8::Local<v8::Value> val = (*info_for_function_)[next_++]; |
| return ConvertFromV8(isolate_, val, out); |
| } |
| |
| template<typename T> |
| bool GetRemaining(std::vector<T>* out) { |
| if (is_for_property_ || next_ >= info_for_function_->Length()) { |
| insufficient_arguments_ = true; |
| return false; |
| } |
| int remaining = info_for_function_->Length() - next_; |
| out->resize(remaining); |
| for (int i = 0; i < remaining; ++i) { |
| v8::Local<v8::Value> val = (*info_for_function_)[next_++]; |
| if (!ConvertFromV8(isolate_, val, &out->at(i))) |
| return false; |
| } |
| return true; |
| } |
| |
| bool Skip() { |
| if (is_for_property_) |
| return false; |
| if (next_ >= info_for_function_->Length()) |
| return false; |
| next_++; |
| return true; |
| } |
| |
| int Length() const { |
| return is_for_property_ ? 0 : info_for_function_->Length(); |
| } |
| |
| template<typename T> |
| void Return(T val) { |
| v8::Local<v8::Value> v8_value; |
| if (!TryConvertToV8(isolate_, val, &v8_value)) |
| return; |
| (is_for_property_ ? info_for_property_->GetReturnValue() |
| : info_for_function_->GetReturnValue()) |
| .Set(v8_value); |
| } |
| |
| // Returns the creation context of the Holder. |
| v8::Local<v8::Context> GetHolderCreationContext() const; |
| |
| // Always check the return value whether the handle is empty before |
| // dereferencing the handle. |
| v8::Local<v8::Value> PeekNext() const; |
| |
| // Returns all arguments. Since this doesn't require any conversion, it |
| // cannot fail. This does not rely on or modify the current position in the |
| // array used by Get/PeekNext(). |
| v8::LocalVector<v8::Value> GetAll() const; |
| |
| // Returns the original v8::FunctionCallbackInfo used to construct this |
| // Arguments if it exists, or nullptr otherwise. |
| const v8::FunctionCallbackInfo<v8::Value>* GetFunctionCallbackInfo() const { |
| return info_for_function_; |
| } |
| |
| void ThrowError() const; |
| void ThrowTypeError(const std::string& message) const; |
| |
| v8::Isolate* isolate() const { return isolate_; } |
| |
| // Allows the function handler to distinguish between normal invocation |
| // and object construction. |
| bool IsConstructCall() const; |
| |
| private: |
| raw_ptr<v8::Isolate> isolate_; |
| union { |
| // This field is not a raw_ptr<> because it was filtered by the rewriter |
| // for: #union |
| RAW_PTR_EXCLUSION const v8::FunctionCallbackInfo<v8::Value>* |
| info_for_function_; |
| // This field is not a raw_ptr<> because it was filtered by the rewriter |
| // for: #union |
| RAW_PTR_EXCLUSION const v8::PropertyCallbackInfo<v8::Value>* |
| info_for_property_; |
| }; |
| int next_ = 0; |
| bool insufficient_arguments_ = false; |
| bool is_for_property_ = false; |
| }; |
| |
| } // namespace gin |
| |
| #endif // GIN_ARGUMENTS_H_ |