1 /*********************************************************************
2 * NAN - Native Abstractions for Node.js
4 * Copyright (c) 2017 NAN contributors
6 * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
7 ********************************************************************/
12 static const int kInternalFieldsInWeakCallback = 2;
13 static const int kNoInternalFieldIndex = -1;
15 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
16 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
17 # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
18 v8::WeakCallbackInfo<WeakCallbackInfo<T> > const&
19 # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
20 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
21 # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
22 # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
23 #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
24 # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
25 v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
26 # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
27 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
28 # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
29 # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
30 #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
31 # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
32 v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
33 # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
34 v8::InternalFieldsCallbackData<WeakCallbackInfo<T>, void> const&
35 # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
36 # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
37 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
38 # define NAN_WEAK_CALLBACK_DATA_TYPE_ \
39 v8::WeakCallbackData<S, WeakCallbackInfo<T> > const&
40 # define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_
42 # define NAN_WEAK_CALLBACK_DATA_TYPE_ void *
43 # define NAN_WEAK_CALLBACK_SIG_ \
44 v8::Persistent<v8::Value>, NAN_WEAK_CALLBACK_DATA_TYPE_
48 class WeakCallbackInfo {
50 typedef void (*Callback)(const WeakCallbackInfo<T>& data);
52 Persistent<v8::Value> *persistent
57 callback_(callback), isolate_(0), parameter_(parameter) {
58 std::memcpy(&persistent_, persistent, sizeof (v8::Persistent<v8::Value>));
59 internal_fields_[0] = field1;
60 internal_fields_[1] = field2;
62 inline v8::Isolate *GetIsolate() const { return isolate_; }
63 inline T *GetParameter() const { return static_cast<T*>(parameter_); }
64 inline void *GetInternalField(int index) const {
65 assert((index == 0 || index == 1) && "internal field index out of bounds");
67 return internal_fields_[0];
69 return internal_fields_[1];
74 NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo)
76 v8::Isolate *isolate_;
78 void *internal_fields_[kInternalFieldsInWeakCallback];
79 v8::Persistent<v8::Value> persistent_;
80 template<typename S, typename M> friend class Persistent;
81 template<typename S> friend class PersistentBase;
82 #if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION
83 # if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
85 static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
87 static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
89 static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
90 static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
93 # if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
94 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
95 template<bool isFirstPass>
96 static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
97 template<bool isFirstPass>
98 static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
100 static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
101 static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
103 static WeakCallbackInfo *unwrapparameter(
104 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data);
105 static WeakCallbackInfo *unwraptwofield(
106 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data);
111 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
112 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
115 template<bool isFirstPass>
117 WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
118 WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
120 cbinfo->persistent_.Reset();
121 data.SetSecondPassCallback(invokeparameter<false>);
123 cbinfo->callback_(*cbinfo);
129 template<bool isFirstPass>
131 WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
132 WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
134 cbinfo->persistent_.Reset();
135 data.SetSecondPassCallback(invoketwofield<false>);
137 cbinfo->callback_(*cbinfo);
143 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
144 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
145 WeakCallbackInfo<T> *cbinfo =
146 static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
147 cbinfo->isolate_ = data.GetIsolate();
152 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
153 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
154 WeakCallbackInfo<T> *cbinfo =
155 static_cast<WeakCallbackInfo<T>*>(data.GetInternalField(0));
156 cbinfo->isolate_ = data.GetIsolate();
160 #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
161 #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
162 #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
163 #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
164 # elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
168 WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
169 WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
170 cbinfo->persistent_.Reset();
171 cbinfo->callback_(*cbinfo);
177 WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
178 WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
179 cbinfo->persistent_.Reset();
180 cbinfo->callback_(*cbinfo);
185 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
186 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
187 WeakCallbackInfo<T> *cbinfo =
188 static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
189 cbinfo->isolate_ = data.GetIsolate();
194 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
195 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
196 WeakCallbackInfo<T> *cbinfo =
197 static_cast<WeakCallbackInfo<T>*>(data.GetInternalField1());
198 cbinfo->isolate_ = data.GetIsolate();
202 #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
203 #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
204 #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
205 #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
206 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
210 void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
211 WeakCallbackInfo<T> *cbinfo = unwrap(data);
212 cbinfo->persistent_.Reset();
213 cbinfo->callback_(*cbinfo);
219 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
220 NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
221 void *parameter = data.GetParameter();
222 WeakCallbackInfo<T> *cbinfo =
223 static_cast<WeakCallbackInfo<T>*>(parameter);
224 cbinfo->isolate_ = data.GetIsolate();
228 #undef NAN_WEAK_CALLBACK_SIG_
229 #undef NAN_WEAK_CALLBACK_DATA_TYPE_
233 void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
234 WeakCallbackInfo<T> *cbinfo = unwrap(data);
235 cbinfo->persistent_.Dispose();
236 cbinfo->persistent_.Clear();
237 cbinfo->callback_(*cbinfo);
242 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
243 NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
244 WeakCallbackInfo<T> *cbinfo =
245 static_cast<WeakCallbackInfo<T>*>(data);
246 cbinfo->isolate_ = v8::Isolate::GetCurrent();
250 #undef NAN_WEAK_CALLBACK_SIG_
251 #undef NAN_WEAK_CALLBACK_DATA_TYPE_
254 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
255 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
256 template<typename T, typename M>
258 inline void Persistent<T, M>::SetWeak(
260 , typename WeakCallbackInfo<P>::Callback callback
261 , WeakCallbackType type) {
262 WeakCallbackInfo<P> *wcbd;
263 if (type == WeakCallbackType::kParameter) {
264 wcbd = new WeakCallbackInfo<P>(
265 reinterpret_cast<Persistent<v8::Value>*>(this)
268 v8::PersistentBase<T>::SetWeak(
270 , WeakCallbackInfo<P>::template invokeparameter<true>
273 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
274 assert((*self)->IsObject());
275 int count = (*self)->InternalFieldCount();
276 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
277 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
278 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
280 wcbd = new WeakCallbackInfo<P>(
281 reinterpret_cast<Persistent<v8::Value>*>(this)
285 , internal_fields[1]);
286 (*self)->SetAlignedPointerInInternalField(0, wcbd);
287 v8::PersistentBase<T>::SetWeak(
288 static_cast<WeakCallbackInfo<P>*>(0)
289 , WeakCallbackInfo<P>::template invoketwofield<true>
293 #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
294 template<typename T, typename M>
296 inline void Persistent<T, M>::SetWeak(
298 , typename WeakCallbackInfo<P>::Callback callback
299 , WeakCallbackType type) {
300 WeakCallbackInfo<P> *wcbd;
301 if (type == WeakCallbackType::kParameter) {
302 wcbd = new WeakCallbackInfo<P>(
303 reinterpret_cast<Persistent<v8::Value>*>(this)
306 v8::PersistentBase<T>::SetPhantom(
308 , WeakCallbackInfo<P>::invokeparameter);
310 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
311 assert((*self)->IsObject());
312 int count = (*self)->InternalFieldCount();
313 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
314 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
315 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
317 wcbd = new WeakCallbackInfo<P>(
318 reinterpret_cast<Persistent<v8::Value>*>(this)
322 , internal_fields[1]);
323 (*self)->SetAlignedPointerInInternalField(0, wcbd);
324 v8::PersistentBase<T>::SetPhantom(
325 static_cast<WeakCallbackInfo<P>*>(0)
326 , WeakCallbackInfo<P>::invoketwofield
328 , count > 1 ? 1 : kNoInternalFieldIndex);
331 #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
332 template<typename T, typename M>
334 inline void Persistent<T, M>::SetWeak(
336 , typename WeakCallbackInfo<P>::Callback callback
337 , WeakCallbackType type) {
338 WeakCallbackInfo<P> *wcbd;
339 if (type == WeakCallbackType::kParameter) {
340 wcbd = new WeakCallbackInfo<P>(
341 reinterpret_cast<Persistent<v8::Value>*>(this)
344 v8::PersistentBase<T>::SetPhantom(
346 , WeakCallbackInfo<P>::invokeparameter);
348 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
349 assert((*self)->IsObject());
350 int count = (*self)->InternalFieldCount();
351 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
352 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
353 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
355 wcbd = new WeakCallbackInfo<P>(
356 reinterpret_cast<Persistent<v8::Value>*>(this)
360 , internal_fields[1]);
361 (*self)->SetAlignedPointerInInternalField(0, wcbd);
362 v8::PersistentBase<T>::SetPhantom(
363 WeakCallbackInfo<P>::invoketwofield
365 , count > 1 ? 1 : kNoInternalFieldIndex);
368 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
369 template<typename T, typename M>
371 inline void Persistent<T, M>::SetWeak(
373 , typename WeakCallbackInfo<P>::Callback callback
374 , WeakCallbackType type) {
375 WeakCallbackInfo<P> *wcbd;
376 if (type == WeakCallbackType::kParameter) {
377 wcbd = new WeakCallbackInfo<P>(
378 reinterpret_cast<Persistent<v8::Value>*>(this)
381 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
383 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
384 assert((*self)->IsObject());
385 int count = (*self)->InternalFieldCount();
386 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
387 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
388 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
390 wcbd = new WeakCallbackInfo<P>(
391 reinterpret_cast<Persistent<v8::Value>*>(this)
395 , internal_fields[1]);
396 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
402 inline void PersistentBase<T>::SetWeak(
404 , typename WeakCallbackInfo<P>::Callback callback
405 , WeakCallbackType type) {
406 WeakCallbackInfo<P> *wcbd;
407 if (type == WeakCallbackType::kParameter) {
408 wcbd = new WeakCallbackInfo<P>(
409 reinterpret_cast<Persistent<v8::Value>*>(this)
412 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
414 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
415 assert((*self)->IsObject());
416 int count = (*self)->InternalFieldCount();
417 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
418 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
419 internal_fields[i] = (*self)->GetPointerFromInternalField(i);
421 wcbd = new WeakCallbackInfo<P>(
422 reinterpret_cast<Persistent<v8::Value>*>(this)
426 , internal_fields[1]);
427 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
432 #endif // NAN_WEAK_H_