#ifndef SRC_NODE_INTERNALS_H_ #define SRC_NODE_INTERNALS_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "node.h" #include "util.h" #include "util-inl.h" #include "uv.h" #include "v8.h" #include #include struct sockaddr; // Variation on NODE_DEFINE_CONSTANT that sets a String value. #define NODE_DEFINE_STRING_CONSTANT(target, name, constant) \ do { \ v8::Isolate* isolate = target->GetIsolate(); \ v8::Local constant_name = \ v8::String::NewFromUtf8(isolate, name); \ v8::Local constant_value = \ v8::String::NewFromUtf8(isolate, constant); \ v8::PropertyAttribute constant_attributes = \ static_cast(v8::ReadOnly | v8::DontDelete); \ target->DefineOwnProperty(isolate->GetCurrentContext(), \ constant_name, \ constant_value, \ constant_attributes).FromJust(); \ } while (0) namespace node { // Set in node.cc by ParseArgs with the value of --openssl-config. // Used in node_crypto.cc when initializing OpenSSL. extern const char* openssl_config; // Set in node.cc by ParseArgs when --preserve-symlinks is used. // Used in node_config.cc to set a constant on process.binding('config') // that is used by lib/module.js extern bool config_preserve_symlinks; // Tells whether it is safe to call v8::Isolate::GetCurrent(). extern bool v8_initialized; // Forward declaration class Environment; // If persistent.IsWeak() == false, then do not call persistent.Reset() // while the returned Local is still in scope, it will destroy the // reference to the object. template inline v8::Local PersistentToLocal( v8::Isolate* isolate, const v8::Persistent& persistent); // Call with valid HandleScope and while inside Context scope. v8::Local MakeCallback(Environment* env, v8::Local recv, const char* method, int argc = 0, v8::Local* argv = nullptr); // Call with valid HandleScope and while inside Context scope. v8::Local MakeCallback(Environment* env, v8::Local recv, v8::Local symbol, int argc = 0, v8::Local* argv = nullptr); // Call with valid HandleScope and while inside Context scope. v8::Local MakeCallback(Environment* env, v8::Local recv, v8::Local callback, int argc = 0, v8::Local* argv = nullptr); // Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object. // Sets address and port properties on the info object and returns it. // If |info| is omitted, a new object is returned. v8::Local AddressToJS( Environment* env, const sockaddr* addr, v8::Local info = v8::Local()); template void GetSockOrPeerName(const v8::FunctionCallbackInfo& args) { T* const wrap = Unwrap(args.Holder()); if (wrap == nullptr) return args.GetReturnValue().Set(UV_EBADF); CHECK(args[0]->IsObject()); sockaddr_storage storage; int addrlen = sizeof(storage); sockaddr* const addr = reinterpret_cast(&storage); const int err = F(&wrap->handle_, addr, &addrlen); if (err == 0) AddressToJS(wrap->env(), addr, args[0].As()); args.GetReturnValue().Set(err); } void SignalExit(int signo); #ifdef __POSIX__ void RegisterSignalHandler(int signal, void (*handler)(int signal), bool reset_handler = false); #endif template constexpr size_t arraysize(const T(&)[N]) { return N; } #ifndef ROUND_UP # define ROUND_UP(a, b) ((a) % (b) ? ((a) + (b)) - ((a) % (b)) : (a)) #endif #ifdef __GNUC__ # define MUST_USE_RESULT __attribute__((warn_unused_result)) #else # define MUST_USE_RESULT #endif bool IsExceptionDecorated(Environment* env, v8::Local er); enum ErrorHandlingMode { FATAL_ERROR, CONTEXTIFY_ERROR }; void AppendExceptionLine(Environment* env, v8::Local er, v8::Local message, enum ErrorHandlingMode mode); NO_RETURN void FatalError(const char* location, const char* message); v8::Local BuildStatsObject(Environment* env, const uv_stat_t* s); void SetupProcessObject(Environment* env, int argc, const char* const* argv, int exec_argc, const char* const* exec_argv); enum Endianness { kLittleEndian, // _Not_ LITTLE_ENDIAN, clashes with endian.h. kBigEndian }; inline enum Endianness GetEndianness() { // Constant-folded by the compiler. const union { uint8_t u8[2]; uint16_t u16; } u = { { 1, 0 } }; return u.u16 == 1 ? kLittleEndian : kBigEndian; } inline bool IsLittleEndian() { return GetEndianness() == kLittleEndian; } inline bool IsBigEndian() { return GetEndianness() == kBigEndian; } class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { public: inline uint32_t* zero_fill_field() { return &zero_fill_field_; } virtual void* Allocate(size_t size); // Defined in src/node.cc virtual void* AllocateUninitialized(size_t size) { return node::UncheckedMalloc(size); } virtual void Free(void* data, size_t) { free(data); } private: uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land. }; // Clear any domain and/or uncaughtException handlers to force the error's // propagation and shutdown the process. Use this to force the process to exit // by clearing all callbacks that could handle the error. void ClearFatalExceptionHandlers(Environment* env); enum NodeInstanceType { MAIN, WORKER, REMOTE_DEBUG_SERVER }; class NodeInstanceData { public: NodeInstanceData(NodeInstanceType node_instance_type, uv_loop_t* event_loop, int argc, const char** argv, int exec_argc, const char** exec_argv, bool use_debug_agent_flag) : node_instance_type_(node_instance_type), exit_code_(1), event_loop_(event_loop), argc_(argc), argv_(argv), exec_argc_(exec_argc), exec_argv_(exec_argv), use_debug_agent_flag_(use_debug_agent_flag) { CHECK_NE(event_loop_, nullptr); } uv_loop_t* event_loop() const { return event_loop_; } int exit_code() { CHECK(is_main()); return exit_code_; } void set_exit_code(int exit_code) { CHECK(is_main()); exit_code_ = exit_code; } bool is_main() { return node_instance_type_ == MAIN; } bool is_worker() { return node_instance_type_ == WORKER; } bool is_remote_debug_server() { return node_instance_type_ == REMOTE_DEBUG_SERVER; } int argc() { return argc_; } const char** argv() { return argv_; } int exec_argc() { return exec_argc_; } const char** exec_argv() { return exec_argv_; } bool use_debug_agent() { return is_main() && use_debug_agent_flag_; } private: const NodeInstanceType node_instance_type_; int exit_code_; uv_loop_t* const event_loop_; const int argc_; const char** argv_; const int exec_argc_; const char** exec_argv_; const bool use_debug_agent_flag_; DISALLOW_COPY_AND_ASSIGN(NodeInstanceData); }; namespace Buffer { v8::MaybeLocal Copy(Environment* env, const char* data, size_t len); v8::MaybeLocal New(Environment* env, size_t size); // Takes ownership of |data|. v8::MaybeLocal New(Environment* env, char* data, size_t length, void (*callback)(char* data, void* hint), void* hint); // Takes ownership of |data|. Must allocate |data| with malloc() or realloc() // because ArrayBufferAllocator::Free() deallocates it again with free(). // Mixing operator new and free() is undefined behavior so don't do that. v8::MaybeLocal New(Environment* env, char* data, size_t length); } // namespace Buffer } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_INTERNALS_H_