You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
520 lines
17 KiB
520 lines
17 KiB
/********************************************************************* |
|
* NAN - Native Abstractions for Node.js |
|
* |
|
* Copyright (c) 2018 NAN contributors |
|
* |
|
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md> |
|
********************************************************************/ |
|
|
|
#ifndef NAN_CALLBACKS_PRE_12_INL_H_ |
|
#define NAN_CALLBACKS_PRE_12_INL_H_ |
|
|
|
namespace imp { |
|
template<typename T> class ReturnValueImp; |
|
} // end of namespace imp |
|
|
|
template<typename T> |
|
class ReturnValue { |
|
v8::Isolate *isolate_; |
|
v8::Persistent<T> *value_; |
|
friend class imp::ReturnValueImp<T>; |
|
|
|
public: |
|
template <class S> |
|
explicit inline ReturnValue(v8::Isolate *isolate, v8::Persistent<S> *p) : |
|
isolate_(isolate), value_(p) {} |
|
template <class S> |
|
explicit inline ReturnValue(const ReturnValue<S>& that) |
|
: isolate_(that.isolate_), value_(that.value_) { |
|
TYPE_CHECK(T, S); |
|
} |
|
|
|
// Handle setters |
|
template <typename S> inline void Set(const v8::Local<S> &handle) { |
|
TYPE_CHECK(T, S); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(handle); |
|
} |
|
|
|
template <typename S> inline void Set(const Global<S> &handle) { |
|
TYPE_CHECK(T, S); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(handle.persistent); |
|
const_cast<Global<S> &>(handle).Reset(); |
|
} |
|
|
|
// Fast primitive setters |
|
inline void Set(bool value) { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::Boolean); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::Boolean::New(value)); |
|
} |
|
|
|
inline void Set(double i) { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::Number); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::Number::New(i)); |
|
} |
|
|
|
inline void Set(int32_t i) { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::Integer); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::Int32::New(i)); |
|
} |
|
|
|
inline void Set(uint32_t i) { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::Integer); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::Uint32::NewFromUnsigned(i)); |
|
} |
|
|
|
// Fast JS primitive setters |
|
inline void SetNull() { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::Primitive); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::Null()); |
|
} |
|
|
|
inline void SetUndefined() { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::Primitive); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::Undefined()); |
|
} |
|
|
|
inline void SetEmptyString() { |
|
v8::HandleScope scope; |
|
|
|
TYPE_CHECK(T, v8::String); |
|
value_->Dispose(); |
|
*value_ = v8::Persistent<T>::New(v8::String::Empty()); |
|
} |
|
|
|
// Convenience getter for isolate |
|
inline v8::Isolate *GetIsolate() const { |
|
return isolate_; |
|
} |
|
|
|
// Pointer setter: Uncompilable to prevent inadvertent misuse. |
|
template<typename S> |
|
inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } |
|
}; |
|
|
|
template<typename T> |
|
class FunctionCallbackInfo { |
|
const v8::Arguments &args_; |
|
v8::Local<v8::Value> data_; |
|
ReturnValue<T> return_value_; |
|
v8::Persistent<T> retval_; |
|
|
|
public: |
|
explicit inline FunctionCallbackInfo( |
|
const v8::Arguments &args |
|
, v8::Local<v8::Value> data) : |
|
args_(args) |
|
, data_(data) |
|
, return_value_(args.GetIsolate(), &retval_) |
|
, retval_(v8::Persistent<T>::New(v8::Undefined())) {} |
|
|
|
inline ~FunctionCallbackInfo() { |
|
retval_.Dispose(); |
|
retval_.Clear(); |
|
} |
|
|
|
inline ReturnValue<T> GetReturnValue() const { |
|
return ReturnValue<T>(return_value_); |
|
} |
|
|
|
inline v8::Local<v8::Function> Callee() const { return args_.Callee(); } |
|
inline v8::Local<v8::Value> Data() const { return data_; } |
|
inline v8::Local<v8::Object> Holder() const { return args_.Holder(); } |
|
inline bool IsConstructCall() const { return args_.IsConstructCall(); } |
|
inline int Length() const { return args_.Length(); } |
|
inline v8::Local<v8::Value> operator[](int i) const { return args_[i]; } |
|
inline v8::Local<v8::Object> This() const { return args_.This(); } |
|
inline v8::Isolate *GetIsolate() const { return args_.GetIsolate(); } |
|
|
|
|
|
protected: |
|
static const int kHolderIndex = 0; |
|
static const int kIsolateIndex = 1; |
|
static const int kReturnValueDefaultValueIndex = 2; |
|
static const int kReturnValueIndex = 3; |
|
static const int kDataIndex = 4; |
|
static const int kCalleeIndex = 5; |
|
static const int kContextSaveIndex = 6; |
|
static const int kArgsLength = 7; |
|
|
|
private: |
|
NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) |
|
}; |
|
|
|
template<typename T> |
|
class PropertyCallbackInfoBase { |
|
const v8::AccessorInfo &info_; |
|
const v8::Local<v8::Value> data_; |
|
|
|
public: |
|
explicit inline PropertyCallbackInfoBase( |
|
const v8::AccessorInfo &info |
|
, const v8::Local<v8::Value> data) : |
|
info_(info) |
|
, data_(data) {} |
|
|
|
inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } |
|
inline v8::Local<v8::Value> Data() const { return data_; } |
|
inline v8::Local<v8::Object> This() const { return info_.This(); } |
|
inline v8::Local<v8::Object> Holder() const { return info_.Holder(); } |
|
|
|
protected: |
|
static const int kHolderIndex = 0; |
|
static const int kIsolateIndex = 1; |
|
static const int kReturnValueDefaultValueIndex = 2; |
|
static const int kReturnValueIndex = 3; |
|
static const int kDataIndex = 4; |
|
static const int kThisIndex = 5; |
|
static const int kArgsLength = 6; |
|
|
|
private: |
|
NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfoBase) |
|
}; |
|
|
|
template<typename T> |
|
class PropertyCallbackInfo : public PropertyCallbackInfoBase<T> { |
|
ReturnValue<T> return_value_; |
|
v8::Persistent<T> retval_; |
|
|
|
public: |
|
explicit inline PropertyCallbackInfo( |
|
const v8::AccessorInfo &info |
|
, const v8::Local<v8::Value> data) : |
|
PropertyCallbackInfoBase<T>(info, data) |
|
, return_value_(info.GetIsolate(), &retval_) |
|
, retval_(v8::Persistent<T>::New(v8::Undefined())) {} |
|
|
|
inline ~PropertyCallbackInfo() { |
|
retval_.Dispose(); |
|
retval_.Clear(); |
|
} |
|
|
|
inline ReturnValue<T> GetReturnValue() const { return return_value_; } |
|
}; |
|
|
|
template<> |
|
class PropertyCallbackInfo<v8::Array> : |
|
public PropertyCallbackInfoBase<v8::Array> { |
|
ReturnValue<v8::Array> return_value_; |
|
v8::Persistent<v8::Array> retval_; |
|
|
|
public: |
|
explicit inline PropertyCallbackInfo( |
|
const v8::AccessorInfo &info |
|
, const v8::Local<v8::Value> data) : |
|
PropertyCallbackInfoBase<v8::Array>(info, data) |
|
, return_value_(info.GetIsolate(), &retval_) |
|
, retval_(v8::Persistent<v8::Array>::New(v8::Local<v8::Array>())) {} |
|
|
|
inline ~PropertyCallbackInfo() { |
|
retval_.Dispose(); |
|
retval_.Clear(); |
|
} |
|
|
|
inline ReturnValue<v8::Array> GetReturnValue() const { |
|
return return_value_; |
|
} |
|
}; |
|
|
|
template<> |
|
class PropertyCallbackInfo<v8::Boolean> : |
|
public PropertyCallbackInfoBase<v8::Boolean> { |
|
ReturnValue<v8::Boolean> return_value_; |
|
v8::Persistent<v8::Boolean> retval_; |
|
|
|
public: |
|
explicit inline PropertyCallbackInfo( |
|
const v8::AccessorInfo &info |
|
, const v8::Local<v8::Value> data) : |
|
PropertyCallbackInfoBase<v8::Boolean>(info, data) |
|
, return_value_(info.GetIsolate(), &retval_) |
|
, retval_(v8::Persistent<v8::Boolean>::New(v8::Local<v8::Boolean>())) {} |
|
|
|
inline ~PropertyCallbackInfo() { |
|
retval_.Dispose(); |
|
retval_.Clear(); |
|
} |
|
|
|
inline ReturnValue<v8::Boolean> GetReturnValue() const { |
|
return return_value_; |
|
} |
|
}; |
|
|
|
template<> |
|
class PropertyCallbackInfo<v8::Integer> : |
|
public PropertyCallbackInfoBase<v8::Integer> { |
|
ReturnValue<v8::Integer> return_value_; |
|
v8::Persistent<v8::Integer> retval_; |
|
|
|
public: |
|
explicit inline PropertyCallbackInfo( |
|
const v8::AccessorInfo &info |
|
, const v8::Local<v8::Value> data) : |
|
PropertyCallbackInfoBase<v8::Integer>(info, data) |
|
, return_value_(info.GetIsolate(), &retval_) |
|
, retval_(v8::Persistent<v8::Integer>::New(v8::Local<v8::Integer>())) {} |
|
|
|
inline ~PropertyCallbackInfo() { |
|
retval_.Dispose(); |
|
retval_.Clear(); |
|
} |
|
|
|
inline ReturnValue<v8::Integer> GetReturnValue() const { |
|
return return_value_; |
|
} |
|
}; |
|
|
|
namespace imp { |
|
template<typename T> |
|
class ReturnValueImp : public ReturnValue<T> { |
|
public: |
|
explicit ReturnValueImp(ReturnValue<T> that) : |
|
ReturnValue<T>(that) {} |
|
inline v8::Handle<T> Value() { |
|
return *ReturnValue<T>::value_; |
|
} |
|
}; |
|
|
|
static |
|
v8::Handle<v8::Value> FunctionCallbackWrapper(const v8::Arguments &args) { |
|
v8::Local<v8::Object> obj = args.Data().As<v8::Object>(); |
|
FunctionCallback callback = reinterpret_cast<FunctionCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kFunctionIndex).As<v8::External>()->Value())); |
|
FunctionCallbackInfo<v8::Value> |
|
cbinfo(args, obj->GetInternalField(kDataIndex)); |
|
callback(cbinfo); |
|
return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Value> (*NativeFunction)(const v8::Arguments &); |
|
|
|
static |
|
v8::Handle<v8::Value> GetterCallbackWrapper( |
|
v8::Local<v8::String> property, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Value> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
GetterCallback callback = reinterpret_cast<GetterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kGetterIndex).As<v8::External>()->Value())); |
|
callback(property, cbinfo); |
|
return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Value> (*NativeGetter) |
|
(v8::Local<v8::String>, const v8::AccessorInfo &); |
|
|
|
static |
|
void SetterCallbackWrapper( |
|
v8::Local<v8::String> property |
|
, v8::Local<v8::Value> value |
|
, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<void> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
SetterCallback callback = reinterpret_cast<SetterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kSetterIndex).As<v8::External>()->Value())); |
|
callback(property, value, cbinfo); |
|
} |
|
|
|
typedef void (*NativeSetter) |
|
(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Value> PropertyGetterCallbackWrapper( |
|
v8::Local<v8::String> property, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Value> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
PropertyGetterCallback callback = reinterpret_cast<PropertyGetterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kPropertyGetterIndex) |
|
.As<v8::External>()->Value())); |
|
callback(property, cbinfo); |
|
return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Value> (*NativePropertyGetter) |
|
(v8::Local<v8::String>, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Value> PropertySetterCallbackWrapper( |
|
v8::Local<v8::String> property |
|
, v8::Local<v8::Value> value |
|
, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Value> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
PropertySetterCallback callback = reinterpret_cast<PropertySetterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kPropertySetterIndex) |
|
.As<v8::External>()->Value())); |
|
callback(property, value, cbinfo); |
|
return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Value> (*NativePropertySetter) |
|
(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Array> PropertyEnumeratorCallbackWrapper( |
|
const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Array> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
PropertyEnumeratorCallback callback = |
|
reinterpret_cast<PropertyEnumeratorCallback>(reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kPropertyEnumeratorIndex) |
|
.As<v8::External>()->Value())); |
|
callback(cbinfo); |
|
return ReturnValueImp<v8::Array>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Array> (*NativePropertyEnumerator) |
|
(const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Boolean> PropertyDeleterCallbackWrapper( |
|
v8::Local<v8::String> property |
|
, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Boolean> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
PropertyDeleterCallback callback = reinterpret_cast<PropertyDeleterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kPropertyDeleterIndex) |
|
.As<v8::External>()->Value())); |
|
callback(property, cbinfo); |
|
return ReturnValueImp<v8::Boolean>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Boolean> (NativePropertyDeleter) |
|
(v8::Local<v8::String>, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Integer> PropertyQueryCallbackWrapper( |
|
v8::Local<v8::String> property, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Integer> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
PropertyQueryCallback callback = reinterpret_cast<PropertyQueryCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kPropertyQueryIndex) |
|
.As<v8::External>()->Value())); |
|
callback(property, cbinfo); |
|
return ReturnValueImp<v8::Integer>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Integer> (*NativePropertyQuery) |
|
(v8::Local<v8::String>, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Value> IndexGetterCallbackWrapper( |
|
uint32_t index, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Value> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
IndexGetterCallback callback = reinterpret_cast<IndexGetterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kIndexPropertyGetterIndex) |
|
.As<v8::External>()->Value())); |
|
callback(index, cbinfo); |
|
return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Value> (*NativeIndexGetter) |
|
(uint32_t, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Value> IndexSetterCallbackWrapper( |
|
uint32_t index |
|
, v8::Local<v8::Value> value |
|
, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Value> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
IndexSetterCallback callback = reinterpret_cast<IndexSetterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kIndexPropertySetterIndex) |
|
.As<v8::External>()->Value())); |
|
callback(index, value, cbinfo); |
|
return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Value> (*NativeIndexSetter) |
|
(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Array> IndexEnumeratorCallbackWrapper( |
|
const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Array> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
IndexEnumeratorCallback callback = reinterpret_cast<IndexEnumeratorCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kIndexPropertyEnumeratorIndex) |
|
.As<v8::External>()->Value())); |
|
callback(cbinfo); |
|
return ReturnValueImp<v8::Array>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Array> (*NativeIndexEnumerator) |
|
(const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Boolean> IndexDeleterCallbackWrapper( |
|
uint32_t index, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Boolean> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
IndexDeleterCallback callback = reinterpret_cast<IndexDeleterCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kIndexPropertyDeleterIndex) |
|
.As<v8::External>()->Value())); |
|
callback(index, cbinfo); |
|
return ReturnValueImp<v8::Boolean>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Boolean> (*NativeIndexDeleter) |
|
(uint32_t, const v8::AccessorInfo &); |
|
|
|
static |
|
v8::Handle<v8::Integer> IndexQueryCallbackWrapper( |
|
uint32_t index, const v8::AccessorInfo &info) { |
|
v8::Local<v8::Object> obj = info.Data().As<v8::Object>(); |
|
PropertyCallbackInfo<v8::Integer> |
|
cbinfo(info, obj->GetInternalField(kDataIndex)); |
|
IndexQueryCallback callback = reinterpret_cast<IndexQueryCallback>( |
|
reinterpret_cast<intptr_t>( |
|
obj->GetInternalField(kIndexPropertyQueryIndex) |
|
.As<v8::External>()->Value())); |
|
callback(index, cbinfo); |
|
return ReturnValueImp<v8::Integer>(cbinfo.GetReturnValue()).Value(); |
|
} |
|
|
|
typedef v8::Handle<v8::Integer> (*NativeIndexQuery) |
|
(uint32_t, const v8::AccessorInfo &); |
|
} // end of namespace imp |
|
|
|
#endif // NAN_CALLBACKS_PRE_12_INL_H_
|
|
|