Initial commit
[yaffs-website] / node_modules / nan / nan.h
1 /*********************************************************************
2  * NAN - Native Abstractions for Node.js
3  *
4  * Copyright (c) 2017 NAN contributors:
5  *   - Rod Vagg <https://github.com/rvagg>
6  *   - Benjamin Byholm <https://github.com/kkoopa>
7  *   - Trevor Norris <https://github.com/trevnorris>
8  *   - Nathan Rajlich <https://github.com/TooTallNate>
9  *   - Brett Lawson <https://github.com/brett19>
10  *   - Ben Noordhuis <https://github.com/bnoordhuis>
11  *   - David Siegel <https://github.com/agnat>
12  *
13  * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
14  *
15  * Version 2.5.1: current Node 7.4.0, Node 12: 0.12.18, Node 10: 0.10.48, iojs: 3.3.1
16  *
17  * See https://github.com/nodejs/nan for the latest update to this file
18  **********************************************************************************/
19
20 #ifndef NAN_H_
21 #define NAN_H_
22
23 #include <node_version.h>
24
25 #define NODE_0_10_MODULE_VERSION 11
26 #define NODE_0_12_MODULE_VERSION 14
27 #define ATOM_0_21_MODULE_VERSION 41
28 #define IOJS_1_0_MODULE_VERSION  42
29 #define IOJS_1_1_MODULE_VERSION  43
30 #define IOJS_2_0_MODULE_VERSION  44
31 #define IOJS_3_0_MODULE_VERSION  45
32 #define NODE_4_0_MODULE_VERSION  46
33 #define NODE_5_0_MODULE_VERSION  47
34 #define NODE_6_0_MODULE_VERSION  48
35
36 #ifdef _MSC_VER
37 # define NAN_HAS_CPLUSPLUS_11 (_MSC_VER >= 1800)
38 #else
39 # define NAN_HAS_CPLUSPLUS_11 (__cplusplus >= 201103L)
40 #endif
41
42 #if NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION && !NAN_HAS_CPLUSPLUS_11
43 # error This version of node/NAN/v8 requires a C++11 compiler
44 #endif
45
46 #include <uv.h>
47 #include <node.h>
48 #include <node_buffer.h>
49 #include <node_object_wrap.h>
50 #include <algorithm>
51 #include <cstring>
52 #include <climits>
53 #include <cstdlib>
54 #if defined(_MSC_VER)
55 # pragma warning( push )
56 # pragma warning( disable : 4530 )
57 # include <string>
58 # include <vector>
59 # pragma warning( pop )
60 #else
61 # include <string>
62 # include <vector>
63 #endif
64
65 // uv helpers
66 #ifdef UV_VERSION_MAJOR
67 # ifndef UV_VERSION_PATCH
68 #  define UV_VERSION_PATCH 0
69 # endif
70 # define NAUV_UVVERSION ((UV_VERSION_MAJOR << 16) | \
71                          (UV_VERSION_MINOR <<  8) | \
72                          (UV_VERSION_PATCH))
73 #else
74 # define NAUV_UVVERSION 0x000b00
75 #endif
76
77 #if NAUV_UVVERSION < 0x000b0b
78 # ifdef WIN32
79 #  include <windows.h>
80 # else
81 #  include <pthread.h>
82 # endif
83 #endif
84
85 namespace Nan {
86
87 #define NAN_INLINE inline  // TODO(bnoordhuis) Remove in v3.0.0.
88
89 #if defined(__GNUC__) && \
90     !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
91 # define NAN_DEPRECATED __attribute__((deprecated))
92 #elif defined(_MSC_VER) && \
93     !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
94 # define NAN_DEPRECATED __declspec(deprecated)
95 #else
96 # define NAN_DEPRECATED
97 #endif
98
99 #if NAN_HAS_CPLUSPLUS_11
100 # define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&) = delete;
101 # define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&) = delete;
102 # define NAN_DISALLOW_MOVE(CLASS)                                              \
103     CLASS(CLASS&&) = delete;  /* NOLINT(build/c++11) */                        \
104     void operator=(CLASS&&) = delete;
105 #else
106 # define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&);
107 # define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&);
108 # define NAN_DISALLOW_MOVE(CLASS)
109 #endif
110
111 #define NAN_DISALLOW_ASSIGN_COPY(CLASS)                                        \
112     NAN_DISALLOW_ASSIGN(CLASS)                                                 \
113     NAN_DISALLOW_COPY(CLASS)
114
115 #define NAN_DISALLOW_ASSIGN_MOVE(CLASS)                                        \
116     NAN_DISALLOW_ASSIGN(CLASS)                                                 \
117     NAN_DISALLOW_MOVE(CLASS)
118
119 #define NAN_DISALLOW_COPY_MOVE(CLASS)                                          \
120     NAN_DISALLOW_COPY(CLASS)                                                   \
121     NAN_DISALLOW_MOVE(CLASS)
122
123 #define NAN_DISALLOW_ASSIGN_COPY_MOVE(CLASS)                                   \
124     NAN_DISALLOW_ASSIGN(CLASS)                                                 \
125     NAN_DISALLOW_COPY(CLASS)                                                   \
126     NAN_DISALLOW_MOVE(CLASS)
127
128 #define TYPE_CHECK(T, S)                                                       \
129     while (false) {                                                            \
130       *(static_cast<T *volatile *>(0)) = static_cast<S*>(0);                   \
131     }
132
133 //=== RegistrationFunction =====================================================
134
135 #if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
136   typedef v8::Handle<v8::Object> ADDON_REGISTER_FUNCTION_ARGS_TYPE;
137 #else
138   typedef v8::Local<v8::Object> ADDON_REGISTER_FUNCTION_ARGS_TYPE;
139 #endif
140
141 #define NAN_MODULE_INIT(name)                                                  \
142     void name(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target)
143
144 //=== CallbackInfo =============================================================
145
146 #include "nan_callbacks.h"  // NOLINT(build/include)
147
148 //==============================================================================
149
150 #if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION)
151 typedef v8::Script             UnboundScript;
152 typedef v8::Script             BoundScript;
153 #else
154 typedef v8::UnboundScript      UnboundScript;
155 typedef v8::Script             BoundScript;
156 #endif
157
158 #if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION)
159 typedef v8::String::ExternalAsciiStringResource
160     ExternalOneByteStringResource;
161 #else
162 typedef v8::String::ExternalOneByteStringResource
163     ExternalOneByteStringResource;
164 #endif
165
166 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
167 template<typename T>
168 class NonCopyablePersistentTraits :
169     public v8::NonCopyablePersistentTraits<T> {};
170 template<typename T>
171 class CopyablePersistentTraits :
172     public v8::CopyablePersistentTraits<T> {};
173
174 template<typename T>
175 class PersistentBase :
176     public v8::PersistentBase<T> {};
177
178 template<typename T, typename M = v8::NonCopyablePersistentTraits<T> >
179 class Persistent;
180 #else
181 template<typename T> class NonCopyablePersistentTraits;
182 template<typename T> class PersistentBase;
183 template<typename T, typename P> class WeakCallbackData;
184 template<typename T, typename M = NonCopyablePersistentTraits<T> >
185 class Persistent;
186 #endif  // NODE_MODULE_VERSION
187
188 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
189   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
190 # include "nan_maybe_43_inl.h"  // NOLINT(build/include)
191 #else
192 # include "nan_maybe_pre_43_inl.h"  // NOLINT(build/include)
193 #endif
194
195 #include "nan_converters.h"  // NOLINT(build/include)
196 #include "nan_new.h"  // NOLINT(build/include)
197
198 #if NAUV_UVVERSION < 0x000b17
199 #define NAUV_WORK_CB(func) \
200     void func(uv_async_t *async, int)
201 #else
202 #define NAUV_WORK_CB(func) \
203     void func(uv_async_t *async)
204 #endif
205
206 #if NAUV_UVVERSION >= 0x000b0b
207
208 typedef uv_key_t nauv_key_t;
209
210 inline int nauv_key_create(nauv_key_t *key) {
211   return uv_key_create(key);
212 }
213
214 inline void nauv_key_delete(nauv_key_t *key) {
215   uv_key_delete(key);
216 }
217
218 inline void* nauv_key_get(nauv_key_t *key) {
219   return uv_key_get(key);
220 }
221
222 inline void nauv_key_set(nauv_key_t *key, void *value) {
223   uv_key_set(key, value);
224 }
225
226 #else
227
228 /* Implement thread local storage for older versions of libuv.
229  * This is essentially a backport of libuv commit 5d2434bf
230  * written by Ben Noordhuis, adjusted for names and inline.
231  */
232
233 #ifndef WIN32
234
235 typedef pthread_key_t nauv_key_t;
236
237 inline int nauv_key_create(nauv_key_t* key) {
238   return -pthread_key_create(key, NULL);
239 }
240
241 inline void nauv_key_delete(nauv_key_t* key) {
242   if (pthread_key_delete(*key))
243     abort();
244 }
245
246 inline void* nauv_key_get(nauv_key_t* key) {
247   return pthread_getspecific(*key);
248 }
249
250 inline void nauv_key_set(nauv_key_t* key, void* value) {
251   if (pthread_setspecific(*key, value))
252     abort();
253 }
254
255 #else
256
257 typedef struct {
258   DWORD tls_index;
259 } nauv_key_t;
260
261 inline int nauv_key_create(nauv_key_t* key) {
262   key->tls_index = TlsAlloc();
263   if (key->tls_index == TLS_OUT_OF_INDEXES)
264     return UV_ENOMEM;
265   return 0;
266 }
267
268 inline void nauv_key_delete(nauv_key_t* key) {
269   if (TlsFree(key->tls_index) == FALSE)
270     abort();
271   key->tls_index = TLS_OUT_OF_INDEXES;
272 }
273
274 inline void* nauv_key_get(nauv_key_t* key) {
275   void* value = TlsGetValue(key->tls_index);
276   if (value == NULL)
277     if (GetLastError() != ERROR_SUCCESS)
278       abort();
279   return value;
280 }
281
282 inline void nauv_key_set(nauv_key_t* key, void* value) {
283   if (TlsSetValue(key->tls_index, value) == FALSE)
284     abort();
285 }
286
287 #endif
288 #endif
289
290 #if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
291 template<typename T>
292 v8::Local<T> New(v8::Handle<T>);
293 #endif
294
295 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
296   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
297   typedef v8::WeakCallbackType WeakCallbackType;
298 #else
299 struct WeakCallbackType {
300   enum E {kParameter, kInternalFields};
301   E type;
302   WeakCallbackType(E other) : type(other) {}  // NOLINT(runtime/explicit)
303   inline bool operator==(E other) { return other == this->type; }
304   inline bool operator!=(E other) { return !operator==(other); }
305 };
306 #endif
307
308 template<typename P> class WeakCallbackInfo;
309
310 #if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
311 # include "nan_persistent_12_inl.h"  // NOLINT(build/include)
312 #else
313 # include "nan_persistent_pre_12_inl.h"  // NOLINT(build/include)
314 #endif
315
316 namespace imp {
317   static const size_t kMaxLength = 0x3fffffff;
318   // v8::String::REPLACE_INVALID_UTF8 was introduced
319   // in node.js v0.10.29 and v0.8.27.
320 #if NODE_MAJOR_VERSION > 0 || \
321     NODE_MINOR_VERSION > 10 || \
322     NODE_MINOR_VERSION == 10 && NODE_PATCH_VERSION >= 29 || \
323     NODE_MINOR_VERSION == 8 && NODE_PATCH_VERSION >= 27
324   static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8;
325 #else
326   static const unsigned kReplaceInvalidUtf8 = 0;
327 #endif
328 }  // end of namespace imp
329
330 //=== HandleScope ==============================================================
331
332 class HandleScope {
333   v8::HandleScope scope;
334
335  public:
336 #if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
337   inline HandleScope() : scope(v8::Isolate::GetCurrent()) {}
338   inline static int NumberOfHandles() {
339     return v8::HandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
340   }
341 #else
342   inline HandleScope() : scope() {}
343   inline static int NumberOfHandles() {
344     return v8::HandleScope::NumberOfHandles();
345   }
346 #endif
347
348  private:
349   // Make it hard to create heap-allocated or illegal handle scopes by
350   // disallowing certain operations.
351   HandleScope(const HandleScope &);
352   void operator=(const HandleScope &);
353   void *operator new(size_t size);
354   void operator delete(void *, size_t) {
355     abort();
356   }
357 };
358
359 class EscapableHandleScope {
360  public:
361 #if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
362   inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {}
363
364   inline static int NumberOfHandles() {
365     return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
366   }
367
368   template<typename T>
369   inline v8::Local<T> Escape(v8::Local<T> value) {
370     return scope.Escape(value);
371   }
372
373  private:
374   v8::EscapableHandleScope scope;
375 #else
376   inline EscapableHandleScope() : scope() {}
377
378   inline static int NumberOfHandles() {
379     return v8::HandleScope::NumberOfHandles();
380   }
381
382   template<typename T>
383   inline v8::Local<T> Escape(v8::Local<T> value) {
384     return scope.Close(value);
385   }
386
387  private:
388   v8::HandleScope scope;
389 #endif
390
391  private:
392   // Make it hard to create heap-allocated or illegal handle scopes by
393   // disallowing certain operations.
394   EscapableHandleScope(const EscapableHandleScope &);
395   void operator=(const EscapableHandleScope &);
396   void *operator new(size_t size);
397   void operator delete(void *, size_t) {
398     abort();
399   }
400 };
401
402 //=== TryCatch =================================================================
403
404 class TryCatch {
405   v8::TryCatch try_catch_;
406   friend void FatalException(const TryCatch&);
407
408  public:
409 #if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
410   TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {}
411 #endif
412
413   inline bool HasCaught() const { return try_catch_.HasCaught(); }
414
415   inline bool CanContinue() const { return try_catch_.CanContinue(); }
416
417   inline v8::Local<v8::Value> ReThrow() {
418 #if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
419     return New(try_catch_.ReThrow());
420 #else
421     return try_catch_.ReThrow();
422 #endif
423   }
424
425   inline v8::Local<v8::Value> Exception() const {
426     return try_catch_.Exception();
427   }
428
429 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
430   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
431   inline v8::MaybeLocal<v8::Value> StackTrace() const {
432     v8::Isolate *isolate = v8::Isolate::GetCurrent();
433     v8::EscapableHandleScope scope(isolate);
434     return scope.Escape(try_catch_.StackTrace(isolate->GetCurrentContext())
435                             .FromMaybe(v8::Local<v8::Value>()));
436   }
437 #else
438   inline MaybeLocal<v8::Value> StackTrace() const {
439     return try_catch_.StackTrace();
440   }
441 #endif
442
443   inline v8::Local<v8::Message> Message() const {
444     return try_catch_.Message();
445   }
446
447   inline void Reset() { try_catch_.Reset(); }
448
449   inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); }
450
451   inline void SetCaptureMessage(bool value) {
452     try_catch_.SetCaptureMessage(value);
453   }
454 };
455
456 //============ =================================================================
457
458 /* node 0.12  */
459 #if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
460   inline
461   void SetCounterFunction(v8::CounterLookupCallback cb) {
462     v8::Isolate::GetCurrent()->SetCounterFunction(cb);
463   }
464
465   inline
466   void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
467     v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
468   }
469
470   inline
471   void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
472     v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
473   }
474
475 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
476   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
477   inline bool IdleNotification(int idle_time_in_ms) {
478     return v8::Isolate::GetCurrent()->IdleNotificationDeadline(
479         idle_time_in_ms * 0.001);
480   }
481 # else
482   inline bool IdleNotification(int idle_time_in_ms) {
483     return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
484   }
485 #endif
486
487   inline void LowMemoryNotification() {
488     v8::Isolate::GetCurrent()->LowMemoryNotification();
489   }
490
491   inline void ContextDisposedNotification() {
492     v8::Isolate::GetCurrent()->ContextDisposedNotification();
493   }
494 #else
495   inline
496   void SetCounterFunction(v8::CounterLookupCallback cb) {
497     v8::V8::SetCounterFunction(cb);
498   }
499
500   inline
501   void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
502     v8::V8::SetCreateHistogramFunction(cb);
503   }
504
505   inline
506   void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
507     v8::V8::SetAddHistogramSampleFunction(cb);
508   }
509
510   inline bool IdleNotification(int idle_time_in_ms) {
511     return v8::V8::IdleNotification(idle_time_in_ms);
512   }
513
514   inline void LowMemoryNotification() {
515     v8::V8::LowMemoryNotification();
516   }
517
518   inline void ContextDisposedNotification() {
519     v8::V8::ContextDisposedNotification();
520   }
521 #endif
522
523 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)  // Node 0.12
524   inline v8::Local<v8::Primitive> Undefined() {
525 # if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
526     EscapableHandleScope scope;
527     return scope.Escape(New(v8::Undefined(v8::Isolate::GetCurrent())));
528 # else
529     return v8::Undefined(v8::Isolate::GetCurrent());
530 # endif
531   }
532
533   inline v8::Local<v8::Primitive> Null() {
534 # if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
535     EscapableHandleScope scope;
536     return scope.Escape(New(v8::Null(v8::Isolate::GetCurrent())));
537 # else
538     return v8::Null(v8::Isolate::GetCurrent());
539 # endif
540   }
541
542   inline v8::Local<v8::Boolean> True() {
543 # if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
544     EscapableHandleScope scope;
545     return scope.Escape(New(v8::True(v8::Isolate::GetCurrent())));
546 # else
547     return v8::True(v8::Isolate::GetCurrent());
548 # endif
549   }
550
551   inline v8::Local<v8::Boolean> False() {
552 # if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
553     EscapableHandleScope scope;
554     return scope.Escape(New(v8::False(v8::Isolate::GetCurrent())));
555 # else
556     return v8::False(v8::Isolate::GetCurrent());
557 # endif
558   }
559
560   inline v8::Local<v8::String> EmptyString() {
561     return v8::String::Empty(v8::Isolate::GetCurrent());
562   }
563
564   inline int AdjustExternalMemory(int bc) {
565     return static_cast<int>(
566         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
567   }
568
569   inline void SetTemplate(
570       v8::Local<v8::Template> templ
571     , const char *name
572     , v8::Local<v8::Data> value) {
573     templ->Set(v8::Isolate::GetCurrent(), name, value);
574   }
575
576   inline void SetTemplate(
577       v8::Local<v8::Template> templ
578     , v8::Local<v8::String> name
579     , v8::Local<v8::Data> value
580     , v8::PropertyAttribute attributes) {
581     templ->Set(name, value, attributes);
582   }
583
584   inline v8::Local<v8::Context> GetCurrentContext() {
585     return v8::Isolate::GetCurrent()->GetCurrentContext();
586   }
587
588   inline void* GetInternalFieldPointer(
589       v8::Local<v8::Object> object
590     , int index) {
591     return object->GetAlignedPointerFromInternalField(index);
592   }
593
594   inline void SetInternalFieldPointer(
595       v8::Local<v8::Object> object
596     , int index
597     , void* value) {
598     object->SetAlignedPointerInInternalField(index, value);
599   }
600
601 # define NAN_GC_CALLBACK(name)                                                 \
602     void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
603
604 #if NODE_MODULE_VERSION <= NODE_4_0_MODULE_VERSION
605   typedef v8::Isolate::GCEpilogueCallback GCEpilogueCallback;
606   typedef v8::Isolate::GCPrologueCallback GCPrologueCallback;
607 #else
608   typedef v8::Isolate::GCCallback GCEpilogueCallback;
609   typedef v8::Isolate::GCCallback GCPrologueCallback;
610 #endif
611
612   inline void AddGCEpilogueCallback(
613       GCEpilogueCallback callback
614     , v8::GCType gc_type_filter = v8::kGCTypeAll) {
615     v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter);
616   }
617
618   inline void RemoveGCEpilogueCallback(
619       GCEpilogueCallback callback) {
620     v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback);
621   }
622
623   inline void AddGCPrologueCallback(
624       GCPrologueCallback callback
625     , v8::GCType gc_type_filter = v8::kGCTypeAll) {
626     v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter);
627   }
628
629   inline void RemoveGCPrologueCallback(
630       GCPrologueCallback callback) {
631     v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
632   }
633
634   inline void GetHeapStatistics(
635       v8::HeapStatistics *heap_statistics) {
636     v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
637   }
638
639 # define X(NAME)                                                               \
640     inline v8::Local<v8::Value> NAME(const char *msg) {                        \
641       EscapableHandleScope scope;                                              \
642       return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked()));     \
643     }                                                                          \
644                                                                                \
645     inline                                                                     \
646     v8::Local<v8::Value> NAME(v8::Local<v8::String> msg) {                     \
647       return v8::Exception::NAME(msg);                                         \
648     }                                                                          \
649                                                                                \
650     inline void Throw ## NAME(const char *msg) {                               \
651       HandleScope scope;                                                       \
652       v8::Isolate::GetCurrent()->ThrowException(                               \
653           v8::Exception::NAME(New(msg).ToLocalChecked()));                     \
654     }                                                                          \
655                                                                                \
656     inline void Throw ## NAME(v8::Local<v8::String> msg) {                     \
657       HandleScope scope;                                                       \
658       v8::Isolate::GetCurrent()->ThrowException(                               \
659           v8::Exception::NAME(msg));                                           \
660     }
661
662   X(Error)
663   X(RangeError)
664   X(ReferenceError)
665   X(SyntaxError)
666   X(TypeError)
667
668 # undef X
669
670   inline void ThrowError(v8::Local<v8::Value> error) {
671     v8::Isolate::GetCurrent()->ThrowException(error);
672   }
673
674   inline MaybeLocal<v8::Object> NewBuffer(
675       char *data
676     , size_t length
677 #if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
678     , node::Buffer::FreeCallback callback
679 #else
680     , node::smalloc::FreeCallback callback
681 #endif
682     , void *hint
683   ) {
684     // arbitrary buffer lengths requires
685     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
686     assert(length <= imp::kMaxLength && "too large buffer");
687 #if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
688     return node::Buffer::New(
689         v8::Isolate::GetCurrent(), data, length, callback, hint);
690 #else
691     return node::Buffer::New(v8::Isolate::GetCurrent(), data, length, callback,
692                              hint);
693 #endif
694   }
695
696   inline MaybeLocal<v8::Object> CopyBuffer(
697       const char *data
698     , uint32_t size
699   ) {
700     // arbitrary buffer lengths requires
701     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
702     assert(size <= imp::kMaxLength && "too large buffer");
703 #if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
704     return node::Buffer::Copy(
705         v8::Isolate::GetCurrent(), data, size);
706 #else
707     return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
708 #endif
709   }
710
711   inline MaybeLocal<v8::Object> NewBuffer(uint32_t size) {
712     // arbitrary buffer lengths requires
713     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
714     assert(size <= imp::kMaxLength && "too large buffer");
715 #if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
716     return node::Buffer::New(
717         v8::Isolate::GetCurrent(), size);
718 #else
719     return node::Buffer::New(v8::Isolate::GetCurrent(), size);
720 #endif
721   }
722
723   inline MaybeLocal<v8::Object> NewBuffer(
724       char* data
725     , uint32_t size
726   ) {
727     // arbitrary buffer lengths requires
728     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
729     assert(size <= imp::kMaxLength && "too large buffer");
730 #if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
731     return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
732 #else
733     return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
734 #endif
735   }
736
737 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
738   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
739   inline MaybeLocal<v8::String>
740   NewOneByteString(const uint8_t * value, int length = -1) {
741     return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
742           v8::NewStringType::kNormal, length);
743   }
744
745   inline MaybeLocal<BoundScript> CompileScript(
746       v8::Local<v8::String> s
747     , const v8::ScriptOrigin& origin
748   ) {
749     v8::Isolate *isolate = v8::Isolate::GetCurrent();
750     v8::EscapableHandleScope scope(isolate);
751     v8::ScriptCompiler::Source source(s, origin);
752     return scope.Escape(
753         v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source)
754             .FromMaybe(v8::Local<BoundScript>()));
755   }
756
757   inline MaybeLocal<BoundScript> CompileScript(
758       v8::Local<v8::String> s
759   ) {
760     v8::Isolate *isolate = v8::Isolate::GetCurrent();
761     v8::EscapableHandleScope scope(isolate);
762     v8::ScriptCompiler::Source source(s);
763     return scope.Escape(
764         v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source)
765             .FromMaybe(v8::Local<BoundScript>()));
766   }
767
768   inline MaybeLocal<v8::Value> RunScript(
769       v8::Local<UnboundScript> script
770   ) {
771     v8::Isolate *isolate = v8::Isolate::GetCurrent();
772     v8::EscapableHandleScope scope(isolate);
773     return scope.Escape(script->BindToCurrentContext()
774                             ->Run(isolate->GetCurrentContext())
775                             .FromMaybe(v8::Local<v8::Value>()));
776   }
777
778   inline MaybeLocal<v8::Value> RunScript(
779       v8::Local<BoundScript> script
780   ) {
781     v8::Isolate *isolate = v8::Isolate::GetCurrent();
782     v8::EscapableHandleScope scope(isolate);
783     return scope.Escape(script->Run(isolate->GetCurrentContext())
784                             .FromMaybe(v8::Local<v8::Value>()));
785   }
786 #else
787   inline MaybeLocal<v8::String>
788   NewOneByteString(const uint8_t * value, int length = -1) {
789     return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
790                                       v8::String::kNormalString, length);
791   }
792
793   inline MaybeLocal<BoundScript> CompileScript(
794       v8::Local<v8::String> s
795     , const v8::ScriptOrigin& origin
796   ) {
797     v8::ScriptCompiler::Source source(s, origin);
798     return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
799   }
800
801   inline MaybeLocal<BoundScript> CompileScript(
802       v8::Local<v8::String> s
803   ) {
804     v8::ScriptCompiler::Source source(s);
805     return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
806   }
807
808   inline MaybeLocal<v8::Value> RunScript(
809       v8::Local<UnboundScript> script
810   ) {
811     EscapableHandleScope scope;
812     return scope.Escape(script->BindToCurrentContext()->Run());
813   }
814
815   inline MaybeLocal<v8::Value> RunScript(
816       v8::Local<BoundScript> script
817   ) {
818     return script->Run();
819   }
820 #endif
821
822   inline v8::Local<v8::Value> MakeCallback(
823       v8::Local<v8::Object> target
824     , v8::Local<v8::Function> func
825     , int argc
826     , v8::Local<v8::Value>* argv) {
827 #if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
828     EscapableHandleScope scope;
829     return scope.Escape(New(node::MakeCallback(
830         v8::Isolate::GetCurrent(), target, func, argc, argv)));
831 #else
832     return node::MakeCallback(
833         v8::Isolate::GetCurrent(), target, func, argc, argv);
834 #endif
835   }
836
837   inline v8::Local<v8::Value> MakeCallback(
838       v8::Local<v8::Object> target
839     , v8::Local<v8::String> symbol
840     , int argc
841     , v8::Local<v8::Value>* argv) {
842 #if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
843     EscapableHandleScope scope;
844     return scope.Escape(New(node::MakeCallback(
845         v8::Isolate::GetCurrent(), target, symbol, argc, argv)));
846 #else
847     return node::MakeCallback(
848         v8::Isolate::GetCurrent(), target, symbol, argc, argv);
849 #endif
850   }
851
852   inline v8::Local<v8::Value> MakeCallback(
853       v8::Local<v8::Object> target
854     , const char* method
855     , int argc
856     , v8::Local<v8::Value>* argv) {
857 #if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
858     EscapableHandleScope scope;
859     return scope.Escape(New(node::MakeCallback(
860         v8::Isolate::GetCurrent(), target, method, argc, argv)));
861 #else
862     return node::MakeCallback(
863         v8::Isolate::GetCurrent(), target, method, argc, argv);
864 #endif
865   }
866
867   inline void FatalException(const TryCatch& try_catch) {
868     node::FatalException(v8::Isolate::GetCurrent(), try_catch.try_catch_);
869   }
870
871   inline v8::Local<v8::Value> ErrnoException(
872           int errorno
873        ,  const char* syscall = NULL
874        ,  const char* message = NULL
875        ,  const char* path = NULL) {
876     return node::ErrnoException(v8::Isolate::GetCurrent(), errorno, syscall,
877             message, path);
878   }
879
880   NAN_DEPRECATED inline v8::Local<v8::Value> NanErrnoException(
881           int errorno
882        ,  const char* syscall = NULL
883        ,  const char* message = NULL
884        ,  const char* path = NULL) {
885     return ErrnoException(errorno, syscall, message, path);
886   }
887
888   template<typename T>
889   inline void SetIsolateData(
890       v8::Isolate *isolate
891     , T *data
892   ) {
893       isolate->SetData(0, data);
894   }
895
896   template<typename T>
897   inline T *GetIsolateData(
898       v8::Isolate *isolate
899   ) {
900       return static_cast<T*>(isolate->GetData(0));
901   }
902
903 class Utf8String {
904  public:
905   inline explicit Utf8String(v8::Local<v8::Value> from) :
906       length_(0), str_(str_st_) {
907     HandleScope scope;
908     if (!from.IsEmpty()) {
909       v8::Local<v8::String> string = from->ToString();
910       if (!string.IsEmpty()) {
911         size_t len = 3 * string->Length() + 1;
912         assert(len <= INT_MAX);
913         if (len > sizeof (str_st_)) {
914           str_ = static_cast<char*>(malloc(len));
915           assert(str_ != 0);
916         }
917         const int flags =
918             v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
919         length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
920         str_[length_] = '\0';
921       }
922     }
923   }
924
925   inline int length() const {
926     return length_;
927   }
928
929   inline char* operator*() { return str_; }
930   inline const char* operator*() const { return str_; }
931
932   inline ~Utf8String() {
933     if (str_ != str_st_) {
934       free(str_);
935     }
936   }
937
938  private:
939   NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String)
940
941   int length_;
942   char *str_;
943   char str_st_[1024];
944 };
945
946 #else  // Node 0.8 and 0.10
947   inline v8::Local<v8::Primitive> Undefined() {
948     EscapableHandleScope scope;
949     return scope.Escape(New(v8::Undefined()));
950   }
951
952   inline v8::Local<v8::Primitive> Null() {
953     EscapableHandleScope scope;
954     return scope.Escape(New(v8::Null()));
955   }
956
957   inline v8::Local<v8::Boolean> True() {
958     EscapableHandleScope scope;
959     return scope.Escape(New(v8::True()));
960   }
961
962   inline v8::Local<v8::Boolean> False() {
963     EscapableHandleScope scope;
964     return scope.Escape(New(v8::False()));
965   }
966
967   inline v8::Local<v8::String> EmptyString() {
968     return v8::String::Empty();
969   }
970
971   inline int AdjustExternalMemory(int bc) {
972     return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
973   }
974
975   inline void SetTemplate(
976       v8::Local<v8::Template> templ
977     , const char *name
978     , v8::Local<v8::Data> value) {
979     templ->Set(name, value);
980   }
981
982   inline void SetTemplate(
983       v8::Local<v8::Template> templ
984     , v8::Local<v8::String> name
985     , v8::Local<v8::Data> value
986     , v8::PropertyAttribute attributes) {
987     templ->Set(name, value, attributes);
988   }
989
990   inline v8::Local<v8::Context> GetCurrentContext() {
991     return v8::Context::GetCurrent();
992   }
993
994   inline void* GetInternalFieldPointer(
995       v8::Local<v8::Object> object
996     , int index) {
997     return object->GetPointerFromInternalField(index);
998   }
999
1000   inline void SetInternalFieldPointer(
1001       v8::Local<v8::Object> object
1002     , int index
1003     , void* value) {
1004     object->SetPointerInInternalField(index, value);
1005   }
1006
1007 # define NAN_GC_CALLBACK(name)                                                 \
1008     void name(v8::GCType type, v8::GCCallbackFlags flags)
1009
1010   inline void AddGCEpilogueCallback(
1011     v8::GCEpilogueCallback callback
1012   , v8::GCType gc_type_filter = v8::kGCTypeAll) {
1013     v8::V8::AddGCEpilogueCallback(callback, gc_type_filter);
1014   }
1015   inline void RemoveGCEpilogueCallback(
1016     v8::GCEpilogueCallback callback) {
1017     v8::V8::RemoveGCEpilogueCallback(callback);
1018   }
1019   inline void AddGCPrologueCallback(
1020     v8::GCPrologueCallback callback
1021   , v8::GCType gc_type_filter = v8::kGCTypeAll) {
1022     v8::V8::AddGCPrologueCallback(callback, gc_type_filter);
1023   }
1024   inline void RemoveGCPrologueCallback(
1025     v8::GCPrologueCallback callback) {
1026     v8::V8::RemoveGCPrologueCallback(callback);
1027   }
1028   inline void GetHeapStatistics(
1029     v8::HeapStatistics *heap_statistics) {
1030     v8::V8::GetHeapStatistics(heap_statistics);
1031   }
1032
1033 # define X(NAME)                                                               \
1034     inline v8::Local<v8::Value> NAME(const char *msg) {                        \
1035       EscapableHandleScope scope;                                              \
1036       return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked()));     \
1037     }                                                                          \
1038                                                                                \
1039     inline                                                                     \
1040     v8::Local<v8::Value> NAME(v8::Local<v8::String> msg) {                     \
1041       return v8::Exception::NAME(msg);                                         \
1042     }                                                                          \
1043                                                                                \
1044     inline void Throw ## NAME(const char *msg) {                               \
1045       HandleScope scope;                                                       \
1046       v8::ThrowException(v8::Exception::NAME(New(msg).ToLocalChecked()));      \
1047     }                                                                          \
1048                                                                                \
1049     inline                                                                     \
1050     void Throw ## NAME(v8::Local<v8::String> errmsg) {                         \
1051       HandleScope scope;                                                       \
1052       v8::ThrowException(v8::Exception::NAME(errmsg));                         \
1053     }
1054
1055   X(Error)
1056   X(RangeError)
1057   X(ReferenceError)
1058   X(SyntaxError)
1059   X(TypeError)
1060
1061 # undef X
1062
1063   inline void ThrowError(v8::Local<v8::Value> error) {
1064     v8::ThrowException(error);
1065   }
1066
1067   inline MaybeLocal<v8::Object> NewBuffer(
1068       char *data
1069     , size_t length
1070     , node::Buffer::free_callback callback
1071     , void *hint
1072   ) {
1073     EscapableHandleScope scope;
1074     // arbitrary buffer lengths requires
1075     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1076     assert(length <= imp::kMaxLength && "too large buffer");
1077     return scope.Escape(
1078         New(node::Buffer::New(data, length, callback, hint)->handle_));
1079   }
1080
1081   inline MaybeLocal<v8::Object> CopyBuffer(
1082       const char *data
1083     , uint32_t size
1084   ) {
1085     EscapableHandleScope scope;
1086     // arbitrary buffer lengths requires
1087     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1088     assert(size <= imp::kMaxLength && "too large buffer");
1089 #if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
1090     return scope.Escape(New(node::Buffer::New(data, size)->handle_));
1091 #else
1092     return scope.Escape(
1093         New(node::Buffer::New(const_cast<char *>(data), size)->handle_));
1094 #endif
1095   }
1096
1097   inline MaybeLocal<v8::Object> NewBuffer(uint32_t size) {
1098     // arbitrary buffer lengths requires
1099     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1100     EscapableHandleScope scope;
1101     assert(size <= imp::kMaxLength && "too large buffer");
1102     return scope.Escape(New(node::Buffer::New(size)->handle_));
1103   }
1104
1105   inline void FreeData(char *data, void *hint) {
1106     (void) hint;  // unused
1107     delete[] data;
1108   }
1109
1110   inline MaybeLocal<v8::Object> NewBuffer(
1111       char* data
1112     , uint32_t size
1113   ) {
1114     EscapableHandleScope scope;
1115     // arbitrary buffer lengths requires
1116     // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1117     assert(size <= imp::kMaxLength && "too large buffer");
1118     return scope.Escape(
1119         New(node::Buffer::New(data, size, FreeData, NULL)->handle_));
1120   }
1121
1122 namespace imp {
1123 inline void
1124 widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l) {
1125   size_t len = static_cast<size_t>(l);
1126   if (l < 0) {
1127     len = strlen(reinterpret_cast<const char*>(s));
1128   }
1129   assert(len <= INT_MAX && "string too long");
1130   ws->resize(len);
1131   std::copy(s, s + len, ws->begin());  // NOLINT(build/include_what_you_use)
1132 }
1133 }  // end of namespace imp
1134
1135   inline MaybeLocal<v8::String>
1136   NewOneByteString(const uint8_t * value, int length = -1) {
1137     std::vector<uint16_t> wideString;  // NOLINT(build/include_what_you_use)
1138     imp::widenString(&wideString, value, length);
1139     return v8::String::New(wideString.data(),
1140                            static_cast<int>(wideString.size()));
1141   }
1142
1143   inline MaybeLocal<BoundScript> CompileScript(
1144       v8::Local<v8::String> s
1145     , const v8::ScriptOrigin& origin
1146   ) {
1147     return v8::Script::Compile(s, const_cast<v8::ScriptOrigin *>(&origin));
1148   }
1149
1150   inline MaybeLocal<BoundScript> CompileScript(
1151     v8::Local<v8::String> s
1152   ) {
1153     return v8::Script::Compile(s);
1154   }
1155
1156   inline
1157   MaybeLocal<v8::Value> RunScript(v8::Local<v8::Script> script) {
1158     return script->Run();
1159   }
1160
1161   inline v8::Local<v8::Value> MakeCallback(
1162       v8::Local<v8::Object> target
1163     , v8::Local<v8::Function> func
1164     , int argc
1165     , v8::Local<v8::Value>* argv) {
1166     v8::HandleScope scope;
1167     return scope.Close(New(node::MakeCallback(target, func, argc, argv)));
1168   }
1169
1170   inline v8::Local<v8::Value> MakeCallback(
1171       v8::Local<v8::Object> target
1172     , v8::Local<v8::String> symbol
1173     , int argc
1174     , v8::Local<v8::Value>* argv) {
1175     v8::HandleScope scope;
1176     return scope.Close(New(node::MakeCallback(target, symbol, argc, argv)));
1177   }
1178
1179   inline v8::Local<v8::Value> MakeCallback(
1180       v8::Local<v8::Object> target
1181     , const char* method
1182     , int argc
1183     , v8::Local<v8::Value>* argv) {
1184     v8::HandleScope scope;
1185     return scope.Close(New(node::MakeCallback(target, method, argc, argv)));
1186   }
1187
1188   inline void FatalException(const TryCatch& try_catch) {
1189     node::FatalException(const_cast<v8::TryCatch &>(try_catch.try_catch_));
1190   }
1191
1192   inline v8::Local<v8::Value> ErrnoException(
1193           int errorno
1194        ,  const char* syscall = NULL
1195        ,  const char* message = NULL
1196        ,  const char* path = NULL) {
1197     return node::ErrnoException(errorno, syscall, message, path);
1198   }
1199
1200   NAN_DEPRECATED inline v8::Local<v8::Value> NanErrnoException(
1201           int errorno
1202        ,  const char* syscall = NULL
1203        ,  const char* message = NULL
1204        ,  const char* path = NULL) {
1205     return ErrnoException(errorno, syscall, message, path);
1206   }
1207
1208
1209   template<typename T>
1210   inline void SetIsolateData(
1211       v8::Isolate *isolate
1212     , T *data
1213   ) {
1214       isolate->SetData(data);
1215   }
1216
1217   template<typename T>
1218   inline T *GetIsolateData(
1219       v8::Isolate *isolate
1220   ) {
1221       return static_cast<T*>(isolate->GetData());
1222   }
1223
1224 class Utf8String {
1225  public:
1226   inline explicit Utf8String(v8::Local<v8::Value> from) :
1227       length_(0), str_(str_st_) {
1228     v8::HandleScope scope;
1229     if (!from.IsEmpty()) {
1230       v8::Local<v8::String> string = from->ToString();
1231       if (!string.IsEmpty()) {
1232         size_t len = 3 * string->Length() + 1;
1233         assert(len <= INT_MAX);
1234         if (len > sizeof (str_st_)) {
1235           str_ = static_cast<char*>(malloc(len));
1236           assert(str_ != 0);
1237         }
1238         const int flags =
1239             v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
1240         length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
1241         str_[length_] = '\0';
1242       }
1243     }
1244   }
1245
1246   inline int length() const {
1247     return length_;
1248   }
1249
1250   inline char* operator*() { return str_; }
1251   inline const char* operator*() const { return str_; }
1252
1253   inline ~Utf8String() {
1254     if (str_ != str_st_) {
1255       free(str_);
1256     }
1257   }
1258
1259  private:
1260   NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String)
1261
1262   int length_;
1263   char *str_;
1264   char str_st_[1024];
1265 };
1266
1267 #endif  // NODE_MODULE_VERSION
1268
1269 typedef void (*FreeCallback)(char *data, void *hint);
1270
1271 typedef const FunctionCallbackInfo<v8::Value>& NAN_METHOD_ARGS_TYPE;
1272 typedef void NAN_METHOD_RETURN_TYPE;
1273
1274 typedef const PropertyCallbackInfo<v8::Value>& NAN_GETTER_ARGS_TYPE;
1275 typedef void NAN_GETTER_RETURN_TYPE;
1276
1277 typedef const PropertyCallbackInfo<void>& NAN_SETTER_ARGS_TYPE;
1278 typedef void NAN_SETTER_RETURN_TYPE;
1279
1280 typedef const PropertyCallbackInfo<v8::Value>&
1281     NAN_PROPERTY_GETTER_ARGS_TYPE;
1282 typedef void NAN_PROPERTY_GETTER_RETURN_TYPE;
1283
1284 typedef const PropertyCallbackInfo<v8::Value>&
1285     NAN_PROPERTY_SETTER_ARGS_TYPE;
1286 typedef void NAN_PROPERTY_SETTER_RETURN_TYPE;
1287
1288 typedef const PropertyCallbackInfo<v8::Array>&
1289     NAN_PROPERTY_ENUMERATOR_ARGS_TYPE;
1290 typedef void NAN_PROPERTY_ENUMERATOR_RETURN_TYPE;
1291
1292 typedef const PropertyCallbackInfo<v8::Boolean>&
1293     NAN_PROPERTY_DELETER_ARGS_TYPE;
1294 typedef void NAN_PROPERTY_DELETER_RETURN_TYPE;
1295
1296 typedef const PropertyCallbackInfo<v8::Integer>&
1297     NAN_PROPERTY_QUERY_ARGS_TYPE;
1298 typedef void NAN_PROPERTY_QUERY_RETURN_TYPE;
1299
1300 typedef const PropertyCallbackInfo<v8::Value>& NAN_INDEX_GETTER_ARGS_TYPE;
1301 typedef void NAN_INDEX_GETTER_RETURN_TYPE;
1302
1303 typedef const PropertyCallbackInfo<v8::Value>& NAN_INDEX_SETTER_ARGS_TYPE;
1304 typedef void NAN_INDEX_SETTER_RETURN_TYPE;
1305
1306 typedef const PropertyCallbackInfo<v8::Array>&
1307     NAN_INDEX_ENUMERATOR_ARGS_TYPE;
1308 typedef void NAN_INDEX_ENUMERATOR_RETURN_TYPE;
1309
1310 typedef const PropertyCallbackInfo<v8::Boolean>&
1311     NAN_INDEX_DELETER_ARGS_TYPE;
1312 typedef void NAN_INDEX_DELETER_RETURN_TYPE;
1313
1314 typedef const PropertyCallbackInfo<v8::Integer>&
1315     NAN_INDEX_QUERY_ARGS_TYPE;
1316 typedef void NAN_INDEX_QUERY_RETURN_TYPE;
1317
1318 #define NAN_METHOD(name)                                                       \
1319     Nan::NAN_METHOD_RETURN_TYPE name(Nan::NAN_METHOD_ARGS_TYPE info)
1320 #define NAN_GETTER(name)                                                       \
1321     Nan::NAN_GETTER_RETURN_TYPE name(                                          \
1322         v8::Local<v8::String> property                                         \
1323       , Nan::NAN_GETTER_ARGS_TYPE info)
1324 #define NAN_SETTER(name)                                                       \
1325     Nan::NAN_SETTER_RETURN_TYPE name(                                          \
1326         v8::Local<v8::String> property                                         \
1327       , v8::Local<v8::Value> value                                             \
1328       , Nan::NAN_SETTER_ARGS_TYPE info)
1329 #define NAN_PROPERTY_GETTER(name)                                              \
1330     Nan::NAN_PROPERTY_GETTER_RETURN_TYPE name(                                 \
1331         v8::Local<v8::String> property                                         \
1332       , Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info)
1333 #define NAN_PROPERTY_SETTER(name)                                              \
1334     Nan::NAN_PROPERTY_SETTER_RETURN_TYPE name(                                 \
1335         v8::Local<v8::String> property                                         \
1336       , v8::Local<v8::Value> value                                             \
1337       , Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info)
1338 #define NAN_PROPERTY_ENUMERATOR(name)                                          \
1339     Nan::NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(                             \
1340         Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info)
1341 #define NAN_PROPERTY_DELETER(name)                                             \
1342     Nan::NAN_PROPERTY_DELETER_RETURN_TYPE name(                                \
1343         v8::Local<v8::String> property                                         \
1344       , Nan::NAN_PROPERTY_DELETER_ARGS_TYPE info)
1345 #define NAN_PROPERTY_QUERY(name)                                               \
1346     Nan::NAN_PROPERTY_QUERY_RETURN_TYPE name(                                  \
1347         v8::Local<v8::String> property                                         \
1348       , Nan::NAN_PROPERTY_QUERY_ARGS_TYPE info)
1349 # define NAN_INDEX_GETTER(name)                                                \
1350     Nan::NAN_INDEX_GETTER_RETURN_TYPE name(                                    \
1351         uint32_t index                                                         \
1352       , Nan::NAN_INDEX_GETTER_ARGS_TYPE info)
1353 #define NAN_INDEX_SETTER(name)                                                 \
1354     Nan::NAN_INDEX_SETTER_RETURN_TYPE name(                                    \
1355         uint32_t index                                                         \
1356       , v8::Local<v8::Value> value                                             \
1357       , Nan::NAN_INDEX_SETTER_ARGS_TYPE info)
1358 #define NAN_INDEX_ENUMERATOR(name)                                             \
1359     Nan::NAN_INDEX_ENUMERATOR_RETURN_TYPE                                      \
1360     name(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info)
1361 #define NAN_INDEX_DELETER(name)                                                \
1362     Nan::NAN_INDEX_DELETER_RETURN_TYPE name(                                   \
1363         uint32_t index                                                         \
1364       , Nan::NAN_INDEX_DELETER_ARGS_TYPE info)
1365 #define NAN_INDEX_QUERY(name)                                                  \
1366     Nan::NAN_INDEX_QUERY_RETURN_TYPE name(                                     \
1367         uint32_t index                                                         \
1368       , Nan::NAN_INDEX_QUERY_ARGS_TYPE info)
1369
1370 class Callback {
1371  public:
1372   Callback() {}
1373
1374   explicit Callback(const v8::Local<v8::Function> &fn) : handle_(fn) {}
1375
1376   ~Callback() {
1377     handle_.Reset();
1378   }
1379
1380   bool operator==(const Callback &other) const {
1381     return handle_ == other.handle_;
1382   }
1383
1384   bool operator!=(const Callback &other) const {
1385     return !operator==(other);
1386   }
1387
1388   inline
1389   v8::Local<v8::Function> operator*() const { return GetFunction(); }
1390
1391   inline v8::Local<v8::Value> operator()(
1392       v8::Local<v8::Object> target
1393     , int argc = 0
1394     , v8::Local<v8::Value> argv[] = 0) const {
1395     return this->Call(target, argc, argv);
1396   }
1397
1398   inline v8::Local<v8::Value> operator()(
1399       int argc = 0
1400     , v8::Local<v8::Value> argv[] = 0) const {
1401     return this->Call(argc, argv);
1402   }
1403
1404   // TODO(kkoopa): remove
1405   inline void SetFunction(const v8::Local<v8::Function> &fn) {
1406     Reset(fn);
1407   }
1408
1409   inline void Reset(const v8::Local<v8::Function> &fn) {
1410     handle_.Reset(fn);
1411   }
1412
1413   inline void Reset() {
1414     handle_.Reset();
1415   }
1416
1417   inline v8::Local<v8::Function> GetFunction() const {
1418     return New(handle_);
1419   }
1420
1421   inline bool IsEmpty() const {
1422     return handle_.IsEmpty();
1423   }
1424
1425   inline v8::Local<v8::Value>
1426   Call(v8::Local<v8::Object> target
1427      , int argc
1428      , v8::Local<v8::Value> argv[]) const {
1429 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
1430     v8::Isolate *isolate = v8::Isolate::GetCurrent();
1431     return Call_(isolate, target, argc, argv);
1432 #else
1433     return Call_(target, argc, argv);
1434 #endif
1435   }
1436
1437   inline v8::Local<v8::Value>
1438   Call(int argc, v8::Local<v8::Value> argv[]) const {
1439 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
1440     v8::Isolate *isolate = v8::Isolate::GetCurrent();
1441     v8::EscapableHandleScope scope(isolate);
1442     return scope.Escape(
1443         Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
1444 #else
1445     v8::HandleScope scope;
1446     return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
1447 #endif
1448   }
1449
1450  private:
1451   NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback)
1452   Persistent<v8::Function> handle_;
1453
1454 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
1455   v8::Local<v8::Value> Call_(v8::Isolate *isolate
1456                            , v8::Local<v8::Object> target
1457                            , int argc
1458                            , v8::Local<v8::Value> argv[]) const {
1459     EscapableHandleScope scope;
1460
1461     v8::Local<v8::Function> callback = New(handle_);
1462 # if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1463     return scope.Escape(New(node::MakeCallback(
1464         isolate
1465       , target
1466       , callback
1467       , argc
1468       , argv
1469     )));
1470 # else
1471     return scope.Escape(node::MakeCallback(
1472         isolate
1473       , target
1474       , callback
1475       , argc
1476       , argv
1477     ));
1478 # endif
1479   }
1480 #else
1481   v8::Local<v8::Value> Call_(v8::Local<v8::Object> target
1482                            , int argc
1483                            , v8::Local<v8::Value> argv[]) const {
1484     EscapableHandleScope scope;
1485
1486     v8::Local<v8::Function> callback = New(handle_);
1487     return scope.Escape(New(node::MakeCallback(
1488         target
1489       , callback
1490       , argc
1491       , argv
1492     )));
1493   }
1494 #endif
1495 };
1496
1497 /* abstract */ class AsyncWorker {
1498  public:
1499   explicit AsyncWorker(Callback *callback_)
1500       : callback(callback_), errmsg_(NULL) {
1501     request.data = this;
1502
1503     HandleScope scope;
1504     v8::Local<v8::Object> obj = New<v8::Object>();
1505     persistentHandle.Reset(obj);
1506   }
1507
1508   virtual ~AsyncWorker() {
1509     HandleScope scope;
1510
1511     if (!persistentHandle.IsEmpty())
1512       persistentHandle.Reset();
1513     delete callback;
1514     delete[] errmsg_;
1515   }
1516
1517   virtual void WorkComplete() {
1518     HandleScope scope;
1519
1520     if (errmsg_ == NULL)
1521       HandleOKCallback();
1522     else
1523       HandleErrorCallback();
1524     delete callback;
1525     callback = NULL;
1526   }
1527
1528   inline void SaveToPersistent(
1529       const char *key, const v8::Local<v8::Value> &value) {
1530     HandleScope scope;
1531     New(persistentHandle)->Set(New(key).ToLocalChecked(), value);
1532   }
1533
1534   inline void SaveToPersistent(
1535       const v8::Local<v8::String> &key, const v8::Local<v8::Value> &value) {
1536     HandleScope scope;
1537     New(persistentHandle)->Set(key, value);
1538   }
1539
1540   inline void SaveToPersistent(
1541       uint32_t index, const v8::Local<v8::Value> &value) {
1542     HandleScope scope;
1543     New(persistentHandle)->Set(index, value);
1544   }
1545
1546   inline v8::Local<v8::Value> GetFromPersistent(const char *key) const {
1547     EscapableHandleScope scope;
1548     return scope.Escape(
1549         New(persistentHandle)->Get(New(key).ToLocalChecked()));
1550   }
1551
1552   inline v8::Local<v8::Value>
1553   GetFromPersistent(const v8::Local<v8::String> &key) const {
1554     EscapableHandleScope scope;
1555     return scope.Escape(New(persistentHandle)->Get(key));
1556   }
1557
1558   inline v8::Local<v8::Value> GetFromPersistent(uint32_t index) const {
1559     EscapableHandleScope scope;
1560     return scope.Escape(New(persistentHandle)->Get(index));
1561   }
1562
1563   virtual void Execute() = 0;
1564
1565   uv_work_t request;
1566
1567   virtual void Destroy() {
1568       delete this;
1569   }
1570
1571  protected:
1572   Persistent<v8::Object> persistentHandle;
1573   Callback *callback;
1574
1575   virtual void HandleOKCallback() {
1576     HandleScope scope;
1577
1578     callback->Call(0, NULL);
1579   }
1580
1581   virtual void HandleErrorCallback() {
1582     HandleScope scope;
1583
1584     v8::Local<v8::Value> argv[] = {
1585       v8::Exception::Error(New<v8::String>(ErrorMessage()).ToLocalChecked())
1586     };
1587     callback->Call(1, argv);
1588   }
1589
1590   void SetErrorMessage(const char *msg) {
1591     delete[] errmsg_;
1592
1593     size_t size = strlen(msg) + 1;
1594     errmsg_ = new char[size];
1595     memcpy(errmsg_, msg, size);
1596   }
1597
1598   const char* ErrorMessage() const {
1599     return errmsg_;
1600   }
1601
1602  private:
1603   NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncWorker)
1604   char *errmsg_;
1605 };
1606
1607
1608 template<class T>
1609 /* abstract */ class AsyncProgressWorkerBase : public AsyncWorker {
1610  public:
1611   explicit AsyncProgressWorkerBase(Callback *callback_)
1612       : AsyncWorker(callback_), asyncdata_(NULL), asyncsize_(0) {
1613     async = new uv_async_t;
1614     uv_async_init(
1615         uv_default_loop()
1616       , async
1617       , AsyncProgress_
1618     );
1619     async->data = this;
1620
1621     uv_mutex_init(&async_lock);
1622   }
1623
1624   virtual ~AsyncProgressWorkerBase() {
1625     uv_mutex_destroy(&async_lock);
1626
1627     delete[] asyncdata_;
1628   }
1629
1630   void WorkProgress() {
1631     uv_mutex_lock(&async_lock);
1632     T *data = asyncdata_;
1633     size_t size = asyncsize_;
1634     asyncdata_ = NULL;
1635     uv_mutex_unlock(&async_lock);
1636
1637     // Don't send progress events after we've already completed.
1638     if (callback) {
1639         HandleProgressCallback(data, size);
1640     }
1641     delete[] data;
1642   }
1643
1644   class ExecutionProgress {
1645     friend class AsyncProgressWorkerBase;
1646    public:
1647     void Signal() const {
1648         uv_async_send(that_->async);
1649     }
1650
1651     void Send(const T* data, size_t size) const {
1652         that_->SendProgress_(data, size);
1653     }
1654
1655    private:
1656     explicit ExecutionProgress(AsyncProgressWorkerBase *that) : that_(that) {}
1657     NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress)
1658     AsyncProgressWorkerBase* const that_;
1659   };
1660
1661   virtual void Execute(const ExecutionProgress& progress) = 0;
1662   virtual void HandleProgressCallback(const T *data, size_t size) = 0;
1663
1664   virtual void Destroy() {
1665       uv_close(reinterpret_cast<uv_handle_t*>(async), AsyncClose_);
1666   }
1667
1668  private:
1669   void Execute() /*final override*/ {
1670       ExecutionProgress progress(this);
1671       Execute(progress);
1672   }
1673
1674   void SendProgress_(const T *data, size_t size) {
1675     T *new_data = new T[size];
1676     {
1677       T *it = new_data;
1678       std::copy(data, data + size, it);
1679     }
1680
1681     uv_mutex_lock(&async_lock);
1682     T *old_data = asyncdata_;
1683     asyncdata_ = new_data;
1684     asyncsize_ = size;
1685     uv_mutex_unlock(&async_lock);
1686
1687     delete[] old_data;
1688     uv_async_send(async);
1689   }
1690
1691   inline static NAUV_WORK_CB(AsyncProgress_) {
1692     AsyncProgressWorkerBase *worker =
1693             static_cast<AsyncProgressWorkerBase*>(async->data);
1694     worker->WorkProgress();
1695   }
1696
1697   inline static void AsyncClose_(uv_handle_t* handle) {
1698     AsyncProgressWorkerBase *worker =
1699             static_cast<AsyncProgressWorkerBase*>(handle->data);
1700     delete reinterpret_cast<uv_async_t*>(handle);
1701     delete worker;
1702   }
1703
1704   uv_async_t *async;
1705   uv_mutex_t async_lock;
1706   T *asyncdata_;
1707   size_t asyncsize_;
1708 };
1709
1710 // This ensures compatibility to the previous un-templated AsyncProgressWorker
1711 // class definition.
1712 typedef AsyncProgressWorkerBase<char> AsyncProgressWorker;
1713
1714 inline void AsyncExecute (uv_work_t* req) {
1715   AsyncWorker *worker = static_cast<AsyncWorker*>(req->data);
1716   worker->Execute();
1717 }
1718
1719 inline void AsyncExecuteComplete (uv_work_t* req) {
1720   AsyncWorker* worker = static_cast<AsyncWorker*>(req->data);
1721   worker->WorkComplete();
1722   worker->Destroy();
1723 }
1724
1725 inline void AsyncQueueWorker (AsyncWorker* worker) {
1726   uv_queue_work(
1727       uv_default_loop()
1728     , &worker->request
1729     , AsyncExecute
1730     , reinterpret_cast<uv_after_work_cb>(AsyncExecuteComplete)
1731   );
1732 }
1733
1734 namespace imp {
1735
1736 inline
1737 ExternalOneByteStringResource const*
1738 GetExternalResource(v8::Local<v8::String> str) {
1739 #if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
1740     return str->GetExternalAsciiStringResource();
1741 #else
1742     return str->GetExternalOneByteStringResource();
1743 #endif
1744 }
1745
1746 inline
1747 bool
1748 IsExternal(v8::Local<v8::String> str) {
1749 #if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
1750     return str->IsExternalAscii();
1751 #else
1752     return str->IsExternalOneByte();
1753 #endif
1754 }
1755
1756 }  // end of namespace imp
1757
1758 enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
1759
1760 #if NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION
1761 # include "nan_string_bytes.h"  // NOLINT(build/include)
1762 #endif
1763
1764 inline v8::Local<v8::Value> Encode(
1765     const void *buf, size_t len, enum Encoding encoding = BINARY) {
1766 #if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION)
1767   v8::Isolate* isolate = v8::Isolate::GetCurrent();
1768   node::encoding node_enc = static_cast<node::encoding>(encoding);
1769
1770   if (encoding == UCS2) {
1771     return node::Encode(
1772         isolate
1773       , reinterpret_cast<const uint16_t *>(buf)
1774       , len / 2);
1775   } else {
1776     return node::Encode(
1777         isolate
1778       , reinterpret_cast<const char *>(buf)
1779       , len
1780       , node_enc);
1781   }
1782 #elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
1783   return node::Encode(
1784       v8::Isolate::GetCurrent()
1785     , buf, len
1786     , static_cast<node::encoding>(encoding));
1787 #else
1788 # if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
1789   return node::Encode(buf, len, static_cast<node::encoding>(encoding));
1790 # else
1791   return imp::Encode(reinterpret_cast<const char*>(buf), len, encoding);
1792 # endif
1793 #endif
1794 }
1795
1796 inline ssize_t DecodeBytes(
1797     v8::Local<v8::Value> val, enum Encoding encoding = BINARY) {
1798 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
1799   return node::DecodeBytes(
1800       v8::Isolate::GetCurrent()
1801     , val
1802     , static_cast<node::encoding>(encoding));
1803 #else
1804 # if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
1805   if (encoding == BUFFER) {
1806     return node::DecodeBytes(val, node::BINARY);
1807   }
1808 # endif
1809   return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
1810 #endif
1811 }
1812
1813 inline ssize_t DecodeWrite(
1814     char *buf
1815   , size_t len
1816   , v8::Local<v8::Value> val
1817   , enum Encoding encoding = BINARY) {
1818 #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
1819   return node::DecodeWrite(
1820       v8::Isolate::GetCurrent()
1821     , buf
1822     , len
1823     , val
1824     , static_cast<node::encoding>(encoding));
1825 #else
1826 # if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
1827   if (encoding == BUFFER) {
1828     return node::DecodeWrite(buf, len, val, node::BINARY);
1829   }
1830 # endif
1831   return node::DecodeWrite(
1832       buf
1833     , len
1834     , val
1835     , static_cast<node::encoding>(encoding));
1836 #endif
1837 }
1838
1839 inline void SetPrototypeTemplate(
1840     v8::Local<v8::FunctionTemplate> templ
1841   , const char *name
1842   , v8::Local<v8::Data> value
1843 ) {
1844   HandleScope scope;
1845   SetTemplate(templ->PrototypeTemplate(), name, value);
1846 }
1847
1848 inline void SetPrototypeTemplate(
1849     v8::Local<v8::FunctionTemplate> templ
1850   , v8::Local<v8::String> name
1851   , v8::Local<v8::Data> value
1852   , v8::PropertyAttribute attributes
1853 ) {
1854   HandleScope scope;
1855   SetTemplate(templ->PrototypeTemplate(), name, value, attributes);
1856 }
1857
1858 inline void SetInstanceTemplate(
1859     v8::Local<v8::FunctionTemplate> templ
1860   , const char *name
1861   , v8::Local<v8::Data> value
1862 ) {
1863   HandleScope scope;
1864   SetTemplate(templ->InstanceTemplate(), name, value);
1865 }
1866
1867 inline void SetInstanceTemplate(
1868     v8::Local<v8::FunctionTemplate> templ
1869   , v8::Local<v8::String> name
1870   , v8::Local<v8::Data> value
1871   , v8::PropertyAttribute attributes
1872 ) {
1873   HandleScope scope;
1874   SetTemplate(templ->InstanceTemplate(), name, value, attributes);
1875 }
1876
1877 namespace imp {
1878
1879 // Note(@agnat): Helper to distinguish different receiver types. The first
1880 // version deals with receivers derived from v8::Template. The second version
1881 // handles everything else. The final argument only serves as discriminator and
1882 // is unused.
1883 template <typename T>
1884 inline
1885 void
1886 SetMethodAux(T recv,
1887              v8::Local<v8::String> name,
1888              v8::Local<v8::FunctionTemplate> tpl,
1889              v8::Template *) {
1890   recv->Set(name, tpl);
1891 }
1892
1893 template <typename T>
1894 inline
1895 void
1896 SetMethodAux(T recv,
1897              v8::Local<v8::String> name,
1898              v8::Local<v8::FunctionTemplate> tpl,
1899              ...) {
1900   recv->Set(name, GetFunction(tpl).ToLocalChecked());
1901 }
1902
1903 }  // end of namespace imp
1904
1905 template <typename T, template <typename> class HandleType>
1906 inline void SetMethod(
1907     HandleType<T> recv
1908   , const char *name
1909   , FunctionCallback callback) {
1910   HandleScope scope;
1911   v8::Local<v8::FunctionTemplate> t = New<v8::FunctionTemplate>(callback);
1912   v8::Local<v8::String> fn_name = New(name).ToLocalChecked();
1913   t->SetClassName(fn_name);
1914   // Note(@agnat): Pass an empty T* as discriminator. See note on
1915   // SetMethodAux(...) above
1916   imp::SetMethodAux(recv, fn_name, t, static_cast<T*>(0));
1917 }
1918
1919 inline void SetPrototypeMethod(
1920     v8::Local<v8::FunctionTemplate> recv
1921   , const char* name, FunctionCallback callback) {
1922   HandleScope scope;
1923   v8::Local<v8::FunctionTemplate> t = New<v8::FunctionTemplate>(
1924       callback
1925     , v8::Local<v8::Value>()
1926     , New<v8::Signature>(recv));
1927   v8::Local<v8::String> fn_name = New(name).ToLocalChecked();
1928   recv->PrototypeTemplate()->Set(fn_name, t);
1929   t->SetClassName(fn_name);
1930 }
1931
1932 //=== Accessors and Such =======================================================
1933
1934 inline void SetAccessor(
1935     v8::Local<v8::ObjectTemplate> tpl
1936   , v8::Local<v8::String> name
1937   , GetterCallback getter
1938   , SetterCallback setter = 0
1939   , v8::Local<v8::Value> data = v8::Local<v8::Value>()
1940   , v8::AccessControl settings = v8::DEFAULT
1941   , v8::PropertyAttribute attribute = v8::None
1942   , imp::Sig signature = imp::Sig()) {
1943   HandleScope scope;
1944
1945   imp::NativeGetter getter_ =
1946       imp::GetterCallbackWrapper;
1947   imp::NativeSetter setter_ =
1948       setter ? imp::SetterCallbackWrapper : 0;
1949
1950   v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
1951   otpl->SetInternalFieldCount(imp::kAccessorFieldCount);
1952   v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
1953
1954   obj->SetInternalField(
1955       imp::kGetterIndex
1956     , New<v8::External>(reinterpret_cast<void *>(getter)));
1957
1958   if (setter != 0) {
1959     obj->SetInternalField(
1960         imp::kSetterIndex
1961       , New<v8::External>(reinterpret_cast<void *>(setter)));
1962   }
1963
1964   if (!data.IsEmpty()) {
1965     obj->SetInternalField(imp::kDataIndex, data);
1966   }
1967
1968   tpl->SetAccessor(
1969       name
1970     , getter_
1971     , setter_
1972     , obj
1973     , settings
1974     , attribute
1975     , signature);
1976 }
1977
1978 inline bool SetAccessor(
1979     v8::Local<v8::Object> obj
1980   , v8::Local<v8::String> name
1981   , GetterCallback getter
1982   , SetterCallback setter = 0
1983   , v8::Local<v8::Value> data = v8::Local<v8::Value>()
1984   , v8::AccessControl settings = v8::DEFAULT
1985   , v8::PropertyAttribute attribute = v8::None) {
1986   HandleScope scope;
1987
1988   imp::NativeGetter getter_ =
1989       imp::GetterCallbackWrapper;
1990   imp::NativeSetter setter_ =
1991       setter ? imp::SetterCallbackWrapper : 0;
1992
1993   v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
1994   otpl->SetInternalFieldCount(imp::kAccessorFieldCount);
1995   v8::Local<v8::Object> dataobj = NewInstance(otpl).ToLocalChecked();
1996
1997   dataobj->SetInternalField(
1998       imp::kGetterIndex
1999     , New<v8::External>(reinterpret_cast<void *>(getter)));
2000
2001   if (!data.IsEmpty()) {
2002     dataobj->SetInternalField(imp::kDataIndex, data);
2003   }
2004
2005   if (setter) {
2006     dataobj->SetInternalField(
2007         imp::kSetterIndex
2008       , New<v8::External>(reinterpret_cast<void *>(setter)));
2009   }
2010
2011 #if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION)
2012   return obj->SetAccessor(
2013       GetCurrentContext()
2014     , name
2015     , getter_
2016     , setter_
2017     , dataobj
2018     , settings
2019     , attribute).FromMaybe(false);
2020 #else
2021   return obj->SetAccessor(
2022       name
2023     , getter_
2024     , setter_
2025     , dataobj
2026     , settings
2027     , attribute);
2028 #endif
2029 }
2030
2031 inline void SetNamedPropertyHandler(
2032     v8::Local<v8::ObjectTemplate> tpl
2033   , PropertyGetterCallback getter
2034   , PropertySetterCallback setter = 0
2035   , PropertyQueryCallback query = 0
2036   , PropertyDeleterCallback deleter = 0
2037   , PropertyEnumeratorCallback enumerator = 0
2038   , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2039   HandleScope scope;
2040
2041   imp::NativePropertyGetter getter_ =
2042       imp::PropertyGetterCallbackWrapper;
2043   imp::NativePropertySetter setter_ =
2044       setter ? imp::PropertySetterCallbackWrapper : 0;
2045   imp::NativePropertyQuery query_ =
2046       query ? imp::PropertyQueryCallbackWrapper : 0;
2047   imp::NativePropertyDeleter *deleter_ =
2048       deleter ? imp::PropertyDeleterCallbackWrapper : 0;
2049   imp::NativePropertyEnumerator enumerator_ =
2050       enumerator ? imp::PropertyEnumeratorCallbackWrapper : 0;
2051
2052   v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2053   otpl->SetInternalFieldCount(imp::kPropertyFieldCount);
2054   v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2055   obj->SetInternalField(
2056       imp::kPropertyGetterIndex
2057     , New<v8::External>(reinterpret_cast<void *>(getter)));
2058
2059   if (setter) {
2060     obj->SetInternalField(
2061         imp::kPropertySetterIndex
2062       , New<v8::External>(reinterpret_cast<void *>(setter)));
2063   }
2064
2065   if (query) {
2066     obj->SetInternalField(
2067         imp::kPropertyQueryIndex
2068       , New<v8::External>(reinterpret_cast<void *>(query)));
2069   }
2070
2071   if (deleter) {
2072     obj->SetInternalField(
2073         imp::kPropertyDeleterIndex
2074       , New<v8::External>(reinterpret_cast<void *>(deleter)));
2075   }
2076
2077   if (enumerator) {
2078     obj->SetInternalField(
2079         imp::kPropertyEnumeratorIndex
2080       , New<v8::External>(reinterpret_cast<void *>(enumerator)));
2081   }
2082
2083   if (!data.IsEmpty()) {
2084     obj->SetInternalField(imp::kDataIndex, data);
2085   }
2086
2087 #if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
2088   tpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
2089       getter_, setter_, query_, deleter_, enumerator_, obj));
2090 #else
2091   tpl->SetNamedPropertyHandler(
2092       getter_
2093     , setter_
2094     , query_
2095     , deleter_
2096     , enumerator_
2097     , obj);
2098 #endif
2099 }
2100
2101 inline void SetIndexedPropertyHandler(
2102     v8::Local<v8::ObjectTemplate> tpl
2103   , IndexGetterCallback getter
2104   , IndexSetterCallback setter = 0
2105   , IndexQueryCallback query = 0
2106   , IndexDeleterCallback deleter = 0
2107   , IndexEnumeratorCallback enumerator = 0
2108   , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2109   HandleScope scope;
2110
2111   imp::NativeIndexGetter getter_ =
2112       imp::IndexGetterCallbackWrapper;
2113   imp::NativeIndexSetter setter_ =
2114       setter ? imp::IndexSetterCallbackWrapper : 0;
2115   imp::NativeIndexQuery query_ =
2116       query ? imp::IndexQueryCallbackWrapper : 0;
2117   imp::NativeIndexDeleter deleter_ =
2118       deleter ? imp::IndexDeleterCallbackWrapper : 0;
2119   imp::NativeIndexEnumerator enumerator_ =
2120       enumerator ? imp::IndexEnumeratorCallbackWrapper : 0;
2121
2122   v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2123   otpl->SetInternalFieldCount(imp::kIndexPropertyFieldCount);
2124   v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2125   obj->SetInternalField(
2126       imp::kIndexPropertyGetterIndex
2127     , New<v8::External>(reinterpret_cast<void *>(getter)));
2128
2129   if (setter) {
2130     obj->SetInternalField(
2131         imp::kIndexPropertySetterIndex
2132       , New<v8::External>(reinterpret_cast<void *>(setter)));
2133   }
2134
2135   if (query) {
2136     obj->SetInternalField(
2137         imp::kIndexPropertyQueryIndex
2138       , New<v8::External>(reinterpret_cast<void *>(query)));
2139   }
2140
2141   if (deleter) {
2142     obj->SetInternalField(
2143         imp::kIndexPropertyDeleterIndex
2144       , New<v8::External>(reinterpret_cast<void *>(deleter)));
2145   }
2146
2147   if (enumerator) {
2148     obj->SetInternalField(
2149         imp::kIndexPropertyEnumeratorIndex
2150       , New<v8::External>(reinterpret_cast<void *>(enumerator)));
2151   }
2152
2153   if (!data.IsEmpty()) {
2154     obj->SetInternalField(imp::kDataIndex, data);
2155   }
2156
2157 #if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
2158   tpl->SetHandler(v8::IndexedPropertyHandlerConfiguration(
2159       getter_, setter_, query_, deleter_, enumerator_, obj));
2160 #else
2161   tpl->SetIndexedPropertyHandler(
2162       getter_
2163     , setter_
2164     , query_
2165     , deleter_
2166     , enumerator_
2167     , obj);
2168 #endif
2169 }
2170
2171 inline void SetCallHandler(
2172     v8::Local<v8::FunctionTemplate> tpl
2173   , FunctionCallback callback
2174   , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2175   HandleScope scope;
2176
2177   v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2178   otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
2179   v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2180
2181   obj->SetInternalField(
2182       imp::kFunctionIndex
2183     , New<v8::External>(reinterpret_cast<void *>(callback)));
2184
2185   if (!data.IsEmpty()) {
2186     obj->SetInternalField(imp::kDataIndex, data);
2187   }
2188
2189   tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj);
2190 }
2191
2192
2193 inline void SetCallAsFunctionHandler(
2194     v8::Local<v8::ObjectTemplate> tpl,
2195     FunctionCallback callback,
2196     v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2197   HandleScope scope;
2198
2199   v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2200   otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
2201   v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2202
2203   obj->SetInternalField(
2204       imp::kFunctionIndex
2205     , New<v8::External>(reinterpret_cast<void *>(callback)));
2206
2207   if (!data.IsEmpty()) {
2208     obj->SetInternalField(imp::kDataIndex, data);
2209   }
2210
2211   tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj);
2212 }
2213
2214 //=== Weak Persistent Handling =================================================
2215
2216 #include "nan_weak.h"  // NOLINT(build/include)
2217
2218 //=== ObjectWrap ===============================================================
2219
2220 #include "nan_object_wrap.h"  // NOLINT(build/include)
2221
2222 //=== HiddenValue/Private ======================================================
2223
2224 #include "nan_private.h"  // NOLINT(build/include)
2225
2226 //=== Export ==================================================================
2227
2228 inline
2229 void
2230 Export(ADDON_REGISTER_FUNCTION_ARGS_TYPE target, const char *name,
2231     FunctionCallback f) {
2232   HandleScope scope;
2233
2234   Set(target, New<v8::String>(name).ToLocalChecked(),
2235       GetFunction(New<v8::FunctionTemplate>(f)).ToLocalChecked());
2236 }
2237
2238 //=== Tap Reverse Binding =====================================================
2239
2240 struct Tap {
2241   explicit Tap(v8::Local<v8::Value> t) : t_() {
2242     HandleScope scope;
2243
2244     t_.Reset(To<v8::Object>(t).ToLocalChecked());
2245   }
2246
2247   ~Tap() { t_.Reset(); }  // not sure if neccessary
2248
2249   inline void plan(int i) {
2250     HandleScope scope;
2251     v8::Local<v8::Value> arg = New(i);
2252     MakeCallback(New(t_), "plan", 1, &arg);
2253   }
2254
2255   inline void ok(bool isOk, const char *msg = NULL) {
2256     HandleScope scope;
2257     v8::Local<v8::Value> args[2];
2258     args[0] = New(isOk);
2259     if (msg) args[1] = New(msg).ToLocalChecked();
2260     MakeCallback(New(t_), "ok", msg ? 2 : 1, args);
2261   }
2262
2263   inline void pass(const char * msg = NULL) {
2264     HandleScope scope;
2265     v8::Local<v8::Value> hmsg;
2266     if (msg) hmsg = New(msg).ToLocalChecked();
2267     MakeCallback(New(t_), "pass", msg ? 1 : 0, &hmsg);
2268   }
2269
2270  private:
2271   Persistent<v8::Object> t_;
2272 };
2273
2274 #define NAN_STRINGIZE2(x) #x
2275 #define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
2276 #define NAN_TEST_EXPRESSION(expression) \
2277   ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
2278
2279 #define NAN_EXPORT(target, function) Export(target, #function, function)
2280
2281 #undef TYPE_CHECK
2282
2283 //=== Generic Maybefication ===================================================
2284
2285 namespace imp {
2286
2287 template <typename T> struct Maybefier;
2288
2289 template <typename T> struct Maybefier<v8::Local<T> > {
2290   inline static MaybeLocal<T> convert(v8::Local<T> v) {
2291     return v;
2292   }
2293 };
2294
2295 template <typename T> struct Maybefier<MaybeLocal<T> > {
2296   inline static MaybeLocal<T> convert(MaybeLocal<T> v) {
2297     return v;
2298   }
2299 };
2300
2301 }  // end of namespace imp
2302
2303 template <typename T, template <typename> class MaybeMaybe>
2304 inline MaybeLocal<T>
2305 MakeMaybe(MaybeMaybe<T> v) {
2306   return imp::Maybefier<MaybeMaybe<T> >::convert(v);
2307 }
2308
2309 //=== TypedArrayContents =======================================================
2310
2311 #include "nan_typedarray_contents.h"  // NOLINT(build/include)
2312
2313 }  // end of namespace Nan
2314
2315 #endif  // NAN_H_