프로젝트

일반

사용자정보

통계
| 개정판:

root / HServer / 00.Server / 00.Program / node_modules / nan / nan.h

이력 | 보기 | 이력해설 | 다운로드 (81.7 KB)

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