UNPKG

15 kBtext/x-cView Raw
1/*********************************************************************
2 * NAN - Native Abstractions for Node.js
3 *
4 * Copyright (c) 2018 NAN contributors
5 *
6 * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
7 ********************************************************************/
8
9#ifndef NAN_WEAK_H_
10#define NAN_WEAK_H_
11
12static const int kInternalFieldsInWeakCallback = 2;
13static const int kNoInternalFieldIndex = -1;
14
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_
41#else
42# define NAN_WEAK_CALLBACK_DATA_TYPE_ void *
43# define NAN_WEAK_CALLBACK_SIG_ \
44 v8::Persistent<v8::Value>, NAN_WEAK_CALLBACK_DATA_TYPE_
45#endif
46
47template<typename T>
48class WeakCallbackInfo {
49 public:
50 typedef void (*Callback)(const WeakCallbackInfo<T>& data);
51 WeakCallbackInfo(
52 Persistent<v8::Value> *persistent
53 , Callback callback
54 , void *parameter
55 , void *field1 = 0
56 , void *field2 = 0) :
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;
61 }
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");
66 if (index == 0) {
67 return internal_fields_[0];
68 } else {
69 return internal_fields_[1];
70 }
71 }
72
73 private:
74 NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo)
75 Callback callback_;
76 v8::Isolate *isolate_;
77 void *parameter_;
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
84 template<typename S>
85 static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
86 template<typename S>
87 static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
88# else
89 static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
90 static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
91# endif
92#else
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);
99# else
100 static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
101 static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
102# endif
103 static WeakCallbackInfo *unwrapparameter(
104 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data);
105 static WeakCallbackInfo *unwraptwofield(
106 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data);
107#endif
108};
109
110
111#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
112 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
113
114template<typename T>
115template<bool isFirstPass>
116void
117WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
118 WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
119 if (isFirstPass) {
120 cbinfo->persistent_.Reset();
121 data.SetSecondPassCallback(invokeparameter<false>);
122 } else {
123 cbinfo->callback_(*cbinfo);
124 delete cbinfo;
125 }
126}
127
128template<typename T>
129template<bool isFirstPass>
130void
131WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
132 WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
133 if (isFirstPass) {
134 cbinfo->persistent_.Reset();
135 data.SetSecondPassCallback(invoketwofield<false>);
136 } else {
137 cbinfo->callback_(*cbinfo);
138 delete cbinfo;
139 }
140}
141
142template<typename T>
143WeakCallbackInfo<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();
148 return cbinfo;
149}
150
151template<typename T>
152WeakCallbackInfo<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();
157 return cbinfo;
158}
159
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
165
166template<typename T>
167void
168WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
169 WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
170 cbinfo->persistent_.Reset();
171 cbinfo->callback_(*cbinfo);
172 delete cbinfo;
173}
174
175template<typename T>
176void
177WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
178 WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
179 cbinfo->persistent_.Reset();
180 cbinfo->callback_(*cbinfo);
181 delete cbinfo;
182}
183
184template<typename T>
185WeakCallbackInfo<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();
190 return cbinfo;
191}
192
193template<typename T>
194WeakCallbackInfo<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();
199 return cbinfo;
200}
201
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
207
208template<typename T>
209template<typename S>
210void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
211 WeakCallbackInfo<T> *cbinfo = unwrap(data);
212 cbinfo->persistent_.Reset();
213 cbinfo->callback_(*cbinfo);
214 delete cbinfo;
215}
216
217template<typename T>
218template<typename S>
219WeakCallbackInfo<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();
225 return cbinfo;
226}
227
228#undef NAN_WEAK_CALLBACK_SIG_
229#undef NAN_WEAK_CALLBACK_DATA_TYPE_
230#else
231
232template<typename T>
233void 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);
238 delete cbinfo;
239}
240
241template<typename T>
242WeakCallbackInfo<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();
247 return cbinfo;
248}
249
250#undef NAN_WEAK_CALLBACK_SIG_
251#undef NAN_WEAK_CALLBACK_DATA_TYPE_
252#endif
253
254#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
255 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
256template<typename T, typename M>
257template<typename P>
258inline void Persistent<T, M>::SetWeak(
259 P *parameter
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)
266 , callback
267 , parameter);
268 v8::PersistentBase<T>::SetWeak(
269 wcbd
270 , WeakCallbackInfo<P>::template invokeparameter<true>
271 , type);
272 } else {
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);
279 }
280 wcbd = new WeakCallbackInfo<P>(
281 reinterpret_cast<Persistent<v8::Value>*>(this)
282 , callback
283 , 0
284 , internal_fields[0]
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>
290 , type);
291 }
292}
293#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
294template<typename T, typename M>
295template<typename P>
296inline void Persistent<T, M>::SetWeak(
297 P *parameter
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)
304 , callback
305 , parameter);
306 v8::PersistentBase<T>::SetPhantom(
307 wcbd
308 , WeakCallbackInfo<P>::invokeparameter);
309 } else {
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);
316 }
317 wcbd = new WeakCallbackInfo<P>(
318 reinterpret_cast<Persistent<v8::Value>*>(this)
319 , callback
320 , 0
321 , internal_fields[0]
322 , internal_fields[1]);
323 (*self)->SetAlignedPointerInInternalField(0, wcbd);
324 v8::PersistentBase<T>::SetPhantom(
325 static_cast<WeakCallbackInfo<P>*>(0)
326 , WeakCallbackInfo<P>::invoketwofield
327 , 0
328 , count > 1 ? 1 : kNoInternalFieldIndex);
329 }
330}
331#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
332template<typename T, typename M>
333template<typename P>
334inline void Persistent<T, M>::SetWeak(
335 P *parameter
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)
342 , callback
343 , parameter);
344 v8::PersistentBase<T>::SetPhantom(
345 wcbd
346 , WeakCallbackInfo<P>::invokeparameter);
347 } else {
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);
354 }
355 wcbd = new WeakCallbackInfo<P>(
356 reinterpret_cast<Persistent<v8::Value>*>(this)
357 , callback
358 , 0
359 , internal_fields[0]
360 , internal_fields[1]);
361 (*self)->SetAlignedPointerInInternalField(0, wcbd);
362 v8::PersistentBase<T>::SetPhantom(
363 WeakCallbackInfo<P>::invoketwofield
364 , 0
365 , count > 1 ? 1 : kNoInternalFieldIndex);
366 }
367}
368#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
369template<typename T, typename M>
370template<typename P>
371inline void Persistent<T, M>::SetWeak(
372 P *parameter
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)
379 , callback
380 , parameter);
381 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
382 } else {
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);
389 }
390 wcbd = new WeakCallbackInfo<P>(
391 reinterpret_cast<Persistent<v8::Value>*>(this)
392 , callback
393 , 0
394 , internal_fields[0]
395 , internal_fields[1]);
396 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
397 }
398}
399#else
400template<typename T>
401template<typename P>
402inline void PersistentBase<T>::SetWeak(
403 P *parameter
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)
410 , callback
411 , parameter);
412 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
413 } else {
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);
420 }
421 wcbd = new WeakCallbackInfo<P>(
422 reinterpret_cast<Persistent<v8::Value>*>(this)
423 , callback
424 , 0
425 , internal_fields[0]
426 , internal_fields[1]);
427 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
428 }
429}
430#endif
431
432#endif // NAN_WEAK_H_