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