Projekt

Obecné

Profil

Stáhnout (85.7 KB) Statistiky
| Větev: | Revize:
1
/*********************************************************************
2
 * NAN - Native Abstractions for Node.js
3
 *
4
 * Copyright (c) 2018 NAN contributors:
5
 *   - Rod Vagg <https://github.com/rvagg>
6
 *   - Benjamin Byholm <https://github.com/kkoopa>
7
 *   - Trevor Norris <https://github.com/trevnorris>
8
 *   - Nathan Rajlich <https://github.com/TooTallNate>
9
 *   - Brett Lawson <https://github.com/brett19>
10
 *   - Ben Noordhuis <https://github.com/bnoordhuis>
11
 *   - David Siegel <https://github.com/agnat>
12
 *   - Michael Ira Krufky <https://github.com/mkrufky>
13
 *
14
 * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
15
 *
16
 * Version 2.14.0: current Node 12.2.0, Node 12: 0.12.18, Node 10: 0.10.48, iojs: 3.3.1
17
 *
18
 * See https://github.com/nodejs/nan for the latest update to this file
19
 **********************************************************************************/
20

    
21
#ifndef NAN_H_
22
#define NAN_H_
23

    
24
#include <node_version.h>
25

    
26
#define NODE_0_10_MODULE_VERSION 11
27
#define NODE_0_12_MODULE_VERSION 14
28
#define ATOM_0_21_MODULE_VERSION 41
29
#define IOJS_1_0_MODULE_VERSION  42
30
#define IOJS_1_1_MODULE_VERSION  43
31
#define IOJS_2_0_MODULE_VERSION  44
32
#define IOJS_3_0_MODULE_VERSION  45
33
#define NODE_4_0_MODULE_VERSION  46
34
#define NODE_5_0_MODULE_VERSION  47
35
#define NODE_6_0_MODULE_VERSION  48
36
#define NODE_7_0_MODULE_VERSION  51
37
#define NODE_8_0_MODULE_VERSION  57
38
#define NODE_9_0_MODULE_VERSION  59
39
#define NODE_10_0_MODULE_VERSION 64
40
#define NODE_11_0_MODULE_VERSION 67
41
#define NODE_12_0_MODULE_VERSION 72
42

    
43
#ifdef _MSC_VER
44
# define NAN_HAS_CPLUSPLUS_11 (_MSC_VER >= 1800)
45
#else
46
# define NAN_HAS_CPLUSPLUS_11 (__cplusplus >= 201103L)
47
#endif
48

    
49
#if NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION && !NAN_HAS_CPLUSPLUS_11
50
# error This version of node/NAN/v8 requires a C++11 compiler
51
#endif
52

    
53
#include <uv.h>
54
#include <node.h>
55
#include <node_buffer.h>
56
#include <node_object_wrap.h>
57
#include <algorithm>
58
#include <cstring>
59
#include <climits>
60
#include <cstdlib>
61
#include <utility>
62
#if defined(_MSC_VER)
63
# pragma warning( push )
64
# pragma warning( disable : 4530 )
65
# include <queue>
66
# include <string>
67
# include <vector>
68
# pragma warning( pop )
69
#else
70
# include <queue>
71
# include <string>
72
# include <vector>
73
#endif
74

    
75
// uv helpers
76
#ifdef UV_VERSION_MAJOR
77
# ifndef UV_VERSION_PATCH
78
#  define UV_VERSION_PATCH 0
79
# endif
80
# define NAUV_UVVERSION ((UV_VERSION_MAJOR << 16) | \
81
                         (UV_VERSION_MINOR <<  8) | \
82
                         (UV_VERSION_PATCH))
83
#else
84
# define NAUV_UVVERSION 0x000b00
85
#endif
86

    
87
#if NAUV_UVVERSION < 0x000b0b
88
# ifdef WIN32
89
#  include <windows.h>
90
# else
91
#  include <pthread.h>
92
# endif
93
#endif
94

    
95
namespace Nan {
96

    
97
#define NAN_CONCAT(a, b) NAN_CONCAT_HELPER(a, b)
98
#define NAN_CONCAT_HELPER(a, b) a##b
99

    
100
#define NAN_INLINE inline  // TODO(bnoordhuis) Remove in v3.0.0.
101

    
102
#if defined(__GNUC__) && \
103
    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
104
# define NAN_DEPRECATED __attribute__((deprecated))
105
#elif defined(_MSC_VER) && \
106
    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
107
# define NAN_DEPRECATED __declspec(deprecated)
108
#else
109
# define NAN_DEPRECATED
110
#endif
111

    
112
#if NAN_HAS_CPLUSPLUS_11
113
# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&) = delete;
114
# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&) = delete;
115
# define NAN_DISALLOW_MOVE(CLASS)                                              \
116
    CLASS(CLASS&&) = delete;  /* NOLINT(build/c++11) */                        \
117
    void operator=(CLASS&&) = delete;
118
#else
119
# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&);
120
# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&);
121
# define NAN_DISALLOW_MOVE(CLASS)
122
#endif
123

    
124
#define NAN_DISALLOW_ASSIGN_COPY(CLASS)                                        \
125
    NAN_DISALLOW_ASSIGN(CLASS)                                                 \
126
    NAN_DISALLOW_COPY(CLASS)
127

    
128
#define NAN_DISALLOW_ASSIGN_MOVE(CLASS)                                        \
129
    NAN_DISALLOW_ASSIGN(CLASS)                                                 \
130
    NAN_DISALLOW_MOVE(CLASS)
131

    
132
#define NAN_DISALLOW_COPY_MOVE(CLASS)                                          \
133
    NAN_DISALLOW_COPY(CLASS)                                                   \
134
    NAN_DISALLOW_MOVE(CLASS)
135

    
136
#define NAN_DISALLOW_ASSIGN_COPY_MOVE(CLASS)                                   \
137
    NAN_DISALLOW_ASSIGN(CLASS)                                                 \
138
    NAN_DISALLOW_COPY(CLASS)                                                   \
139
    NAN_DISALLOW_MOVE(CLASS)
140

    
141
#define TYPE_CHECK(T, S)                                                       \
142
    while (false) {                                                            \
143
      *(static_cast<T *volatile *>(0)) = static_cast<S*>(0);                   \
144
    }
145

    
146
//=== RegistrationFunction =====================================================
147

    
148
#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
149
  typedef v8::Handle<v8::Object> ADDON_REGISTER_FUNCTION_ARGS_TYPE;
150
#else
151
  typedef v8::Local<v8::Object> ADDON_REGISTER_FUNCTION_ARGS_TYPE;
152
#endif
153

    
154
#define NAN_MODULE_INIT(name)                                                  \
155
    void name(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target)
156

    
157
#if NODE_MAJOR_VERSION >= 10 || \
158
    NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3
159
#define NAN_MODULE_WORKER_ENABLED(module_name, registration)                   \
160
    extern "C" NODE_MODULE_EXPORT void                                         \
161
      NAN_CONCAT(node_register_module_v, NODE_MODULE_VERSION)(                 \
162
        v8::Local<v8::Object> exports, v8::Local<v8::Value> module,            \
163
        v8::Local<v8::Context> context)                                        \
164
    {                                                                          \
165
        registration(exports);                                                 \
166
    }
167
#else
168
#define NAN_MODULE_WORKER_ENABLED(module_name, registration)                   \
169
    NODE_MODULE(module_name, registration)
170
#endif
171

    
172
//=== CallbackInfo =============================================================
173

    
174
#include "nan_callbacks.h"  // NOLINT(build/include)
175

    
176
//==============================================================================
177

    
178
#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION)
179
typedef v8::Script             UnboundScript;
180
typedef v8::Script             BoundScript;
181
#else
182
typedef v8::UnboundScript      UnboundScript;
183
typedef v8::Script             BoundScript;
184
#endif
185

    
186
#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION)
187
typedef v8::String::ExternalAsciiStringResource
188
    ExternalOneByteStringResource;
189
#else
190
typedef v8::String::ExternalOneByteStringResource
191
    ExternalOneByteStringResource;
192
#endif
193

    
194
#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
195
template<typename T>
196
class NonCopyablePersistentTraits :
197
    public v8::NonCopyablePersistentTraits<T> {};
198
template<typename T>
199
class CopyablePersistentTraits :
200
    public v8::CopyablePersistentTraits<T> {};
201

    
202
template<typename T>
203
class PersistentBase :
204
    public v8::PersistentBase<T> {};
205

    
206
template<typename T, typename M = v8::NonCopyablePersistentTraits<T> >
207
class Persistent;
208
#else
209
template<typename T> class NonCopyablePersistentTraits;
210
template<typename T> class PersistentBase;
211
template<typename T, typename P> class WeakCallbackData;
212
template<typename T, typename M = NonCopyablePersistentTraits<T> >
213
class Persistent;
214
#endif  // NODE_MODULE_VERSION
215

    
216
template<typename T>
217
class Maybe {
218
 public:
219
  inline bool IsNothing() const { return !has_value_; }
220
  inline bool IsJust() const { return has_value_; }
221

    
222
  inline T ToChecked() const { return FromJust(); }
223
  inline void Check() const { FromJust(); }
224

    
225
  inline bool To(T* out) const {
226
    if (IsJust()) *out = value_;
227
    return IsJust();
228
  }
229

    
230
  inline T FromJust() const {
231
#if defined(V8_ENABLE_CHECKS)
232
    assert(IsJust() && "FromJust is Nothing");
233
#endif  // V8_ENABLE_CHECKS
234
    return value_;
235
  }
236

    
237
  inline T FromMaybe(const T& default_value) const {
238
    return has_value_ ? value_ : default_value;
239
  }
240

    
241
  inline bool operator==(const Maybe &other) const {
242
    return (IsJust() == other.IsJust()) &&
243
        (!IsJust() || FromJust() == other.FromJust());
244
  }
245

    
246
  inline bool operator!=(const Maybe &other) const {
247
    return !operator==(other);
248
  }
249

    
250
#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
251
  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
252
  // Allow implicit conversions from v8::Maybe<T> to Nan::Maybe<T>.
253
  Maybe(const v8::Maybe<T>& that)  // NOLINT(runtime/explicit)
254
    : has_value_(that.IsJust())
255
    , value_(that.FromMaybe(T())) {}
256
#endif
257

    
258
 private:
259
  Maybe() : has_value_(false) {}
260
  explicit Maybe(const T& t) : has_value_(true), value_(t) {}
261
  bool has_value_;
262
  T value_;
263

    
264
  template<typename U>
265
  friend Maybe<U> Nothing();
266
  template<typename U>
267
  friend Maybe<U> Just(const U& u);
268
};
269

    
270
template<typename T>
271
inline Maybe<T> Nothing() {
272
  return Maybe<T>();
273
}
274

    
275
template<typename T>
276
inline Maybe<T> Just(const T& t) {
277
  return Maybe<T>(t);
278
}
279

    
280
#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
281
  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
282
# include "nan_maybe_43_inl.h"  // NOLINT(build/include)
283
#else
284
# include "nan_maybe_pre_43_inl.h"  // NOLINT(build/include)
285
#endif
286

    
287
#include "nan_converters.h"  // NOLINT(build/include)
288
#include "nan_new.h"  // NOLINT(build/include)
289

    
290
#if NAUV_UVVERSION < 0x000b17
291
#define NAUV_WORK_CB(func) \
292
    void func(uv_async_t *async, int)
293
#else
294
#define NAUV_WORK_CB(func) \
295
    void func(uv_async_t *async)
296
#endif
297

    
298
#if NAUV_UVVERSION >= 0x000b0b
299

    
300
typedef uv_key_t nauv_key_t;
301

    
302
inline int nauv_key_create(nauv_key_t *key) {
303
  return uv_key_create(key);
304
}
305

    
306
inline void nauv_key_delete(nauv_key_t *key) {
307
  uv_key_delete(key);
308
}
309

    
310
inline void* nauv_key_get(nauv_key_t *key) {
311
  return uv_key_get(key);
312
}
313

    
314
inline void nauv_key_set(nauv_key_t *key, void *value) {
315
  uv_key_set(key, value);
316
}
317

    
318
#else
319

    
320
/* Implement thread local storage for older versions of libuv.
321
 * This is essentially a backport of libuv commit 5d2434bf
322
 * written by Ben Noordhuis, adjusted for names and inline.
323
 */
324

    
325
#ifndef WIN32
326

    
327
typedef pthread_key_t nauv_key_t;
328

    
329
inline int nauv_key_create(nauv_key_t* key) {
330
  return -pthread_key_create(key, NULL);
331
}
332

    
333
inline void nauv_key_delete(nauv_key_t* key) {
334
  if (pthread_key_delete(*key))
335
    abort();
336
}
337

    
338
inline void* nauv_key_get(nauv_key_t* key) {
339
  return pthread_getspecific(*key);
340
}
341

    
342
inline void nauv_key_set(nauv_key_t* key, void* value) {
343
  if (pthread_setspecific(*key, value))
344
    abort();
345
}
346

    
347
#else
348

    
349
typedef struct {
350
  DWORD tls_index;
351
} nauv_key_t;
352

    
353
inline int nauv_key_create(nauv_key_t* key) {
354
  key->tls_index = TlsAlloc();
355
  if (key->tls_index == TLS_OUT_OF_INDEXES)
356
    return UV_ENOMEM;
357
  return 0;
358
}
359

    
360
inline void nauv_key_delete(nauv_key_t* key) {
361
  if (TlsFree(key->tls_index) == FALSE)
362
    abort();
363
  key->tls_index = TLS_OUT_OF_INDEXES;
364
}
365

    
366
inline void* nauv_key_get(nauv_key_t* key) {
367
  void* value = TlsGetValue(key->tls_index);
368
  if (value == NULL)
369
    if (GetLastError() != ERROR_SUCCESS)
370
      abort();
371
  return value;
372
}
373

    
374
inline void nauv_key_set(nauv_key_t* key, void* value) {
375
  if (TlsSetValue(key->tls_index, value) == FALSE)
376
    abort();
377
}
378

    
379
#endif
380
#endif
381

    
382
#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
383
template<typename T>
384
v8::Local<T> New(v8::Handle<T>);
385
#endif
386

    
387
#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
388
  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
389
  typedef v8::WeakCallbackType WeakCallbackType;
390
#else
391
struct WeakCallbackType {
392
  enum E {kParameter, kInternalFields};
393
  E type;
394
  WeakCallbackType(E other) : type(other) {}  // NOLINT(runtime/explicit)
395
  inline bool operator==(E other) { return other == this->type; }
396
  inline bool operator!=(E other) { return !operator==(other); }
397
};
398
#endif
399

    
400
template<typename P> class WeakCallbackInfo;
401

    
402
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
403
# include "nan_persistent_12_inl.h"  // NOLINT(build/include)
404
#else
405
# include "nan_persistent_pre_12_inl.h"  // NOLINT(build/include)
406
#endif
407

    
408
namespace imp {
409
  static const size_t kMaxLength = 0x3fffffff;
410
  // v8::String::REPLACE_INVALID_UTF8 was introduced
411
  // in node.js v0.10.29 and v0.8.27.
412
#if NODE_MAJOR_VERSION > 0 || \
413
    NODE_MINOR_VERSION > 10 || \
414
    NODE_MINOR_VERSION == 10 && NODE_PATCH_VERSION >= 29 || \
415
    NODE_MINOR_VERSION == 8 && NODE_PATCH_VERSION >= 27
416
  static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8;
417
#else
418
  static const unsigned kReplaceInvalidUtf8 = 0;
419
#endif
420
}  // end of namespace imp
421

    
422
//=== HandleScope ==============================================================
423

    
424
class HandleScope {
425
  v8::HandleScope scope;
426

    
427
 public:
428
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
429
  inline HandleScope() : scope(v8::Isolate::GetCurrent()) {}
430
  inline static int NumberOfHandles() {
431
    return v8::HandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
432
  }
433
#else
434
  inline HandleScope() : scope() {}
435
  inline static int NumberOfHandles() {
436
    return v8::HandleScope::NumberOfHandles();
437
  }
438
#endif
439

    
440
 private:
441
  // Make it hard to create heap-allocated or illegal handle scopes by
442
  // disallowing certain operations.
443
  HandleScope(const HandleScope &);
444
  void operator=(const HandleScope &);
445
  void *operator new(size_t size);
446
  void operator delete(void *, size_t) {
447
    abort();
448
  }
449
};
450

    
451
class EscapableHandleScope {
452
 public:
453
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
454
  inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {}
455

    
456
  inline static int NumberOfHandles() {
457
    return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
458
  }
459

    
460
  template<typename T>
461
  inline v8::Local<T> Escape(v8::Local<T> value) {
462
    return scope.Escape(value);
463
  }
464

    
465
 private:
466
  v8::EscapableHandleScope scope;
467
#else
468
  inline EscapableHandleScope() : scope() {}
469

    
470
  inline static int NumberOfHandles() {
471
    return v8::HandleScope::NumberOfHandles();
472
  }
473

    
474
  template<typename T>
475
  inline v8::Local<T> Escape(v8::Local<T> value) {
476
    return scope.Close(value);
477
  }
478

    
479
 private:
480
  v8::HandleScope scope;
481
#endif
482

    
483
 private:
484
  // Make it hard to create heap-allocated or illegal handle scopes by
485
  // disallowing certain operations.
486
  EscapableHandleScope(const EscapableHandleScope &);
487
  void operator=(const EscapableHandleScope &);
488
  void *operator new(size_t size);
489
  void operator delete(void *, size_t) {
490
    abort();
491
  }
492
};
493

    
494
//=== TryCatch =================================================================
495

    
496
class TryCatch {
497
  v8::TryCatch try_catch_;
498
  friend void FatalException(const TryCatch&);
499

    
500
 public:
501
#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
502
  TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {}
503
#endif
504

    
505
  inline bool HasCaught() const { return try_catch_.HasCaught(); }
506

    
507
  inline bool CanContinue() const { return try_catch_.CanContinue(); }
508

    
509
  inline v8::Local<v8::Value> ReThrow() {
510
#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
511
    return New(try_catch_.ReThrow());
512
#else
513
    return try_catch_.ReThrow();
514
#endif
515
  }
516

    
517
  inline v8::Local<v8::Value> Exception() const {
518
    return try_catch_.Exception();
519
  }
520

    
521
#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
522
  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
523
  inline v8::MaybeLocal<v8::Value> StackTrace() const {
524
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
525
    v8::EscapableHandleScope scope(isolate);
526
    return scope.Escape(try_catch_.StackTrace(isolate->GetCurrentContext())
527
                            .FromMaybe(v8::Local<v8::Value>()));
528
  }
529
#else
530
  inline MaybeLocal<v8::Value> StackTrace() const {
531
    return try_catch_.StackTrace();
532
  }
533
#endif
534

    
535
  inline v8::Local<v8::Message> Message() const {
536
    return try_catch_.Message();
537
  }
538

    
539
  inline void Reset() { try_catch_.Reset(); }
540

    
541
  inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); }
542

    
543
  inline void SetCaptureMessage(bool value) {
544
    try_catch_.SetCaptureMessage(value);
545
  }
546
};
547

    
548
v8::Local<v8::Value> MakeCallback(v8::Local<v8::Object> target,
549
                                  v8::Local<v8::Function> func,
550
                                  int argc,
551
                                  v8::Local<v8::Value>* argv);
552
v8::Local<v8::Value> MakeCallback(v8::Local<v8::Object> target,
553
                                  v8::Local<v8::String> symbol,
554
                                  int argc,
555
                                  v8::Local<v8::Value>* argv);
556
v8::Local<v8::Value> MakeCallback(v8::Local<v8::Object> target,
557
                                  const char* method,
558
                                  int argc,
559
                                  v8::Local<v8::Value>* argv);
560

    
561
// === AsyncResource ===========================================================
562

    
563
class AsyncResource {
564
 public:
565
  AsyncResource(
566
      v8::Local<v8::String> name
567
    , v8::Local<v8::Object> resource = New<v8::Object>()) {
568
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
569
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
570

    
571
    if (resource.IsEmpty()) {
572
      resource = New<v8::Object>();
573
    }
574

    
575
    context = node::EmitAsyncInit(isolate, resource, name);
576
#endif
577
  }
578

    
579
  AsyncResource(
580
      const char* name
581
    , v8::Local<v8::Object> resource = New<v8::Object>()) {
582
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
583
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
584

    
585
    if (resource.IsEmpty()) {
586
      resource = New<v8::Object>();
587
    }
588

    
589
    v8::Local<v8::String> name_string =
590
        New<v8::String>(name).ToLocalChecked();
591
    context = node::EmitAsyncInit(isolate, resource, name_string);
592
#endif
593
  }
594

    
595
  ~AsyncResource() {
596
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
597
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
598
    node::EmitAsyncDestroy(isolate, context);
599
#endif
600
  }
601

    
602
  inline MaybeLocal<v8::Value> runInAsyncScope(
603
      v8::Local<v8::Object> target
604
    , v8::Local<v8::Function> func
605
    , int argc
606
    , v8::Local<v8::Value>* argv) {
607
#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION
608
    return MakeCallback(target, func, argc, argv);
609
#else
610
    return node::MakeCallback(
611
        v8::Isolate::GetCurrent(), target, func, argc, argv, context);
612
#endif
613
  }
614

    
615
  inline MaybeLocal<v8::Value> runInAsyncScope(
616
      v8::Local<v8::Object> target
617
    , v8::Local<v8::String> symbol
618
    , int argc
619
    , v8::Local<v8::Value>* argv) {
620
#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION
621
    return MakeCallback(target, symbol, argc, argv);
622
#else
623
    return node::MakeCallback(
624
        v8::Isolate::GetCurrent(), target, symbol, argc, argv, context);
625
#endif
626
  }
627

    
628
  inline MaybeLocal<v8::Value> runInAsyncScope(
629
      v8::Local<v8::Object> target
630
    , const char* method
631
    , int argc
632
    , v8::Local<v8::Value>* argv) {
633
#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION
634
    return MakeCallback(target, method, argc, argv);
635
#else
636
    return node::MakeCallback(
637
        v8::Isolate::GetCurrent(), target, method, argc, argv, context);
638
#endif
639
  }
640

    
641
 private:
642
  NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncResource)
643
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
644
  node::async_context context;
645
#endif
646
};
647

    
648
inline uv_loop_t* GetCurrentEventLoop() {
649
#if NODE_MAJOR_VERSION >= 10 || \
650
  NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3 || \
651
  NODE_MAJOR_VERSION == 8 && NODE_MINOR_VERSION >= 10
652
    return node::GetCurrentEventLoop(v8::Isolate::GetCurrent());
653
#else
654
    return uv_default_loop();
655
#endif
656
}
657

    
658
//============ =================================================================
659

    
660
/* node 0.12  */
661
#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
662
  inline
663
  void SetCounterFunction(v8::CounterLookupCallback cb) {
664
    v8::Isolate::GetCurrent()->SetCounterFunction(cb);
665
  }
666

    
667
  inline
668
  void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
669
    v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
670
  }
671

    
672
  inline
673
  void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
674
    v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
675
  }
676

    
677
#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
678
  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
679
  inline bool IdleNotification(int idle_time_in_ms) {
680
    return v8::Isolate::GetCurrent()->IdleNotificationDeadline(
681
        idle_time_in_ms * 0.001);
682
  }
683
# else
684
  inline bool IdleNotification(int idle_time_in_ms) {
685
    return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
686
  }
687
#endif
688

    
689
  inline void LowMemoryNotification() {
690
    v8::Isolate::GetCurrent()->LowMemoryNotification();
691
  }
692

    
693
  inline void ContextDisposedNotification() {
694
    v8::Isolate::GetCurrent()->ContextDisposedNotification();
695
  }
696
#else
697
  inline
698
  void SetCounterFunction(v8::CounterLookupCallback cb) {
699
    v8::V8::SetCounterFunction(cb);
700
  }
701

    
702
  inline
703
  void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
704
    v8::V8::SetCreateHistogramFunction(cb);
705
  }
706

    
707
  inline
708
  void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
709
    v8::V8::SetAddHistogramSampleFunction(cb);
710
  }
711

    
712
  inline bool IdleNotification(int idle_time_in_ms) {
713
    return v8::V8::IdleNotification(idle_time_in_ms);
714
  }
715

    
716
  inline void LowMemoryNotification() {
717
    v8::V8::LowMemoryNotification();
718
  }
719

    
720
  inline void ContextDisposedNotification() {
721
    v8::V8::ContextDisposedNotification();
722
  }
723
#endif
724

    
725
#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)  // Node 0.12
726
  inline v8::Local<v8::Primitive> Undefined() {
727
# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
728
    EscapableHandleScope scope;
729
    return scope.Escape(New(v8::Undefined(v8::Isolate::GetCurrent())));
730
# else
731
    return v8::Undefined(v8::Isolate::GetCurrent());
732
# endif
733
  }
734

    
735
  inline v8::Local<v8::Primitive> Null() {
736
# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
737
    EscapableHandleScope scope;
738
    return scope.Escape(New(v8::Null(v8::Isolate::GetCurrent())));
739
# else
740
    return v8::Null(v8::Isolate::GetCurrent());
741
# endif
742
  }
743

    
744
  inline v8::Local<v8::Boolean> True() {
745
# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
746
    EscapableHandleScope scope;
747
    return scope.Escape(New(v8::True(v8::Isolate::GetCurrent())));
748
# else
749
    return v8::True(v8::Isolate::GetCurrent());
750
# endif
751
  }
752

    
753
  inline v8::Local<v8::Boolean> False() {
754
# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
755
    EscapableHandleScope scope;
756
    return scope.Escape(New(v8::False(v8::Isolate::GetCurrent())));
757
# else
758
    return v8::False(v8::Isolate::GetCurrent());
759
# endif
760
  }
761

    
762
  inline v8::Local<v8::String> EmptyString() {
763
    return v8::String::Empty(v8::Isolate::GetCurrent());
764
  }
765

    
766
  inline int AdjustExternalMemory(int bc) {
767
    return static_cast<int>(
768
        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
769
  }
770

    
771
  inline void SetTemplate(
772
      v8::Local<v8::Template> templ
773
    , const char *name
774
    , v8::Local<v8::Data> value) {
775
    templ->Set(v8::Isolate::GetCurrent(), name, value);
776
  }
777

    
778
  inline void SetTemplate(
779
      v8::Local<v8::Template> templ
780
    , v8::Local<v8::String> name
781
    , v8::Local<v8::Data> value
782
    , v8::PropertyAttribute attributes) {
783
    templ->Set(name, value, attributes);
784
  }
785

    
786
  inline v8::Local<v8::Context> GetCurrentContext() {
787
    return v8::Isolate::GetCurrent()->GetCurrentContext();
788
  }
789

    
790
  inline void* GetInternalFieldPointer(
791
      v8::Local<v8::Object> object
792
    , int index) {
793
    return object->GetAlignedPointerFromInternalField(index);
794
  }
795

    
796
  inline void SetInternalFieldPointer(
797
      v8::Local<v8::Object> object
798
    , int index
799
    , void* value) {
800
    object->SetAlignedPointerInInternalField(index, value);
801
  }
802

    
803
# define NAN_GC_CALLBACK(name)                                                 \
804
    void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
805

    
806
#if NODE_MODULE_VERSION <= NODE_4_0_MODULE_VERSION
807
  typedef v8::Isolate::GCEpilogueCallback GCEpilogueCallback;
808
  typedef v8::Isolate::GCPrologueCallback GCPrologueCallback;
809
#else
810
  typedef v8::Isolate::GCCallback GCEpilogueCallback;
811
  typedef v8::Isolate::GCCallback GCPrologueCallback;
812
#endif
813

    
814
  inline void AddGCEpilogueCallback(
815
      GCEpilogueCallback callback
816
    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
817
    v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter);
818
  }
819

    
820
  inline void RemoveGCEpilogueCallback(
821
      GCEpilogueCallback callback) {
822
    v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback);
823
  }
824

    
825
  inline void AddGCPrologueCallback(
826
      GCPrologueCallback callback
827
    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
828
    v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter);
829
  }
830

    
831
  inline void RemoveGCPrologueCallback(
832
      GCPrologueCallback callback) {
833
    v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
834
  }
835

    
836
  inline void GetHeapStatistics(
837
      v8::HeapStatistics *heap_statistics) {
838
    v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
839
  }
840

    
841
# define X(NAME)                                                               \
842
    inline v8::Local<v8::Value> NAME(const char *msg) {                        \
843
      EscapableHandleScope scope;                                              \
844
      return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked()));     \
845
    }                                                                          \
846
                                                                               \
847
    inline                                                                     \
848
    v8::Local<v8::Value> NAME(v8::Local<v8::String> msg) {                     \
849
      return v8::Exception::NAME(msg);                                         \
850
    }                                                                          \
851
                                                                               \
852
    inline void Throw ## NAME(const char *msg) {                               \
853
      HandleScope scope;                                                       \
854
      v8::Isolate::GetCurrent()->ThrowException(                               \
855
          v8::Exception::NAME(New(msg).ToLocalChecked()));                     \
856
    }                                                                          \
857
                                                                               \
858
    inline void Throw ## NAME(v8::Local<v8::String> msg) {                     \
859
      HandleScope scope;                                                       \
860
      v8::Isolate::GetCurrent()->ThrowException(                               \
861
          v8::Exception::NAME(msg));                                           \
862
    }
863

    
864
  X(Error)
865
  X(RangeError)
866
  X(ReferenceError)
867
  X(SyntaxError)
868
  X(TypeError)
869

    
870
# undef X
871

    
872
  inline void ThrowError(v8::Local<v8::Value> error) {
873
    v8::Isolate::GetCurrent()->ThrowException(error);
874
  }
875

    
876
  inline MaybeLocal<v8::Object> NewBuffer(
877
      char *data
878
    , size_t length
879
#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
880
    , node::Buffer::FreeCallback callback
881
#else
882
    , node::smalloc::FreeCallback callback
883
#endif
884
    , void *hint
885
  ) {
886
    // arbitrary buffer lengths requires
887
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
888
    assert(length <= imp::kMaxLength && "too large buffer");
889
#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
890
    return node::Buffer::New(
891
        v8::Isolate::GetCurrent(), data, length, callback, hint);
892
#else
893
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, length, callback,
894
                             hint);
895
#endif
896
  }
897

    
898
  inline MaybeLocal<v8::Object> CopyBuffer(
899
      const char *data
900
    , uint32_t size
901
  ) {
902
    // arbitrary buffer lengths requires
903
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
904
    assert(size <= imp::kMaxLength && "too large buffer");
905
#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
906
    return node::Buffer::Copy(
907
        v8::Isolate::GetCurrent(), data, size);
908
#else
909
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
910
#endif
911
  }
912

    
913
  inline MaybeLocal<v8::Object> NewBuffer(uint32_t size) {
914
    // arbitrary buffer lengths requires
915
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
916
    assert(size <= imp::kMaxLength && "too large buffer");
917
#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
918
    return node::Buffer::New(
919
        v8::Isolate::GetCurrent(), size);
920
#else
921
    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
922
#endif
923
  }
924

    
925
  inline MaybeLocal<v8::Object> NewBuffer(
926
      char* data
927
    , uint32_t size
928
  ) {
929
    // arbitrary buffer lengths requires
930
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
931
    assert(size <= imp::kMaxLength && "too large buffer");
932
#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
933
    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
934
#else
935
    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
936
#endif
937
  }
938

    
939
#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
940
  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
941
  inline MaybeLocal<v8::String>
942
  NewOneByteString(const uint8_t * value, int length = -1) {
943
    return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
944
          v8::NewStringType::kNormal, length);
945
  }
946

    
947
  inline MaybeLocal<BoundScript> CompileScript(
948
      v8::Local<v8::String> s
949
    , const v8::ScriptOrigin& origin
950
  ) {
951
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
952
    v8::EscapableHandleScope scope(isolate);
953
    v8::ScriptCompiler::Source source(s, origin);
954
    return scope.Escape(
955
        v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source)
956
            .FromMaybe(v8::Local<BoundScript>()));
957
  }
958

    
959
  inline MaybeLocal<BoundScript> CompileScript(
960
      v8::Local<v8::String> s
961
  ) {
962
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
963
    v8::EscapableHandleScope scope(isolate);
964
    v8::ScriptCompiler::Source source(s);
965
    return scope.Escape(
966
        v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source)
967
            .FromMaybe(v8::Local<BoundScript>()));
968
  }
969

    
970
  inline MaybeLocal<v8::Value> RunScript(
971
      v8::Local<UnboundScript> script
972
  ) {
973
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
974
    v8::EscapableHandleScope scope(isolate);
975
    return scope.Escape(script->BindToCurrentContext()
976
                            ->Run(isolate->GetCurrentContext())
977
                            .FromMaybe(v8::Local<v8::Value>()));
978
  }
979

    
980
  inline MaybeLocal<v8::Value> RunScript(
981
      v8::Local<BoundScript> script
982
  ) {
983
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
984
    v8::EscapableHandleScope scope(isolate);
985
    return scope.Escape(script->Run(isolate->GetCurrentContext())
986
                            .FromMaybe(v8::Local<v8::Value>()));
987
  }
988
#else
989
  inline MaybeLocal<v8::String>
990
  NewOneByteString(const uint8_t * value, int length = -1) {
991
    return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
992
                                      v8::String::kNormalString, length);
993
  }
994

    
995
  inline MaybeLocal<BoundScript> CompileScript(
996
      v8::Local<v8::String> s
997
    , const v8::ScriptOrigin& origin
998
  ) {
999
    v8::ScriptCompiler::Source source(s, origin);
1000
    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
1001
  }
1002

    
1003
  inline MaybeLocal<BoundScript> CompileScript(
1004
      v8::Local<v8::String> s
1005
  ) {
1006
    v8::ScriptCompiler::Source source(s);
1007
    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
1008
  }
1009

    
1010
  inline MaybeLocal<v8::Value> RunScript(
1011
      v8::Local<UnboundScript> script
1012
  ) {
1013
    EscapableHandleScope scope;
1014
    return scope.Escape(script->BindToCurrentContext()->Run());
1015
  }
1016

    
1017
  inline MaybeLocal<v8::Value> RunScript(
1018
      v8::Local<BoundScript> script
1019
  ) {
1020
    return script->Run();
1021
  }
1022
#endif
1023

    
1024
  NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
1025
      v8::Local<v8::Object> target
1026
    , v8::Local<v8::Function> func
1027
    , int argc
1028
    , v8::Local<v8::Value>* argv) {
1029
#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1030
    EscapableHandleScope scope;
1031
    return scope.Escape(New(node::MakeCallback(
1032
        v8::Isolate::GetCurrent(), target, func, argc, argv)));
1033
#else
1034
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1035
    AsyncResource res("nan:makeCallback");
1036
    return res.runInAsyncScope(target, func, argc, argv)
1037
        .FromMaybe(v8::Local<v8::Value>());
1038
# else
1039
    return node::MakeCallback(
1040
        v8::Isolate::GetCurrent(), target, func, argc, argv);
1041
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1042
#endif  // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1043
  }
1044

    
1045
  NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
1046
      v8::Local<v8::Object> target
1047
    , v8::Local<v8::String> symbol
1048
    , int argc
1049
    , v8::Local<v8::Value>* argv) {
1050
#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1051
    EscapableHandleScope scope;
1052
    return scope.Escape(New(node::MakeCallback(
1053
        v8::Isolate::GetCurrent(), target, symbol, argc, argv)));
1054
#else
1055
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1056
    AsyncResource res("nan:makeCallback");
1057
    return res.runInAsyncScope(target, symbol, argc, argv)
1058
        .FromMaybe(v8::Local<v8::Value>());
1059
# else
1060
    return node::MakeCallback(
1061
        v8::Isolate::GetCurrent(), target, symbol, argc, argv);
1062
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1063
#endif  // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1064
  }
1065

    
1066
  NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
1067
      v8::Local<v8::Object> target
1068
    , const char* method
1069
    , int argc
1070
    , v8::Local<v8::Value>* argv) {
1071
#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1072
    EscapableHandleScope scope;
1073
    return scope.Escape(New(node::MakeCallback(
1074
        v8::Isolate::GetCurrent(), target, method, argc, argv)));
1075
#else
1076
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1077
    AsyncResource res("nan:makeCallback");
1078
    return res.runInAsyncScope(target, method, argc, argv)
1079
        .FromMaybe(v8::Local<v8::Value>());
1080
# else
1081
    return node::MakeCallback(
1082
        v8::Isolate::GetCurrent(), target, method, argc, argv);
1083
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1084
#endif  // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1085
  }
1086

    
1087
  inline void FatalException(const TryCatch& try_catch) {
1088
    node::FatalException(v8::Isolate::GetCurrent(), try_catch.try_catch_);
1089
  }
1090

    
1091
  inline v8::Local<v8::Value> ErrnoException(
1092
          int errorno
1093
       ,  const char* syscall = NULL
1094
       ,  const char* message = NULL
1095
       ,  const char* path = NULL) {
1096
    return node::ErrnoException(v8::Isolate::GetCurrent(), errorno, syscall,
1097
            message, path);
1098
  }
1099

    
1100
  NAN_DEPRECATED inline v8::Local<v8::Value> NanErrnoException(
1101
          int errorno
1102
       ,  const char* syscall = NULL
1103
       ,  const char* message = NULL
1104
       ,  const char* path = NULL) {
1105
    return ErrnoException(errorno, syscall, message, path);
1106
  }
1107

    
1108
  template<typename T>
1109
  inline void SetIsolateData(
1110
      v8::Isolate *isolate
1111
    , T *data
1112
  ) {
1113
      isolate->SetData(0, data);
1114
  }
1115

    
1116
  template<typename T>
1117
  inline T *GetIsolateData(
1118
      v8::Isolate *isolate
1119
  ) {
1120
      return static_cast<T*>(isolate->GetData(0));
1121
  }
1122

    
1123
class Utf8String {
1124
 public:
1125
  inline explicit Utf8String(v8::Local<v8::Value> from) :
1126
      length_(0), str_(str_st_) {
1127
    HandleScope scope;
1128
    if (!from.IsEmpty()) {
1129
#if NODE_MAJOR_VERSION >= 10
1130
      v8::Local<v8::Context> context = GetCurrentContext();
1131
      v8::Local<v8::String> string =
1132
          from->ToString(context).FromMaybe(v8::Local<v8::String>());
1133
#else
1134
      v8::Local<v8::String> string = from->ToString();
1135
#endif
1136
      if (!string.IsEmpty()) {
1137
        size_t len = 3 * string->Length() + 1;
1138
        assert(len <= INT_MAX);
1139
        if (len > sizeof (str_st_)) {
1140
          str_ = static_cast<char*>(malloc(len));
1141
          assert(str_ != 0);
1142
        }
1143
        const int flags =
1144
            v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
1145
#if NODE_MAJOR_VERSION >= 11
1146
        length_ = string->WriteUtf8(v8::Isolate::GetCurrent(), str_,
1147
                                    static_cast<int>(len), 0, flags);
1148
#else
1149
        // See https://github.com/nodejs/nan/issues/832.
1150
        // Disable the warning as there is no way around it.
1151
#ifdef _MSC_VER
1152
#pragma warning(push)
1153
#pragma warning(disable : 4996)
1154
#endif
1155
#ifdef __GNUC__
1156
#pragma GCC diagnostic push
1157
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1158
#endif
1159
        length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
1160
#ifdef __GNUC__
1161
#pragma GCC diagnostic pop
1162
#endif
1163
#ifdef _MSC_VER
1164
#pragma warning(pop)
1165
#endif
1166
#endif  // NODE_MAJOR_VERSION < 11
1167
        str_[length_] = '\0';
1168
      }
1169
    }
1170
  }
1171

    
1172
  inline int length() const {
1173
    return length_;
1174
  }
1175

    
1176
  inline char* operator*() { return str_; }
1177
  inline const char* operator*() const { return str_; }
1178

    
1179
  inline ~Utf8String() {
1180
    if (str_ != str_st_) {
1181
      free(str_);
1182
    }
1183
  }
1184

    
1185
 private:
1186
  NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String)
1187

    
1188
  int length_;
1189
  char *str_;
1190
  char str_st_[1024];
1191
};
1192

    
1193
#else  // Node 0.8 and 0.10
1194
  inline v8::Local<v8::Primitive> Undefined() {
1195
    EscapableHandleScope scope;
1196
    return scope.Escape(New(v8::Undefined()));
1197
  }
1198

    
1199
  inline v8::Local<v8::Primitive> Null() {
1200
    EscapableHandleScope scope;
1201
    return scope.Escape(New(v8::Null()));
1202
  }
1203

    
1204
  inline v8::Local<v8::Boolean> True() {
1205
    EscapableHandleScope scope;
1206
    return scope.Escape(New(v8::True()));
1207
  }
1208

    
1209
  inline v8::Local<v8::Boolean> False() {
1210
    EscapableHandleScope scope;
1211
    return scope.Escape(New(v8::False()));
1212
  }
1213

    
1214
  inline v8::Local<v8::String> EmptyString() {
1215
    return v8::String::Empty();
1216
  }
1217

    
1218
  inline int AdjustExternalMemory(int bc) {
1219
    return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
1220
  }
1221

    
1222
  inline void SetTemplate(
1223
      v8::Local<v8::Template> templ
1224
    , const char *name
1225
    , v8::Local<v8::Data> value) {
1226
    templ->Set(name, value);
1227
  }
1228

    
1229
  inline void SetTemplate(
1230
      v8::Local<v8::Template> templ
1231
    , v8::Local<v8::String> name
1232
    , v8::Local<v8::Data> value
1233
    , v8::PropertyAttribute attributes) {
1234
    templ->Set(name, value, attributes);
1235
  }
1236

    
1237
  inline v8::Local<v8::Context> GetCurrentContext() {
1238
    return v8::Context::GetCurrent();
1239
  }
1240

    
1241
  inline void* GetInternalFieldPointer(
1242
      v8::Local<v8::Object> object
1243
    , int index) {
1244
    return object->GetPointerFromInternalField(index);
1245
  }
1246

    
1247
  inline void SetInternalFieldPointer(
1248
      v8::Local<v8::Object> object
1249
    , int index
1250
    , void* value) {
1251
    object->SetPointerInInternalField(index, value);
1252
  }
1253

    
1254
# define NAN_GC_CALLBACK(name)                                                 \
1255
    void name(v8::GCType type, v8::GCCallbackFlags flags)
1256

    
1257
  inline void AddGCEpilogueCallback(
1258
    v8::GCEpilogueCallback callback
1259
  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
1260
    v8::V8::AddGCEpilogueCallback(callback, gc_type_filter);
1261
  }
1262
  inline void RemoveGCEpilogueCallback(
1263
    v8::GCEpilogueCallback callback) {
1264
    v8::V8::RemoveGCEpilogueCallback(callback);
1265
  }
1266
  inline void AddGCPrologueCallback(
1267
    v8::GCPrologueCallback callback
1268
  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
1269
    v8::V8::AddGCPrologueCallback(callback, gc_type_filter);
1270
  }
1271
  inline void RemoveGCPrologueCallback(
1272
    v8::GCPrologueCallback callback) {
1273
    v8::V8::RemoveGCPrologueCallback(callback);
1274
  }
1275
  inline void GetHeapStatistics(
1276
    v8::HeapStatistics *heap_statistics) {
1277
    v8::V8::GetHeapStatistics(heap_statistics);
1278
  }
1279

    
1280
# define X(NAME)                                                               \
1281
    inline v8::Local<v8::Value> NAME(const char *msg) {                        \
1282
      EscapableHandleScope scope;                                              \
1283
      return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked()));     \
1284
    }                                                                          \
1285
                                                                               \
1286
    inline                                                                     \
1287
    v8::Local<v8::Value> NAME(v8::Local<v8::String> msg) {                     \
1288
      return v8::Exception::NAME(msg);                                         \
1289
    }                                                                          \
1290
                                                                               \
1291
    inline void Throw ## NAME(const char *msg) {                               \
1292
      HandleScope scope;                                                       \
1293
      v8::ThrowException(v8::Exception::NAME(New(msg).ToLocalChecked()));      \
1294
    }                                                                          \
1295
                                                                               \
1296
    inline                                                                     \
1297
    void Throw ## NAME(v8::Local<v8::String> errmsg) {                         \
1298
      HandleScope scope;                                                       \
1299
      v8::ThrowException(v8::Exception::NAME(errmsg));                         \
1300
    }
1301

    
1302
  X(Error)
1303
  X(RangeError)
1304
  X(ReferenceError)
1305
  X(SyntaxError)
1306
  X(TypeError)
1307

    
1308
# undef X
1309

    
1310
  inline void ThrowError(v8::Local<v8::Value> error) {
1311
    v8::ThrowException(error);
1312
  }
1313

    
1314
  inline MaybeLocal<v8::Object> NewBuffer(
1315
      char *data
1316
    , size_t length
1317
    , node::Buffer::free_callback callback
1318
    , void *hint
1319
  ) {
1320
    EscapableHandleScope scope;
1321
    // arbitrary buffer lengths requires
1322
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1323
    assert(length <= imp::kMaxLength && "too large buffer");
1324
    return scope.Escape(
1325
        New(node::Buffer::New(data, length, callback, hint)->handle_));
1326
  }
1327

    
1328
  inline MaybeLocal<v8::Object> CopyBuffer(
1329
      const char *data
1330
    , uint32_t size
1331
  ) {
1332
    EscapableHandleScope scope;
1333
    // arbitrary buffer lengths requires
1334
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1335
    assert(size <= imp::kMaxLength && "too large buffer");
1336
#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
1337
    return scope.Escape(New(node::Buffer::New(data, size)->handle_));
1338
#else
1339
    return scope.Escape(
1340
        New(node::Buffer::New(const_cast<char *>(data), size)->handle_));
1341
#endif
1342
  }
1343

    
1344
  inline MaybeLocal<v8::Object> NewBuffer(uint32_t size) {
1345
    // arbitrary buffer lengths requires
1346
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1347
    EscapableHandleScope scope;
1348
    assert(size <= imp::kMaxLength && "too large buffer");
1349
    return scope.Escape(New(node::Buffer::New(size)->handle_));
1350
  }
1351

    
1352
  inline void FreeData(char *data, void *hint) {
1353
    (void) hint;  // unused
1354
    delete[] data;
1355
  }
1356

    
1357
  inline MaybeLocal<v8::Object> NewBuffer(
1358
      char* data
1359
    , uint32_t size
1360
  ) {
1361
    EscapableHandleScope scope;
1362
    // arbitrary buffer lengths requires
1363
    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
1364
    assert(size <= imp::kMaxLength && "too large buffer");
1365
    return scope.Escape(
1366
        New(node::Buffer::New(data, size, FreeData, NULL)->handle_));
1367
  }
1368

    
1369
namespace imp {
1370
inline void
1371
widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l) {
1372
  size_t len = static_cast<size_t>(l);
1373
  if (l < 0) {
1374
    len = strlen(reinterpret_cast<const char*>(s));
1375
  }
1376
  assert(len <= INT_MAX && "string too long");
1377
  ws->resize(len);
1378
  std::copy(s, s + len, ws->begin());  // NOLINT(build/include_what_you_use)
1379
}
1380
}  // end of namespace imp
1381

    
1382
  inline MaybeLocal<v8::String>
1383
  NewOneByteString(const uint8_t * value, int length = -1) {
1384
    std::vector<uint16_t> wideString;  // NOLINT(build/include_what_you_use)
1385
    imp::widenString(&wideString, value, length);
1386
    return v8::String::New(wideString.data(),
1387
                           static_cast<int>(wideString.size()));
1388
  }
1389

    
1390
  inline MaybeLocal<BoundScript> CompileScript(
1391
      v8::Local<v8::String> s
1392
    , const v8::ScriptOrigin& origin
1393
  ) {
1394
    return v8::Script::Compile(s, const_cast<v8::ScriptOrigin *>(&origin));
1395
  }
1396

    
1397
  inline MaybeLocal<BoundScript> CompileScript(
1398
    v8::Local<v8::String> s
1399
  ) {
1400
    return v8::Script::Compile(s);
1401
  }
1402

    
1403
  inline
1404
  MaybeLocal<v8::Value> RunScript(v8::Local<v8::Script> script) {
1405
    return script->Run();
1406
  }
1407

    
1408
  inline v8::Local<v8::Value> MakeCallback(
1409
      v8::Local<v8::Object> target
1410
    , v8::Local<v8::Function> func
1411
    , int argc
1412
    , v8::Local<v8::Value>* argv) {
1413
    v8::HandleScope scope;
1414
    return scope.Close(New(node::MakeCallback(target, func, argc, argv)));
1415
  }
1416

    
1417
  inline v8::Local<v8::Value> MakeCallback(
1418
      v8::Local<v8::Object> target
1419
    , v8::Local<v8::String> symbol
1420
    , int argc
1421
    , v8::Local<v8::Value>* argv) {
1422
    v8::HandleScope scope;
1423
    return scope.Close(New(node::MakeCallback(target, symbol, argc, argv)));
1424
  }
1425

    
1426
  inline v8::Local<v8::Value> MakeCallback(
1427
      v8::Local<v8::Object> target
1428
    , const char* method
1429
    , int argc
1430
    , v8::Local<v8::Value>* argv) {
1431
    v8::HandleScope scope;
1432
    return scope.Close(New(node::MakeCallback(target, method, argc, argv)));
1433
  }
1434

    
1435
  inline void FatalException(const TryCatch& try_catch) {
1436
    node::FatalException(const_cast<v8::TryCatch &>(try_catch.try_catch_));
1437
  }
1438

    
1439
  inline v8::Local<v8::Value> ErrnoException(
1440
          int errorno
1441
       ,  const char* syscall = NULL
1442
       ,  const char* message = NULL
1443
       ,  const char* path = NULL) {
1444
    return node::ErrnoException(errorno, syscall, message, path);
1445
  }
1446

    
1447
  NAN_DEPRECATED inline v8::Local<v8::Value> NanErrnoException(
1448
          int errorno
1449
       ,  const char* syscall = NULL
1450
       ,  const char* message = NULL
1451
       ,  const char* path = NULL) {
1452
    return ErrnoException(errorno, syscall, message, path);
1453
  }
1454

    
1455

    
1456
  template<typename T>
1457
  inline void SetIsolateData(
1458
      v8::Isolate *isolate
1459
    , T *data
1460
  ) {
1461
      isolate->SetData(data);
1462
  }
1463

    
1464
  template<typename T>
1465
  inline T *GetIsolateData(
1466
      v8::Isolate *isolate
1467
  ) {
1468
      return static_cast<T*>(isolate->GetData());
1469
  }
1470

    
1471
class Utf8String {
1472
 public:
1473
  inline explicit Utf8String(v8::Local<v8::Value> from) :
1474
      length_(0), str_(str_st_) {
1475
    v8::HandleScope scope;
1476
    if (!from.IsEmpty()) {
1477
      v8::Local<v8::String> string = from->ToString();
1478
      if (!string.IsEmpty()) {
1479
        size_t len = 3 * string->Length() + 1;
1480
        assert(len <= INT_MAX);
1481
        if (len > sizeof (str_st_)) {
1482
          str_ = static_cast<char*>(malloc(len));
1483
          assert(str_ != 0);
1484
        }
1485
        const int flags =
1486
            v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
1487
        length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
1488
        str_[length_] = '\0';
1489
      }
1490
    }
1491
  }
1492

    
1493
  inline int length() const {
1494
    return length_;
1495
  }
1496

    
1497
  inline char* operator*() { return str_; }
1498
  inline const char* operator*() const { return str_; }
1499

    
1500
  inline ~Utf8String() {
1501
    if (str_ != str_st_) {
1502
      free(str_);
1503
    }
1504
  }
1505

    
1506
 private:
1507
  NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String)
1508

    
1509
  int length_;
1510
  char *str_;
1511
  char str_st_[1024];
1512
};
1513

    
1514
#endif  // NODE_MODULE_VERSION
1515

    
1516
typedef void (*FreeCallback)(char *data, void *hint);
1517

    
1518
typedef const FunctionCallbackInfo<v8::Value>& NAN_METHOD_ARGS_TYPE;
1519
typedef void NAN_METHOD_RETURN_TYPE;
1520

    
1521
typedef const PropertyCallbackInfo<v8::Value>& NAN_GETTER_ARGS_TYPE;
1522
typedef void NAN_GETTER_RETURN_TYPE;
1523

    
1524
typedef const PropertyCallbackInfo<void>& NAN_SETTER_ARGS_TYPE;
1525
typedef void NAN_SETTER_RETURN_TYPE;
1526

    
1527
typedef const PropertyCallbackInfo<v8::Value>&
1528
    NAN_PROPERTY_GETTER_ARGS_TYPE;
1529
typedef void NAN_PROPERTY_GETTER_RETURN_TYPE;
1530

    
1531
typedef const PropertyCallbackInfo<v8::Value>&
1532
    NAN_PROPERTY_SETTER_ARGS_TYPE;
1533
typedef void NAN_PROPERTY_SETTER_RETURN_TYPE;
1534

    
1535
typedef const PropertyCallbackInfo<v8::Array>&
1536
    NAN_PROPERTY_ENUMERATOR_ARGS_TYPE;
1537
typedef void NAN_PROPERTY_ENUMERATOR_RETURN_TYPE;
1538

    
1539
typedef const PropertyCallbackInfo<v8::Boolean>&
1540
    NAN_PROPERTY_DELETER_ARGS_TYPE;
1541
typedef void NAN_PROPERTY_DELETER_RETURN_TYPE;
1542

    
1543
typedef const PropertyCallbackInfo<v8::Integer>&
1544
    NAN_PROPERTY_QUERY_ARGS_TYPE;
1545
typedef void NAN_PROPERTY_QUERY_RETURN_TYPE;
1546

    
1547
typedef const PropertyCallbackInfo<v8::Value>& NAN_INDEX_GETTER_ARGS_TYPE;
1548
typedef void NAN_INDEX_GETTER_RETURN_TYPE;
1549

    
1550
typedef const PropertyCallbackInfo<v8::Value>& NAN_INDEX_SETTER_ARGS_TYPE;
1551
typedef void NAN_INDEX_SETTER_RETURN_TYPE;
1552

    
1553
typedef const PropertyCallbackInfo<v8::Array>&
1554
    NAN_INDEX_ENUMERATOR_ARGS_TYPE;
1555
typedef void NAN_INDEX_ENUMERATOR_RETURN_TYPE;
1556

    
1557
typedef const PropertyCallbackInfo<v8::Boolean>&
1558
    NAN_INDEX_DELETER_ARGS_TYPE;
1559
typedef void NAN_INDEX_DELETER_RETURN_TYPE;
1560

    
1561
typedef const PropertyCallbackInfo<v8::Integer>&
1562
    NAN_INDEX_QUERY_ARGS_TYPE;
1563
typedef void NAN_INDEX_QUERY_RETURN_TYPE;
1564

    
1565
#define NAN_METHOD(name)                                                       \
1566
    Nan::NAN_METHOD_RETURN_TYPE name(Nan::NAN_METHOD_ARGS_TYPE info)
1567
#define NAN_GETTER(name)                                                       \
1568
    Nan::NAN_GETTER_RETURN_TYPE name(                                          \
1569
        v8::Local<v8::String> property                                         \
1570
      , Nan::NAN_GETTER_ARGS_TYPE info)
1571
#define NAN_SETTER(name)                                                       \
1572
    Nan::NAN_SETTER_RETURN_TYPE name(                                          \
1573
        v8::Local<v8::String> property                                         \
1574
      , v8::Local<v8::Value> value                                             \
1575
      , Nan::NAN_SETTER_ARGS_TYPE info)
1576
#define NAN_PROPERTY_GETTER(name)                                              \
1577
    Nan::NAN_PROPERTY_GETTER_RETURN_TYPE name(                                 \
1578
        v8::Local<v8::String> property                                         \
1579
      , Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info)
1580
#define NAN_PROPERTY_SETTER(name)                                              \
1581
    Nan::NAN_PROPERTY_SETTER_RETURN_TYPE name(                                 \
1582
        v8::Local<v8::String> property                                         \
1583
      , v8::Local<v8::Value> value                                             \
1584
      , Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info)
1585
#define NAN_PROPERTY_ENUMERATOR(name)                                          \
1586
    Nan::NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(                             \
1587
        Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info)
1588
#define NAN_PROPERTY_DELETER(name)                                             \
1589
    Nan::NAN_PROPERTY_DELETER_RETURN_TYPE name(                                \
1590
        v8::Local<v8::String> property                                         \
1591
      , Nan::NAN_PROPERTY_DELETER_ARGS_TYPE info)
1592
#define NAN_PROPERTY_QUERY(name)                                               \
1593
    Nan::NAN_PROPERTY_QUERY_RETURN_TYPE name(                                  \
1594
        v8::Local<v8::String> property                                         \
1595
      , Nan::NAN_PROPERTY_QUERY_ARGS_TYPE info)
1596
# define NAN_INDEX_GETTER(name)                                                \
1597
    Nan::NAN_INDEX_GETTER_RETURN_TYPE name(                                    \
1598
        uint32_t index                                                         \
1599
      , Nan::NAN_INDEX_GETTER_ARGS_TYPE info)
1600
#define NAN_INDEX_SETTER(name)                                                 \
1601
    Nan::NAN_INDEX_SETTER_RETURN_TYPE name(                                    \
1602
        uint32_t index                                                         \
1603
      , v8::Local<v8::Value> value                                             \
1604
      , Nan::NAN_INDEX_SETTER_ARGS_TYPE info)
1605
#define NAN_INDEX_ENUMERATOR(name)                                             \
1606
    Nan::NAN_INDEX_ENUMERATOR_RETURN_TYPE                                      \
1607
    name(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info)
1608
#define NAN_INDEX_DELETER(name)                                                \
1609
    Nan::NAN_INDEX_DELETER_RETURN_TYPE name(                                   \
1610
        uint32_t index                                                         \
1611
      , Nan::NAN_INDEX_DELETER_ARGS_TYPE info)
1612
#define NAN_INDEX_QUERY(name)                                                  \
1613
    Nan::NAN_INDEX_QUERY_RETURN_TYPE name(                                     \
1614
        uint32_t index                                                         \
1615
      , Nan::NAN_INDEX_QUERY_ARGS_TYPE info)
1616

    
1617
class Callback {
1618
 public:
1619
  Callback() {}
1620

    
1621
  explicit Callback(const v8::Local<v8::Function> &fn) : handle_(fn) {}
1622

    
1623
  ~Callback() {
1624
    handle_.Reset();
1625
  }
1626

    
1627
  bool operator==(const Callback &other) const {
1628
    return handle_ == other.handle_;
1629
  }
1630

    
1631
  bool operator!=(const Callback &other) const {
1632
    return !operator==(other);
1633
  }
1634

    
1635
  inline
1636
  v8::Local<v8::Function> operator*() const { return GetFunction(); }
1637

    
1638
  NAN_DEPRECATED inline v8::Local<v8::Value> operator()(
1639
      v8::Local<v8::Object> target
1640
    , int argc = 0
1641
    , v8::Local<v8::Value> argv[] = 0) const {
1642
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1643
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
1644
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1645
    AsyncResource async("nan:Callback:operator()");
1646
    return Call_(isolate, target, argc, argv, &async)
1647
        .FromMaybe(v8::Local<v8::Value>());
1648
# else
1649
    return Call_(isolate, target, argc, argv);
1650
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1651
#else
1652
    return Call_(target, argc, argv);
1653
#endif  //  NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1654
  }
1655

    
1656
  NAN_DEPRECATED inline v8::Local<v8::Value> operator()(
1657
      int argc = 0
1658
    , v8::Local<v8::Value> argv[] = 0) const {
1659
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1660
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
1661
    v8::EscapableHandleScope scope(isolate);
1662
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1663
    AsyncResource async("nan:Callback:operator()");
1664
    return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(),
1665
                              argc, argv, &async)
1666
                            .FromMaybe(v8::Local<v8::Value>()));
1667
# else
1668
    return scope.Escape(
1669
        Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
1670
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1671
#else
1672
    v8::HandleScope scope;
1673
    return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
1674
#endif  //  NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1675
  }
1676

    
1677
  inline MaybeLocal<v8::Value> operator()(
1678
      AsyncResource* resource
1679
    , int argc = 0
1680
    , v8::Local<v8::Value> argv[] = 0) const {
1681
    return this->Call(argc, argv, resource);
1682
  }
1683

    
1684
  inline MaybeLocal<v8::Value> operator()(
1685
      AsyncResource* resource
1686
    , v8::Local<v8::Object> target
1687
    , int argc = 0
1688
    , v8::Local<v8::Value> argv[] = 0) const {
1689
    return this->Call(target, argc, argv, resource);
1690
  }
1691

    
1692
  // TODO(kkoopa): remove
1693
  inline void SetFunction(const v8::Local<v8::Function> &fn) {
1694
    Reset(fn);
1695
  }
1696

    
1697
  inline void Reset(const v8::Local<v8::Function> &fn) {
1698
    handle_.Reset(fn);
1699
  }
1700

    
1701
  inline void Reset() {
1702
    handle_.Reset();
1703
  }
1704

    
1705
  inline v8::Local<v8::Function> GetFunction() const {
1706
    return New(handle_);
1707
  }
1708

    
1709
  inline bool IsEmpty() const {
1710
    return handle_.IsEmpty();
1711
  }
1712

    
1713
  // Deprecated: For async callbacks Use the versions that accept an
1714
  // AsyncResource. If this callback does not correspond to an async resource,
1715
  // that is, it is a synchronous function call on a non-empty JS stack, you
1716
  // should Nan::Call instead.
1717
  NAN_DEPRECATED inline v8::Local<v8::Value>
1718
  Call(v8::Local<v8::Object> target
1719
     , int argc
1720
     , v8::Local<v8::Value> argv[]) const {
1721
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1722
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
1723
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1724
    AsyncResource async("nan:Callback:Call");
1725
    return Call_(isolate, target, argc, argv, &async)
1726
        .FromMaybe(v8::Local<v8::Value>());
1727
# else
1728
    return Call_(isolate, target, argc, argv);
1729
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1730
#else
1731
    return Call_(target, argc, argv);
1732
#endif
1733
  }
1734

    
1735
  // Deprecated: For async callbacks Use the versions that accept an
1736
  // AsyncResource. If this callback does not correspond to an async resource,
1737
  // that is, it is a synchronous function call on a non-empty JS stack, you
1738
  // should Nan::Call instead.
1739
  NAN_DEPRECATED inline v8::Local<v8::Value>
1740
  Call(int argc, v8::Local<v8::Value> argv[]) const {
1741
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1742
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
1743
    v8::EscapableHandleScope scope(isolate);
1744
# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1745
    AsyncResource async("nan:Callback:Call");
1746
    return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(),
1747
                              argc, argv, &async)
1748
                            .FromMaybe(v8::Local<v8::Value>()));
1749
# else
1750
    return scope.Escape(
1751
        Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
1752
# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1753
#else
1754
    v8::HandleScope scope;
1755
    return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
1756
#endif
1757
  }
1758

    
1759
  inline MaybeLocal<v8::Value>
1760
  Call(v8::Local<v8::Object> target
1761
     , int argc
1762
     , v8::Local<v8::Value> argv[]
1763
     , AsyncResource* resource) const {
1764
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1765
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
1766
    return Call_(isolate, target, argc, argv, resource);
1767
#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1768
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
1769
    return Call_(isolate, target, argc, argv);
1770
#else
1771
    return Call_(target, argc, argv);
1772
#endif
1773
  }
1774

    
1775
  inline MaybeLocal<v8::Value>
1776
  Call(int argc, v8::Local<v8::Value> argv[], AsyncResource* resource) const {
1777
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1778
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
1779
    return Call(isolate->GetCurrentContext()->Global(), argc, argv, resource);
1780
#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1781
    v8::Isolate *isolate = v8::Isolate::GetCurrent();
1782
    v8::EscapableHandleScope scope(isolate);
1783
    return scope.Escape(
1784
        Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
1785
#else
1786
    v8::HandleScope scope;
1787
    return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
1788
#endif
1789
  }
1790

    
1791
 private:
1792
  NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback)
1793
  Persistent<v8::Function> handle_;
1794

    
1795
#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
1796
  MaybeLocal<v8::Value> Call_(v8::Isolate *isolate
1797
                            , v8::Local<v8::Object> target
1798
                            , int argc
1799
                            , v8::Local<v8::Value> argv[]
1800
                            , AsyncResource* resource) const {
1801
    EscapableHandleScope scope;
1802
    v8::Local<v8::Function> func = New(handle_);
1803
    auto maybe = resource->runInAsyncScope(target, func, argc, argv);
1804
    v8::Local<v8::Value> local;
1805
    if (!maybe.ToLocal(&local)) return MaybeLocal<v8::Value>();
1806
    return scope.Escape(local);
1807
  }
1808
#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1809
  v8::Local<v8::Value> Call_(v8::Isolate *isolate
1810
                           , v8::Local<v8::Object> target
1811
                           , int argc
1812
                           , v8::Local<v8::Value> argv[]) const {
1813
    EscapableHandleScope scope;
1814

    
1815
    v8::Local<v8::Function> callback = New(handle_);
1816
# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
1817
    return scope.Escape(New(node::MakeCallback(
1818
        isolate
1819
      , target
1820
      , callback
1821
      , argc
1822
      , argv
1823
    )));
1824
# else
1825
    return scope.Escape(node::MakeCallback(
1826
        isolate
1827
      , target
1828
      , callback
1829
      , argc
1830
      , argv
1831
    ));
1832
# endif
1833
  }
1834
#else
1835
  v8::Local<v8::Value> Call_(v8::Local<v8::Object> target
1836
                           , int argc
1837
                           , v8::Local<v8::Value> argv[]) const {
1838
    EscapableHandleScope scope;
1839

    
1840
    v8::Local<v8::Function> callback = New(handle_);
1841
    return scope.Escape(New(node::MakeCallback(
1842
        target
1843
      , callback
1844
      , argc
1845
      , argv
1846
    )));
1847
  }
1848
#endif
1849
};
1850

    
1851
inline MaybeLocal<v8::Value> Call(
1852
    const Nan::Callback& callback
1853
  , v8::Local<v8::Object> recv
1854
  , int argc
1855
  , v8::Local<v8::Value> argv[]) {
1856
  return Call(*callback, recv, argc, argv);
1857
}
1858

    
1859
inline MaybeLocal<v8::Value> Call(
1860
    const Nan::Callback& callback
1861
  , int argc
1862
  , v8::Local<v8::Value> argv[]) {
1863
#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
1864
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
1865
  v8::EscapableHandleScope scope(isolate);
1866
  return scope.Escape(
1867
      Call(*callback, isolate->GetCurrentContext()->Global(), argc, argv)
1868
          .FromMaybe(v8::Local<v8::Value>()));
1869
#else
1870
  EscapableHandleScope scope;
1871
  return scope.Escape(
1872
      Call(*callback, v8::Context::GetCurrent()->Global(), argc, argv)
1873
          .FromMaybe(v8::Local<v8::Value>()));
1874
#endif
1875
}
1876

    
1877
inline MaybeLocal<v8::Value> Call(
1878
    v8::Local<v8::String> symbol
1879
  , v8::Local<v8::Object> recv
1880
  , int argc
1881
  , v8::Local<v8::Value> argv[]) {
1882
  EscapableHandleScope scope;
1883
  v8::Local<v8::Value> fn_v =
1884
      Get(recv, symbol).FromMaybe(v8::Local<v8::Value>());
1885
  if (fn_v.IsEmpty() || !fn_v->IsFunction()) return v8::Local<v8::Value>();
1886
  v8::Local<v8::Function> fn = fn_v.As<v8::Function>();
1887
  return scope.Escape(
1888
      Call(fn, recv, argc, argv).FromMaybe(v8::Local<v8::Value>()));
1889
}
1890

    
1891
inline MaybeLocal<v8::Value> Call(
1892
    const char* method
1893
  , v8::Local<v8::Object> recv
1894
  , int argc
1895
  , v8::Local<v8::Value> argv[]) {
1896
  EscapableHandleScope scope;
1897
  v8::Local<v8::String> method_string =
1898
      New<v8::String>(method).ToLocalChecked();
1899
  return scope.Escape(
1900
      Call(method_string, recv, argc, argv).FromMaybe(v8::Local<v8::Value>()));
1901
}
1902

    
1903
/* abstract */ class AsyncWorker {
1904
 public:
1905
  explicit AsyncWorker(Callback *callback_,
1906
                       const char* resource_name = "nan:AsyncWorker")
1907
      : callback(callback_), errmsg_(NULL) {
1908
    request.data = this;
1909

    
1910
    HandleScope scope;
1911
    v8::Local<v8::Object> obj = New<v8::Object>();
1912
    persistentHandle.Reset(obj);
1913
    async_resource = new AsyncResource(resource_name, obj);
1914
  }
1915

    
1916
  virtual ~AsyncWorker() {
1917
    HandleScope scope;
1918

    
1919
    if (!persistentHandle.IsEmpty())
1920
      persistentHandle.Reset();
1921
    delete callback;
1922
    delete[] errmsg_;
1923
    delete async_resource;
1924
  }
1925

    
1926
  virtual void WorkComplete() {
1927
    HandleScope scope;
1928

    
1929
    if (errmsg_ == NULL)
1930
      HandleOKCallback();
1931
    else
1932
      HandleErrorCallback();
1933
    delete callback;
1934
    callback = NULL;
1935
  }
1936

    
1937
  inline void SaveToPersistent(
1938
      const char *key, const v8::Local<v8::Value> &value) {
1939
    HandleScope scope;
1940
    Set(New(persistentHandle), New(key).ToLocalChecked(), value).FromJust();
1941
  }
1942

    
1943
  inline void SaveToPersistent(
1944
      const v8::Local<v8::String> &key, const v8::Local<v8::Value> &value) {
1945
    HandleScope scope;
1946
    Set(New(persistentHandle), key, value).FromJust();
1947
  }
1948

    
1949
  inline void SaveToPersistent(
1950
      uint32_t index, const v8::Local<v8::Value> &value) {
1951
    HandleScope scope;
1952
    Set(New(persistentHandle), index, value).FromJust();
1953
  }
1954

    
1955
  inline v8::Local<v8::Value> GetFromPersistent(const char *key) const {
1956
    EscapableHandleScope scope;
1957
    return scope.Escape(
1958
        Get(New(persistentHandle), New(key).ToLocalChecked())
1959
        .FromMaybe(v8::Local<v8::Value>()));
1960
  }
1961

    
1962
  inline v8::Local<v8::Value>
1963
  GetFromPersistent(const v8::Local<v8::String> &key) const {
1964
    EscapableHandleScope scope;
1965
    return scope.Escape(
1966
        Get(New(persistentHandle), key)
1967
        .FromMaybe(v8::Local<v8::Value>()));
1968
  }
1969

    
1970
  inline v8::Local<v8::Value> GetFromPersistent(uint32_t index) const {
1971
    EscapableHandleScope scope;
1972
    return scope.Escape(
1973
        Get(New(persistentHandle), index)
1974
        .FromMaybe(v8::Local<v8::Value>()));
1975
  }
1976

    
1977
  virtual void Execute() = 0;
1978

    
1979
  uv_work_t request;
1980

    
1981
  virtual void Destroy() {
1982
      delete this;
1983
  }
1984

    
1985
 protected:
1986
  Persistent<v8::Object> persistentHandle;
1987
  Callback *callback;
1988
  AsyncResource *async_resource;
1989

    
1990
  virtual void HandleOKCallback() {
1991
    HandleScope scope;
1992

    
1993
    callback->Call(0, NULL, async_resource);
1994
  }
1995

    
1996
  virtual void HandleErrorCallback() {
1997
    HandleScope scope;
1998

    
1999
    v8::Local<v8::Value> argv[] = {
2000
      v8::Exception::Error(New<v8::String>(ErrorMessage()).ToLocalChecked())
2001
    };
2002
    callback->Call(1, argv, async_resource);
2003
  }
2004

    
2005
  void SetErrorMessage(const char *msg) {
2006
    delete[] errmsg_;
2007

    
2008
    size_t size = strlen(msg) + 1;
2009
    errmsg_ = new char[size];
2010
    memcpy(errmsg_, msg, size);
2011
  }
2012

    
2013
  const char* ErrorMessage() const {
2014
    return errmsg_;
2015
  }
2016

    
2017
 private:
2018
  NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncWorker)
2019
  char *errmsg_;
2020
};
2021

    
2022
/* abstract */ class AsyncBareProgressWorkerBase : public AsyncWorker {
2023
 public:
2024
  explicit AsyncBareProgressWorkerBase(
2025
      Callback *callback_,
2026
      const char* resource_name = "nan:AsyncBareProgressWorkerBase")
2027
      : AsyncWorker(callback_, resource_name) {
2028
    uv_async_init(
2029
        GetCurrentEventLoop()
2030
      , &async
2031
      , AsyncProgress_
2032
    );
2033
    async.data = this;
2034
  }
2035

    
2036
  virtual ~AsyncBareProgressWorkerBase() {
2037
  }
2038

    
2039
  virtual void WorkProgress() = 0;
2040

    
2041
  virtual void Destroy() {
2042
      uv_close(reinterpret_cast<uv_handle_t*>(&async), AsyncClose_);
2043
  }
2044

    
2045
 private:
2046
  inline static NAUV_WORK_CB(AsyncProgress_) {
2047
    AsyncBareProgressWorkerBase *worker =
2048
            static_cast<AsyncBareProgressWorkerBase*>(async->data);
2049
    worker->WorkProgress();
2050
  }
2051

    
2052
  inline static void AsyncClose_(uv_handle_t* handle) {
2053
    AsyncBareProgressWorkerBase *worker =
2054
            static_cast<AsyncBareProgressWorkerBase*>(handle->data);
2055
    delete worker;
2056
  }
2057

    
2058
 protected:
2059
  uv_async_t async;
2060
};
2061

    
2062
template<class T>
2063
/* abstract */
2064
class AsyncBareProgressWorker : public AsyncBareProgressWorkerBase {
2065
 public:
2066
  explicit AsyncBareProgressWorker(
2067
      Callback *callback_,
2068
      const char* resource_name = "nan:AsyncBareProgressWorker")
2069
      : AsyncBareProgressWorkerBase(callback_, resource_name) {
2070
    uv_mutex_init(&async_lock);
2071
  }
2072

    
2073
  virtual ~AsyncBareProgressWorker() {
2074
    uv_mutex_destroy(&async_lock);
2075
  }
2076

    
2077
  class ExecutionProgress {
2078
    friend class AsyncBareProgressWorker;
2079
   public:
2080
    void Signal() const {
2081
      uv_mutex_lock(&that_->async_lock);
2082
      uv_async_send(&that_->async);
2083
      uv_mutex_unlock(&that_->async_lock);
2084
    }
2085

    
2086
    void Send(const T* data, size_t count) const {
2087
      that_->SendProgress_(data, count);
2088
    }
2089

    
2090
   private:
2091
    explicit ExecutionProgress(AsyncBareProgressWorker *that) : that_(that) {}
2092
    NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress)
2093
    AsyncBareProgressWorker* const that_;
2094
  };
2095

    
2096
  virtual void Execute(const ExecutionProgress& progress) = 0;
2097
  virtual void HandleProgressCallback(const T *data, size_t size) = 0;
2098

    
2099
 protected:
2100
  uv_mutex_t async_lock;
2101

    
2102
 private:
2103
  void Execute() /*final override*/ {
2104
    ExecutionProgress progress(this);
2105
    Execute(progress);
2106
  }
2107

    
2108
  virtual void SendProgress_(const T *data, size_t count) = 0;
2109
};
2110

    
2111
template<class T>
2112
/* abstract */
2113
class AsyncProgressWorkerBase : public AsyncBareProgressWorker<T> {
2114
 public:
2115
  explicit AsyncProgressWorkerBase(
2116
      Callback *callback_,
2117
      const char* resource_name = "nan:AsyncProgressWorkerBase")
2118
      : AsyncBareProgressWorker<T>(callback_, resource_name), asyncdata_(NULL),
2119
        asyncsize_(0) {
2120
  }
2121

    
2122
  virtual ~AsyncProgressWorkerBase() {
2123
    delete[] asyncdata_;
2124
  }
2125

    
2126
  void WorkProgress() {
2127
    uv_mutex_lock(&this->async_lock);
2128
    T *data = asyncdata_;
2129
    size_t size = asyncsize_;
2130
    asyncdata_ = NULL;
2131
    asyncsize_ = 0;
2132
    uv_mutex_unlock(&this->async_lock);
2133

    
2134
    // Don't send progress events after we've already completed.
2135
    if (this->callback) {
2136
        this->HandleProgressCallback(data, size);
2137
    }
2138
    delete[] data;
2139
  }
2140

    
2141
 private:
2142
  void SendProgress_(const T *data, size_t count) {
2143
    T *new_data = new T[count];
2144
    {
2145
      T *it = new_data;
2146
      std::copy(data, data + count, it);
2147
    }
2148

    
2149
    uv_mutex_lock(&this->async_lock);
2150
    T *old_data = asyncdata_;
2151
    asyncdata_ = new_data;
2152
    asyncsize_ = count;
2153
    uv_async_send(&this->async);
2154
    uv_mutex_unlock(&this->async_lock);
2155

    
2156
    delete[] old_data;
2157
  }
2158

    
2159
  T *asyncdata_;
2160
  size_t asyncsize_;
2161
};
2162

    
2163
// This ensures compatibility to the previous un-templated AsyncProgressWorker
2164
// class definition.
2165
typedef AsyncProgressWorkerBase<char> AsyncProgressWorker;
2166

    
2167
template<class T>
2168
/* abstract */
2169
class AsyncBareProgressQueueWorker : public AsyncBareProgressWorkerBase {
2170
 public:
2171
  explicit AsyncBareProgressQueueWorker(
2172
      Callback *callback_,
2173
      const char* resource_name = "nan:AsyncBareProgressQueueWorker")
2174
      : AsyncBareProgressWorkerBase(callback_, resource_name) {
2175
  }
2176

    
2177
  virtual ~AsyncBareProgressQueueWorker() {
2178
  }
2179

    
2180
  class ExecutionProgress {
2181
    friend class AsyncBareProgressQueueWorker;
2182
   public:
2183
    void Send(const T* data, size_t count) const {
2184
      that_->SendProgress_(data, count);
2185
    }
2186

    
2187
   private:
2188
    explicit ExecutionProgress(AsyncBareProgressQueueWorker *that)
2189
        : that_(that) {}
2190
    NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress)
2191
    AsyncBareProgressQueueWorker* const that_;
2192
  };
2193

    
2194
  virtual void Execute(const ExecutionProgress& progress) = 0;
2195
  virtual void HandleProgressCallback(const T *data, size_t size) = 0;
2196

    
2197
 private:
2198
  void Execute() /*final override*/ {
2199
    ExecutionProgress progress(this);
2200
    Execute(progress);
2201
  }
2202

    
2203
  virtual void SendProgress_(const T *data, size_t count) = 0;
2204
};
2205

    
2206
template<class T>
2207
/* abstract */
2208
class AsyncProgressQueueWorker : public AsyncBareProgressQueueWorker<T> {
2209
 public:
2210
  explicit AsyncProgressQueueWorker(
2211
      Callback *callback_,
2212
      const char* resource_name = "nan:AsyncProgressQueueWorker")
2213
      : AsyncBareProgressQueueWorker<T>(callback_) {
2214
    uv_mutex_init(&async_lock);
2215
  }
2216

    
2217
  virtual ~AsyncProgressQueueWorker() {
2218
    uv_mutex_lock(&async_lock);
2219

    
2220
    while (!asyncdata_.empty()) {
2221
      std::pair<T*, size_t> &datapair = asyncdata_.front();
2222
      T *data = datapair.first;
2223

    
2224
      asyncdata_.pop();
2225

    
2226
      delete[] data;
2227
    }
2228

    
2229
    uv_mutex_unlock(&async_lock);
2230
    uv_mutex_destroy(&async_lock);
2231
  }
2232

    
2233
  void WorkComplete() {
2234
    WorkProgress();
2235
    AsyncWorker::WorkComplete();
2236
  }
2237

    
2238
  void WorkProgress() {
2239
    uv_mutex_lock(&async_lock);
2240

    
2241
    while (!asyncdata_.empty()) {
2242
      std::pair<T*, size_t> &datapair = asyncdata_.front();
2243

    
2244
      T *data = datapair.first;
2245
      size_t size = datapair.second;
2246

    
2247
      asyncdata_.pop();
2248
      uv_mutex_unlock(&async_lock);
2249

    
2250
      // Don't send progress events after we've already completed.
2251
      if (this->callback) {
2252
          this->HandleProgressCallback(data, size);
2253
      }
2254

    
2255
      delete[] data;
2256

    
2257
      uv_mutex_lock(&async_lock);
2258
    }
2259

    
2260
    uv_mutex_unlock(&async_lock);
2261
  }
2262

    
2263
 private:
2264
  void SendProgress_(const T *data, size_t count) {
2265
    T *new_data = new T[count];
2266
    {
2267
      T *it = new_data;
2268
      std::copy(data, data + count, it);
2269
    }
2270

    
2271
    uv_mutex_lock(&async_lock);
2272
    asyncdata_.push(std::pair<T*, size_t>(new_data, count));
2273
    uv_mutex_unlock(&async_lock);
2274

    
2275
    uv_async_send(&this->async);
2276
  }
2277

    
2278
  uv_mutex_t async_lock;
2279
  std::queue<std::pair<T*, size_t> > asyncdata_;
2280
};
2281

    
2282
inline void AsyncExecute (uv_work_t* req) {
2283
  AsyncWorker *worker = static_cast<AsyncWorker*>(req->data);
2284
  worker->Execute();
2285
}
2286

    
2287
inline void AsyncExecuteComplete (uv_work_t* req) {
2288
  AsyncWorker* worker = static_cast<AsyncWorker*>(req->data);
2289
  worker->WorkComplete();
2290
  worker->Destroy();
2291
}
2292

    
2293
inline void AsyncQueueWorker (AsyncWorker* worker) {
2294
  uv_queue_work(
2295
      GetCurrentEventLoop()
2296
    , &worker->request
2297
    , AsyncExecute
2298
    , reinterpret_cast<uv_after_work_cb>(AsyncExecuteComplete)
2299
  );
2300
}
2301

    
2302
namespace imp {
2303

    
2304
inline
2305
ExternalOneByteStringResource const*
2306
GetExternalResource(v8::Local<v8::String> str) {
2307
#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
2308
    return str->GetExternalAsciiStringResource();
2309
#else
2310
    return str->GetExternalOneByteStringResource();
2311
#endif
2312
}
2313

    
2314
inline
2315
bool
2316
IsExternal(v8::Local<v8::String> str) {
2317
#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
2318
    return str->IsExternalAscii();
2319
#else
2320
    return str->IsExternalOneByte();
2321
#endif
2322
}
2323

    
2324
}  // end of namespace imp
2325

    
2326
enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
2327

    
2328
#if NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION
2329
# include "nan_string_bytes.h"  // NOLINT(build/include)
2330
#endif
2331

    
2332
inline v8::Local<v8::Value> Encode(
2333
    const void *buf, size_t len, enum Encoding encoding = BINARY) {
2334
#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION)
2335
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
2336
  node::encoding node_enc = static_cast<node::encoding>(encoding);
2337

    
2338
  if (encoding == UCS2) {
2339
    return node::Encode(
2340
        isolate
2341
      , reinterpret_cast<const uint16_t *>(buf)
2342
      , len / 2);
2343
  } else {
2344
    return node::Encode(
2345
        isolate
2346
      , reinterpret_cast<const char *>(buf)
2347
      , len
2348
      , node_enc);
2349
  }
2350
#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
2351
  return node::Encode(
2352
      v8::Isolate::GetCurrent()
2353
    , buf, len
2354
    , static_cast<node::encoding>(encoding));
2355
#else
2356
# if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
2357
  return node::Encode(buf, len, static_cast<node::encoding>(encoding));
2358
# else
2359
  return imp::Encode(reinterpret_cast<const char*>(buf), len, encoding);
2360
# endif
2361
#endif
2362
}
2363

    
2364
inline ssize_t DecodeBytes(
2365
    v8::Local<v8::Value> val, enum Encoding encoding = BINARY) {
2366
#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
2367
  return node::DecodeBytes(
2368
      v8::Isolate::GetCurrent()
2369
    , val
2370
    , static_cast<node::encoding>(encoding));
2371
#else
2372
# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
2373
  if (encoding == BUFFER) {
2374
    return node::DecodeBytes(val, node::BINARY);
2375
  }
2376
# endif
2377
  return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
2378
#endif
2379
}
2380

    
2381
inline ssize_t DecodeWrite(
2382
    char *buf
2383
  , size_t len
2384
  , v8::Local<v8::Value> val
2385
  , enum Encoding encoding = BINARY) {
2386
#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
2387
  return node::DecodeWrite(
2388
      v8::Isolate::GetCurrent()
2389
    , buf
2390
    , len
2391
    , val
2392
    , static_cast<node::encoding>(encoding));
2393
#else
2394
# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
2395
  if (encoding == BUFFER) {
2396
    return node::DecodeWrite(buf, len, val, node::BINARY);
2397
  }
2398
# endif
2399
  return node::DecodeWrite(
2400
      buf
2401
    , len
2402
    , val
2403
    , static_cast<node::encoding>(encoding));
2404
#endif
2405
}
2406

    
2407
inline void SetPrototypeTemplate(
2408
    v8::Local<v8::FunctionTemplate> templ
2409
  , const char *name
2410
  , v8::Local<v8::Data> value
2411
) {
2412
  HandleScope scope;
2413
  SetTemplate(templ->PrototypeTemplate(), name, value);
2414
}
2415

    
2416
inline void SetPrototypeTemplate(
2417
    v8::Local<v8::FunctionTemplate> templ
2418
  , v8::Local<v8::String> name
2419
  , v8::Local<v8::Data> value
2420
  , v8::PropertyAttribute attributes
2421
) {
2422
  HandleScope scope;
2423
  SetTemplate(templ->PrototypeTemplate(), name, value, attributes);
2424
}
2425

    
2426
inline void SetInstanceTemplate(
2427
    v8::Local<v8::FunctionTemplate> templ
2428
  , const char *name
2429
  , v8::Local<v8::Data> value
2430
) {
2431
  HandleScope scope;
2432
  SetTemplate(templ->InstanceTemplate(), name, value);
2433
}
2434

    
2435
inline void SetInstanceTemplate(
2436
    v8::Local<v8::FunctionTemplate> templ
2437
  , v8::Local<v8::String> name
2438
  , v8::Local<v8::Data> value
2439
  , v8::PropertyAttribute attributes
2440
) {
2441
  HandleScope scope;
2442
  SetTemplate(templ->InstanceTemplate(), name, value, attributes);
2443
}
2444

    
2445
namespace imp {
2446

    
2447
// Note(@agnat): Helper to distinguish different receiver types. The first
2448
// version deals with receivers derived from v8::Template. The second version
2449
// handles everything else. The final argument only serves as discriminator and
2450
// is unused.
2451
template <typename T>
2452
inline
2453
void
2454
SetMethodAux(T recv,
2455
             v8::Local<v8::String> name,
2456
             v8::Local<v8::FunctionTemplate> tpl,
2457
             v8::Template *) {
2458
  recv->Set(name, tpl);
2459
}
2460

    
2461
template <typename T>
2462
inline
2463
void
2464
SetMethodAux(T recv,
2465
             v8::Local<v8::String> name,
2466
             v8::Local<v8::FunctionTemplate> tpl,
2467
             ...) {
2468
  Set(recv, name, GetFunction(tpl).ToLocalChecked());
2469
}
2470

    
2471
}  // end of namespace imp
2472

    
2473
template <typename T, template <typename> class HandleType>
2474
inline void SetMethod(
2475
    HandleType<T> recv
2476
  , const char *name
2477
  , FunctionCallback callback) {
2478
  HandleScope scope;
2479
  v8::Local<v8::FunctionTemplate> t = New<v8::FunctionTemplate>(callback);
2480
  v8::Local<v8::String> fn_name = New(name).ToLocalChecked();
2481
  t->SetClassName(fn_name);
2482
  // Note(@agnat): Pass an empty T* as discriminator. See note on
2483
  // SetMethodAux(...) above
2484
  imp::SetMethodAux(recv, fn_name, t, static_cast<T*>(0));
2485
}
2486

    
2487
inline void SetPrototypeMethod(
2488
    v8::Local<v8::FunctionTemplate> recv
2489
  , const char* name, FunctionCallback callback) {
2490
  HandleScope scope;
2491
  v8::Local<v8::FunctionTemplate> t = New<v8::FunctionTemplate>(
2492
      callback
2493
    , v8::Local<v8::Value>()
2494
    , New<v8::Signature>(recv));
2495
  v8::Local<v8::String> fn_name = New(name).ToLocalChecked();
2496
  recv->PrototypeTemplate()->Set(fn_name, t);
2497
  t->SetClassName(fn_name);
2498
}
2499

    
2500
//=== Accessors and Such =======================================================
2501

    
2502
inline void SetAccessor(
2503
    v8::Local<v8::ObjectTemplate> tpl
2504
  , v8::Local<v8::String> name
2505
  , GetterCallback getter
2506
  , SetterCallback setter = 0
2507
  , v8::Local<v8::Value> data = v8::Local<v8::Value>()
2508
  , v8::AccessControl settings = v8::DEFAULT
2509
  , v8::PropertyAttribute attribute = v8::None
2510
  , imp::Sig signature = imp::Sig()) {
2511
  HandleScope scope;
2512

    
2513
  imp::NativeGetter getter_ =
2514
      imp::GetterCallbackWrapper;
2515
  imp::NativeSetter setter_ =
2516
      setter ? imp::SetterCallbackWrapper : 0;
2517

    
2518
  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2519
  otpl->SetInternalFieldCount(imp::kAccessorFieldCount);
2520
  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2521

    
2522
  obj->SetInternalField(
2523
      imp::kGetterIndex
2524
    , New<v8::External>(reinterpret_cast<void *>(getter)));
2525

    
2526
  if (setter != 0) {
2527
    obj->SetInternalField(
2528
        imp::kSetterIndex
2529
      , New<v8::External>(reinterpret_cast<void *>(setter)));
2530
  }
2531

    
2532
  if (!data.IsEmpty()) {
2533
    obj->SetInternalField(imp::kDataIndex, data);
2534
  }
2535

    
2536
  tpl->SetAccessor(
2537
      name
2538
    , getter_
2539
    , setter_
2540
    , obj
2541
    , settings
2542
    , attribute
2543
    , signature);
2544
}
2545

    
2546
inline bool SetAccessor(
2547
    v8::Local<v8::Object> obj
2548
  , v8::Local<v8::String> name
2549
  , GetterCallback getter
2550
  , SetterCallback setter = 0
2551
  , v8::Local<v8::Value> data = v8::Local<v8::Value>()
2552
  , v8::AccessControl settings = v8::DEFAULT
2553
  , v8::PropertyAttribute attribute = v8::None) {
2554
  HandleScope scope;
2555

    
2556
  imp::NativeGetter getter_ =
2557
      imp::GetterCallbackWrapper;
2558
  imp::NativeSetter setter_ =
2559
      setter ? imp::SetterCallbackWrapper : 0;
2560

    
2561
  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2562
  otpl->SetInternalFieldCount(imp::kAccessorFieldCount);
2563
  v8::Local<v8::Object> dataobj = NewInstance(otpl).ToLocalChecked();
2564

    
2565
  dataobj->SetInternalField(
2566
      imp::kGetterIndex
2567
    , New<v8::External>(reinterpret_cast<void *>(getter)));
2568

    
2569
  if (!data.IsEmpty()) {
2570
    dataobj->SetInternalField(imp::kDataIndex, data);
2571
  }
2572

    
2573
  if (setter) {
2574
    dataobj->SetInternalField(
2575
        imp::kSetterIndex
2576
      , New<v8::External>(reinterpret_cast<void *>(setter)));
2577
  }
2578

    
2579
#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION)
2580
  return obj->SetAccessor(
2581
      GetCurrentContext()
2582
    , name
2583
    , getter_
2584
    , setter_
2585
    , dataobj
2586
    , settings
2587
    , attribute).FromMaybe(false);
2588
#else
2589
  return obj->SetAccessor(
2590
      name
2591
    , getter_
2592
    , setter_
2593
    , dataobj
2594
    , settings
2595
    , attribute);
2596
#endif
2597
}
2598

    
2599
inline void SetNamedPropertyHandler(
2600
    v8::Local<v8::ObjectTemplate> tpl
2601
  , PropertyGetterCallback getter
2602
  , PropertySetterCallback setter = 0
2603
  , PropertyQueryCallback query = 0
2604
  , PropertyDeleterCallback deleter = 0
2605
  , PropertyEnumeratorCallback enumerator = 0
2606
  , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2607
  HandleScope scope;
2608

    
2609
  imp::NativePropertyGetter getter_ =
2610
      imp::PropertyGetterCallbackWrapper;
2611
  imp::NativePropertySetter setter_ =
2612
      setter ? imp::PropertySetterCallbackWrapper : 0;
2613
  imp::NativePropertyQuery query_ =
2614
      query ? imp::PropertyQueryCallbackWrapper : 0;
2615
  imp::NativePropertyDeleter *deleter_ =
2616
      deleter ? imp::PropertyDeleterCallbackWrapper : 0;
2617
  imp::NativePropertyEnumerator enumerator_ =
2618
      enumerator ? imp::PropertyEnumeratorCallbackWrapper : 0;
2619

    
2620
  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2621
  otpl->SetInternalFieldCount(imp::kPropertyFieldCount);
2622
  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2623
  obj->SetInternalField(
2624
      imp::kPropertyGetterIndex
2625
    , New<v8::External>(reinterpret_cast<void *>(getter)));
2626

    
2627
  if (setter) {
2628
    obj->SetInternalField(
2629
        imp::kPropertySetterIndex
2630
      , New<v8::External>(reinterpret_cast<void *>(setter)));
2631
  }
2632

    
2633
  if (query) {
2634
    obj->SetInternalField(
2635
        imp::kPropertyQueryIndex
2636
      , New<v8::External>(reinterpret_cast<void *>(query)));
2637
  }
2638

    
2639
  if (deleter) {
2640
    obj->SetInternalField(
2641
        imp::kPropertyDeleterIndex
2642
      , New<v8::External>(reinterpret_cast<void *>(deleter)));
2643
  }
2644

    
2645
  if (enumerator) {
2646
    obj->SetInternalField(
2647
        imp::kPropertyEnumeratorIndex
2648
      , New<v8::External>(reinterpret_cast<void *>(enumerator)));
2649
  }
2650

    
2651
  if (!data.IsEmpty()) {
2652
    obj->SetInternalField(imp::kDataIndex, data);
2653
  }
2654

    
2655
#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
2656
  tpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
2657
      getter_, setter_, query_, deleter_, enumerator_, obj));
2658
#else
2659
  tpl->SetNamedPropertyHandler(
2660
      getter_
2661
    , setter_
2662
    , query_
2663
    , deleter_
2664
    , enumerator_
2665
    , obj);
2666
#endif
2667
}
2668

    
2669
inline void SetIndexedPropertyHandler(
2670
    v8::Local<v8::ObjectTemplate> tpl
2671
  , IndexGetterCallback getter
2672
  , IndexSetterCallback setter = 0
2673
  , IndexQueryCallback query = 0
2674
  , IndexDeleterCallback deleter = 0
2675
  , IndexEnumeratorCallback enumerator = 0
2676
  , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2677
  HandleScope scope;
2678

    
2679
  imp::NativeIndexGetter getter_ =
2680
      imp::IndexGetterCallbackWrapper;
2681
  imp::NativeIndexSetter setter_ =
2682
      setter ? imp::IndexSetterCallbackWrapper : 0;
2683
  imp::NativeIndexQuery query_ =
2684
      query ? imp::IndexQueryCallbackWrapper : 0;
2685
  imp::NativeIndexDeleter deleter_ =
2686
      deleter ? imp::IndexDeleterCallbackWrapper : 0;
2687
  imp::NativeIndexEnumerator enumerator_ =
2688
      enumerator ? imp::IndexEnumeratorCallbackWrapper : 0;
2689

    
2690
  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2691
  otpl->SetInternalFieldCount(imp::kIndexPropertyFieldCount);
2692
  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2693
  obj->SetInternalField(
2694
      imp::kIndexPropertyGetterIndex
2695
    , New<v8::External>(reinterpret_cast<void *>(getter)));
2696

    
2697
  if (setter) {
2698
    obj->SetInternalField(
2699
        imp::kIndexPropertySetterIndex
2700
      , New<v8::External>(reinterpret_cast<void *>(setter)));
2701
  }
2702

    
2703
  if (query) {
2704
    obj->SetInternalField(
2705
        imp::kIndexPropertyQueryIndex
2706
      , New<v8::External>(reinterpret_cast<void *>(query)));
2707
  }
2708

    
2709
  if (deleter) {
2710
    obj->SetInternalField(
2711
        imp::kIndexPropertyDeleterIndex
2712
      , New<v8::External>(reinterpret_cast<void *>(deleter)));
2713
  }
2714

    
2715
  if (enumerator) {
2716
    obj->SetInternalField(
2717
        imp::kIndexPropertyEnumeratorIndex
2718
      , New<v8::External>(reinterpret_cast<void *>(enumerator)));
2719
  }
2720

    
2721
  if (!data.IsEmpty()) {
2722
    obj->SetInternalField(imp::kDataIndex, data);
2723
  }
2724

    
2725
#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
2726
  tpl->SetHandler(v8::IndexedPropertyHandlerConfiguration(
2727
      getter_, setter_, query_, deleter_, enumerator_, obj));
2728
#else
2729
  tpl->SetIndexedPropertyHandler(
2730
      getter_
2731
    , setter_
2732
    , query_
2733
    , deleter_
2734
    , enumerator_
2735
    , obj);
2736
#endif
2737
}
2738

    
2739
inline void SetCallHandler(
2740
    v8::Local<v8::FunctionTemplate> tpl
2741
  , FunctionCallback callback
2742
  , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2743
  HandleScope scope;
2744

    
2745
  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2746
  otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
2747
  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2748

    
2749
  obj->SetInternalField(
2750
      imp::kFunctionIndex
2751
    , New<v8::External>(reinterpret_cast<void *>(callback)));
2752

    
2753
  if (!data.IsEmpty()) {
2754
    obj->SetInternalField(imp::kDataIndex, data);
2755
  }
2756

    
2757
  tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj);
2758
}
2759

    
2760

    
2761
inline void SetCallAsFunctionHandler(
2762
    v8::Local<v8::ObjectTemplate> tpl,
2763
    FunctionCallback callback,
2764
    v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2765
  HandleScope scope;
2766

    
2767
  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2768
  otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
2769
  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2770

    
2771
  obj->SetInternalField(
2772
      imp::kFunctionIndex
2773
    , New<v8::External>(reinterpret_cast<void *>(callback)));
2774

    
2775
  if (!data.IsEmpty()) {
2776
    obj->SetInternalField(imp::kDataIndex, data);
2777
  }
2778

    
2779
  tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj);
2780
}
2781

    
2782
//=== Weak Persistent Handling =================================================
2783

    
2784
#include "nan_weak.h"  // NOLINT(build/include)
2785

    
2786
//=== ObjectWrap ===============================================================
2787

    
2788
#include "nan_object_wrap.h"  // NOLINT(build/include)
2789

    
2790
//=== HiddenValue/Private ======================================================
2791

    
2792
#include "nan_private.h"  // NOLINT(build/include)
2793

    
2794
//=== Export ==================================================================
2795

    
2796
inline
2797
void
2798
Export(ADDON_REGISTER_FUNCTION_ARGS_TYPE target, const char *name,
2799
    FunctionCallback f) {
2800
  HandleScope scope;
2801

    
2802
  Set(target, New<v8::String>(name).ToLocalChecked(),
2803
      GetFunction(New<v8::FunctionTemplate>(f)).ToLocalChecked());
2804
}
2805

    
2806
//=== Tap Reverse Binding =====================================================
2807

    
2808
struct Tap {
2809
  explicit Tap(v8::Local<v8::Value> t) : t_() {
2810
    HandleScope scope;
2811

    
2812
    t_.Reset(To<v8::Object>(t).ToLocalChecked());
2813
  }
2814

    
2815
  ~Tap() { t_.Reset(); }  // not sure if neccessary
2816

    
2817
  inline void plan(int i) {
2818
    HandleScope scope;
2819
    v8::Local<v8::Value> arg = New(i);
2820
    Call("plan", New(t_), 1, &arg);
2821
  }
2822

    
2823
  inline void ok(bool isOk, const char *msg = NULL) {
2824
    HandleScope scope;
2825
    v8::Local<v8::Value> args[2];
2826
    args[0] = New(isOk);
2827
    if (msg) args[1] = New(msg).ToLocalChecked();
2828
    Call("ok", New(t_), msg ? 2 : 1, args);
2829
  }
2830

    
2831
  inline void pass(const char * msg = NULL) {
2832
    HandleScope scope;
2833
    v8::Local<v8::Value> hmsg;
2834
    if (msg) hmsg = New(msg).ToLocalChecked();
2835
    Call("pass", New(t_), msg ? 1 : 0, &hmsg);
2836
  }
2837

    
2838
  inline void end() {
2839
    HandleScope scope;
2840
    Call("end", New(t_), 0, NULL);
2841
  }
2842

    
2843
 private:
2844
  Persistent<v8::Object> t_;
2845
};
2846

    
2847
#define NAN_STRINGIZE2(x) #x
2848
#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
2849
#define NAN_TEST_EXPRESSION(expression) \
2850
  ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
2851

    
2852
#define NAN_EXPORT(target, function) Export(target, #function, function)
2853

    
2854
#undef TYPE_CHECK
2855

    
2856
//=== Generic Maybefication ===================================================
2857

    
2858
namespace imp {
2859

    
2860
template <typename T> struct Maybefier;
2861

    
2862
template <typename T> struct Maybefier<v8::Local<T> > {
2863
  inline static MaybeLocal<T> convert(v8::Local<T> v) {
2864
    return v;
2865
  }
2866
};
2867

    
2868
template <typename T> struct Maybefier<MaybeLocal<T> > {
2869
  inline static MaybeLocal<T> convert(MaybeLocal<T> v) {
2870
    return v;
2871
  }
2872
};
2873

    
2874
}  // end of namespace imp
2875

    
2876
template <typename T, template <typename> class MaybeMaybe>
2877
inline MaybeLocal<T>
2878
MakeMaybe(MaybeMaybe<T> v) {
2879
  return imp::Maybefier<MaybeMaybe<T> >::convert(v);
2880
}
2881

    
2882
//=== TypedArrayContents =======================================================
2883

    
2884
#include "nan_typedarray_contents.h"  // NOLINT(build/include)
2885

    
2886
//=== JSON =====================================================================
2887

    
2888
#include "nan_json.h"  // NOLINT(build/include)
2889

    
2890
}  // end of namespace Nan
2891

    
2892
#endif  // NAN_H_
(5-5/26)