00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef NAN_WEAK_H_
00010 #define NAN_WEAK_H_
00011
00012 static const int kInternalFieldsInWeakCallback = 2;
00013 static const int kNoInternalFieldIndex = -1;
00014
00015 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
00016 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
00017 # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
00018 v8::WeakCallbackInfo<WeakCallbackInfo<T> > const&
00019 # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
00020 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00021 # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00022 # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
00023 #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
00024 # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
00025 v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
00026 # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
00027 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00028 # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00029 # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
00030 #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
00031 # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
00032 v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
00033 # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
00034 v8::InternalFieldsCallbackData<WeakCallbackInfo<T>, void> const&
00035 # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00036 # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
00037 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
00038 # define NAN_WEAK_CALLBACK_DATA_TYPE_ \
00039 v8::WeakCallbackData<S, WeakCallbackInfo<T> > const&
00040 # define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_
00041 #else
00042 # define NAN_WEAK_CALLBACK_DATA_TYPE_ void *
00043 # define NAN_WEAK_CALLBACK_SIG_ \
00044 v8::Persistent<v8::Value>, NAN_WEAK_CALLBACK_DATA_TYPE_
00045 #endif
00046
00047 template<typename T>
00048 class WeakCallbackInfo {
00049 public:
00050 typedef void (*Callback)(const WeakCallbackInfo<T>& data);
00051 WeakCallbackInfo(
00052 Persistent<v8::Value> *persistent
00053 , Callback callback
00054 , void *parameter
00055 , void *field1 = 0
00056 , void *field2 = 0) :
00057 callback_(callback), isolate_(0), parameter_(parameter) {
00058 std::memcpy(&persistent_, persistent, sizeof (v8::Persistent<v8::Value>));
00059 internal_fields_[0] = field1;
00060 internal_fields_[1] = field2;
00061 }
00062 inline v8::Isolate *GetIsolate() const { return isolate_; }
00063 inline T *GetParameter() const { return static_cast<T*>(parameter_); }
00064 inline void *GetInternalField(int index) const {
00065 assert((index == 0 || index == 1) && "internal field index out of bounds");
00066 if (index == 0) {
00067 return internal_fields_[0];
00068 } else {
00069 return internal_fields_[1];
00070 }
00071 }
00072
00073 private:
00074 NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo)
00075 Callback callback_;
00076 v8::Isolate *isolate_;
00077 void *parameter_;
00078 void *internal_fields_[kInternalFieldsInWeakCallback];
00079 v8::Persistent<v8::Value> persistent_;
00080 template<typename S, typename M> friend class Persistent;
00081 template<typename S> friend class PersistentBase;
00082 #if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION
00083 # if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
00084 template<typename S>
00085 static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
00086 template<typename S>
00087 static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
00088 # else
00089 static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
00090 static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
00091 # endif
00092 #else
00093 # if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
00094 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
00095 template<bool isFirstPass>
00096 static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
00097 template<bool isFirstPass>
00098 static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
00099 # else
00100 static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
00101 static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
00102 # endif
00103 static WeakCallbackInfo *unwrapparameter(
00104 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data);
00105 static WeakCallbackInfo *unwraptwofield(
00106 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data);
00107 #endif
00108 };
00109
00110
00111 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
00112 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
00113
00114 template<typename T>
00115 template<bool isFirstPass>
00116 void
00117 WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
00118 WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
00119 if (isFirstPass) {
00120 cbinfo->persistent_.Reset();
00121 data.SetSecondPassCallback(invokeparameter<false>);
00122 } else {
00123 cbinfo->callback_(*cbinfo);
00124 delete cbinfo;
00125 }
00126 }
00127
00128 template<typename T>
00129 template<bool isFirstPass>
00130 void
00131 WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
00132 WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
00133 if (isFirstPass) {
00134 cbinfo->persistent_.Reset();
00135 data.SetSecondPassCallback(invoketwofield<false>);
00136 } else {
00137 cbinfo->callback_(*cbinfo);
00138 delete cbinfo;
00139 }
00140 }
00141
00142 template<typename T>
00143 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
00144 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
00145 WeakCallbackInfo<T> *cbinfo =
00146 static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
00147 cbinfo->isolate_ = data.GetIsolate();
00148 return cbinfo;
00149 }
00150
00151 template<typename T>
00152 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
00153 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
00154 WeakCallbackInfo<T> *cbinfo =
00155 static_cast<WeakCallbackInfo<T>*>(data.GetInternalField(0));
00156 cbinfo->isolate_ = data.GetIsolate();
00157 return cbinfo;
00158 }
00159
00160 #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
00161 #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
00162 #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00163 #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
00164 # elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
00165
00166 template<typename T>
00167 void
00168 WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
00169 WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
00170 cbinfo->persistent_.Reset();
00171 cbinfo->callback_(*cbinfo);
00172 delete cbinfo;
00173 }
00174
00175 template<typename T>
00176 void
00177 WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
00178 WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
00179 cbinfo->persistent_.Reset();
00180 cbinfo->callback_(*cbinfo);
00181 delete cbinfo;
00182 }
00183
00184 template<typename T>
00185 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
00186 NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
00187 WeakCallbackInfo<T> *cbinfo =
00188 static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
00189 cbinfo->isolate_ = data.GetIsolate();
00190 return cbinfo;
00191 }
00192
00193 template<typename T>
00194 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
00195 NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
00196 WeakCallbackInfo<T> *cbinfo =
00197 static_cast<WeakCallbackInfo<T>*>(data.GetInternalField1());
00198 cbinfo->isolate_ = data.GetIsolate();
00199 return cbinfo;
00200 }
00201
00202 #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
00203 #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
00204 #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
00205 #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
00206 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
00207
00208 template<typename T>
00209 template<typename S>
00210 void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
00211 WeakCallbackInfo<T> *cbinfo = unwrap(data);
00212 cbinfo->persistent_.Reset();
00213 cbinfo->callback_(*cbinfo);
00214 delete cbinfo;
00215 }
00216
00217 template<typename T>
00218 template<typename S>
00219 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
00220 NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
00221 void *parameter = data.GetParameter();
00222 WeakCallbackInfo<T> *cbinfo =
00223 static_cast<WeakCallbackInfo<T>*>(parameter);
00224 cbinfo->isolate_ = data.GetIsolate();
00225 return cbinfo;
00226 }
00227
00228 #undef NAN_WEAK_CALLBACK_SIG_
00229 #undef NAN_WEAK_CALLBACK_DATA_TYPE_
00230 #else
00231
00232 template<typename T>
00233 void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
00234 WeakCallbackInfo<T> *cbinfo = unwrap(data);
00235 cbinfo->persistent_.Dispose();
00236 cbinfo->persistent_.Clear();
00237 cbinfo->callback_(*cbinfo);
00238 delete cbinfo;
00239 }
00240
00241 template<typename T>
00242 WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
00243 NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
00244 WeakCallbackInfo<T> *cbinfo =
00245 static_cast<WeakCallbackInfo<T>*>(data);
00246 cbinfo->isolate_ = v8::Isolate::GetCurrent();
00247 return cbinfo;
00248 }
00249
00250 #undef NAN_WEAK_CALLBACK_SIG_
00251 #undef NAN_WEAK_CALLBACK_DATA_TYPE_
00252 #endif
00253
00254 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
00255 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
00256 template<typename T, typename M>
00257 template<typename P>
00258 inline void Persistent<T, M>::SetWeak(
00259 P *parameter
00260 , typename WeakCallbackInfo<P>::Callback callback
00261 , WeakCallbackType type) {
00262 WeakCallbackInfo<P> *wcbd;
00263 if (type == WeakCallbackType::kParameter) {
00264 wcbd = new WeakCallbackInfo<P>(
00265 reinterpret_cast<Persistent<v8::Value>*>(this)
00266 , callback
00267 , parameter);
00268 v8::PersistentBase<T>::SetWeak(
00269 wcbd
00270 , WeakCallbackInfo<P>::template invokeparameter<true>
00271 , type);
00272 } else {
00273 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
00274 assert((*self)->IsObject());
00275 int count = (*self)->InternalFieldCount();
00276 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
00277 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
00278 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
00279 }
00280 wcbd = new WeakCallbackInfo<P>(
00281 reinterpret_cast<Persistent<v8::Value>*>(this)
00282 , callback
00283 , 0
00284 , internal_fields[0]
00285 , internal_fields[1]);
00286 (*self)->SetAlignedPointerInInternalField(0, wcbd);
00287 v8::PersistentBase<T>::SetWeak(
00288 static_cast<WeakCallbackInfo<P>*>(0)
00289 , WeakCallbackInfo<P>::template invoketwofield<true>
00290 , type);
00291 }
00292 }
00293 #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
00294 template<typename T, typename M>
00295 template<typename P>
00296 inline void Persistent<T, M>::SetWeak(
00297 P *parameter
00298 , typename WeakCallbackInfo<P>::Callback callback
00299 , WeakCallbackType type) {
00300 WeakCallbackInfo<P> *wcbd;
00301 if (type == WeakCallbackType::kParameter) {
00302 wcbd = new WeakCallbackInfo<P>(
00303 reinterpret_cast<Persistent<v8::Value>*>(this)
00304 , callback
00305 , parameter);
00306 v8::PersistentBase<T>::SetPhantom(
00307 wcbd
00308 , WeakCallbackInfo<P>::invokeparameter);
00309 } else {
00310 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
00311 assert((*self)->IsObject());
00312 int count = (*self)->InternalFieldCount();
00313 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
00314 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
00315 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
00316 }
00317 wcbd = new WeakCallbackInfo<P>(
00318 reinterpret_cast<Persistent<v8::Value>*>(this)
00319 , callback
00320 , 0
00321 , internal_fields[0]
00322 , internal_fields[1]);
00323 (*self)->SetAlignedPointerInInternalField(0, wcbd);
00324 v8::PersistentBase<T>::SetPhantom(
00325 static_cast<WeakCallbackInfo<P>*>(0)
00326 , WeakCallbackInfo<P>::invoketwofield
00327 , 0
00328 , count > 1 ? 1 : kNoInternalFieldIndex);
00329 }
00330 }
00331 #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
00332 template<typename T, typename M>
00333 template<typename P>
00334 inline void Persistent<T, M>::SetWeak(
00335 P *parameter
00336 , typename WeakCallbackInfo<P>::Callback callback
00337 , WeakCallbackType type) {
00338 WeakCallbackInfo<P> *wcbd;
00339 if (type == WeakCallbackType::kParameter) {
00340 wcbd = new WeakCallbackInfo<P>(
00341 reinterpret_cast<Persistent<v8::Value>*>(this)
00342 , callback
00343 , parameter);
00344 v8::PersistentBase<T>::SetPhantom(
00345 wcbd
00346 , WeakCallbackInfo<P>::invokeparameter);
00347 } else {
00348 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
00349 assert((*self)->IsObject());
00350 int count = (*self)->InternalFieldCount();
00351 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
00352 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
00353 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
00354 }
00355 wcbd = new WeakCallbackInfo<P>(
00356 reinterpret_cast<Persistent<v8::Value>*>(this)
00357 , callback
00358 , 0
00359 , internal_fields[0]
00360 , internal_fields[1]);
00361 (*self)->SetAlignedPointerInInternalField(0, wcbd);
00362 v8::PersistentBase<T>::SetPhantom(
00363 WeakCallbackInfo<P>::invoketwofield
00364 , 0
00365 , count > 1 ? 1 : kNoInternalFieldIndex);
00366 }
00367 }
00368 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
00369 template<typename T, typename M>
00370 template<typename P>
00371 inline void Persistent<T, M>::SetWeak(
00372 P *parameter
00373 , typename WeakCallbackInfo<P>::Callback callback
00374 , WeakCallbackType type) {
00375 WeakCallbackInfo<P> *wcbd;
00376 if (type == WeakCallbackType::kParameter) {
00377 wcbd = new WeakCallbackInfo<P>(
00378 reinterpret_cast<Persistent<v8::Value>*>(this)
00379 , callback
00380 , parameter);
00381 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
00382 } else {
00383 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
00384 assert((*self)->IsObject());
00385 int count = (*self)->InternalFieldCount();
00386 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
00387 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
00388 internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
00389 }
00390 wcbd = new WeakCallbackInfo<P>(
00391 reinterpret_cast<Persistent<v8::Value>*>(this)
00392 , callback
00393 , 0
00394 , internal_fields[0]
00395 , internal_fields[1]);
00396 v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
00397 }
00398 }
00399 #else
00400 template<typename T>
00401 template<typename P>
00402 inline void PersistentBase<T>::SetWeak(
00403 P *parameter
00404 , typename WeakCallbackInfo<P>::Callback callback
00405 , WeakCallbackType type) {
00406 WeakCallbackInfo<P> *wcbd;
00407 if (type == WeakCallbackType::kParameter) {
00408 wcbd = new WeakCallbackInfo<P>(
00409 reinterpret_cast<Persistent<v8::Value>*>(this)
00410 , callback
00411 , parameter);
00412 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
00413 } else {
00414 v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
00415 assert((*self)->IsObject());
00416 int count = (*self)->InternalFieldCount();
00417 void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
00418 for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
00419 internal_fields[i] = (*self)->GetPointerFromInternalField(i);
00420 }
00421 wcbd = new WeakCallbackInfo<P>(
00422 reinterpret_cast<Persistent<v8::Value>*>(this)
00423 , callback
00424 , 0
00425 , internal_fields[0]
00426 , internal_fields[1]);
00427 persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
00428 }
00429 }
00430 #endif
00431
00432 #endif // NAN_WEAK_H_