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