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