From 7f6cac3721ae6d0e861b3e7e021ef7df5723cf2c Mon Sep 17 00:00:00 2001 From: Mike Kaufman Date: Tue, 19 Sep 2017 11:18:15 -0700 Subject: [PATCH] env: fixing line endings fixing crlf line endings that were incorrectly checked in --- src/env-inl.h | 1366 +++++++++++++++++++++---------------------- src/env.h | 1548 ++++++++++++++++++++++++------------------------- 2 files changed, 1457 insertions(+), 1457 deletions(-) diff --git a/src/env-inl.h b/src/env-inl.h index 4fa3057aa33..3325a81e1e5 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -1,683 +1,683 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SRC_ENV_INL_H_ -#define SRC_ENV_INL_H_ - -#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -#include "env.h" -#include "node.h" -#include "util.h" -#include "util-inl.h" -#include "uv.h" -#include "v8.h" - -#include -#include - -namespace node { - -inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop, - uint32_t* zero_fill_field) : - -// Create string and private symbol properties as internalized one byte strings. -// -// Internalized because it makes property lookups a little faster and because -// the string is created in the old space straight away. It's going to end up -// in the old space sooner or later anyway but now it doesn't go through -// v8::Eternal's new space handling first. -// -// One byte because our strings are ASCII and we can safely skip V8's UTF-8 -// decoding step. It's a one-time cost, but why pay it when you don't have to? -#define V(PropertyName, StringValue) \ - PropertyName ## _( \ - isolate, \ - v8::Private::New( \ - isolate, \ - v8::String::NewFromOneByte( \ - isolate, \ - reinterpret_cast(StringValue), \ - v8::NewStringType::kInternalized, \ - sizeof(StringValue) - 1).ToLocalChecked())), - PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) -#undef V -#define V(PropertyName, StringValue) \ - PropertyName ## _( \ - isolate, \ - v8::String::NewFromOneByte( \ - isolate, \ - reinterpret_cast(StringValue), \ - v8::NewStringType::kInternalized, \ - sizeof(StringValue) - 1).ToLocalChecked()), - PER_ISOLATE_STRING_PROPERTIES(V) -#undef V - event_loop_(event_loop), zero_fill_field_(zero_fill_field) {} - -inline uv_loop_t* IsolateData::event_loop() const { - return event_loop_; -} - -inline uint32_t* IsolateData::zero_fill_field() const { - return zero_fill_field_; -} - -inline Environment::AsyncHooks::AsyncHooks(v8::Isolate* isolate) - : isolate_(isolate), - fields_(), - uid_fields_() -{ - v8::HandleScope handle_scope(isolate_); - - // kAsyncUidCntr should start at 1 because that'll be the id the execution - // context during bootstrap (code that runs before entering uv_run()). - uid_fields_[AsyncHooks::kAsyncUidCntr] = 1; - - // Create all the provider strings that will be passed to JS. Place them in - // an array so the array index matches the PROVIDER id offset. This way the - // strings can be retrieved quickly. -#define V(Provider) \ - providers_[AsyncWrap::PROVIDER_ ## Provider].Set( \ - isolate_, \ - v8::String::NewFromOneByte( \ - isolate_, \ - reinterpret_cast(#Provider), \ - v8::NewStringType::kInternalized, \ - sizeof(#Provider) - 1).ToLocalChecked()); - NODE_ASYNC_PROVIDER_TYPES(V) -#undef V -} - -inline uint32_t* Environment::AsyncHooks::fields() { - return fields_; -} - -inline int Environment::AsyncHooks::fields_count() const { - return kFieldsCount; -} - -inline double* Environment::AsyncHooks::uid_fields() { - return uid_fields_; -} - -inline int Environment::AsyncHooks::uid_fields_count() const { - return kUidFieldsCount; -} - -inline v8::Local Environment::AsyncHooks::provider_string(int idx) { - return providers_[idx].Get(isolate_); -} - -inline void Environment::AsyncHooks::push_ids(double async_id, - double trigger_id) { - CHECK_GE(async_id, -1); - CHECK_GE(trigger_id, -1); - - ids_stack_.push({ uid_fields_[kCurrentAsyncId], - uid_fields_[kCurrentTriggerId] }); - uid_fields_[kCurrentAsyncId] = async_id; - uid_fields_[kCurrentTriggerId] = trigger_id; -} - -inline bool Environment::AsyncHooks::pop_ids(double async_id) { - // In case of an exception then this may have already been reset, if the - // stack was multiple MakeCallback()'s deep. - if (ids_stack_.empty()) return false; - - // Ask for the async_id to be restored as a sanity check that the stack - // hasn't been corrupted. - if (uid_fields_[kCurrentAsyncId] != async_id) { - fprintf(stderr, - "Error: async hook stack has become corrupted (" - "actual: %.f, expected: %.f)\n", - uid_fields_[kCurrentAsyncId], - async_id); - Environment* env = Environment::GetCurrent(isolate_); - DumpBacktrace(stderr); - fflush(stderr); - if (!env->abort_on_uncaught_exception()) - exit(1); - fprintf(stderr, "\n"); - fflush(stderr); - ABORT_NO_BACKTRACE(); - } - - auto ids = ids_stack_.top(); - ids_stack_.pop(); - uid_fields_[kCurrentAsyncId] = ids.async_id; - uid_fields_[kCurrentTriggerId] = ids.trigger_id; - return !ids_stack_.empty(); -} - -inline size_t Environment::AsyncHooks::stack_size() { - return ids_stack_.size(); -} - -inline void Environment::AsyncHooks::clear_id_stack() { - while (!ids_stack_.empty()) - ids_stack_.pop(); - uid_fields_[kCurrentAsyncId] = 0; - uid_fields_[kCurrentTriggerId] = 0; -} - -inline Environment::AsyncHooks::InitScope::InitScope( - Environment* env, double init_trigger_id) - : env_(env), - uid_fields_ref_(env->async_hooks()->uid_fields()) { - CHECK_GE(init_trigger_id, -1); - env->async_hooks()->push_ids(uid_fields_ref_[AsyncHooks::kCurrentAsyncId], - init_trigger_id); -} - -inline Environment::AsyncHooks::InitScope::~InitScope() { - env_->async_hooks()->pop_ids(uid_fields_ref_[AsyncHooks::kCurrentAsyncId]); -} - -inline Environment::AsyncHooks::ExecScope::ExecScope( - Environment* env, double async_id, double trigger_id) - : env_(env), - async_id_(async_id), - disposed_(false) { - CHECK_GE(async_id, -1); - CHECK_GE(trigger_id, -1); - env->async_hooks()->push_ids(async_id, trigger_id); -} - -inline Environment::AsyncHooks::ExecScope::~ExecScope() { - if (disposed_) return; - Dispose(); -} - -inline void Environment::AsyncHooks::ExecScope::Dispose() { - disposed_ = true; - env_->async_hooks()->pop_ids(async_id_); -} - -inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env) - : env_(env) { - env_->makecallback_cntr_++; -} - -inline Environment::AsyncCallbackScope::~AsyncCallbackScope() { - env_->makecallback_cntr_--; -} - -inline bool Environment::AsyncCallbackScope::in_makecallback() { - return env_->makecallback_cntr_ > 1; -} - -inline Environment::DomainFlag::DomainFlag() { - for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0; -} - -inline uint32_t* Environment::DomainFlag::fields() { - return fields_; -} - -inline int Environment::DomainFlag::fields_count() const { - return kFieldsCount; -} - -inline uint32_t Environment::DomainFlag::count() const { - return fields_[kCount]; -} - -inline Environment::TickInfo::TickInfo() { - for (int i = 0; i < kFieldsCount; ++i) - fields_[i] = 0; -} - -inline uint32_t* Environment::TickInfo::fields() { - return fields_; -} - -inline int Environment::TickInfo::fields_count() const { - return kFieldsCount; -} - -inline uint32_t Environment::TickInfo::index() const { - return fields_[kIndex]; -} - -inline uint32_t Environment::TickInfo::length() const { - return fields_[kLength]; -} - -inline void Environment::TickInfo::set_index(uint32_t value) { - fields_[kIndex] = value; -} - -inline void Environment::AssignToContext(v8::Local context) { - context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, this); -#if HAVE_INSPECTOR - inspector_agent()->ContextCreated(context); -#endif // HAVE_INSPECTOR -} - -inline Environment* Environment::GetCurrent(v8::Isolate* isolate) { - return GetCurrent(isolate->GetCurrentContext()); -} - -inline Environment* Environment::GetCurrent(v8::Local context) { - return static_cast( - context->GetAlignedPointerFromEmbedderData(kContextEmbedderDataIndex)); -} - -inline Environment* Environment::GetCurrent( - const v8::FunctionCallbackInfo& info) { - CHECK(info.Data()->IsExternal()); - return static_cast(info.Data().As()->Value()); -} - -template -inline Environment* Environment::GetCurrent( - const v8::PropertyCallbackInfo& info) { - CHECK(info.Data()->IsExternal()); - return static_cast( - info.Data().template As()->Value()); -} - -inline Environment::Environment(IsolateData* isolate_data, - v8::Local context) - : isolate_(context->GetIsolate()), - isolate_data_(isolate_data), - async_hooks_(context->GetIsolate()), - timer_base_(uv_now(isolate_data->event_loop())), - using_domains_(false), - printed_error_(false), - trace_sync_io_(false), - abort_on_uncaught_exception_(false), - makecallback_cntr_(0), -#if HAVE_INSPECTOR - inspector_agent_(this), -#endif - handle_cleanup_waiting_(0), - http_parser_buffer_(nullptr), - fs_stats_field_array_(), - context_(context->GetIsolate(), context) { - // We'll be creating new objects so make sure we've entered the context. - v8::HandleScope handle_scope(isolate()); - v8::Context::Scope context_scope(context); - set_as_external(v8::External::New(isolate(), this)); - set_binding_cache_object(v8::Object::New(isolate())); - set_module_load_list_array(v8::Array::New(isolate())); - - AssignToContext(context); - - destroy_ids_list_.reserve(512); - performance_state_ = Calloc(1); - performance_state_->milestones[ - performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT] = - PERFORMANCE_NOW(); - performance_state_->milestones[ - performance::NODE_PERFORMANCE_MILESTONE_NODE_START] = - performance::performance_node_start; - performance_state_->milestones[ - performance::NODE_PERFORMANCE_MILESTONE_V8_START] = - performance::performance_v8_start; -} - -inline Environment::~Environment() { - v8::HandleScope handle_scope(isolate()); - - fs_stats_field_array_.Empty(); - - context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, - nullptr); -#define V(PropertyName, TypeName) PropertyName ## _.Reset(); - ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) -#undef V - - delete[] heap_statistics_buffer_; - delete[] heap_space_statistics_buffer_; - delete[] http_parser_buffer_; - free(http2_state_buffer_); - free(performance_state_); -} - -inline v8::Isolate* Environment::isolate() const { - return isolate_; -} - -inline bool Environment::in_domain() const { - // The const_cast is okay, it doesn't violate conceptual const-ness. - return using_domains() && - const_cast(this)->domain_flag()->count() > 0; -} - -inline Environment* Environment::from_immediate_check_handle( - uv_check_t* handle) { - return ContainerOf(&Environment::immediate_check_handle_, handle); -} - -inline uv_check_t* Environment::immediate_check_handle() { - return &immediate_check_handle_; -} - -inline uv_idle_t* Environment::immediate_idle_handle() { - return &immediate_idle_handle_; -} - -inline Environment* Environment::from_destroy_ids_timer_handle( - uv_timer_t* handle) { - return ContainerOf(&Environment::destroy_ids_timer_handle_, handle); -} - -inline uv_timer_t* Environment::destroy_ids_timer_handle() { - return &destroy_ids_timer_handle_; -} - -inline void Environment::RegisterHandleCleanup(uv_handle_t* handle, - HandleCleanupCb cb, - void *arg) { - handle_cleanup_queue_.PushBack(new HandleCleanup(handle, cb, arg)); -} - -inline void Environment::FinishHandleCleanup(uv_handle_t* handle) { - handle_cleanup_waiting_--; -} - -inline uv_loop_t* Environment::event_loop() const { - return isolate_data()->event_loop(); -} - -inline Environment::AsyncHooks* Environment::async_hooks() { - return &async_hooks_; -} - -inline Environment::DomainFlag* Environment::domain_flag() { - return &domain_flag_; -} - -inline Environment::TickInfo* Environment::tick_info() { - return &tick_info_; -} - -inline uint64_t Environment::timer_base() const { - return timer_base_; -} - -inline bool Environment::using_domains() const { - return using_domains_; -} - -inline void Environment::set_using_domains(bool value) { - using_domains_ = value; -} - -inline bool Environment::printed_error() const { - return printed_error_; -} - -inline void Environment::set_printed_error(bool value) { - printed_error_ = value; -} - -inline void Environment::set_trace_sync_io(bool value) { - trace_sync_io_ = value; -} - -inline bool Environment::abort_on_uncaught_exception() const { - return abort_on_uncaught_exception_; -} - -inline void Environment::set_abort_on_uncaught_exception(bool value) { - abort_on_uncaught_exception_ = value; -} - -inline std::vector* Environment::destroy_ids_list() { - return &destroy_ids_list_; -} - -inline double Environment::new_async_id() { - return ++async_hooks()->uid_fields()[AsyncHooks::kAsyncUidCntr]; -} - -inline double Environment::current_async_id() { - return async_hooks()->uid_fields()[AsyncHooks::kCurrentAsyncId]; -} - -inline double Environment::trigger_id() { - return async_hooks()->uid_fields()[AsyncHooks::kCurrentTriggerId]; -} - -inline double Environment::get_init_trigger_id() { - double* uid_fields = async_hooks()->uid_fields(); - double tid = uid_fields[AsyncHooks::kInitTriggerId]; - uid_fields[AsyncHooks::kInitTriggerId] = 0; - - if (tid <= 0) tid = current_async_id(); - return tid; -} - -inline void Environment::set_init_trigger_id(const double id) { - async_hooks()->uid_fields()[AsyncHooks::kInitTriggerId] = id; -} - -inline double* Environment::heap_statistics_buffer() const { - CHECK_NE(heap_statistics_buffer_, nullptr); - return heap_statistics_buffer_; -} - -inline void Environment::set_heap_statistics_buffer(double* pointer) { - CHECK_EQ(heap_statistics_buffer_, nullptr); // Should be set only once. - heap_statistics_buffer_ = pointer; -} - -inline double* Environment::heap_space_statistics_buffer() const { - CHECK_NE(heap_space_statistics_buffer_, nullptr); - return heap_space_statistics_buffer_; -} - -inline void Environment::set_heap_space_statistics_buffer(double* pointer) { - CHECK_EQ(heap_space_statistics_buffer_, nullptr); // Should be set only once. - heap_space_statistics_buffer_ = pointer; -} - -inline char* Environment::http_parser_buffer() const { - return http_parser_buffer_; -} - -inline void Environment::set_http_parser_buffer(char* buffer) { - CHECK_EQ(http_parser_buffer_, nullptr); // Should be set only once. - http_parser_buffer_ = buffer; -} - -inline http2::http2_state* Environment::http2_state_buffer() const { - return http2_state_buffer_; -} - -inline void Environment::set_http2_state_buffer(http2::http2_state* buffer) { - CHECK_EQ(http2_state_buffer_, nullptr); // Should be set only once. - http2_state_buffer_ = buffer; -} - -inline v8::Local Environment::fs_stats_field_array() const { - return v8::Local::New(isolate_, fs_stats_field_array_); -} - -inline void Environment::set_fs_stats_field_array( - v8::Local fields) { - CHECK_EQ(fs_stats_field_array_.IsEmpty(), true); // Should be set only once. - fs_stats_field_array_ = v8::Global(isolate_, fields); -} - -inline performance::performance_state* Environment::performance_state() { - return performance_state_; -} - -inline std::map* Environment::performance_marks() { - return &performance_marks_; -} - -inline Environment* Environment::from_performance_check_handle( - uv_check_t* handle) { - return ContainerOf(&Environment::performance_check_handle_, handle); -} - -inline Environment* Environment::from_performance_idle_handle( - uv_idle_t* handle) { - return ContainerOf(&Environment::performance_idle_handle_, handle); -} - -inline Environment* Environment::from_performance_prepare_handle( - uv_prepare_t* handle) { - return ContainerOf(&Environment::performance_prepare_handle_, handle); -} - -inline uv_check_t* Environment::performance_check_handle() { - return &performance_check_handle_; -} - -inline uv_idle_t* Environment::performance_idle_handle() { - return &performance_idle_handle_; -} - -inline uv_prepare_t* Environment::performance_prepare_handle() { - return &performance_prepare_handle_; -} - -inline IsolateData* Environment::isolate_data() const { - return isolate_data_; -} - -inline void Environment::ThrowError(const char* errmsg) { - ThrowError(v8::Exception::Error, errmsg); -} - -inline void Environment::ThrowTypeError(const char* errmsg) { - ThrowError(v8::Exception::TypeError, errmsg); -} - -inline void Environment::ThrowRangeError(const char* errmsg) { - ThrowError(v8::Exception::RangeError, errmsg); -} - -inline void Environment::ThrowError( - v8::Local (*fun)(v8::Local), - const char* errmsg) { - v8::HandleScope handle_scope(isolate()); - isolate()->ThrowException(fun(OneByteString(isolate(), errmsg))); -} - -inline void Environment::ThrowErrnoException(int errorno, - const char* syscall, - const char* message, - const char* path) { - isolate()->ThrowException( - ErrnoException(isolate(), errorno, syscall, message, path)); -} - -inline void Environment::ThrowUVException(int errorno, - const char* syscall, - const char* message, - const char* path, - const char* dest) { - isolate()->ThrowException( - UVException(isolate(), errorno, syscall, message, path, dest)); -} - -inline v8::Local - Environment::NewFunctionTemplate(v8::FunctionCallback callback, - v8::Local signature) { - v8::Local external = as_external(); - return v8::FunctionTemplate::New(isolate(), callback, external, signature); -} - -inline void Environment::SetMethod(v8::Local that, - const char* name, - v8::FunctionCallback callback) { - v8::Local function = - NewFunctionTemplate(callback)->GetFunction(); - // kInternalized strings are created in the old space. - const v8::NewStringType type = v8::NewStringType::kInternalized; - v8::Local name_string = - v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); - that->Set(name_string, function); - function->SetName(name_string); // NODE_SET_METHOD() compatibility. -} - -inline void Environment::SetProtoMethod(v8::Local that, - const char* name, - v8::FunctionCallback callback) { - v8::Local signature = v8::Signature::New(isolate(), that); - v8::Local t = NewFunctionTemplate(callback, signature); - // kInternalized strings are created in the old space. - const v8::NewStringType type = v8::NewStringType::kInternalized; - v8::Local name_string = - v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); - that->PrototypeTemplate()->Set(name_string, t); - t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility. -} - -inline void Environment::SetTemplateMethod(v8::Local that, - const char* name, - v8::FunctionCallback callback) { - v8::Local t = NewFunctionTemplate(callback); - // kInternalized strings are created in the old space. - const v8::NewStringType type = v8::NewStringType::kInternalized; - v8::Local name_string = - v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); - that->Set(name_string, t); - t->SetClassName(name_string); // NODE_SET_METHOD() compatibility. -} - -#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) -#define VS(PropertyName, StringValue) V(v8::String, PropertyName) -#define V(TypeName, PropertyName) \ - inline \ - v8::Local IsolateData::PropertyName(v8::Isolate* isolate) const { \ - /* Strings are immutable so casting away const-ness here is okay. */ \ - return const_cast(this)->PropertyName ## _.Get(isolate); \ - } - PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) - PER_ISOLATE_STRING_PROPERTIES(VS) -#undef V -#undef VS -#undef VP - -#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) -#define VS(PropertyName, StringValue) V(v8::String, PropertyName) -#define V(TypeName, PropertyName) \ - inline v8::Local Environment::PropertyName() const { \ - return isolate_data()->PropertyName(isolate()); \ - } - PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) - PER_ISOLATE_STRING_PROPERTIES(VS) -#undef V -#undef VS -#undef VP - -#define V(PropertyName, TypeName) \ - inline v8::Local Environment::PropertyName() const { \ - return StrongPersistentToLocal(PropertyName ## _); \ - } \ - inline void Environment::set_ ## PropertyName(v8::Local value) { \ - PropertyName ## _.Reset(isolate(), value); \ - } - ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) -#undef V - -} // namespace node - -#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -#endif // SRC_ENV_INL_H_ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SRC_ENV_INL_H_ +#define SRC_ENV_INL_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "env.h" +#include "node.h" +#include "util.h" +#include "util-inl.h" +#include "uv.h" +#include "v8.h" + +#include +#include + +namespace node { + +inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop, + uint32_t* zero_fill_field) : + +// Create string and private symbol properties as internalized one byte strings. +// +// Internalized because it makes property lookups a little faster and because +// the string is created in the old space straight away. It's going to end up +// in the old space sooner or later anyway but now it doesn't go through +// v8::Eternal's new space handling first. +// +// One byte because our strings are ASCII and we can safely skip V8's UTF-8 +// decoding step. It's a one-time cost, but why pay it when you don't have to? +#define V(PropertyName, StringValue) \ + PropertyName ## _( \ + isolate, \ + v8::Private::New( \ + isolate, \ + v8::String::NewFromOneByte( \ + isolate, \ + reinterpret_cast(StringValue), \ + v8::NewStringType::kInternalized, \ + sizeof(StringValue) - 1).ToLocalChecked())), + PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) +#undef V +#define V(PropertyName, StringValue) \ + PropertyName ## _( \ + isolate, \ + v8::String::NewFromOneByte( \ + isolate, \ + reinterpret_cast(StringValue), \ + v8::NewStringType::kInternalized, \ + sizeof(StringValue) - 1).ToLocalChecked()), + PER_ISOLATE_STRING_PROPERTIES(V) +#undef V + event_loop_(event_loop), zero_fill_field_(zero_fill_field) {} + +inline uv_loop_t* IsolateData::event_loop() const { + return event_loop_; +} + +inline uint32_t* IsolateData::zero_fill_field() const { + return zero_fill_field_; +} + +inline Environment::AsyncHooks::AsyncHooks(v8::Isolate* isolate) + : isolate_(isolate), + fields_(), + uid_fields_() +{ + v8::HandleScope handle_scope(isolate_); + + // kAsyncUidCntr should start at 1 because that'll be the id the execution + // context during bootstrap (code that runs before entering uv_run()). + uid_fields_[AsyncHooks::kAsyncUidCntr] = 1; + + // Create all the provider strings that will be passed to JS. Place them in + // an array so the array index matches the PROVIDER id offset. This way the + // strings can be retrieved quickly. +#define V(Provider) \ + providers_[AsyncWrap::PROVIDER_ ## Provider].Set( \ + isolate_, \ + v8::String::NewFromOneByte( \ + isolate_, \ + reinterpret_cast(#Provider), \ + v8::NewStringType::kInternalized, \ + sizeof(#Provider) - 1).ToLocalChecked()); + NODE_ASYNC_PROVIDER_TYPES(V) +#undef V +} + +inline uint32_t* Environment::AsyncHooks::fields() { + return fields_; +} + +inline int Environment::AsyncHooks::fields_count() const { + return kFieldsCount; +} + +inline double* Environment::AsyncHooks::uid_fields() { + return uid_fields_; +} + +inline int Environment::AsyncHooks::uid_fields_count() const { + return kUidFieldsCount; +} + +inline v8::Local Environment::AsyncHooks::provider_string(int idx) { + return providers_[idx].Get(isolate_); +} + +inline void Environment::AsyncHooks::push_ids(double async_id, + double trigger_id) { + CHECK_GE(async_id, -1); + CHECK_GE(trigger_id, -1); + + ids_stack_.push({ uid_fields_[kCurrentAsyncId], + uid_fields_[kCurrentTriggerId] }); + uid_fields_[kCurrentAsyncId] = async_id; + uid_fields_[kCurrentTriggerId] = trigger_id; +} + +inline bool Environment::AsyncHooks::pop_ids(double async_id) { + // In case of an exception then this may have already been reset, if the + // stack was multiple MakeCallback()'s deep. + if (ids_stack_.empty()) return false; + + // Ask for the async_id to be restored as a sanity check that the stack + // hasn't been corrupted. + if (uid_fields_[kCurrentAsyncId] != async_id) { + fprintf(stderr, + "Error: async hook stack has become corrupted (" + "actual: %.f, expected: %.f)\n", + uid_fields_[kCurrentAsyncId], + async_id); + Environment* env = Environment::GetCurrent(isolate_); + DumpBacktrace(stderr); + fflush(stderr); + if (!env->abort_on_uncaught_exception()) + exit(1); + fprintf(stderr, "\n"); + fflush(stderr); + ABORT_NO_BACKTRACE(); + } + + auto ids = ids_stack_.top(); + ids_stack_.pop(); + uid_fields_[kCurrentAsyncId] = ids.async_id; + uid_fields_[kCurrentTriggerId] = ids.trigger_id; + return !ids_stack_.empty(); +} + +inline size_t Environment::AsyncHooks::stack_size() { + return ids_stack_.size(); +} + +inline void Environment::AsyncHooks::clear_id_stack() { + while (!ids_stack_.empty()) + ids_stack_.pop(); + uid_fields_[kCurrentAsyncId] = 0; + uid_fields_[kCurrentTriggerId] = 0; +} + +inline Environment::AsyncHooks::InitScope::InitScope( + Environment* env, double init_trigger_id) + : env_(env), + uid_fields_ref_(env->async_hooks()->uid_fields()) { + CHECK_GE(init_trigger_id, -1); + env->async_hooks()->push_ids(uid_fields_ref_[AsyncHooks::kCurrentAsyncId], + init_trigger_id); +} + +inline Environment::AsyncHooks::InitScope::~InitScope() { + env_->async_hooks()->pop_ids(uid_fields_ref_[AsyncHooks::kCurrentAsyncId]); +} + +inline Environment::AsyncHooks::ExecScope::ExecScope( + Environment* env, double async_id, double trigger_id) + : env_(env), + async_id_(async_id), + disposed_(false) { + CHECK_GE(async_id, -1); + CHECK_GE(trigger_id, -1); + env->async_hooks()->push_ids(async_id, trigger_id); +} + +inline Environment::AsyncHooks::ExecScope::~ExecScope() { + if (disposed_) return; + Dispose(); +} + +inline void Environment::AsyncHooks::ExecScope::Dispose() { + disposed_ = true; + env_->async_hooks()->pop_ids(async_id_); +} + +inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env) + : env_(env) { + env_->makecallback_cntr_++; +} + +inline Environment::AsyncCallbackScope::~AsyncCallbackScope() { + env_->makecallback_cntr_--; +} + +inline bool Environment::AsyncCallbackScope::in_makecallback() { + return env_->makecallback_cntr_ > 1; +} + +inline Environment::DomainFlag::DomainFlag() { + for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0; +} + +inline uint32_t* Environment::DomainFlag::fields() { + return fields_; +} + +inline int Environment::DomainFlag::fields_count() const { + return kFieldsCount; +} + +inline uint32_t Environment::DomainFlag::count() const { + return fields_[kCount]; +} + +inline Environment::TickInfo::TickInfo() { + for (int i = 0; i < kFieldsCount; ++i) + fields_[i] = 0; +} + +inline uint32_t* Environment::TickInfo::fields() { + return fields_; +} + +inline int Environment::TickInfo::fields_count() const { + return kFieldsCount; +} + +inline uint32_t Environment::TickInfo::index() const { + return fields_[kIndex]; +} + +inline uint32_t Environment::TickInfo::length() const { + return fields_[kLength]; +} + +inline void Environment::TickInfo::set_index(uint32_t value) { + fields_[kIndex] = value; +} + +inline void Environment::AssignToContext(v8::Local context) { + context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, this); +#if HAVE_INSPECTOR + inspector_agent()->ContextCreated(context); +#endif // HAVE_INSPECTOR +} + +inline Environment* Environment::GetCurrent(v8::Isolate* isolate) { + return GetCurrent(isolate->GetCurrentContext()); +} + +inline Environment* Environment::GetCurrent(v8::Local context) { + return static_cast( + context->GetAlignedPointerFromEmbedderData(kContextEmbedderDataIndex)); +} + +inline Environment* Environment::GetCurrent( + const v8::FunctionCallbackInfo& info) { + CHECK(info.Data()->IsExternal()); + return static_cast(info.Data().As()->Value()); +} + +template +inline Environment* Environment::GetCurrent( + const v8::PropertyCallbackInfo& info) { + CHECK(info.Data()->IsExternal()); + return static_cast( + info.Data().template As()->Value()); +} + +inline Environment::Environment(IsolateData* isolate_data, + v8::Local context) + : isolate_(context->GetIsolate()), + isolate_data_(isolate_data), + async_hooks_(context->GetIsolate()), + timer_base_(uv_now(isolate_data->event_loop())), + using_domains_(false), + printed_error_(false), + trace_sync_io_(false), + abort_on_uncaught_exception_(false), + makecallback_cntr_(0), +#if HAVE_INSPECTOR + inspector_agent_(this), +#endif + handle_cleanup_waiting_(0), + http_parser_buffer_(nullptr), + fs_stats_field_array_(), + context_(context->GetIsolate(), context) { + // We'll be creating new objects so make sure we've entered the context. + v8::HandleScope handle_scope(isolate()); + v8::Context::Scope context_scope(context); + set_as_external(v8::External::New(isolate(), this)); + set_binding_cache_object(v8::Object::New(isolate())); + set_module_load_list_array(v8::Array::New(isolate())); + + AssignToContext(context); + + destroy_ids_list_.reserve(512); + performance_state_ = Calloc(1); + performance_state_->milestones[ + performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT] = + PERFORMANCE_NOW(); + performance_state_->milestones[ + performance::NODE_PERFORMANCE_MILESTONE_NODE_START] = + performance::performance_node_start; + performance_state_->milestones[ + performance::NODE_PERFORMANCE_MILESTONE_V8_START] = + performance::performance_v8_start; +} + +inline Environment::~Environment() { + v8::HandleScope handle_scope(isolate()); + + fs_stats_field_array_.Empty(); + + context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, + nullptr); +#define V(PropertyName, TypeName) PropertyName ## _.Reset(); + ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) +#undef V + + delete[] heap_statistics_buffer_; + delete[] heap_space_statistics_buffer_; + delete[] http_parser_buffer_; + free(http2_state_buffer_); + free(performance_state_); +} + +inline v8::Isolate* Environment::isolate() const { + return isolate_; +} + +inline bool Environment::in_domain() const { + // The const_cast is okay, it doesn't violate conceptual const-ness. + return using_domains() && + const_cast(this)->domain_flag()->count() > 0; +} + +inline Environment* Environment::from_immediate_check_handle( + uv_check_t* handle) { + return ContainerOf(&Environment::immediate_check_handle_, handle); +} + +inline uv_check_t* Environment::immediate_check_handle() { + return &immediate_check_handle_; +} + +inline uv_idle_t* Environment::immediate_idle_handle() { + return &immediate_idle_handle_; +} + +inline Environment* Environment::from_destroy_ids_timer_handle( + uv_timer_t* handle) { + return ContainerOf(&Environment::destroy_ids_timer_handle_, handle); +} + +inline uv_timer_t* Environment::destroy_ids_timer_handle() { + return &destroy_ids_timer_handle_; +} + +inline void Environment::RegisterHandleCleanup(uv_handle_t* handle, + HandleCleanupCb cb, + void *arg) { + handle_cleanup_queue_.PushBack(new HandleCleanup(handle, cb, arg)); +} + +inline void Environment::FinishHandleCleanup(uv_handle_t* handle) { + handle_cleanup_waiting_--; +} + +inline uv_loop_t* Environment::event_loop() const { + return isolate_data()->event_loop(); +} + +inline Environment::AsyncHooks* Environment::async_hooks() { + return &async_hooks_; +} + +inline Environment::DomainFlag* Environment::domain_flag() { + return &domain_flag_; +} + +inline Environment::TickInfo* Environment::tick_info() { + return &tick_info_; +} + +inline uint64_t Environment::timer_base() const { + return timer_base_; +} + +inline bool Environment::using_domains() const { + return using_domains_; +} + +inline void Environment::set_using_domains(bool value) { + using_domains_ = value; +} + +inline bool Environment::printed_error() const { + return printed_error_; +} + +inline void Environment::set_printed_error(bool value) { + printed_error_ = value; +} + +inline void Environment::set_trace_sync_io(bool value) { + trace_sync_io_ = value; +} + +inline bool Environment::abort_on_uncaught_exception() const { + return abort_on_uncaught_exception_; +} + +inline void Environment::set_abort_on_uncaught_exception(bool value) { + abort_on_uncaught_exception_ = value; +} + +inline std::vector* Environment::destroy_ids_list() { + return &destroy_ids_list_; +} + +inline double Environment::new_async_id() { + return ++async_hooks()->uid_fields()[AsyncHooks::kAsyncUidCntr]; +} + +inline double Environment::current_async_id() { + return async_hooks()->uid_fields()[AsyncHooks::kCurrentAsyncId]; +} + +inline double Environment::trigger_id() { + return async_hooks()->uid_fields()[AsyncHooks::kCurrentTriggerId]; +} + +inline double Environment::get_init_trigger_id() { + double* uid_fields = async_hooks()->uid_fields(); + double tid = uid_fields[AsyncHooks::kInitTriggerId]; + uid_fields[AsyncHooks::kInitTriggerId] = 0; + + if (tid <= 0) tid = current_async_id(); + return tid; +} + +inline void Environment::set_init_trigger_id(const double id) { + async_hooks()->uid_fields()[AsyncHooks::kInitTriggerId] = id; +} + +inline double* Environment::heap_statistics_buffer() const { + CHECK_NE(heap_statistics_buffer_, nullptr); + return heap_statistics_buffer_; +} + +inline void Environment::set_heap_statistics_buffer(double* pointer) { + CHECK_EQ(heap_statistics_buffer_, nullptr); // Should be set only once. + heap_statistics_buffer_ = pointer; +} + +inline double* Environment::heap_space_statistics_buffer() const { + CHECK_NE(heap_space_statistics_buffer_, nullptr); + return heap_space_statistics_buffer_; +} + +inline void Environment::set_heap_space_statistics_buffer(double* pointer) { + CHECK_EQ(heap_space_statistics_buffer_, nullptr); // Should be set only once. + heap_space_statistics_buffer_ = pointer; +} + +inline char* Environment::http_parser_buffer() const { + return http_parser_buffer_; +} + +inline void Environment::set_http_parser_buffer(char* buffer) { + CHECK_EQ(http_parser_buffer_, nullptr); // Should be set only once. + http_parser_buffer_ = buffer; +} + +inline http2::http2_state* Environment::http2_state_buffer() const { + return http2_state_buffer_; +} + +inline void Environment::set_http2_state_buffer(http2::http2_state* buffer) { + CHECK_EQ(http2_state_buffer_, nullptr); // Should be set only once. + http2_state_buffer_ = buffer; +} + +inline v8::Local Environment::fs_stats_field_array() const { + return v8::Local::New(isolate_, fs_stats_field_array_); +} + +inline void Environment::set_fs_stats_field_array( + v8::Local fields) { + CHECK_EQ(fs_stats_field_array_.IsEmpty(), true); // Should be set only once. + fs_stats_field_array_ = v8::Global(isolate_, fields); +} + +inline performance::performance_state* Environment::performance_state() { + return performance_state_; +} + +inline std::map* Environment::performance_marks() { + return &performance_marks_; +} + +inline Environment* Environment::from_performance_check_handle( + uv_check_t* handle) { + return ContainerOf(&Environment::performance_check_handle_, handle); +} + +inline Environment* Environment::from_performance_idle_handle( + uv_idle_t* handle) { + return ContainerOf(&Environment::performance_idle_handle_, handle); +} + +inline Environment* Environment::from_performance_prepare_handle( + uv_prepare_t* handle) { + return ContainerOf(&Environment::performance_prepare_handle_, handle); +} + +inline uv_check_t* Environment::performance_check_handle() { + return &performance_check_handle_; +} + +inline uv_idle_t* Environment::performance_idle_handle() { + return &performance_idle_handle_; +} + +inline uv_prepare_t* Environment::performance_prepare_handle() { + return &performance_prepare_handle_; +} + +inline IsolateData* Environment::isolate_data() const { + return isolate_data_; +} + +inline void Environment::ThrowError(const char* errmsg) { + ThrowError(v8::Exception::Error, errmsg); +} + +inline void Environment::ThrowTypeError(const char* errmsg) { + ThrowError(v8::Exception::TypeError, errmsg); +} + +inline void Environment::ThrowRangeError(const char* errmsg) { + ThrowError(v8::Exception::RangeError, errmsg); +} + +inline void Environment::ThrowError( + v8::Local (*fun)(v8::Local), + const char* errmsg) { + v8::HandleScope handle_scope(isolate()); + isolate()->ThrowException(fun(OneByteString(isolate(), errmsg))); +} + +inline void Environment::ThrowErrnoException(int errorno, + const char* syscall, + const char* message, + const char* path) { + isolate()->ThrowException( + ErrnoException(isolate(), errorno, syscall, message, path)); +} + +inline void Environment::ThrowUVException(int errorno, + const char* syscall, + const char* message, + const char* path, + const char* dest) { + isolate()->ThrowException( + UVException(isolate(), errorno, syscall, message, path, dest)); +} + +inline v8::Local + Environment::NewFunctionTemplate(v8::FunctionCallback callback, + v8::Local signature) { + v8::Local external = as_external(); + return v8::FunctionTemplate::New(isolate(), callback, external, signature); +} + +inline void Environment::SetMethod(v8::Local that, + const char* name, + v8::FunctionCallback callback) { + v8::Local function = + NewFunctionTemplate(callback)->GetFunction(); + // kInternalized strings are created in the old space. + const v8::NewStringType type = v8::NewStringType::kInternalized; + v8::Local name_string = + v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); + that->Set(name_string, function); + function->SetName(name_string); // NODE_SET_METHOD() compatibility. +} + +inline void Environment::SetProtoMethod(v8::Local that, + const char* name, + v8::FunctionCallback callback) { + v8::Local signature = v8::Signature::New(isolate(), that); + v8::Local t = NewFunctionTemplate(callback, signature); + // kInternalized strings are created in the old space. + const v8::NewStringType type = v8::NewStringType::kInternalized; + v8::Local name_string = + v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); + that->PrototypeTemplate()->Set(name_string, t); + t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility. +} + +inline void Environment::SetTemplateMethod(v8::Local that, + const char* name, + v8::FunctionCallback callback) { + v8::Local t = NewFunctionTemplate(callback); + // kInternalized strings are created in the old space. + const v8::NewStringType type = v8::NewStringType::kInternalized; + v8::Local name_string = + v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked(); + that->Set(name_string, t); + t->SetClassName(name_string); // NODE_SET_METHOD() compatibility. +} + +#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) +#define VS(PropertyName, StringValue) V(v8::String, PropertyName) +#define V(TypeName, PropertyName) \ + inline \ + v8::Local IsolateData::PropertyName(v8::Isolate* isolate) const { \ + /* Strings are immutable so casting away const-ness here is okay. */ \ + return const_cast(this)->PropertyName ## _.Get(isolate); \ + } + PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) + PER_ISOLATE_STRING_PROPERTIES(VS) +#undef V +#undef VS +#undef VP + +#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) +#define VS(PropertyName, StringValue) V(v8::String, PropertyName) +#define V(TypeName, PropertyName) \ + inline v8::Local Environment::PropertyName() const { \ + return isolate_data()->PropertyName(isolate()); \ + } + PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) + PER_ISOLATE_STRING_PROPERTIES(VS) +#undef V +#undef VS +#undef VP + +#define V(PropertyName, TypeName) \ + inline v8::Local Environment::PropertyName() const { \ + return StrongPersistentToLocal(PropertyName ## _); \ + } \ + inline void Environment::set_ ## PropertyName(v8::Local value) { \ + PropertyName ## _.Reset(isolate(), value); \ + } + ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) +#undef V + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_ENV_INL_H_ diff --git a/src/env.h b/src/env.h index f1f85a0b020..c81096f66d9 100644 --- a/src/env.h +++ b/src/env.h @@ -1,774 +1,774 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SRC_ENV_H_ -#define SRC_ENV_H_ - -#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -#include "ares.h" -#if HAVE_INSPECTOR -#include "inspector_agent.h" -#endif -#include "handle_wrap.h" -#include "req-wrap.h" -#include "util.h" -#include "uv.h" -#include "v8.h" -#include "node.h" - -#include -#include -#include -#include -#include -#include - -struct nghttp2_rcbuf; - -namespace node { - -namespace http2 { -struct http2_state; -} - -// Pick an index that's hopefully out of the way when we're embedded inside -// another application. Performance-wise or memory-wise it doesn't matter: -// Context::SetAlignedPointerInEmbedderData() is backed by a FixedArray, -// worst case we pay a one-time penalty for resizing the array. -#ifndef NODE_CONTEXT_EMBEDDER_DATA_INDEX -#define NODE_CONTEXT_EMBEDDER_DATA_INDEX 32 -#endif - -// The number of items passed to push_values_to_array_function has diminishing -// returns around 8. This should be used at all call sites using said function. -#ifndef NODE_PUSH_VAL_TO_ARRAY_MAX -#define NODE_PUSH_VAL_TO_ARRAY_MAX 8 -#endif - -// PER_ISOLATE_* macros: We have a lot of per-isolate properties -// and adding and maintaining their getters and setters by hand would be -// difficult so let's make the preprocessor generate them for us. -// -// In each macro, `V` is expected to be the name of a macro or function which -// accepts the number of arguments provided in each tuple in the macro body, -// typically two. The named function will be invoked against each tuple. -// -// Make sure that any macro V defined for use with the PER_ISOLATE_* macros is -// undefined again after use. - -// Private symbols are per-isolate primitives but Environment proxies them -// for the sake of convenience. Strings should be ASCII-only and have a -// "node:" prefix to avoid name clashes with third-party code. -#define PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) \ - V(alpn_buffer_private_symbol, "node:alpnBuffer") \ - V(arrow_message_private_symbol, "node:arrowMessage") \ - V(contextify_context_private_symbol, "node:contextify:context") \ - V(contextify_global_private_symbol, "node:contextify:global") \ - V(inspector_delegate_private_symbol, "node:inspector:delegate") \ - V(decorated_private_symbol, "node:decorated") \ - V(npn_buffer_private_symbol, "node:npnBuffer") \ - V(processed_private_symbol, "node:processed") \ - V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \ - -// Strings are per-isolate primitives but Environment proxies them -// for the sake of convenience. Strings should be ASCII-only. -#define PER_ISOLATE_STRING_PROPERTIES(V) \ - V(address_string, "address") \ - V(args_string, "args") \ - V(async, "async") \ - V(buffer_string, "buffer") \ - V(bytes_string, "bytes") \ - V(bytes_parsed_string, "bytesParsed") \ - V(bytes_read_string, "bytesRead") \ - V(cached_data_string, "cachedData") \ - V(cached_data_produced_string, "cachedDataProduced") \ - V(cached_data_rejected_string, "cachedDataRejected") \ - V(callback_string, "callback") \ - V(change_string, "change") \ - V(channel_string, "channel") \ - V(constants_string, "constants") \ - V(oncertcb_string, "oncertcb") \ - V(onclose_string, "_onclose") \ - V(code_string, "code") \ - V(configurable_string, "configurable") \ - V(cwd_string, "cwd") \ - V(dest_string, "dest") \ - V(destroy_string, "destroy") \ - V(detached_string, "detached") \ - V(disposed_string, "_disposed") \ - V(dns_a_string, "A") \ - V(dns_aaaa_string, "AAAA") \ - V(dns_cname_string, "CNAME") \ - V(dns_mx_string, "MX") \ - V(dns_naptr_string, "NAPTR") \ - V(dns_ns_string, "NS") \ - V(dns_ptr_string, "PTR") \ - V(dns_soa_string, "SOA") \ - V(dns_srv_string, "SRV") \ - V(dns_txt_string, "TXT") \ - V(domain_string, "domain") \ - V(emit_string, "emit") \ - V(emitting_top_level_domain_error_string, "_emittingTopLevelDomainError") \ - V(exchange_string, "exchange") \ - V(enumerable_string, "enumerable") \ - V(idle_string, "idle") \ - V(irq_string, "irq") \ - V(enablepush_string, "enablePush") \ - V(encoding_string, "encoding") \ - V(enter_string, "enter") \ - V(entries_string, "entries") \ - V(env_pairs_string, "envPairs") \ - V(errno_string, "errno") \ - V(error_string, "error") \ - V(events_string, "_events") \ - V(exiting_string, "_exiting") \ - V(exit_code_string, "exitCode") \ - V(exit_string, "exit") \ - V(expire_string, "expire") \ - V(exponent_string, "exponent") \ - V(exports_string, "exports") \ - V(ext_key_usage_string, "ext_key_usage") \ - V(external_stream_string, "_externalStream") \ - V(family_string, "family") \ - V(fatal_exception_string, "_fatalException") \ - V(fd_string, "fd") \ - V(file_string, "file") \ - V(fingerprint_string, "fingerprint") \ - V(flags_string, "flags") \ - V(get_string, "get") \ - V(get_data_clone_error_string, "_getDataCloneError") \ - V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \ - V(gid_string, "gid") \ - V(handle_string, "handle") \ - V(heap_total_string, "heapTotal") \ - V(heap_used_string, "heapUsed") \ - V(homedir_string, "homedir") \ - V(hostmaster_string, "hostmaster") \ - V(id_string, "id") \ - V(ignore_string, "ignore") \ - V(immediate_callback_string, "_immediateCallback") \ - V(infoaccess_string, "infoAccess") \ - V(inherit_string, "inherit") \ - V(input_string, "input") \ - V(internal_string, "internal") \ - V(ipv4_string, "IPv4") \ - V(ipv6_string, "IPv6") \ - V(isalive_string, "isAlive") \ - V(isclosing_string, "isClosing") \ - V(issuer_string, "issuer") \ - V(issuercert_string, "issuerCertificate") \ - V(kill_signal_string, "killSignal") \ - V(length_string, "length") \ - V(mac_string, "mac") \ - V(max_buffer_string, "maxBuffer") \ - V(message_string, "message") \ - V(minttl_string, "minttl") \ - V(model_string, "model") \ - V(modulus_string, "modulus") \ - V(name_string, "name") \ - V(netmask_string, "netmask") \ - V(nice_string, "nice") \ - V(nsname_string, "nsname") \ - V(nexttick_string, "nextTick") \ - V(ocsp_request_string, "OCSPRequest") \ - V(onchange_string, "onchange") \ - V(onclienthello_string, "onclienthello") \ - V(oncomplete_string, "oncomplete") \ - V(onconnection_string, "onconnection") \ - V(ondone_string, "ondone") \ - V(onerror_string, "onerror") \ - V(onexit_string, "onexit") \ - V(onframeerror_string, "onframeerror") \ - V(ongetpadding_string, "ongetpadding") \ - V(onhandshakedone_string, "onhandshakedone") \ - V(onhandshakestart_string, "onhandshakestart") \ - V(onheaders_string, "onheaders") \ - V(onmessage_string, "onmessage") \ - V(onnewsession_string, "onnewsession") \ - V(onnewsessiondone_string, "onnewsessiondone") \ - V(onocspresponse_string, "onocspresponse") \ - V(ongoawaydata_string, "ongoawaydata") \ - V(onpriority_string, "onpriority") \ - V(onread_string, "onread") \ - V(onreadstart_string, "onreadstart") \ - V(onreadstop_string, "onreadstop") \ - V(onselect_string, "onselect") \ - V(onsettings_string, "onsettings") \ - V(onshutdown_string, "onshutdown") \ - V(onsignal_string, "onsignal") \ - V(onstop_string, "onstop") \ - V(onstreamclose_string, "onstreamclose") \ - V(ontrailers_string, "ontrailers") \ - V(onwrite_string, "onwrite") \ - V(output_string, "output") \ - V(order_string, "order") \ - V(owner_string, "owner") \ - V(parse_error_string, "Parse Error") \ - V(path_string, "path") \ - V(pbkdf2_error_string, "PBKDF2 Error") \ - V(pid_string, "pid") \ - V(pipe_string, "pipe") \ - V(port_string, "port") \ - V(preference_string, "preference") \ - V(priority_string, "priority") \ - V(produce_cached_data_string, "produceCachedData") \ - V(raw_string, "raw") \ - V(read_host_object_string, "_readHostObject") \ - V(readable_string, "readable") \ - V(received_shutdown_string, "receivedShutdown") \ - V(refresh_string, "refresh") \ - V(regexp_string, "regexp") \ - V(rename_string, "rename") \ - V(replacement_string, "replacement") \ - V(retry_string, "retry") \ - V(serial_string, "serial") \ - V(scopeid_string, "scopeid") \ - V(sent_shutdown_string, "sentShutdown") \ - V(serial_number_string, "serialNumber") \ - V(service_string, "service") \ - V(servername_string, "servername") \ - V(session_id_string, "sessionId") \ - V(set_string, "set") \ - V(shell_string, "shell") \ - V(signal_string, "signal") \ - V(size_string, "size") \ - V(sni_context_err_string, "Invalid SNI context") \ - V(sni_context_string, "sni_context") \ - V(speed_string, "speed") \ - V(stack_string, "stack") \ - V(status_string, "status") \ - V(stdio_string, "stdio") \ - V(stream_string, "stream") \ - V(subject_string, "subject") \ - V(subjectaltname_string, "subjectaltname") \ - V(sys_string, "sys") \ - V(syscall_string, "syscall") \ - V(tick_callback_string, "_tickCallback") \ - V(tick_domain_cb_string, "_tickDomainCallback") \ - V(ticketkeycallback_string, "onticketkeycallback") \ - V(timeout_string, "timeout") \ - V(times_string, "times") \ - V(tls_ticket_string, "tlsTicket") \ - V(ttl_string, "ttl") \ - V(type_string, "type") \ - V(uid_string, "uid") \ - V(unknown_string, "") \ - V(user_string, "user") \ - V(username_string, "username") \ - V(valid_from_string, "valid_from") \ - V(valid_to_string, "valid_to") \ - V(value_string, "value") \ - V(verify_error_string, "verifyError") \ - V(version_string, "version") \ - V(weight_string, "weight") \ - V(windows_verbatim_arguments_string, "windowsVerbatimArguments") \ - V(wrap_string, "wrap") \ - V(writable_string, "writable") \ - V(write_host_object_string, "_writeHostObject") \ - V(write_queue_size_string, "writeQueueSize") \ - V(x_forwarded_string, "x-forwarded-for") \ - V(zero_return_string, "ZERO_RETURN") - -#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \ - V(as_external, v8::External) \ - V(async_hooks_destroy_function, v8::Function) \ - V(async_hooks_init_function, v8::Function) \ - V(async_hooks_before_function, v8::Function) \ - V(async_hooks_after_function, v8::Function) \ - V(binding_cache_object, v8::Object) \ - V(buffer_prototype_object, v8::Object) \ - V(context, v8::Context) \ - V(domain_array, v8::Array) \ - V(domains_stack_array, v8::Array) \ - V(inspector_console_api_object, v8::Object) \ - V(module_load_list_array, v8::Array) \ - V(pbkdf2_constructor_template, v8::ObjectTemplate) \ - V(pipe_constructor_template, v8::FunctionTemplate) \ - V(performance_entry_callback, v8::Function) \ - V(performance_entry_template, v8::Function) \ - V(process_object, v8::Object) \ - V(promise_reject_function, v8::Function) \ - V(promise_wrap_template, v8::ObjectTemplate) \ - V(push_values_to_array_function, v8::Function) \ - V(randombytes_constructor_template, v8::ObjectTemplate) \ - V(script_context_constructor_template, v8::FunctionTemplate) \ - V(script_data_constructor_function, v8::Function) \ - V(secure_context_constructor_template, v8::FunctionTemplate) \ - V(tcp_constructor_template, v8::FunctionTemplate) \ - V(tick_callback_function, v8::Function) \ - V(tls_wrap_constructor_function, v8::Function) \ - V(tty_constructor_template, v8::FunctionTemplate) \ - V(udp_constructor_function, v8::Function) \ - V(vm_parsing_context_symbol, v8::Symbol) \ - V(url_constructor_function, v8::Function) \ - V(write_wrap_constructor_function, v8::Function) \ - -class Environment; - -struct node_async_ids { - double async_id; - double trigger_id; -}; - -class IsolateData { - public: - inline IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop, - uint32_t* zero_fill_field = nullptr); - inline uv_loop_t* event_loop() const; - inline uint32_t* zero_fill_field() const; - -#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) -#define VS(PropertyName, StringValue) V(v8::String, PropertyName) -#define V(TypeName, PropertyName) \ - inline v8::Local PropertyName(v8::Isolate* isolate) const; - PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) - PER_ISOLATE_STRING_PROPERTIES(VS) -#undef V -#undef VS -#undef VP - - std::unordered_map> http2_static_strs; - - private: -#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) -#define VS(PropertyName, StringValue) V(v8::String, PropertyName) -#define V(TypeName, PropertyName) \ - v8::Eternal PropertyName ## _; - PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) - PER_ISOLATE_STRING_PROPERTIES(VS) -#undef V -#undef VS -#undef VP - - uv_loop_t* const event_loop_; - uint32_t* const zero_fill_field_; - - DISALLOW_COPY_AND_ASSIGN(IsolateData); -}; - -class Environment { - public: - class AsyncHooks { - public: - // Reason for both UidFields and Fields are that one is stored as a double* - // and the other as a uint32_t*. - enum Fields { - kInit, - kBefore, - kAfter, - kDestroy, - kTotals, - kFieldsCount, - }; - - enum UidFields { - kCurrentAsyncId, - kCurrentTriggerId, - kAsyncUidCntr, - kInitTriggerId, - kUidFieldsCount, - }; - - - AsyncHooks() = delete; - - inline uint32_t* fields(); - inline int fields_count() const; - inline double* uid_fields(); - inline int uid_fields_count() const; - inline v8::Local provider_string(int idx); - - inline void push_ids(double async_id, double trigger_id); - inline bool pop_ids(double async_id); - inline size_t stack_size(); - inline void clear_id_stack(); // Used in fatal exceptions. - - // Used to propagate the trigger_id to the constructor of any newly created - // resources using RAII. Instead of needing to pass the trigger_id along - // with other constructor arguments. - class InitScope { - public: - InitScope() = delete; - explicit InitScope(Environment* env, double init_trigger_id); - ~InitScope(); - - private: - Environment* env_; - double* uid_fields_ref_; - - DISALLOW_COPY_AND_ASSIGN(InitScope); - }; - - // Used to manage the stack of async and trigger ids as calls are made into - // JS. Mainly used in MakeCallback(). - class ExecScope { - public: - ExecScope() = delete; - explicit ExecScope(Environment* env, double async_id, double trigger_id); - ~ExecScope(); - void Dispose(); - - private: - Environment* env_; - double async_id_; - // Manually track if the destructor has run so it isn't accidentally run - // twice on RAII cleanup. - bool disposed_; - - DISALLOW_COPY_AND_ASSIGN(ExecScope); - }; - - private: - friend class Environment; // So we can call the constructor. - inline explicit AsyncHooks(v8::Isolate* isolate); - // Keep a list of all Persistent strings used for Provider types. - v8::Eternal providers_[AsyncWrap::PROVIDERS_LENGTH]; - // Used by provider_string(). - v8::Isolate* isolate_; - // Stores the ids of the current execution context stack. - std::stack ids_stack_; - // Attached to a Uint32Array that tracks the number of active hooks for - // each type. - uint32_t fields_[kFieldsCount]; - // Attached to a Float64Array that tracks the state of async resources. - double uid_fields_[kUidFieldsCount]; - - DISALLOW_COPY_AND_ASSIGN(AsyncHooks); - }; - - class AsyncCallbackScope { - public: - AsyncCallbackScope() = delete; - explicit AsyncCallbackScope(Environment* env); - ~AsyncCallbackScope(); - inline bool in_makecallback(); - - private: - Environment* env_; - - DISALLOW_COPY_AND_ASSIGN(AsyncCallbackScope); - }; - - class DomainFlag { - public: - inline uint32_t* fields(); - inline int fields_count() const; - inline uint32_t count() const; - - private: - friend class Environment; // So we can call the constructor. - inline DomainFlag(); - - enum Fields { - kCount, - kFieldsCount - }; - - uint32_t fields_[kFieldsCount]; - - DISALLOW_COPY_AND_ASSIGN(DomainFlag); - }; - - class TickInfo { - public: - inline uint32_t* fields(); - inline int fields_count() const; - inline uint32_t index() const; - inline uint32_t length() const; - inline void set_index(uint32_t value); - - private: - friend class Environment; // So we can call the constructor. - inline TickInfo(); - - enum Fields { - kIndex, - kLength, - kFieldsCount - }; - - uint32_t fields_[kFieldsCount]; - - DISALLOW_COPY_AND_ASSIGN(TickInfo); - }; - - typedef void (*HandleCleanupCb)(Environment* env, - uv_handle_t* handle, - void* arg); - - class HandleCleanup { - private: - friend class Environment; - - HandleCleanup(uv_handle_t* handle, HandleCleanupCb cb, void* arg) - : handle_(handle), - cb_(cb), - arg_(arg) { - } - - uv_handle_t* handle_; - HandleCleanupCb cb_; - void* arg_; - ListNode handle_cleanup_queue_; - }; - - static inline Environment* GetCurrent(v8::Isolate* isolate); - static inline Environment* GetCurrent(v8::Local context); - static inline Environment* GetCurrent( - const v8::FunctionCallbackInfo& info); - - template - static inline Environment* GetCurrent( - const v8::PropertyCallbackInfo& info); - - inline Environment(IsolateData* isolate_data, v8::Local context); - inline ~Environment(); - - void Start(int argc, - const char* const* argv, - int exec_argc, - const char* const* exec_argv, - bool start_profiler_idle_notifier); - void AssignToContext(v8::Local context); - void CleanupHandles(); - - void StartProfilerIdleNotifier(); - void StopProfilerIdleNotifier(); - - inline v8::Isolate* isolate() const; - inline uv_loop_t* event_loop() const; - inline bool in_domain() const; - inline uint32_t watched_providers() const; - - static inline Environment* from_immediate_check_handle(uv_check_t* handle); - static inline Environment* from_destroy_ids_timer_handle(uv_timer_t* handle); - inline uv_check_t* immediate_check_handle(); - inline uv_idle_t* immediate_idle_handle(); - inline uv_timer_t* destroy_ids_timer_handle(); - - // Register clean-up cb to be called on environment destruction. - inline void RegisterHandleCleanup(uv_handle_t* handle, - HandleCleanupCb cb, - void *arg); - inline void FinishHandleCleanup(uv_handle_t* handle); - - inline AsyncHooks* async_hooks(); - inline DomainFlag* domain_flag(); - inline TickInfo* tick_info(); - inline uint64_t timer_base() const; - - inline IsolateData* isolate_data() const; - - inline bool using_domains() const; - inline void set_using_domains(bool value); - - inline bool printed_error() const; - inline void set_printed_error(bool value); - - void PrintSyncTrace() const; - inline void set_trace_sync_io(bool value); - - inline bool abort_on_uncaught_exception() const; - inline void set_abort_on_uncaught_exception(bool value); - - // The necessary API for async_hooks. - inline double new_async_id(); - inline double current_async_id(); - inline double trigger_id(); - inline double get_init_trigger_id(); - inline void set_init_trigger_id(const double id); - - // List of id's that have been destroyed and need the destroy() cb called. - inline std::vector* destroy_ids_list(); - - inline double* heap_statistics_buffer() const; - inline void set_heap_statistics_buffer(double* pointer); - - inline double* heap_space_statistics_buffer() const; - inline void set_heap_space_statistics_buffer(double* pointer); - - inline char* http_parser_buffer() const; - inline void set_http_parser_buffer(char* buffer); - - inline http2::http2_state* http2_state_buffer() const; - inline void set_http2_state_buffer(http2::http2_state* buffer); - - inline v8::Local fs_stats_field_array() const; - inline void set_fs_stats_field_array(v8::Local fields); - - inline performance::performance_state* performance_state(); - inline std::map* performance_marks(); - - static inline Environment* from_performance_check_handle(uv_check_t* handle); - static inline Environment* from_performance_idle_handle(uv_idle_t* handle); - static inline Environment* from_performance_prepare_handle( - uv_prepare_t* handle); - inline uv_check_t* performance_check_handle(); - inline uv_idle_t* performance_idle_handle(); - inline uv_prepare_t* performance_prepare_handle(); - - inline void ThrowError(const char* errmsg); - inline void ThrowTypeError(const char* errmsg); - inline void ThrowRangeError(const char* errmsg); - inline void ThrowErrnoException(int errorno, - const char* syscall = nullptr, - const char* message = nullptr, - const char* path = nullptr); - inline void ThrowUVException(int errorno, - const char* syscall = nullptr, - const char* message = nullptr, - const char* path = nullptr, - const char* dest = nullptr); - - inline v8::Local - NewFunctionTemplate(v8::FunctionCallback callback, - v8::Local signature = - v8::Local()); - - // Convenience methods for NewFunctionTemplate(). - inline void SetMethod(v8::Local that, - const char* name, - v8::FunctionCallback callback); - inline void SetProtoMethod(v8::Local that, - const char* name, - v8::FunctionCallback callback); - inline void SetTemplateMethod(v8::Local that, - const char* name, - v8::FunctionCallback callback); - - void AtExit(void (*cb)(void* arg), void* arg); - void RunAtExitCallbacks(); - - // Strings and private symbols are shared across shared contexts - // The getters simply proxy to the per-isolate primitive. -#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) -#define VS(PropertyName, StringValue) V(v8::String, PropertyName) -#define V(TypeName, PropertyName) \ - inline v8::Local PropertyName() const; - PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) - PER_ISOLATE_STRING_PROPERTIES(VS) -#undef V -#undef VS -#undef VP - -#define V(PropertyName, TypeName) \ - inline v8::Local PropertyName() const; \ - inline void set_ ## PropertyName(v8::Local value); - ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) -#undef V - -#if HAVE_INSPECTOR - inline inspector::Agent* inspector_agent() { - return &inspector_agent_; - } -#endif - - typedef ListHead HandleWrapQueue; - typedef ListHead, &ReqWrap::req_wrap_queue_> - ReqWrapQueue; - - inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; } - inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; } - - static const int kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX; - - void AddPromiseHook(promise_hook_func fn, void* arg); - bool RemovePromiseHook(promise_hook_func fn, void* arg); - - private: - inline void ThrowError(v8::Local (*fun)(v8::Local), - const char* errmsg); - - v8::Isolate* const isolate_; - IsolateData* const isolate_data_; - uv_check_t immediate_check_handle_; - uv_idle_t immediate_idle_handle_; - uv_timer_t destroy_ids_timer_handle_; - uv_prepare_t idle_prepare_handle_; - uv_check_t idle_check_handle_; - uv_prepare_t performance_prepare_handle_; - uv_check_t performance_check_handle_; - uv_idle_t performance_idle_handle_; - - AsyncHooks async_hooks_; - DomainFlag domain_flag_; - TickInfo tick_info_; - const uint64_t timer_base_; - bool using_domains_; - bool printed_error_; - bool trace_sync_io_; - bool abort_on_uncaught_exception_; - size_t makecallback_cntr_; - std::vector destroy_ids_list_; - - performance::performance_state* performance_state_ = nullptr; - std::map performance_marks_; - -#if HAVE_INSPECTOR - inspector::Agent inspector_agent_; -#endif - - HandleWrapQueue handle_wrap_queue_; - ReqWrapQueue req_wrap_queue_; - ListHead handle_cleanup_queue_; - int handle_cleanup_waiting_; - - double* heap_statistics_buffer_ = nullptr; - double* heap_space_statistics_buffer_ = nullptr; - - char* http_parser_buffer_; - http2::http2_state* http2_state_buffer_ = nullptr; - - // We depend on the property in fs.js to manage the lifetime appropriately - v8::Global fs_stats_field_array_; - - struct AtExitCallback { - void (*cb_)(void* arg); - void* arg_; - }; - std::list at_exit_functions_; - - struct PromiseHookCallback { - promise_hook_func cb_; - void* arg_; - size_t enable_count_; - }; - std::vector promise_hooks_; - - static void EnvPromiseHook(v8::PromiseHookType type, - v8::Local promise, - v8::Local parent); - -#define V(PropertyName, TypeName) \ - v8::Persistent PropertyName ## _; - ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) -#undef V - - DISALLOW_COPY_AND_ASSIGN(Environment); -}; - -} // namespace node - -#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -#endif // SRC_ENV_H_ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SRC_ENV_H_ +#define SRC_ENV_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "ares.h" +#if HAVE_INSPECTOR +#include "inspector_agent.h" +#endif +#include "handle_wrap.h" +#include "req-wrap.h" +#include "util.h" +#include "uv.h" +#include "v8.h" +#include "node.h" + +#include +#include +#include +#include +#include +#include + +struct nghttp2_rcbuf; + +namespace node { + +namespace http2 { +struct http2_state; +} + +// Pick an index that's hopefully out of the way when we're embedded inside +// another application. Performance-wise or memory-wise it doesn't matter: +// Context::SetAlignedPointerInEmbedderData() is backed by a FixedArray, +// worst case we pay a one-time penalty for resizing the array. +#ifndef NODE_CONTEXT_EMBEDDER_DATA_INDEX +#define NODE_CONTEXT_EMBEDDER_DATA_INDEX 32 +#endif + +// The number of items passed to push_values_to_array_function has diminishing +// returns around 8. This should be used at all call sites using said function. +#ifndef NODE_PUSH_VAL_TO_ARRAY_MAX +#define NODE_PUSH_VAL_TO_ARRAY_MAX 8 +#endif + +// PER_ISOLATE_* macros: We have a lot of per-isolate properties +// and adding and maintaining their getters and setters by hand would be +// difficult so let's make the preprocessor generate them for us. +// +// In each macro, `V` is expected to be the name of a macro or function which +// accepts the number of arguments provided in each tuple in the macro body, +// typically two. The named function will be invoked against each tuple. +// +// Make sure that any macro V defined for use with the PER_ISOLATE_* macros is +// undefined again after use. + +// Private symbols are per-isolate primitives but Environment proxies them +// for the sake of convenience. Strings should be ASCII-only and have a +// "node:" prefix to avoid name clashes with third-party code. +#define PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) \ + V(alpn_buffer_private_symbol, "node:alpnBuffer") \ + V(arrow_message_private_symbol, "node:arrowMessage") \ + V(contextify_context_private_symbol, "node:contextify:context") \ + V(contextify_global_private_symbol, "node:contextify:global") \ + V(inspector_delegate_private_symbol, "node:inspector:delegate") \ + V(decorated_private_symbol, "node:decorated") \ + V(npn_buffer_private_symbol, "node:npnBuffer") \ + V(processed_private_symbol, "node:processed") \ + V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \ + +// Strings are per-isolate primitives but Environment proxies them +// for the sake of convenience. Strings should be ASCII-only. +#define PER_ISOLATE_STRING_PROPERTIES(V) \ + V(address_string, "address") \ + V(args_string, "args") \ + V(async, "async") \ + V(buffer_string, "buffer") \ + V(bytes_string, "bytes") \ + V(bytes_parsed_string, "bytesParsed") \ + V(bytes_read_string, "bytesRead") \ + V(cached_data_string, "cachedData") \ + V(cached_data_produced_string, "cachedDataProduced") \ + V(cached_data_rejected_string, "cachedDataRejected") \ + V(callback_string, "callback") \ + V(change_string, "change") \ + V(channel_string, "channel") \ + V(constants_string, "constants") \ + V(oncertcb_string, "oncertcb") \ + V(onclose_string, "_onclose") \ + V(code_string, "code") \ + V(configurable_string, "configurable") \ + V(cwd_string, "cwd") \ + V(dest_string, "dest") \ + V(destroy_string, "destroy") \ + V(detached_string, "detached") \ + V(disposed_string, "_disposed") \ + V(dns_a_string, "A") \ + V(dns_aaaa_string, "AAAA") \ + V(dns_cname_string, "CNAME") \ + V(dns_mx_string, "MX") \ + V(dns_naptr_string, "NAPTR") \ + V(dns_ns_string, "NS") \ + V(dns_ptr_string, "PTR") \ + V(dns_soa_string, "SOA") \ + V(dns_srv_string, "SRV") \ + V(dns_txt_string, "TXT") \ + V(domain_string, "domain") \ + V(emit_string, "emit") \ + V(emitting_top_level_domain_error_string, "_emittingTopLevelDomainError") \ + V(exchange_string, "exchange") \ + V(enumerable_string, "enumerable") \ + V(idle_string, "idle") \ + V(irq_string, "irq") \ + V(enablepush_string, "enablePush") \ + V(encoding_string, "encoding") \ + V(enter_string, "enter") \ + V(entries_string, "entries") \ + V(env_pairs_string, "envPairs") \ + V(errno_string, "errno") \ + V(error_string, "error") \ + V(events_string, "_events") \ + V(exiting_string, "_exiting") \ + V(exit_code_string, "exitCode") \ + V(exit_string, "exit") \ + V(expire_string, "expire") \ + V(exponent_string, "exponent") \ + V(exports_string, "exports") \ + V(ext_key_usage_string, "ext_key_usage") \ + V(external_stream_string, "_externalStream") \ + V(family_string, "family") \ + V(fatal_exception_string, "_fatalException") \ + V(fd_string, "fd") \ + V(file_string, "file") \ + V(fingerprint_string, "fingerprint") \ + V(flags_string, "flags") \ + V(get_string, "get") \ + V(get_data_clone_error_string, "_getDataCloneError") \ + V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \ + V(gid_string, "gid") \ + V(handle_string, "handle") \ + V(heap_total_string, "heapTotal") \ + V(heap_used_string, "heapUsed") \ + V(homedir_string, "homedir") \ + V(hostmaster_string, "hostmaster") \ + V(id_string, "id") \ + V(ignore_string, "ignore") \ + V(immediate_callback_string, "_immediateCallback") \ + V(infoaccess_string, "infoAccess") \ + V(inherit_string, "inherit") \ + V(input_string, "input") \ + V(internal_string, "internal") \ + V(ipv4_string, "IPv4") \ + V(ipv6_string, "IPv6") \ + V(isalive_string, "isAlive") \ + V(isclosing_string, "isClosing") \ + V(issuer_string, "issuer") \ + V(issuercert_string, "issuerCertificate") \ + V(kill_signal_string, "killSignal") \ + V(length_string, "length") \ + V(mac_string, "mac") \ + V(max_buffer_string, "maxBuffer") \ + V(message_string, "message") \ + V(minttl_string, "minttl") \ + V(model_string, "model") \ + V(modulus_string, "modulus") \ + V(name_string, "name") \ + V(netmask_string, "netmask") \ + V(nice_string, "nice") \ + V(nsname_string, "nsname") \ + V(nexttick_string, "nextTick") \ + V(ocsp_request_string, "OCSPRequest") \ + V(onchange_string, "onchange") \ + V(onclienthello_string, "onclienthello") \ + V(oncomplete_string, "oncomplete") \ + V(onconnection_string, "onconnection") \ + V(ondone_string, "ondone") \ + V(onerror_string, "onerror") \ + V(onexit_string, "onexit") \ + V(onframeerror_string, "onframeerror") \ + V(ongetpadding_string, "ongetpadding") \ + V(onhandshakedone_string, "onhandshakedone") \ + V(onhandshakestart_string, "onhandshakestart") \ + V(onheaders_string, "onheaders") \ + V(onmessage_string, "onmessage") \ + V(onnewsession_string, "onnewsession") \ + V(onnewsessiondone_string, "onnewsessiondone") \ + V(onocspresponse_string, "onocspresponse") \ + V(ongoawaydata_string, "ongoawaydata") \ + V(onpriority_string, "onpriority") \ + V(onread_string, "onread") \ + V(onreadstart_string, "onreadstart") \ + V(onreadstop_string, "onreadstop") \ + V(onselect_string, "onselect") \ + V(onsettings_string, "onsettings") \ + V(onshutdown_string, "onshutdown") \ + V(onsignal_string, "onsignal") \ + V(onstop_string, "onstop") \ + V(onstreamclose_string, "onstreamclose") \ + V(ontrailers_string, "ontrailers") \ + V(onwrite_string, "onwrite") \ + V(output_string, "output") \ + V(order_string, "order") \ + V(owner_string, "owner") \ + V(parse_error_string, "Parse Error") \ + V(path_string, "path") \ + V(pbkdf2_error_string, "PBKDF2 Error") \ + V(pid_string, "pid") \ + V(pipe_string, "pipe") \ + V(port_string, "port") \ + V(preference_string, "preference") \ + V(priority_string, "priority") \ + V(produce_cached_data_string, "produceCachedData") \ + V(raw_string, "raw") \ + V(read_host_object_string, "_readHostObject") \ + V(readable_string, "readable") \ + V(received_shutdown_string, "receivedShutdown") \ + V(refresh_string, "refresh") \ + V(regexp_string, "regexp") \ + V(rename_string, "rename") \ + V(replacement_string, "replacement") \ + V(retry_string, "retry") \ + V(serial_string, "serial") \ + V(scopeid_string, "scopeid") \ + V(sent_shutdown_string, "sentShutdown") \ + V(serial_number_string, "serialNumber") \ + V(service_string, "service") \ + V(servername_string, "servername") \ + V(session_id_string, "sessionId") \ + V(set_string, "set") \ + V(shell_string, "shell") \ + V(signal_string, "signal") \ + V(size_string, "size") \ + V(sni_context_err_string, "Invalid SNI context") \ + V(sni_context_string, "sni_context") \ + V(speed_string, "speed") \ + V(stack_string, "stack") \ + V(status_string, "status") \ + V(stdio_string, "stdio") \ + V(stream_string, "stream") \ + V(subject_string, "subject") \ + V(subjectaltname_string, "subjectaltname") \ + V(sys_string, "sys") \ + V(syscall_string, "syscall") \ + V(tick_callback_string, "_tickCallback") \ + V(tick_domain_cb_string, "_tickDomainCallback") \ + V(ticketkeycallback_string, "onticketkeycallback") \ + V(timeout_string, "timeout") \ + V(times_string, "times") \ + V(tls_ticket_string, "tlsTicket") \ + V(ttl_string, "ttl") \ + V(type_string, "type") \ + V(uid_string, "uid") \ + V(unknown_string, "") \ + V(user_string, "user") \ + V(username_string, "username") \ + V(valid_from_string, "valid_from") \ + V(valid_to_string, "valid_to") \ + V(value_string, "value") \ + V(verify_error_string, "verifyError") \ + V(version_string, "version") \ + V(weight_string, "weight") \ + V(windows_verbatim_arguments_string, "windowsVerbatimArguments") \ + V(wrap_string, "wrap") \ + V(writable_string, "writable") \ + V(write_host_object_string, "_writeHostObject") \ + V(write_queue_size_string, "writeQueueSize") \ + V(x_forwarded_string, "x-forwarded-for") \ + V(zero_return_string, "ZERO_RETURN") + +#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \ + V(as_external, v8::External) \ + V(async_hooks_destroy_function, v8::Function) \ + V(async_hooks_init_function, v8::Function) \ + V(async_hooks_before_function, v8::Function) \ + V(async_hooks_after_function, v8::Function) \ + V(binding_cache_object, v8::Object) \ + V(buffer_prototype_object, v8::Object) \ + V(context, v8::Context) \ + V(domain_array, v8::Array) \ + V(domains_stack_array, v8::Array) \ + V(inspector_console_api_object, v8::Object) \ + V(module_load_list_array, v8::Array) \ + V(pbkdf2_constructor_template, v8::ObjectTemplate) \ + V(pipe_constructor_template, v8::FunctionTemplate) \ + V(performance_entry_callback, v8::Function) \ + V(performance_entry_template, v8::Function) \ + V(process_object, v8::Object) \ + V(promise_reject_function, v8::Function) \ + V(promise_wrap_template, v8::ObjectTemplate) \ + V(push_values_to_array_function, v8::Function) \ + V(randombytes_constructor_template, v8::ObjectTemplate) \ + V(script_context_constructor_template, v8::FunctionTemplate) \ + V(script_data_constructor_function, v8::Function) \ + V(secure_context_constructor_template, v8::FunctionTemplate) \ + V(tcp_constructor_template, v8::FunctionTemplate) \ + V(tick_callback_function, v8::Function) \ + V(tls_wrap_constructor_function, v8::Function) \ + V(tty_constructor_template, v8::FunctionTemplate) \ + V(udp_constructor_function, v8::Function) \ + V(vm_parsing_context_symbol, v8::Symbol) \ + V(url_constructor_function, v8::Function) \ + V(write_wrap_constructor_function, v8::Function) \ + +class Environment; + +struct node_async_ids { + double async_id; + double trigger_id; +}; + +class IsolateData { + public: + inline IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop, + uint32_t* zero_fill_field = nullptr); + inline uv_loop_t* event_loop() const; + inline uint32_t* zero_fill_field() const; + +#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) +#define VS(PropertyName, StringValue) V(v8::String, PropertyName) +#define V(TypeName, PropertyName) \ + inline v8::Local PropertyName(v8::Isolate* isolate) const; + PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) + PER_ISOLATE_STRING_PROPERTIES(VS) +#undef V +#undef VS +#undef VP + + std::unordered_map> http2_static_strs; + + private: +#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) +#define VS(PropertyName, StringValue) V(v8::String, PropertyName) +#define V(TypeName, PropertyName) \ + v8::Eternal PropertyName ## _; + PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) + PER_ISOLATE_STRING_PROPERTIES(VS) +#undef V +#undef VS +#undef VP + + uv_loop_t* const event_loop_; + uint32_t* const zero_fill_field_; + + DISALLOW_COPY_AND_ASSIGN(IsolateData); +}; + +class Environment { + public: + class AsyncHooks { + public: + // Reason for both UidFields and Fields are that one is stored as a double* + // and the other as a uint32_t*. + enum Fields { + kInit, + kBefore, + kAfter, + kDestroy, + kTotals, + kFieldsCount, + }; + + enum UidFields { + kCurrentAsyncId, + kCurrentTriggerId, + kAsyncUidCntr, + kInitTriggerId, + kUidFieldsCount, + }; + + + AsyncHooks() = delete; + + inline uint32_t* fields(); + inline int fields_count() const; + inline double* uid_fields(); + inline int uid_fields_count() const; + inline v8::Local provider_string(int idx); + + inline void push_ids(double async_id, double trigger_id); + inline bool pop_ids(double async_id); + inline size_t stack_size(); + inline void clear_id_stack(); // Used in fatal exceptions. + + // Used to propagate the trigger_id to the constructor of any newly created + // resources using RAII. Instead of needing to pass the trigger_id along + // with other constructor arguments. + class InitScope { + public: + InitScope() = delete; + explicit InitScope(Environment* env, double init_trigger_id); + ~InitScope(); + + private: + Environment* env_; + double* uid_fields_ref_; + + DISALLOW_COPY_AND_ASSIGN(InitScope); + }; + + // Used to manage the stack of async and trigger ids as calls are made into + // JS. Mainly used in MakeCallback(). + class ExecScope { + public: + ExecScope() = delete; + explicit ExecScope(Environment* env, double async_id, double trigger_id); + ~ExecScope(); + void Dispose(); + + private: + Environment* env_; + double async_id_; + // Manually track if the destructor has run so it isn't accidentally run + // twice on RAII cleanup. + bool disposed_; + + DISALLOW_COPY_AND_ASSIGN(ExecScope); + }; + + private: + friend class Environment; // So we can call the constructor. + inline explicit AsyncHooks(v8::Isolate* isolate); + // Keep a list of all Persistent strings used for Provider types. + v8::Eternal providers_[AsyncWrap::PROVIDERS_LENGTH]; + // Used by provider_string(). + v8::Isolate* isolate_; + // Stores the ids of the current execution context stack. + std::stack ids_stack_; + // Attached to a Uint32Array that tracks the number of active hooks for + // each type. + uint32_t fields_[kFieldsCount]; + // Attached to a Float64Array that tracks the state of async resources. + double uid_fields_[kUidFieldsCount]; + + DISALLOW_COPY_AND_ASSIGN(AsyncHooks); + }; + + class AsyncCallbackScope { + public: + AsyncCallbackScope() = delete; + explicit AsyncCallbackScope(Environment* env); + ~AsyncCallbackScope(); + inline bool in_makecallback(); + + private: + Environment* env_; + + DISALLOW_COPY_AND_ASSIGN(AsyncCallbackScope); + }; + + class DomainFlag { + public: + inline uint32_t* fields(); + inline int fields_count() const; + inline uint32_t count() const; + + private: + friend class Environment; // So we can call the constructor. + inline DomainFlag(); + + enum Fields { + kCount, + kFieldsCount + }; + + uint32_t fields_[kFieldsCount]; + + DISALLOW_COPY_AND_ASSIGN(DomainFlag); + }; + + class TickInfo { + public: + inline uint32_t* fields(); + inline int fields_count() const; + inline uint32_t index() const; + inline uint32_t length() const; + inline void set_index(uint32_t value); + + private: + friend class Environment; // So we can call the constructor. + inline TickInfo(); + + enum Fields { + kIndex, + kLength, + kFieldsCount + }; + + uint32_t fields_[kFieldsCount]; + + DISALLOW_COPY_AND_ASSIGN(TickInfo); + }; + + typedef void (*HandleCleanupCb)(Environment* env, + uv_handle_t* handle, + void* arg); + + class HandleCleanup { + private: + friend class Environment; + + HandleCleanup(uv_handle_t* handle, HandleCleanupCb cb, void* arg) + : handle_(handle), + cb_(cb), + arg_(arg) { + } + + uv_handle_t* handle_; + HandleCleanupCb cb_; + void* arg_; + ListNode handle_cleanup_queue_; + }; + + static inline Environment* GetCurrent(v8::Isolate* isolate); + static inline Environment* GetCurrent(v8::Local context); + static inline Environment* GetCurrent( + const v8::FunctionCallbackInfo& info); + + template + static inline Environment* GetCurrent( + const v8::PropertyCallbackInfo& info); + + inline Environment(IsolateData* isolate_data, v8::Local context); + inline ~Environment(); + + void Start(int argc, + const char* const* argv, + int exec_argc, + const char* const* exec_argv, + bool start_profiler_idle_notifier); + void AssignToContext(v8::Local context); + void CleanupHandles(); + + void StartProfilerIdleNotifier(); + void StopProfilerIdleNotifier(); + + inline v8::Isolate* isolate() const; + inline uv_loop_t* event_loop() const; + inline bool in_domain() const; + inline uint32_t watched_providers() const; + + static inline Environment* from_immediate_check_handle(uv_check_t* handle); + static inline Environment* from_destroy_ids_timer_handle(uv_timer_t* handle); + inline uv_check_t* immediate_check_handle(); + inline uv_idle_t* immediate_idle_handle(); + inline uv_timer_t* destroy_ids_timer_handle(); + + // Register clean-up cb to be called on environment destruction. + inline void RegisterHandleCleanup(uv_handle_t* handle, + HandleCleanupCb cb, + void *arg); + inline void FinishHandleCleanup(uv_handle_t* handle); + + inline AsyncHooks* async_hooks(); + inline DomainFlag* domain_flag(); + inline TickInfo* tick_info(); + inline uint64_t timer_base() const; + + inline IsolateData* isolate_data() const; + + inline bool using_domains() const; + inline void set_using_domains(bool value); + + inline bool printed_error() const; + inline void set_printed_error(bool value); + + void PrintSyncTrace() const; + inline void set_trace_sync_io(bool value); + + inline bool abort_on_uncaught_exception() const; + inline void set_abort_on_uncaught_exception(bool value); + + // The necessary API for async_hooks. + inline double new_async_id(); + inline double current_async_id(); + inline double trigger_id(); + inline double get_init_trigger_id(); + inline void set_init_trigger_id(const double id); + + // List of id's that have been destroyed and need the destroy() cb called. + inline std::vector* destroy_ids_list(); + + inline double* heap_statistics_buffer() const; + inline void set_heap_statistics_buffer(double* pointer); + + inline double* heap_space_statistics_buffer() const; + inline void set_heap_space_statistics_buffer(double* pointer); + + inline char* http_parser_buffer() const; + inline void set_http_parser_buffer(char* buffer); + + inline http2::http2_state* http2_state_buffer() const; + inline void set_http2_state_buffer(http2::http2_state* buffer); + + inline v8::Local fs_stats_field_array() const; + inline void set_fs_stats_field_array(v8::Local fields); + + inline performance::performance_state* performance_state(); + inline std::map* performance_marks(); + + static inline Environment* from_performance_check_handle(uv_check_t* handle); + static inline Environment* from_performance_idle_handle(uv_idle_t* handle); + static inline Environment* from_performance_prepare_handle( + uv_prepare_t* handle); + inline uv_check_t* performance_check_handle(); + inline uv_idle_t* performance_idle_handle(); + inline uv_prepare_t* performance_prepare_handle(); + + inline void ThrowError(const char* errmsg); + inline void ThrowTypeError(const char* errmsg); + inline void ThrowRangeError(const char* errmsg); + inline void ThrowErrnoException(int errorno, + const char* syscall = nullptr, + const char* message = nullptr, + const char* path = nullptr); + inline void ThrowUVException(int errorno, + const char* syscall = nullptr, + const char* message = nullptr, + const char* path = nullptr, + const char* dest = nullptr); + + inline v8::Local + NewFunctionTemplate(v8::FunctionCallback callback, + v8::Local signature = + v8::Local()); + + // Convenience methods for NewFunctionTemplate(). + inline void SetMethod(v8::Local that, + const char* name, + v8::FunctionCallback callback); + inline void SetProtoMethod(v8::Local that, + const char* name, + v8::FunctionCallback callback); + inline void SetTemplateMethod(v8::Local that, + const char* name, + v8::FunctionCallback callback); + + void AtExit(void (*cb)(void* arg), void* arg); + void RunAtExitCallbacks(); + + // Strings and private symbols are shared across shared contexts + // The getters simply proxy to the per-isolate primitive. +#define VP(PropertyName, StringValue) V(v8::Private, PropertyName) +#define VS(PropertyName, StringValue) V(v8::String, PropertyName) +#define V(TypeName, PropertyName) \ + inline v8::Local PropertyName() const; + PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) + PER_ISOLATE_STRING_PROPERTIES(VS) +#undef V +#undef VS +#undef VP + +#define V(PropertyName, TypeName) \ + inline v8::Local PropertyName() const; \ + inline void set_ ## PropertyName(v8::Local value); + ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) +#undef V + +#if HAVE_INSPECTOR + inline inspector::Agent* inspector_agent() { + return &inspector_agent_; + } +#endif + + typedef ListHead HandleWrapQueue; + typedef ListHead, &ReqWrap::req_wrap_queue_> + ReqWrapQueue; + + inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; } + inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; } + + static const int kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX; + + void AddPromiseHook(promise_hook_func fn, void* arg); + bool RemovePromiseHook(promise_hook_func fn, void* arg); + + private: + inline void ThrowError(v8::Local (*fun)(v8::Local), + const char* errmsg); + + v8::Isolate* const isolate_; + IsolateData* const isolate_data_; + uv_check_t immediate_check_handle_; + uv_idle_t immediate_idle_handle_; + uv_timer_t destroy_ids_timer_handle_; + uv_prepare_t idle_prepare_handle_; + uv_check_t idle_check_handle_; + uv_prepare_t performance_prepare_handle_; + uv_check_t performance_check_handle_; + uv_idle_t performance_idle_handle_; + + AsyncHooks async_hooks_; + DomainFlag domain_flag_; + TickInfo tick_info_; + const uint64_t timer_base_; + bool using_domains_; + bool printed_error_; + bool trace_sync_io_; + bool abort_on_uncaught_exception_; + size_t makecallback_cntr_; + std::vector destroy_ids_list_; + + performance::performance_state* performance_state_ = nullptr; + std::map performance_marks_; + +#if HAVE_INSPECTOR + inspector::Agent inspector_agent_; +#endif + + HandleWrapQueue handle_wrap_queue_; + ReqWrapQueue req_wrap_queue_; + ListHead handle_cleanup_queue_; + int handle_cleanup_waiting_; + + double* heap_statistics_buffer_ = nullptr; + double* heap_space_statistics_buffer_ = nullptr; + + char* http_parser_buffer_; + http2::http2_state* http2_state_buffer_ = nullptr; + + // We depend on the property in fs.js to manage the lifetime appropriately + v8::Global fs_stats_field_array_; + + struct AtExitCallback { + void (*cb_)(void* arg); + void* arg_; + }; + std::list at_exit_functions_; + + struct PromiseHookCallback { + promise_hook_func cb_; + void* arg_; + size_t enable_count_; + }; + std::vector promise_hooks_; + + static void EnvPromiseHook(v8::PromiseHookType type, + v8::Local promise, + v8::Local parent); + +#define V(PropertyName, TypeName) \ + v8::Persistent PropertyName ## _; + ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) +#undef V + + DISALLOW_COPY_AND_ASSIGN(Environment); +}; + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_ENV_H_