Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

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