1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #ifndef SRC_NODE_H_
23 #define SRC_NODE_H_
24 
25 #ifdef _WIN32
26 # ifndef BUILDING_NODE_EXTENSION
27 #   define NODE_EXTERN __declspec(dllexport)
28 # else
29 #   define NODE_EXTERN __declspec(dllimport)
30 # endif
31 #else
32 # define NODE_EXTERN /* nothing */
33 #endif
34 
35 #ifdef BUILDING_NODE_EXTENSION
36 # undef BUILDING_V8_SHARED
37 # undef BUILDING_UV_SHARED
38 # define USING_V8_SHARED 1
39 # define USING_UV_SHARED 1
40 #endif
41 
42 // This should be defined in make system.
43 // See issue https://github.com/nodejs/node-v0.x-archive/issues/1236
44 #if defined(__MINGW32__) || defined(_MSC_VER)
45 #ifndef _WIN32_WINNT
46 # define _WIN32_WINNT   0x0600  // Windows Server 2008
47 #endif
48 
49 #ifndef NOMINMAX
50 # define NOMINMAX
51 #endif
52 
53 #endif
54 
55 #if defined(_MSC_VER)
56 #define PATH_MAX MAX_PATH
57 #endif
58 
59 #ifdef _WIN32
60 # define SIGKILL         9
61 #endif
62 
63 #include "v8.h"  // NOLINT(build/include_order)
64 #include "v8-platform.h"  // NOLINT(build/include_order)
65 #include "node_version.h"  // NODE_MODULE_VERSION
66 
67 #define NODE_MAKE_VERSION(major, minor, patch)                                \
68   ((major) * 0x1000 + (minor) * 0x100 + (patch))
69 
70 #ifdef __clang__
71 # define NODE_CLANG_AT_LEAST(major, minor, patch)                             \
72   (NODE_MAKE_VERSION(major, minor, patch) <=                                  \
73       NODE_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__))
74 #else
75 # define NODE_CLANG_AT_LEAST(major, minor, patch) (0)
76 #endif
77 
78 #ifdef __GNUC__
79 # define NODE_GNUC_AT_LEAST(major, minor, patch)                              \
80   (NODE_MAKE_VERSION(major, minor, patch) <=                                  \
81       NODE_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__))
82 #else
83 # define NODE_GNUC_AT_LEAST(major, minor, patch) (0)
84 #endif
85 
86 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
87 # define NODE_DEPRECATED(message, declarator) declarator
88 #else  // NODE_WANT_INTERNALS
89 # if NODE_CLANG_AT_LEAST(2, 9, 0) || NODE_GNUC_AT_LEAST(4, 5, 0)
90 #  define NODE_DEPRECATED(message, declarator)                                 \
91     __attribute__((deprecated(message))) declarator
92 # elif defined(_MSC_VER)
93 #  define NODE_DEPRECATED(message, declarator)                                 \
94     __declspec(deprecated) declarator
95 # else
96 #  define NODE_DEPRECATED(message, declarator) declarator
97 # endif
98 #endif
99 
100 // Forward-declare libuv loop
101 struct uv_loop_s;
102 
103 // Forward-declare these functions now to stop MSVS from becoming
104 // terminally confused when it's done in node_internals.h
105 namespace node {
106 
107 namespace tracing {
108 
109 class TracingController;
110 
111 }
112 
113 NODE_EXTERN v8::Local<v8::Value> ErrnoException(v8::Isolate* isolate,
114                                                 int errorno,
115                                                 const char* syscall = nullptr,
116                                                 const char* message = nullptr,
117                                                 const char* path = nullptr);
118 NODE_EXTERN v8::Local<v8::Value> UVException(v8::Isolate* isolate,
119                                              int errorno,
120                                              const char* syscall = nullptr,
121                                              const char* message = nullptr,
122                                              const char* path = nullptr);
123 NODE_EXTERN v8::Local<v8::Value> UVException(v8::Isolate* isolate,
124                                              int errorno,
125                                              const char* syscall,
126                                              const char* message,
127                                              const char* path,
128                                              const char* dest);
129 
130 NODE_DEPRECATED("Use ErrnoException(isolate, ...)",
131                 inline v8::Local<v8::Value> ErrnoException(
132       int errorno,
133       const char* syscall = nullptr,
134       const char* message = nullptr,
135       const char* path = nullptr) {
136   return ErrnoException(v8::Isolate::GetCurrent(),
137                         errorno,
138                         syscall,
139                         message,
140                         path);
141 })
142 
143 NODE_DEPRECATED("Use UVException(isolate, ...)",
144                 inline v8::Local<v8::Value> UVException(int errorno,
145                                         const char* syscall = nullptr,
146                                         const char* message = nullptr,
147                                         const char* path = nullptr) {
148   return UVException(v8::Isolate::GetCurrent(),
149                      errorno,
150                      syscall,
151                      message,
152                      path);
153 })
154 
155 /*
156  * These methods need to be called in a HandleScope.
157  *
158  * It is preferred that you use the `MakeCallback` overloads taking
159  * `async_context` arguments.
160  */
161 
162 NODE_DEPRECATED("Use MakeCallback(..., async_context)",
163                 NODE_EXTERN v8::Local<v8::Value> MakeCallback(
164                     v8::Isolate* isolate,
165                     v8::Local<v8::Object> recv,
166                     const char* method,
167                     int argc,
168                     v8::Local<v8::Value>* argv));
169 NODE_DEPRECATED("Use MakeCallback(..., async_context)",
170                 NODE_EXTERN v8::Local<v8::Value> MakeCallback(
171                     v8::Isolate* isolate,
172                     v8::Local<v8::Object> recv,
173                     v8::Local<v8::String> symbol,
174                     int argc,
175                     v8::Local<v8::Value>* argv));
176 NODE_DEPRECATED("Use MakeCallback(..., async_context)",
177                 NODE_EXTERN v8::Local<v8::Value> MakeCallback(
178                     v8::Isolate* isolate,
179                     v8::Local<v8::Object> recv,
180                     v8::Local<v8::Function> callback,
181                     int argc,
182                     v8::Local<v8::Value>* argv));
183 
184 }  // namespace node
185 
186 #include <assert.h>
187 #include <stdint.h>
188 
189 #ifndef NODE_STRINGIFY
190 #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
191 #define NODE_STRINGIFY_HELPER(n) #n
192 #endif
193 
194 #ifdef _WIN32
195 #if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
196 typedef intptr_t ssize_t;
197 # define _SSIZE_T_
198 # define _SSIZE_T_DEFINED
199 #endif
200 #else  // !_WIN32
201 # include <sys/types.h>  // size_t, ssize_t
202 #endif  // _WIN32
203 
204 
205 namespace node {
206 
207 // TODO(addaleax): Remove all of these.
208 NODE_DEPRECATED("use command-line flags",
209                 NODE_EXTERN extern bool no_deprecation);
210 #if HAVE_OPENSSL
211 NODE_DEPRECATED("use command-line flags",
212                 NODE_EXTERN extern bool ssl_openssl_cert_store);
213 # if NODE_FIPS_MODE
214 NODE_DEPRECATED("use command-line flags",
215                 NODE_EXTERN extern bool enable_fips_crypto);
216 NODE_DEPRECATED("user command-line flags",
217                 NODE_EXTERN extern bool force_fips_crypto);
218 # endif
219 #endif
220 
221 // TODO(addaleax): Officially deprecate this and replace it with something
222 // better suited for a public embedder API.
223 NODE_EXTERN int Start(int argc, char* argv[]);
224 
225 // TODO(addaleax): Officially deprecate this and replace it with something
226 // better suited for a public embedder API.
227 NODE_EXTERN void Init(int* argc,
228                       const char** argv,
229                       int* exec_argc,
230                       const char*** exec_argv);
231 
232 class ArrayBufferAllocator;
233 
234 NODE_EXTERN ArrayBufferAllocator* CreateArrayBufferAllocator();
235 NODE_EXTERN void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator);
236 
237 class IsolateData;
238 class Environment;
239 
240 class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {
241  public:
~MultiIsolatePlatform()242   virtual ~MultiIsolatePlatform() { }
243   // Returns true if work was dispatched or executed. New tasks that are
244   // posted during flushing of the queue are postponed until the next
245   // flushing.
246   virtual bool FlushForegroundTasks(v8::Isolate* isolate) = 0;
247   virtual void DrainBackgroundTasks(v8::Isolate* isolate) = 0;
248   virtual void CancelPendingDelayedTasks(v8::Isolate* isolate) = 0;
249 
250   // These will be called by the `IsolateData` creation/destruction functions.
251   virtual void RegisterIsolate(IsolateData* isolate_data,
252                                struct uv_loop_s* loop) = 0;
253   virtual void UnregisterIsolate(IsolateData* isolate_data) = 0;
254 };
255 
256 // Creates a new isolate with Node.js-specific settings.
257 NODE_EXTERN v8::Isolate* NewIsolate(ArrayBufferAllocator* allocator);
258 
259 // Creates a new context with Node.js-specific tweaks.
260 NODE_EXTERN v8::Local<v8::Context> NewContext(
261     v8::Isolate* isolate,
262     v8::Local<v8::ObjectTemplate> object_template =
263         v8::Local<v8::ObjectTemplate>());
264 
265 // If `platform` is passed, it will be used to register new Worker instances.
266 // It can be `nullptr`, in which case creating new Workers inside of
267 // Environments that use this `IsolateData` will not work.
268 // TODO(helloshuangzi): switch to default parameters.
269 NODE_EXTERN IsolateData* CreateIsolateData(
270     v8::Isolate* isolate,
271     struct uv_loop_s* loop);
272 NODE_EXTERN IsolateData* CreateIsolateData(
273     v8::Isolate* isolate,
274     struct uv_loop_s* loop,
275     MultiIsolatePlatform* platform);
276 NODE_EXTERN IsolateData* CreateIsolateData(
277     v8::Isolate* isolate,
278     struct uv_loop_s* loop,
279     MultiIsolatePlatform* platform,
280     ArrayBufferAllocator* allocator);
281 NODE_EXTERN void FreeIsolateData(IsolateData* isolate_data);
282 
283 // TODO(addaleax): Add an official variant using STL containers, and move
284 // per-Environment options parsing here.
285 NODE_EXTERN Environment* CreateEnvironment(IsolateData* isolate_data,
286                                            v8::Local<v8::Context> context,
287                                            int argc,
288                                            const char* const* argv,
289                                            int exec_argc,
290                                            const char* const* exec_argv);
291 
292 NODE_EXTERN void LoadEnvironment(Environment* env);
293 NODE_EXTERN void FreeEnvironment(Environment* env);
294 
295 // This may return nullptr if context is not associated with a Node instance.
296 NODE_EXTERN Environment* GetCurrentEnvironment(v8::Local<v8::Context> context);
297 
298 // This returns the MultiIsolatePlatform used in the main thread of Node.js.
299 // If NODE_USE_V8_PLATFORM haven't been defined when Node.js was built,
300 // it returns nullptr.
301 NODE_EXTERN MultiIsolatePlatform* GetMainThreadMultiIsolatePlatform();
302 
303 NODE_EXTERN MultiIsolatePlatform* CreatePlatform(
304     int thread_pool_size,
305     node::tracing::TracingController* tracing_controller);
306 MultiIsolatePlatform* InitializeV8Platform(int thread_pool_size);
307 NODE_EXTERN void FreePlatform(MultiIsolatePlatform* platform);
308 
309 NODE_EXTERN void EmitBeforeExit(Environment* env);
310 NODE_EXTERN int EmitExit(Environment* env);
311 NODE_EXTERN void RunAtExit(Environment* env);
312 
313 // This may return nullptr if the current v8::Context is not associated
314 // with a Node instance.
315 NODE_EXTERN struct uv_loop_s* GetCurrentEventLoop(v8::Isolate* isolate);
316 
317 /* Converts a unixtime to V8 Date */
318 NODE_DEPRECATED("Use v8::Date::New() directly",
319                 inline v8::Local<v8::Value> NODE_UNIXTIME_V8(double time) {
320                   return v8::Date::New(
321                              v8::Isolate::GetCurrent()->GetCurrentContext(),
322                              1000 * time)
323                       .ToLocalChecked();
324                 })
325 #define NODE_UNIXTIME_V8 node::NODE_UNIXTIME_V8
326 NODE_DEPRECATED("Use v8::Date::ValueOf() directly",
NODE_V8_UNIXTIME(v8::Local<v8::Date> date)327                 inline double NODE_V8_UNIXTIME(v8::Local<v8::Date> date) {
328   return date->ValueOf() / 1000;
329 })
330 #define NODE_V8_UNIXTIME node::NODE_V8_UNIXTIME
331 
332 #define NODE_DEFINE_CONSTANT(target, constant)                                \
333   do {                                                                        \
334     v8::Isolate* isolate = target->GetIsolate();                              \
335     v8::Local<v8::Context> context = isolate->GetCurrentContext();            \
336     v8::Local<v8::String> constant_name =                                     \
337         v8::String::NewFromUtf8(isolate, #constant,                           \
338             v8::NewStringType::kInternalized).ToLocalChecked();               \
339     v8::Local<v8::Number> constant_value =                                    \
340         v8::Number::New(isolate, static_cast<double>(constant));              \
341     v8::PropertyAttribute constant_attributes =                               \
342         static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);    \
343     (target)->DefineOwnProperty(context,                                      \
344                                 constant_name,                                \
345                                 constant_value,                               \
346                                 constant_attributes).FromJust();              \
347   }                                                                           \
348   while (0)
349 
350 #define NODE_DEFINE_HIDDEN_CONSTANT(target, constant)                         \
351   do {                                                                        \
352     v8::Isolate* isolate = target->GetIsolate();                              \
353     v8::Local<v8::Context> context = isolate->GetCurrentContext();            \
354     v8::Local<v8::String> constant_name =                                     \
355         v8::String::NewFromUtf8(isolate, #constant,                           \
356                                 v8::NewStringType::kInternalized)             \
357                                   .ToLocalChecked();                          \
358     v8::Local<v8::Number> constant_value =                                    \
359         v8::Number::New(isolate, static_cast<double>(constant));              \
360     v8::PropertyAttribute constant_attributes =                               \
361         static_cast<v8::PropertyAttribute>(v8::ReadOnly |                     \
362                                            v8::DontDelete |                   \
363                                            v8::DontEnum);                     \
364     (target)->DefineOwnProperty(context,                                      \
365                                 constant_name,                                \
366                                 constant_value,                               \
367                                 constant_attributes).FromJust();              \
368   }                                                                           \
369   while (0)
370 
371 // Used to be a macro, hence the uppercase name.
372 inline void NODE_SET_METHOD(v8::Local<v8::Template> recv,
373                             const char* name,
374                             v8::FunctionCallback callback) {
375   v8::Isolate* isolate = v8::Isolate::GetCurrent();
376   v8::HandleScope handle_scope(isolate);
377   v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate,
378                                                                 callback);
379   v8::Local<v8::String> fn_name = v8::String::NewFromUtf8(isolate, name,
380       v8::NewStringType::kInternalized).ToLocalChecked();
381   t->SetClassName(fn_name);
382   recv->Set(fn_name, t);
383 }
384 
385 // Used to be a macro, hence the uppercase name.
NODE_SET_METHOD(v8::Local<v8::Object> recv,const char * name,v8::FunctionCallback callback)386 inline void NODE_SET_METHOD(v8::Local<v8::Object> recv,
387                             const char* name,
388                             v8::FunctionCallback callback) {
389   v8::Isolate* isolate = v8::Isolate::GetCurrent();
390   v8::HandleScope handle_scope(isolate);
391   v8::Local<v8::Context> context = isolate->GetCurrentContext();
392   v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate,
393                                                                 callback);
394   v8::Local<v8::Function> fn = t->GetFunction(context).ToLocalChecked();
395   v8::Local<v8::String> fn_name = v8::String::NewFromUtf8(isolate, name,
396       v8::NewStringType::kInternalized).ToLocalChecked();
397   fn->SetName(fn_name);
398   recv->Set(fn_name, fn);
399 }
400 #define NODE_SET_METHOD node::NODE_SET_METHOD
401 
402 // Used to be a macro, hence the uppercase name.
403 // Not a template because it only makes sense for FunctionTemplates.
NODE_SET_PROTOTYPE_METHOD(v8::Local<v8::FunctionTemplate> recv,const char * name,v8::FunctionCallback callback)404 inline void NODE_SET_PROTOTYPE_METHOD(v8::Local<v8::FunctionTemplate> recv,
405                                       const char* name,
406                                       v8::FunctionCallback callback) {
407   v8::Isolate* isolate = v8::Isolate::GetCurrent();
408   v8::HandleScope handle_scope(isolate);
409   v8::Local<v8::Signature> s = v8::Signature::New(isolate, recv);
410   v8::Local<v8::FunctionTemplate> t =
411       v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(), s);
412   v8::Local<v8::String> fn_name = v8::String::NewFromUtf8(isolate, name,
413       v8::NewStringType::kInternalized).ToLocalChecked();
414   t->SetClassName(fn_name);
415   recv->PrototypeTemplate()->Set(fn_name, t);
416 }
417 #define NODE_SET_PROTOTYPE_METHOD node::NODE_SET_PROTOTYPE_METHOD
418 
419 // BINARY is a deprecated alias of LATIN1.
420 enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER, LATIN1 = BINARY};
421 
422 NODE_EXTERN enum encoding ParseEncoding(
423     v8::Isolate* isolate,
424     v8::Local<v8::Value> encoding_v,
425     enum encoding default_encoding = LATIN1);
426 NODE_DEPRECATED("Use ParseEncoding(isolate, ...)",
427                 inline enum encoding ParseEncoding(
428       v8::Local<v8::Value> encoding_v,
429       enum encoding default_encoding = LATIN1) {
430   return ParseEncoding(v8::Isolate::GetCurrent(), encoding_v, default_encoding);
431 })
432 
433 NODE_EXTERN void FatalException(v8::Isolate* isolate,
434                                 const v8::TryCatch& try_catch);
435 
436 NODE_DEPRECATED("Use FatalException(isolate, ...)",
437                 inline void FatalException(const v8::TryCatch& try_catch) {
438   return FatalException(v8::Isolate::GetCurrent(), try_catch);
439 })
440 
441 NODE_EXTERN v8::Local<v8::Value> Encode(v8::Isolate* isolate,
442                                         const char* buf,
443                                         size_t len,
444                                         enum encoding encoding = LATIN1);
445 
446 // Warning: This reverses endianness on Big Endian platforms, even though the
447 // signature using uint16_t implies that it should not.
448 NODE_EXTERN v8::Local<v8::Value> Encode(v8::Isolate* isolate,
449                                         const uint16_t* buf,
450                                         size_t len);
451 
452 NODE_DEPRECATED("Use Encode(isolate, ...)",
453                 inline v8::Local<v8::Value> Encode(
454     const void* buf,
455     size_t len,
456     enum encoding encoding = LATIN1) {
457   v8::Isolate* isolate = v8::Isolate::GetCurrent();
458   if (encoding == UCS2) {
459     assert(reinterpret_cast<uintptr_t>(buf) % sizeof(uint16_t) == 0 &&
460            "UCS2 buffer must be aligned on two-byte boundary.");
461     const uint16_t* that = static_cast<const uint16_t*>(buf);
462     return Encode(isolate, that, len / sizeof(*that));
463   }
464   return Encode(isolate, static_cast<const char*>(buf), len, encoding);
465 })
466 
467 // Returns -1 if the handle was not valid for decoding
468 NODE_EXTERN ssize_t DecodeBytes(v8::Isolate* isolate,
469                                 v8::Local<v8::Value>,
470                                 enum encoding encoding = LATIN1);
471 NODE_DEPRECATED("Use DecodeBytes(isolate, ...)",
472                 inline ssize_t DecodeBytes(
473     v8::Local<v8::Value> val,
474     enum encoding encoding = LATIN1) {
475   return DecodeBytes(v8::Isolate::GetCurrent(), val, encoding);
476 })
477 
478 // returns bytes written.
479 NODE_EXTERN ssize_t DecodeWrite(v8::Isolate* isolate,
480                                 char* buf,
481                                 size_t buflen,
482                                 v8::Local<v8::Value>,
483                                 enum encoding encoding = LATIN1);
484 NODE_DEPRECATED("Use DecodeWrite(isolate, ...)",
485                 inline ssize_t DecodeWrite(char* buf,
486                                            size_t buflen,
487                                            v8::Local<v8::Value> val,
488                                            enum encoding encoding = LATIN1) {
489   return DecodeWrite(v8::Isolate::GetCurrent(), buf, buflen, val, encoding);
490 })
491 
492 #ifdef _WIN32
493 NODE_EXTERN v8::Local<v8::Value> WinapiErrnoException(
494     v8::Isolate* isolate,
495     int errorno,
496     const char* syscall = nullptr,
497     const char* msg = "",
498     const char* path = nullptr);
499 
500 NODE_DEPRECATED("Use WinapiErrnoException(isolate, ...)",
501                 inline v8::Local<v8::Value> WinapiErrnoException(int errorno,
502     const char* syscall = nullptr,  const char* msg = "",
503     const char* path = nullptr) {
504   return WinapiErrnoException(v8::Isolate::GetCurrent(),
505                               errorno,
506                               syscall,
507                               msg,
508                               path);
509 })
510 #endif
511 
512 const char* signo_string(int errorno);
513 
514 
515 typedef void (*addon_register_func)(
516     v8::Local<v8::Object> exports,
517     v8::Local<v8::Value> module,
518     void* priv);
519 
520 typedef void (*addon_context_register_func)(
521     v8::Local<v8::Object> exports,
522     v8::Local<v8::Value> module,
523     v8::Local<v8::Context> context,
524     void* priv);
525 
526 struct node_module {
527   int nm_version;
528   unsigned int nm_flags;
529   void* nm_dso_handle;
530   const char* nm_filename;
531   node::addon_register_func nm_register_func;
532   node::addon_context_register_func nm_context_register_func;
533   const char* nm_modname;
534   void* nm_priv;
535   struct node_module* nm_link;
536 };
537 
538 extern "C" NODE_EXTERN void node_module_register(void* mod);
539 
540 #ifdef _WIN32
541 # define NODE_MODULE_EXPORT __declspec(dllexport)
542 #else
543 # define NODE_MODULE_EXPORT __attribute__((visibility("default")))
544 #endif
545 
546 #ifdef NODE_SHARED_MODE
547 # define NODE_CTOR_PREFIX
548 #else
549 # define NODE_CTOR_PREFIX static
550 #endif
551 
552 #if defined(_MSC_VER)
553 #pragma section(".CRT$XCU", read)
554 #define NODE_C_CTOR(fn)                                               \
555   NODE_CTOR_PREFIX void __cdecl fn(void);                             \
556   __declspec(dllexport, allocate(".CRT$XCU"))                         \
557       void (__cdecl*fn ## _)(void) = fn;                              \
558   NODE_CTOR_PREFIX void __cdecl fn(void)
559 #else
560 #define NODE_C_CTOR(fn)                                               \
561   NODE_CTOR_PREFIX void fn(void) __attribute__((constructor));        \
562   NODE_CTOR_PREFIX void fn(void)
563 #endif
564 
565 #define NODE_MODULE_X(modname, regfunc, priv, flags)                  \
566   extern "C" {                                                        \
567     static node::node_module _module =                                \
568     {                                                                 \
569       NODE_MODULE_VERSION,                                            \
570       flags,                                                          \
571       NULL,  /* NOLINT (readability/null_usage) */                    \
572       __FILE__,                                                       \
573       (node::addon_register_func) (regfunc),                          \
574       NULL,  /* NOLINT (readability/null_usage) */                    \
575       NODE_STRINGIFY(modname),                                        \
576       priv,                                                           \
577       NULL   /* NOLINT (readability/null_usage) */                    \
578     };                                                                \
579     NODE_C_CTOR(_register_ ## modname) {                              \
580       node_module_register(&_module);                                 \
581     }                                                                 \
582   }
583 
584 #define NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, priv, flags)    \
585   extern "C" {                                                        \
586     static node::node_module _module =                                \
587     {                                                                 \
588       NODE_MODULE_VERSION,                                            \
589       flags,                                                          \
590       NULL,  /* NOLINT (readability/null_usage) */                    \
591       __FILE__,                                                       \
592       NULL,  /* NOLINT (readability/null_usage) */                    \
593       (node::addon_context_register_func) (regfunc),                  \
594       NODE_STRINGIFY(modname),                                        \
595       priv,                                                           \
596       NULL  /* NOLINT (readability/null_usage) */                     \
597     };                                                                \
598     NODE_C_CTOR(_register_ ## modname) {                              \
599       node_module_register(&_module);                                 \
600     }                                                                 \
601   }
602 
603 // Usage: `NODE_MODULE(NODE_GYP_MODULE_NAME, InitializerFunction)`
604 // If no NODE_MODULE is declared, Node.js looks for the well-known
605 // symbol `node_register_module_v${NODE_MODULE_VERSION}`.
606 #define NODE_MODULE(modname, regfunc)                                 \
607   NODE_MODULE_X(modname, regfunc, NULL, 0)  // NOLINT (readability/null_usage)
608 
609 #define NODE_MODULE_CONTEXT_AWARE(modname, regfunc)                   \
610   /* NOLINTNEXTLINE (readability/null_usage) */                       \
611   NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0)
612 
613 /*
614  * For backward compatibility in add-on modules.
615  */
616 #define NODE_MODULE_DECL /* nothing */
617 
618 #define NODE_MODULE_INITIALIZER_BASE node_register_module_v
619 
620 #define NODE_MODULE_INITIALIZER_X(base, version)                      \
621     NODE_MODULE_INITIALIZER_X_HELPER(base, version)
622 
623 #define NODE_MODULE_INITIALIZER_X_HELPER(base, version) base##version
624 
625 #define NODE_MODULE_INITIALIZER                                       \
626   NODE_MODULE_INITIALIZER_X(NODE_MODULE_INITIALIZER_BASE,             \
627       NODE_MODULE_VERSION)
628 
629 #define NODE_MODULE_INIT()                                            \
630   extern "C" NODE_MODULE_EXPORT void                                  \
631   NODE_MODULE_INITIALIZER(v8::Local<v8::Object> exports,              \
632                           v8::Local<v8::Value> module,                \
633                           v8::Local<v8::Context> context);            \
634   NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME,                     \
635                             NODE_MODULE_INITIALIZER)                  \
636   void NODE_MODULE_INITIALIZER(v8::Local<v8::Object> exports,         \
637                                v8::Local<v8::Value> module,           \
638                                v8::Local<v8::Context> context)
639 
640 /* Called after the event loop exits but before the VM is disposed.
641  * Callbacks are run in reverse order of registration, i.e. newest first.
642  */
643 NODE_EXTERN void AtExit(void (*cb)(void* arg), void* arg = 0);
644 
645 /* Registers a callback with the passed-in Environment instance. The callback
646  * is called after the event loop exits, but before the VM is disposed.
647  * Callbacks are run in reverse order of registration, i.e. newest first.
648  */
649 NODE_EXTERN void AtExit(Environment* env, void (*cb)(void* arg), void* arg = 0);
650 
651 typedef void (*promise_hook_func) (v8::PromiseHookType type,
652                                    v8::Local<v8::Promise> promise,
653                                    v8::Local<v8::Value> parent,
654                                    void* arg);
655 
656 typedef double async_id;
657 struct async_context {
658   ::node::async_id async_id;
659   ::node::async_id trigger_async_id;
660 };
661 
662 /* Registers an additional v8::PromiseHook wrapper. This API exists because V8
663  * itself supports only a single PromiseHook. */
664 NODE_DEPRECATED("Use async_hooks directly instead",
665                 NODE_EXTERN void AddPromiseHook(v8::Isolate* isolate,
666                                                 promise_hook_func fn,
667                                                 void* arg));
668 
669 /* This is a lot like node::AtExit, except that the hooks added via this
670  * function are run before the AtExit ones and will always be registered
671  * for the current Environment instance.
672  * These functions are safe to use in an addon supporting multiple
673  * threads/isolates. */
674 NODE_EXTERN void AddEnvironmentCleanupHook(v8::Isolate* isolate,
675                                            void (*fun)(void* arg),
676                                            void* arg);
677 
678 NODE_EXTERN void RemoveEnvironmentCleanupHook(v8::Isolate* isolate,
679                                               void (*fun)(void* arg),
680                                               void* arg);
681 
682 /* Returns the id of the current execution context. If the return value is
683  * zero then no execution has been set. This will happen if the user handles
684  * I/O from native code. */
685 NODE_EXTERN async_id AsyncHooksGetExecutionAsyncId(v8::Isolate* isolate);
686 
687 /* Return same value as async_hooks.triggerAsyncId(); */
688 NODE_EXTERN async_id AsyncHooksGetTriggerAsyncId(v8::Isolate* isolate);
689 
690 /* If the native API doesn't inherit from the helper class then the callbacks
691  * must be triggered manually. This triggers the init() callback. The return
692  * value is the async id assigned to the resource.
693  *
694  * The `trigger_async_id` parameter should correspond to the resource which is
695  * creating the new resource, which will usually be the return value of
696  * `AsyncHooksGetTriggerAsyncId()`. */
697 NODE_EXTERN async_context EmitAsyncInit(v8::Isolate* isolate,
698                                         v8::Local<v8::Object> resource,
699                                         const char* name,
700                                         async_id trigger_async_id = -1);
701 
702 NODE_EXTERN async_context EmitAsyncInit(v8::Isolate* isolate,
703                                         v8::Local<v8::Object> resource,
704                                         v8::Local<v8::String> name,
705                                         async_id trigger_async_id = -1);
706 
707 /* Emit the destroy() callback. */
708 NODE_EXTERN void EmitAsyncDestroy(v8::Isolate* isolate,
709                                   async_context asyncContext);
710 
711 class InternalCallbackScope;
712 
713 /* This class works like `MakeCallback()` in that it sets up a specific
714  * asyncContext as the current one and informs the async_hooks and domains
715  * modules that this context is currently active.
716  *
717  * `MakeCallback()` is a wrapper around this class as well as
718  * `Function::Call()`. Either one of these mechanisms needs to be used for
719  * top-level calls into JavaScript (i.e. without any existing JS stack).
720  *
721  * This object should be stack-allocated to ensure that it is contained in a
722  * valid HandleScope.
723  *
724  * Exceptions happening within this scope will be treated like uncaught
725  * exceptions. If this behaviour is undesirable, a new `v8::TryCatch` scope
726  * needs to be created inside of this scope.
727  */
728 class NODE_EXTERN CallbackScope {
729  public:
730   CallbackScope(v8::Isolate* isolate,
731                 v8::Local<v8::Object> resource,
732                 async_context asyncContext);
733   ~CallbackScope();
734 
735  private:
736   InternalCallbackScope* private_;
737   v8::TryCatch try_catch_;
738 
739   void operator=(const CallbackScope&) = delete;
740   void operator=(CallbackScope&&) = delete;
741   CallbackScope(const CallbackScope&) = delete;
742   CallbackScope(CallbackScope&&) = delete;
743 };
744 
745 /* An API specific to emit before/after callbacks is unnecessary because
746  * MakeCallback will automatically call them for you.
747  *
748  * These methods may create handles on their own, so run them inside a
749  * HandleScope.
750  *
751  * `asyncId` and `triggerAsyncId` should correspond to the values returned by
752  * `EmitAsyncInit()` and `AsyncHooksGetTriggerAsyncId()`, respectively, when the
753  * invoking resource was created. If these values are unknown, 0 can be passed.
754  * */
755 NODE_EXTERN
756 v8::MaybeLocal<v8::Value> MakeCallback(v8::Isolate* isolate,
757                                        v8::Local<v8::Object> recv,
758                                        v8::Local<v8::Function> callback,
759                                        int argc,
760                                        v8::Local<v8::Value>* argv,
761                                        async_context asyncContext);
762 NODE_EXTERN
763 v8::MaybeLocal<v8::Value> MakeCallback(v8::Isolate* isolate,
764                                        v8::Local<v8::Object> recv,
765                                        const char* method,
766                                        int argc,
767                                        v8::Local<v8::Value>* argv,
768                                        async_context asyncContext);
769 NODE_EXTERN
770 v8::MaybeLocal<v8::Value> MakeCallback(v8::Isolate* isolate,
771                                        v8::Local<v8::Object> recv,
772                                        v8::Local<v8::String> symbol,
773                                        int argc,
774                                        v8::Local<v8::Value>* argv,
775                                        async_context asyncContext);
776 
777 /* Helper class users can optionally inherit from. If
778  * `AsyncResource::MakeCallback()` is used, then all four callbacks will be
779  * called automatically. */
780 class AsyncResource {
781  public:
782   AsyncResource(v8::Isolate* isolate,
783                 v8::Local<v8::Object> resource,
784                 const char* name,
785                 async_id trigger_async_id = -1)
isolate_(isolate)786       : isolate_(isolate),
787         resource_(isolate, resource) {
788     async_context_ = EmitAsyncInit(isolate, resource, name,
789                                    trigger_async_id);
790   }
791 
792   AsyncResource(v8::Isolate* isolate,
793                 v8::Local<v8::Object> resource,
794                 v8::Local<v8::String> name,
795                 async_id trigger_async_id = -1)
isolate_(isolate)796       : isolate_(isolate),
797         resource_(isolate, resource) {
798     async_context_ = EmitAsyncInit(isolate, resource, name,
799                                    trigger_async_id);
800   }
801 
~AsyncResource()802   virtual ~AsyncResource() {
803     EmitAsyncDestroy(isolate_, async_context_);
804     resource_.Reset();
805   }
806 
MakeCallback(v8::Local<v8::Function> callback,int argc,v8::Local<v8::Value> * argv)807   v8::MaybeLocal<v8::Value> MakeCallback(
808       v8::Local<v8::Function> callback,
809       int argc,
810       v8::Local<v8::Value>* argv) {
811     return node::MakeCallback(isolate_, get_resource(),
812                               callback, argc, argv,
813                               async_context_);
814   }
815 
MakeCallback(const char * method,int argc,v8::Local<v8::Value> * argv)816   v8::MaybeLocal<v8::Value> MakeCallback(
817       const char* method,
818       int argc,
819       v8::Local<v8::Value>* argv) {
820     return node::MakeCallback(isolate_, get_resource(),
821                               method, argc, argv,
822                               async_context_);
823   }
824 
MakeCallback(v8::Local<v8::String> symbol,int argc,v8::Local<v8::Value> * argv)825   v8::MaybeLocal<v8::Value> MakeCallback(
826       v8::Local<v8::String> symbol,
827       int argc,
828       v8::Local<v8::Value>* argv) {
829     return node::MakeCallback(isolate_, get_resource(),
830                               symbol, argc, argv,
831                               async_context_);
832   }
833 
get_resource()834   v8::Local<v8::Object> get_resource() {
835     return resource_.Get(isolate_);
836   }
837 
get_async_id()838   async_id get_async_id() const {
839     return async_context_.async_id;
840   }
841 
get_trigger_async_id()842   async_id get_trigger_async_id() const {
843     return async_context_.trigger_async_id;
844   }
845 
846  protected:
847   class CallbackScope : public node::CallbackScope {
848    public:
CallbackScope(AsyncResource * res)849     explicit CallbackScope(AsyncResource* res)
850       : node::CallbackScope(res->isolate_,
851                             res->resource_.Get(res->isolate_),
852                             res->async_context_) {}
853   };
854 
855  private:
856   v8::Isolate* isolate_;
857   v8::Persistent<v8::Object> resource_;
858   async_context async_context_;
859 };
860 
861 }  // namespace node
862 
863 #endif  // SRC_NODE_H_
864