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:
IsNothing()221   inline bool IsNothing() const { return !has_value_; }
IsJust()222   inline bool IsJust() const { return has_value_; }
223 
ToChecked()224   inline T ToChecked() const { return FromJust(); }
Check()225   inline void Check() const { FromJust(); }
226 
To(T * out)227   inline bool To(T* out) const {
228     if (IsJust()) *out = value_;
229     return IsJust();
230   }
231 
FromJust()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 
FromMaybe(const T & default_value)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>.
Maybe(const v8::Maybe<T> & that)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:
Maybe()261   Maybe() : has_value_(false) {}
Maybe(const T & t)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>
Nothing()273 inline Maybe<T> Nothing() {
274   return Maybe<T>();
275 }
276 
277 template<typename T>
Just(const T & 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 
nauv_key_create(nauv_key_t * key)304 inline int nauv_key_create(nauv_key_t *key) {
305   return uv_key_create(key);
306 }
307 
nauv_key_delete(nauv_key_t * key)308 inline void nauv_key_delete(nauv_key_t *key) {
309   uv_key_delete(key);
310 }
311 
nauv_key_get(nauv_key_t * key)312 inline void* nauv_key_get(nauv_key_t *key) {
313   return uv_key_get(key);
314 }
315 
nauv_key_set(nauv_key_t * key,void * value)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 
nauv_key_create(nauv_key_t * key)331 inline int nauv_key_create(nauv_key_t* key) {
332   return -pthread_key_create(key, NULL);
333 }
334 
nauv_key_delete(nauv_key_t * key)335 inline void nauv_key_delete(nauv_key_t* key) {
336   if (pthread_key_delete(*key))
337     abort();
338 }
339 
nauv_key_get(nauv_key_t * key)340 inline void* nauv_key_get(nauv_key_t* key) {
341   return pthread_getspecific(*key);
342 }
343 
nauv_key_set(nauv_key_t * key,void * value)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 
nauv_key_create(nauv_key_t * key)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 
nauv_key_delete(nauv_key_t * key)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 
nauv_key_get(nauv_key_t * key)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 
nauv_key_set(nauv_key_t * key,void * value)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;
WeakCallbackTypeWeakCallbackType396   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
HandleScope()431   inline HandleScope() : scope(v8::Isolate::GetCurrent()) {}
NumberOfHandles()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);
delete(void *,size_t)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
EscapableHandleScope()456   inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {}
457 
NumberOfHandles()458   inline static int NumberOfHandles() {
459     return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
460   }
461 
462   template<typename T>
Escape(v8::Local<T> value)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);
delete(void *,size_t)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
TryCatch()504   TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {}
505 #endif
506 
HasCaught()507   inline bool HasCaught() const { return try_catch_.HasCaught(); }
508 
CanContinue()509   inline bool CanContinue() const { return try_catch_.CanContinue(); }
510 
ReThrow()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 
Exception()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))
StackTrace()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
StackTrace()532   inline MaybeLocal<v8::Value> StackTrace() const {
533     return try_catch_.StackTrace();
534   }
535 #endif
536 
Message()537   inline v8::Local<v8::Message> Message() const {
538     return try_catch_.Message();
539   }
540 
Reset()541   inline void Reset() { try_catch_.Reset(); }
542 
SetVerbose(bool value)543   inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); }
544 
SetCaptureMessage(bool value)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 
~AsyncResource()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 
runInAsyncScope(v8::Local<v8::Object> target,v8::Local<v8::Function> func,int argc,v8::Local<v8::Value> * argv)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 
runInAsyncScope(v8::Local<v8::Object> target,v8::Local<v8::String> symbol,int argc,v8::Local<v8::Value> * argv)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 
runInAsyncScope(v8::Local<v8::Object> target,const char * method,int argc,v8::Local<v8::Value> * argv)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 
GetCurrentEventLoop()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
SetCounterFunction(v8::CounterLookupCallback cb)665   void SetCounterFunction(v8::CounterLookupCallback cb) {
666     v8::Isolate::GetCurrent()->SetCounterFunction(cb);
667   }
668 
669   inline
SetCreateHistogramFunction(v8::CreateHistogramCallback cb)670   void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
671     v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
672   }
673 
674   inline
SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb)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))
IdleNotification(int idle_time_in_ms)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
IdleNotification(int idle_time_in_ms)686   inline bool IdleNotification(int idle_time_in_ms) {
687     return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
688   }
689 #endif
690 
LowMemoryNotification()691   inline void LowMemoryNotification() {
692     v8::Isolate::GetCurrent()->LowMemoryNotification();
693   }
694 
ContextDisposedNotification()695   inline void ContextDisposedNotification() {
696     v8::Isolate::GetCurrent()->ContextDisposedNotification();
697   }
698 #else
699   inline
SetCounterFunction(v8::CounterLookupCallback cb)700   void SetCounterFunction(v8::CounterLookupCallback cb) {
701     v8::V8::SetCounterFunction(cb);
702   }
703 
704   inline
SetCreateHistogramFunction(v8::CreateHistogramCallback cb)705   void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
706     v8::V8::SetCreateHistogramFunction(cb);
707   }
708 
709   inline
SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb)710   void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
711     v8::V8::SetAddHistogramSampleFunction(cb);
712   }
713 
IdleNotification(int idle_time_in_ms)714   inline bool IdleNotification(int idle_time_in_ms) {
715     return v8::V8::IdleNotification(idle_time_in_ms);
716   }
717 
LowMemoryNotification()718   inline void LowMemoryNotification() {
719     v8::V8::LowMemoryNotification();
720   }
721 
ContextDisposedNotification()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
Undefined()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 
Null()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 
True()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 
False()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 
EmptyString()764   inline v8::Local<v8::String> EmptyString() {
765     return v8::String::Empty(v8::Isolate::GetCurrent());
766   }
767 
AdjustExternalMemory(int bc)768   inline int AdjustExternalMemory(int bc) {
769     return static_cast<int>(
770         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
771   }
772 
SetTemplate(v8::Local<v8::Template> templ,const char * name,v8::Local<v8::Data> value)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 
SetTemplate(v8::Local<v8::Template> templ,v8::Local<v8::String> name,v8::Local<v8::Data> value,v8::PropertyAttribute attributes)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 
GetCurrentContext()788   inline v8::Local<v8::Context> GetCurrentContext() {
789     return v8::Isolate::GetCurrent()->GetCurrentContext();
790   }
791 
GetInternalFieldPointer(v8::Local<v8::Object> object,int index)792   inline void* GetInternalFieldPointer(
793       v8::Local<v8::Object> object
794     , int index) {
795     return object->GetAlignedPointerFromInternalField(index);
796   }
797 
SetInternalFieldPointer(v8::Local<v8::Object> object,int index,void * value)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 
RemoveGCEpilogueCallback(GCEpilogueCallback callback)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 
RemoveGCPrologueCallback(GCPrologueCallback callback)833   inline void RemoveGCPrologueCallback(
834       GCPrologueCallback callback) {
835     v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
836   }
837 
GetHeapStatistics(v8::HeapStatistics * heap_statistics)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)
X(RangeError)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 
NewBuffer(char * data,size_t length,node::Buffer::FreeCallback callback,void * hint)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 
CopyBuffer(const char * data,uint32_t size)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 
NewBuffer(uint32_t size)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 
NewBuffer(char * data,uint32_t size)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 
CompileScript(v8::Local<v8::String> s,const v8::ScriptOrigin & origin)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 
CompileScript(v8::Local<v8::String> s)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 
RunScript(v8::Local<UnboundScript> script)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 
RunScript(v8::Local<BoundScript> script)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 
CompileScript(v8::Local<v8::String> s,const v8::ScriptOrigin & origin)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 
CompileScript(v8::Local<v8::String> s)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 
RunScript(v8::Local<UnboundScript> script)1012   inline MaybeLocal<v8::Value> RunScript(
1013       v8::Local<UnboundScript> script
1014   ) {
1015     EscapableHandleScope scope;
1016     return scope.Escape(script->BindToCurrentContext()->Run());
1017   }
1018 
RunScript(v8::Local<BoundScript> script)1019   inline MaybeLocal<v8::Value> RunScript(
1020       v8::Local<BoundScript> script
1021   ) {
1022     return script->Run();
1023   }
1024 #endif
1025 
MakeCallback(v8::Local<v8::Object> target,v8::Local<v8::Function> func,int argc,v8::Local<v8::Value> * argv)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 
MakeCallback(v8::Local<v8::Object> target,v8::Local<v8::String> symbol,int argc,v8::Local<v8::Value> * argv)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 
MakeCallback(v8::Local<v8::Object> target,const char * method,int argc,v8::Local<v8::Value> * argv)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 
FatalException(const TryCatch & try_catch)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>
SetIsolateData(v8::Isolate * isolate,T * data)1111   inline void SetIsolateData(
1112       v8::Isolate *isolate
1113     , T *data
1114   ) {
1115       isolate->SetData(0, data);
1116   }
1117 
1118   template<typename T>
GetIsolateData(v8::Isolate * isolate)1119   inline T *GetIsolateData(
1120       v8::Isolate *isolate
1121   ) {
1122       return static_cast<T*>(isolate->GetData(0));
1123   }
1124 
1125 class Utf8String {
1126  public:
Utf8String(v8::Local<v8::Value> from)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 
length()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 
~Utf8String()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
Undefined()1196   inline v8::Local<v8::Primitive> Undefined() {
1197     EscapableHandleScope scope;
1198     return scope.Escape(New(v8::Undefined()));
1199   }
1200 
Null()1201   inline v8::Local<v8::Primitive> Null() {
1202     EscapableHandleScope scope;
1203     return scope.Escape(New(v8::Null()));
1204   }
1205 
True()1206   inline v8::Local<v8::Boolean> True() {
1207     EscapableHandleScope scope;
1208     return scope.Escape(New(v8::True()));
1209   }
1210 
False()1211   inline v8::Local<v8::Boolean> False() {
1212     EscapableHandleScope scope;
1213     return scope.Escape(New(v8::False()));
1214   }
1215 
EmptyString()1216   inline v8::Local<v8::String> EmptyString() {
1217     return v8::String::Empty();
1218   }
1219 
AdjustExternalMemory(int bc)1220   inline int AdjustExternalMemory(int bc) {
1221     return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
1222   }
1223 
SetTemplate(v8::Local<v8::Template> templ,const char * name,v8::Local<v8::Data> value)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 
SetTemplate(v8::Local<v8::Template> templ,v8::Local<v8::String> name,v8::Local<v8::Data> value,v8::PropertyAttribute attributes)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 
GetCurrentContext()1239   inline v8::Local<v8::Context> GetCurrentContext() {
1240     return v8::Context::GetCurrent();
1241   }
1242 
GetInternalFieldPointer(v8::Local<v8::Object> object,int index)1243   inline void* GetInternalFieldPointer(
1244       v8::Local<v8::Object> object
1245     , int index) {
1246     return object->GetPointerFromInternalField(index);
1247   }
1248 
SetInternalFieldPointer(v8::Local<v8::Object> object,int index,void * value)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   }
RemoveGCEpilogueCallback(v8::GCEpilogueCallback callback)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   }
RemoveGCPrologueCallback(v8::GCPrologueCallback callback)1273   inline void RemoveGCPrologueCallback(
1274     v8::GCPrologueCallback callback) {
1275     v8::V8::RemoveGCPrologueCallback(callback);
1276   }
GetHeapStatistics(v8::HeapStatistics * heap_statistics)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)
X(RangeError)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 
NewBuffer(char * data,size_t length,node::Buffer::free_callback callback,void * hint)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 
CopyBuffer(const char * data,uint32_t size)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 
NewBuffer(uint32_t size)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 
FreeData(char * data,void * hint)1354   inline void FreeData(char *data, void *hint) {
1355     (void) hint;  // unused
1356     delete[] data;
1357   }
1358 
NewBuffer(char * data,uint32_t size)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
widenString(std::vector<uint16_t> * ws,const uint8_t * s,int l)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 
CompileScript(v8::Local<v8::String> s,const v8::ScriptOrigin & origin)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 
CompileScript(v8::Local<v8::String> s)1399   inline MaybeLocal<BoundScript> CompileScript(
1400     v8::Local<v8::String> s
1401   ) {
1402     return v8::Script::Compile(s);
1403   }
1404 
1405   inline
RunScript(v8::Local<v8::Script> script)1406   MaybeLocal<v8::Value> RunScript(v8::Local<v8::Script> script) {
1407     return script->Run();
1408   }
1409 
MakeCallback(v8::Local<v8::Object> target,v8::Local<v8::Function> func,int argc,v8::Local<v8::Value> * argv)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 
MakeCallback(v8::Local<v8::Object> target,v8::Local<v8::String> symbol,int argc,v8::Local<v8::Value> * argv)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 
MakeCallback(v8::Local<v8::Object> target,const char * method,int argc,v8::Local<v8::Value> * argv)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 
FatalException(const TryCatch & try_catch)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>
SetIsolateData(v8::Isolate * isolate,T * data)1459   inline void SetIsolateData(
1460       v8::Isolate *isolate
1461     , T *data
1462   ) {
1463       isolate->SetData(data);
1464   }
1465 
1466   template<typename T>
GetIsolateData(v8::Isolate * isolate)1467   inline T *GetIsolateData(
1468       v8::Isolate *isolate
1469   ) {
1470       return static_cast<T*>(isolate->GetData());
1471   }
1472 
1473 class Utf8String {
1474  public:
Utf8String(v8::Local<v8::Value> from)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 
length()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 
~Utf8String()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:
Callback()1621   Callback() {}
1622 
Callback(const v8::Local<v8::Function> & fn)1623   explicit Callback(const v8::Local<v8::Function> &fn) : handle_(fn) {}
1624 
~Callback()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 
operator()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 
operator()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 
operator()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 
operator()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
SetFunction(const v8::Local<v8::Function> & fn)1695   inline void SetFunction(const v8::Local<v8::Function> &fn) {
1696     Reset(fn);
1697   }
1698 
Reset(const v8::Local<v8::Function> & fn)1699   inline void Reset(const v8::Local<v8::Function> &fn) {
1700     handle_.Reset(fn);
1701   }
1702 
Reset()1703   inline void Reset() {
1704     handle_.Reset();
1705   }
1706 
GetFunction()1707   inline v8::Local<v8::Function> GetFunction() const {
1708     return New(handle_);
1709   }
1710 
IsEmpty()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>
Call(v8::Local<v8::Object> target,int argc,v8::Local<v8::Value> argv[])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>
Call(int argc,v8::Local<v8::Value> argv[])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>
Call(v8::Local<v8::Object> target,int argc,v8::Local<v8::Value> argv[],AsyncResource * resource)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>
Call(int argc,v8::Local<v8::Value> argv[],AsyncResource * resource)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
Call_(v8::Isolate * isolate,v8::Local<v8::Object> target,int argc,v8::Local<v8::Value> argv[],AsyncResource * resource)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
Call_(v8::Isolate * isolate,v8::Local<v8::Object> target,int argc,v8::Local<v8::Value> argv[])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
Call_(v8::Local<v8::Object> target,int argc,v8::Local<v8::Value> argv[])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 
Call(const Nan::Callback & callback,v8::Local<v8::Object> recv,int argc,v8::Local<v8::Value> argv[])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 
Call(const Nan::Callback & callback,int argc,v8::Local<v8::Value> argv[])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 
Call(v8::Local<v8::String> symbol,v8::Local<v8::Object> recv,int argc,v8::Local<v8::Value> argv[])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 
Call(const char * method,v8::Local<v8::Object> recv,int argc,v8::Local<v8::Value> argv[])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")
callback(callback_)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 
~AsyncWorker()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 
WorkComplete()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 
SaveToPersistent(const char * key,const v8::Local<v8::Value> & value)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 
SaveToPersistent(const v8::Local<v8::String> & key,const v8::Local<v8::Value> & value)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 
SaveToPersistent(uint32_t index,const v8::Local<v8::Value> & value)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 
GetFromPersistent(const char * key)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>
GetFromPersistent(const v8::Local<v8::String> & key)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 
GetFromPersistent(uint32_t index)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 
Destroy()1983   virtual void Destroy() {
1984       delete this;
1985   }
1986 
1987  protected:
1988   Persistent<v8::Object> persistentHandle;
1989   Callback *callback;
1990   AsyncResource *async_resource;
1991 
HandleOKCallback()1992   virtual void HandleOKCallback() {
1993     HandleScope scope;
1994 
1995     callback->Call(0, NULL, async_resource);
1996   }
1997 
HandleErrorCallback()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 
SetErrorMessage(const char * msg)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 
ErrorMessage()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_
2899