@@ -49,36 +49,73 @@ union pointer_cast
49
49
};
50
50
51
51
template <typename T>
52
- typename std::enable_if<is_pointer_cast_allowed<T>::value, v8::Local<v8::Value>>::type
53
- set_external_data (v8::Isolate* isolate, T value)
54
- {
55
- return v8::External::New (isolate, pointer_cast<T>(value));
56
- }
57
-
58
- template <typename T>
59
- typename std::enable_if<!is_pointer_cast_allowed<T>::value, v8::Local<v8::Value>>::type
60
- set_external_data (v8::Isolate* isolate, T const & value)
52
+ class external_data
61
53
{
62
- T* data = new T (value);
63
-
64
- v8::Local<v8::External> ext = v8::External::New (isolate, data);
54
+ public:
55
+ static v8::Local<v8::External> set (v8::Isolate* isolate, T&& data)
56
+ {
57
+ external_data* value = new external_data;
58
+ try
59
+ {
60
+ new (value->storage ()) T (std::forward<T>(data));
61
+ }
62
+ catch (...)
63
+ {
64
+ delete value;
65
+ throw ;
66
+ }
65
67
66
- v8::Persistent<v8::External> pext (isolate, ext);
67
- pext.SetWeak (data,
68
+ v8::Local<v8::External> ext = v8::External::New (isolate, value);
69
+ value->pext_ .Reset (isolate, ext);
70
+ value->pext_ .SetWeak (value,
68
71
#ifdef V8_USE_WEAK_CB_INFO
69
- [](v8::WeakCallbackInfo<T > const & data)
72
+ [](v8::WeakCallbackInfo<external_data > const & data)
70
73
#else
71
- [](v8::WeakCallbackData<v8::External, T > const & data)
74
+ [](v8::WeakCallbackData<v8::External, external_data > const & data)
72
75
#endif
73
76
{
74
77
delete data.GetParameter ();
75
78
}
76
79
#ifdef V8_USE_WEAK_CB_INFO
77
- , v8::WeakCallbackType::kParameter
80
+ , v8::WeakCallbackType::kParameter
78
81
#endif
79
- );
82
+ );
83
+ return ext;
84
+ }
85
+
86
+ static T& get (v8::Local<v8::External> ext)
87
+ {
88
+ external_data* value = static_cast <external_data*>(ext->Value ());
89
+ return *static_cast <T*>(value->storage ());
90
+ }
80
91
81
- return ext;
92
+ private:
93
+ void * storage () { return &storage_; }
94
+ ~external_data ()
95
+ {
96
+ if (!pext_.IsEmpty ())
97
+ {
98
+ static_cast <T*>(storage ())->~T ();
99
+ pext_.Reset ();
100
+ }
101
+ }
102
+ using data_storage = typename std::aligned_storage<sizeof (T)>::type;
103
+ data_storage storage_;
104
+ v8::UniquePersistent<v8::External> pext_;
105
+ };
106
+
107
+ template <typename T>
108
+ typename std::enable_if<is_pointer_cast_allowed<T>::value, v8::Local<v8::Value>>::type
109
+ set_external_data (v8::Isolate* isolate, T value)
110
+ {
111
+ return v8::External::New (isolate, pointer_cast<T>(value));
112
+ }
113
+
114
+ template <typename T>
115
+ typename std::enable_if<!is_pointer_cast_allowed<T>::value, v8::Local<v8::Value>>::type
116
+ set_external_data (v8::Isolate* isolate, T&& value)
117
+ {
118
+ return external_data<T>::set (isolate, std::forward<T>(value));
82
119
}
83
120
84
121
template <typename T>
@@ -92,17 +129,15 @@ template<typename T>
92
129
typename std::enable_if<!is_pointer_cast_allowed<T>::value, T&>::type
93
130
get_external_data (v8::Handle <v8::Value> value)
94
131
{
95
- T* data = static_cast <T*>(value.As <v8::External>()->Value ());
96
- return *data;
132
+ return external_data<T>::get (value.As <v8::External>());
97
133
}
98
134
99
135
template <typename F>
100
136
typename std::enable_if<is_callable<F>::value,
101
137
typename function_traits<F>::return_type>::type
102
138
invoke (v8::FunctionCallbackInfo<v8::Value> const & args)
103
139
{
104
- F f = get_external_data<F>(args.Data ());
105
- return call_from_v8 (std::forward<F>(f), args);
140
+ return call_from_v8 (std::forward<F>(get_external_data<F>(args.Data ())), args);
106
141
}
107
142
108
143
template <typename F>
@@ -114,10 +149,8 @@ invoke(v8::FunctionCallbackInfo<v8::Value> const& args)
114
149
static_assert (std::tuple_size<arguments>::value > 0 , " " );
115
150
using class_type = typename std::tuple_element<0 , arguments>::type;
116
151
117
- F f = get_external_data<F>(args.Data ());
118
- class_type& obj = from_v8<class_type&>(args.GetIsolate (), args.This ());
119
-
120
- return call_from_v8 (obj, std::forward<F>(f), args);
152
+ return call_from_v8 (from_v8<class_type&>(args.GetIsolate (), args.This ()),
153
+ std::forward<F>(get_external_data<F>(args.Data ())), args);
121
154
}
122
155
123
156
template <typename F>
@@ -157,20 +190,22 @@ void forward_function(v8::FunctionCallbackInfo<v8::Value> const& args)
157
190
158
191
// / Wrap C++ function into new V8 function template
159
192
template <typename F>
160
- v8::Handle <v8::FunctionTemplate> wrap_function_template (v8::Isolate* isolate, F func)
193
+ v8::Handle <v8::FunctionTemplate> wrap_function_template (v8::Isolate* isolate, F&& func)
161
194
{
162
- return v8::FunctionTemplate::New (isolate, &detail::forward_function<F>,
163
- detail::set_external_data (isolate, func));
195
+ using F_type = typename std::decay<F>::type;
196
+ return v8::FunctionTemplate::New (isolate, &detail::forward_function<F_type>,
197
+ detail::set_external_data (isolate, std::forward<F_type>(func)));
164
198
}
165
199
166
200
// / Wrap C++ function into new V8 function
167
201
// / Set nullptr or empty string for name
168
202
// / to make the function anonymous
169
203
template <typename F>
170
- v8::Handle <v8::Function> wrap_function (v8::Isolate* isolate, char const * name, F func)
204
+ v8::Handle <v8::Function> wrap_function (v8::Isolate* isolate, char const * name, F&& func)
171
205
{
172
- v8::Handle <v8::Function> fn = v8::Function::New (isolate, &detail::forward_function<F>,
173
- detail::set_external_data (isolate, func));
206
+ using F_type = typename std::decay<F>::type;
207
+ v8::Handle <v8::Function> fn = v8::Function::New (isolate, &detail::forward_function<F_type>,
208
+ detail::set_external_data (isolate, std::forward<F_type>(func)));
174
209
if (name && *name)
175
210
{
176
211
fn->SetName (to_v8 (isolate, name));
0 commit comments