UNPKG

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