UNPKG

15.4 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<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
274 assert((*self_v)->IsObject());
275 v8::Local<v8::Object> self((*self_v).As<v8::Object>());
276 int count = self->InternalFieldCount();
277 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
278 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
279 internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
280 }
281 wcbd = new WeakCallbackInfo<P>(
282 reinterpret_cast<Persistent<v8::Value>*>(this)
283 , callback
284 , 0
285 , internal_fields[0]
286 , internal_fields[1]);
287 self->SetAlignedPointerInInternalField(0, wcbd);
288 v8::PersistentBase<T>::SetWeak(
289 static_cast<WeakCallbackInfo<P>*>(0)
290 , WeakCallbackInfo<P>::template invoketwofield<true>
291 , type);
292 }
293}
294#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
295template<typename T, typename M>
296template<typename P>
297inline void Persistent<T, M>::SetWeak(
298 P *parameter
299 , typename WeakCallbackInfo<P>::Callback callback
300 , WeakCallbackType type) {
301 WeakCallbackInfo<P> *wcbd;
302 if (type == WeakCallbackType::kParameter) {
303 wcbd = new WeakCallbackInfo<P>(
304 reinterpret_cast<Persistent<v8::Value>*>(this)
305 , callback
306 , parameter);
307 v8::PersistentBase<T>::SetPhantom(
308 wcbd
309 , WeakCallbackInfo<P>::invokeparameter);
310 } else {
311 v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
312 assert((*self_v)->IsObject());
313 v8::Local<v8::Object> self((*self_v).As<v8::Object>());
314 int count = self->InternalFieldCount();
315 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
316 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
317 internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
318 }
319 wcbd = new WeakCallbackInfo<P>(
320 reinterpret_cast<Persistent<v8::Value>*>(this)
321 , callback
322 , 0
323 , internal_fields[0]
324 , internal_fields[1]);
325 self->SetAlignedPointerInInternalField(0, wcbd);
326 v8::PersistentBase<T>::SetPhantom(
327 static_cast<WeakCallbackInfo<P>*>(0)
328 , WeakCallbackInfo<P>::invoketwofield
329 , 0
330 , count > 1 ? 1 : kNoInternalFieldIndex);
331 }
332}
333#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
334template<typename T, typename M>
335template<typename P>
336inline void Persistent<T, M>::SetWeak(
337 P *parameter
338 , typename WeakCallbackInfo<P>::Callback callback
339 , WeakCallbackType type) {
340 WeakCallbackInfo<P> *wcbd;
341 if (type == WeakCallbackType::kParameter) {
342 wcbd = new WeakCallbackInfo<P>(
343 reinterpret_cast<Persistent<v8::Value>*>(this)
344 , callback
345 , parameter);
346 v8::PersistentBase<T>::SetPhantom(
347 wcbd
348 , WeakCallbackInfo<P>::invokeparameter);
349 } else {
350 v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
351 assert((*self_v)->IsObject());
352 v8::Local<v8::Object> self((*self_v).As<v8::Object>());
353 int count = self->InternalFieldCount();
354 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
355 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
356 internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
357 }
358 wcbd = new WeakCallbackInfo<P>(
359 reinterpret_cast<Persistent<v8::Value>*>(this)
360 , callback
361 , 0
362 , internal_fields[0]
363 , internal_fields[1]);
364 self->SetAlignedPointerInInternalField(0, wcbd);
365 v8::PersistentBase<T>::SetPhantom(
366 WeakCallbackInfo<P>::invoketwofield
367 , 0
368 , count > 1 ? 1 : kNoInternalFieldIndex);
369 }
370}
371#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
372template<typename T, typename M>
373template<typename P>
374inline void Persistent<T, M>::SetWeak(
375 P *parameter
376 , typename WeakCallbackInfo<P>::Callback callback
377 , WeakCallbackType type) {
378 WeakCallbackInfo<P> *wcbd;
379 if (type == WeakCallbackType::kParameter) {
380 wcbd = new WeakCallbackInfo<P>(
381 reinterpret_cast<Persistent<v8::Value>*>(this)
382 , callback
383 , parameter);
384 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
385 } else {
386 v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
387 assert((*self_v)->IsObject());
388 v8::Local<v8::Object> self((*self_v).As<v8::Object>());
389 int count = self->InternalFieldCount();
390 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
391 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
392 internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
393 }
394 wcbd = new WeakCallbackInfo<P>(
395 reinterpret_cast<Persistent<v8::Value>*>(this)
396 , callback
397 , 0
398 , internal_fields[0]
399 , internal_fields[1]);
400 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
401 }
402}
403#else
404template<typename T>
405template<typename P>
406inline void PersistentBase<T>::SetWeak(
407 P *parameter
408 , typename WeakCallbackInfo<P>::Callback callback
409 , WeakCallbackType type) {
410 WeakCallbackInfo<P> *wcbd;
411 if (type == WeakCallbackType::kParameter) {
412 wcbd = new WeakCallbackInfo<P>(
413 reinterpret_cast<Persistent<v8::Value>*>(this)
414 , callback
415 , parameter);
416 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
417 } else {
418 v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
419 assert((*self_v)->IsObject());
420 v8::Local<v8::Object> self((*self_v).As<v8::Object>());
421 int count = self->InternalFieldCount();
422 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
423 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
424 internal_fields[i] = self->GetPointerFromInternalField(i);
425 }
426 wcbd = new WeakCallbackInfo<P>(
427 reinterpret_cast<Persistent<v8::Value>*>(this)
428 , callback
429 , 0
430 , internal_fields[0]
431 , internal_fields[1]);
432 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
433 }
434}
435#endif
436
437#endif // NAN_WEAK_H_