blob: d99bb63db6fb29b584ad43ccd5c1a422e4acc91c [file] [log] [blame]
// 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 "aliased_buffer.h"
#if HAVE_INSPECTOR
#include "inspector_agent.h"
#include "inspector_profiler.h"
#endif
#include "callback_queue.h"
#include "debug_utils.h"
#include "handle_wrap.h"
#include "node.h"
#include "node_binding.h"
#include "node_main_instance.h"
#include "node_options.h"
#include "node_perf_common.h"
#include "req_wrap.h"
#include "util.h"
#include "uv.h"
#include "v8.h"
#include <array>
#include <atomic>
#include <cstdint>
#include <functional>
#include <iostream>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace node {
namespace contextify {
class ContextifyScript;
class CompiledFnEntry;
}
namespace performance {
class PerformanceState;
}
namespace tracing {
class AgentWriterHandle;
}
#if HAVE_INSPECTOR
namespace profiler {
class V8CoverageConnection;
class V8CpuProfilerConnection;
class V8HeapProfilerConnection;
} // namespace profiler
namespace inspector {
class ParentInspectorHandle;
}
#endif // HAVE_INSPECTOR
namespace worker {
class Worker;
}
namespace loader {
class ModuleWrap;
struct PackageConfig {
enum class Exists { Yes, No };
enum class IsValid { Yes, No };
enum class HasMain { Yes, No };
enum class HasName { Yes, No };
enum PackageType : uint32_t { None = 0, CommonJS, Module };
const Exists exists;
const IsValid is_valid;
const HasMain has_main;
const std::string main;
const HasName has_name;
const std::string name;
const PackageType type;
v8::Global<v8::Value> exports;
};
} // namespace loader
enum class FsStatsOffset {
kDev = 0,
kMode,
kNlink,
kUid,
kGid,
kRdev,
kBlkSize,
kIno,
kSize,
kBlocks,
kATimeSec,
kATimeNsec,
kMTimeSec,
kMTimeNsec,
kCTimeSec,
kCTimeNsec,
kBirthTimeSec,
kBirthTimeNsec,
kFsStatsFieldsNumber
};
// Stat fields buffers contain twice the number of entries in an uv_stat_t
// because `fs.StatWatcher` needs room to store 2 `fs.Stats` instances.
constexpr size_t kFsStatsBufferLength =
static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber) * 2;
// 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(decorated_private_symbol, "node:decorated") \
V(napi_type_tag, "node:napi:type_tag") \
V(napi_wrapper, "node:napi:wrapper") \
V(untransferable_object_private_symbol, "node:untransferableObject") \
// Symbols are per-isolate primitives but Environment proxies them
// for the sake of convenience.
#define PER_ISOLATE_SYMBOL_PROPERTIES(V) \
V(async_id_symbol, "async_id_symbol") \
V(handle_onclose_symbol, "handle_onclose") \
V(no_message_symbol, "no_message_symbol") \
V(messaging_deserialize_symbol, "messaging_deserialize_symbol") \
V(messaging_transfer_symbol, "messaging_transfer_symbol") \
V(messaging_clone_symbol, "messaging_clone_symbol") \
V(messaging_transfer_list_symbol, "messaging_transfer_list_symbol") \
V(oninit_symbol, "oninit") \
V(owner_symbol, "owner_symbol") \
V(onpskexchange_symbol, "onpskexchange") \
V(resource_symbol, "resource_symbol") \
V(trigger_async_id_symbol, "trigger_async_id_symbol") \
// 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(ack_string, "ack") \
V(address_string, "address") \
V(aliases_string, "aliases") \
V(args_string, "args") \
V(asn1curve_string, "asn1Curve") \
V(async_ids_stack_string, "async_ids_stack") \
V(bits_string, "bits") \
V(buffer_string, "buffer") \
V(bytes_parsed_string, "bytesParsed") \
V(bytes_read_string, "bytesRead") \
V(bytes_written_string, "bytesWritten") \
V(cached_data_produced_string, "cachedDataProduced") \
V(cached_data_rejected_string, "cachedDataRejected") \
V(cached_data_string, "cachedData") \
V(cache_key_string, "cacheKey") \
V(change_string, "change") \
V(channel_string, "channel") \
V(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite") \
V(clone_unsupported_type_str, "Cannot transfer object of unsupported type.") \
V(code_string, "code") \
V(commonjs_string, "commonjs") \
V(config_string, "config") \
V(constants_string, "constants") \
V(crypto_dh_string, "dh") \
V(crypto_dsa_string, "dsa") \
V(crypto_ec_string, "ec") \
V(crypto_ed25519_string, "ed25519") \
V(crypto_ed448_string, "ed448") \
V(crypto_x25519_string, "x25519") \
V(crypto_x448_string, "x448") \
V(crypto_rsa_string, "rsa") \
V(crypto_rsa_pss_string, "rsa-pss") \
V(cwd_string, "cwd") \
V(data_string, "data") \
V(deserialize_info_string, "deserializeInfo") \
V(dest_string, "dest") \
V(destroyed_string, "destroyed") \
V(detached_string, "detached") \
V(dh_string, "DH") \
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(done_string, "done") \
V(duration_string, "duration") \
V(ecdh_string, "ECDH") \
V(emit_string, "emit") \
V(emit_warning_string, "emitWarning") \
V(empty_object_string, "{}") \
V(encoding_string, "encoding") \
V(entries_string, "entries") \
V(entry_type_string, "entryType") \
V(env_pairs_string, "envPairs") \
V(env_var_settings_string, "envVarSettings") \
V(errno_string, "errno") \
V(error_string, "error") \
V(exchange_string, "exchange") \
V(exit_code_string, "exitCode") \
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(fields_string, "fields") \
V(file_string, "file") \
V(fingerprint256_string, "fingerprint256") \
V(fingerprint_string, "fingerprint") \
V(flags_string, "flags") \
V(fragment_string, "fragment") \
V(function_string, "function") \
V(get_data_clone_error_string, "_getDataCloneError") \
V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \
V(gid_string, "gid") \
V(h2_string, "h2") \
V(handle_string, "handle") \
V(help_text_string, "helpText") \
V(homedir_string, "homedir") \
V(host_string, "host") \
V(hostmaster_string, "hostmaster") \
V(http_1_1_string, "http/1.1") \
V(identity_string, "identity") \
V(ignore_string, "ignore") \
V(infoaccess_string, "infoAccess") \
V(inherit_string, "inherit") \
V(input_string, "input") \
V(internal_binding_string, "internalBinding") \
V(internal_string, "internal") \
V(ipv4_string, "IPv4") \
V(ipv6_string, "IPv6") \
V(isclosing_string, "isClosing") \
V(issuer_string, "issuer") \
V(issuercert_string, "issuerCertificate") \
V(kill_signal_string, "killSignal") \
V(kind_string, "kind") \
V(length_string, "length") \
V(library_string, "library") \
V(mac_string, "mac") \
V(max_buffer_string, "maxBuffer") \
V(message_port_constructor_string, "MessagePort") \
V(message_port_string, "messagePort") \
V(message_string, "message") \
V(messageerror_string, "messageerror") \
V(minttl_string, "minttl") \
V(module_string, "module") \
V(modulus_string, "modulus") \
V(name_string, "name") \
V(netmask_string, "netmask") \
V(next_string, "next") \
V(nistcurve_string, "nistCurve") \
V(node_string, "node") \
V(nsname_string, "nsname") \
V(ocsp_request_string, "OCSPRequest") \
V(oncertcb_string, "oncertcb") \
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(onhandshakedone_string, "onhandshakedone") \
V(onhandshakestart_string, "onhandshakestart") \
V(onkeylog_string, "onkeylog") \
V(onmessage_string, "onmessage") \
V(onnewsession_string, "onnewsession") \
V(onocspresponse_string, "onocspresponse") \
V(onreadstart_string, "onreadstart") \
V(onreadstop_string, "onreadstop") \
V(onshutdown_string, "onshutdown") \
V(onsignal_string, "onsignal") \
V(onunpipe_string, "onunpipe") \
V(onwrite_string, "onwrite") \
V(openssl_error_stack, "opensslErrorStack") \
V(options_string, "options") \
V(order_string, "order") \
V(output_string, "output") \
V(parse_error_string, "Parse Error") \
V(password_string, "password") \
V(path_string, "path") \
V(pending_handle_string, "pendingHandle") \
V(pid_string, "pid") \
V(pipe_source_string, "pipeSource") \
V(pipe_string, "pipe") \
V(pipe_target_string, "pipeTarget") \
V(port1_string, "port1") \
V(port2_string, "port2") \
V(port_string, "port") \
V(preference_string, "preference") \
V(primordials_string, "primordials") \
V(priority_string, "priority") \
V(process_string, "process") \
V(promise_string, "promise") \
V(psk_string, "psk") \
V(pubkey_string, "pubkey") \
V(query_string, "query") \
V(http3_alpn_string, "h3-29") \
V(rate_string, "rate") \
V(raw_string, "raw") \
V(read_host_object_string, "_readHostObject") \
V(readable_string, "readable") \
V(reason_string, "reason") \
V(refresh_string, "refresh") \
V(regexp_string, "regexp") \
V(rename_string, "rename") \
V(replacement_string, "replacement") \
V(require_string, "require") \
V(retry_string, "retry") \
V(scheme_string, "scheme") \
V(scopeid_string, "scopeid") \
V(serial_number_string, "serialNumber") \
V(serial_string, "serial") \
V(servername_string, "servername") \
V(service_string, "service") \
V(session_id_string, "sessionId") \
V(shell_string, "shell") \
V(signal_string, "signal") \
V(sink_string, "sink") \
V(size_string, "size") \
V(sni_context_err_string, "Invalid SNI context") \
V(sni_context_string, "sni_context") \
V(source_string, "source") \
V(stack_string, "stack") \
V(standard_name_string, "standardName") \
V(start_time_string, "startTime") \
V(state_string, "state") \
V(stats_string, "stats") \
V(status_string, "status") \
V(stdio_string, "stdio") \
V(subject_string, "subject") \
V(subjectaltname_string, "subjectaltname") \
V(syscall_string, "syscall") \
V(target_string, "target") \
V(thread_id_string, "threadId") \
V(ticketkeycallback_string, "onticketkeycallback") \
V(timeout_string, "timeout") \
V(tls_ticket_string, "tlsTicket") \
V(transfer_string, "transfer") \
V(ttl_string, "ttl") \
V(type_string, "type") \
V(uid_string, "uid") \
V(unknown_string, "<unknown>") \
V(url_special_ftp_string, "ftp:") \
V(url_special_file_string, "file:") \
V(url_special_http_string, "http:") \
V(url_special_https_string, "https:") \
V(url_special_ws_string, "ws:") \
V(url_special_wss_string, "wss:") \
V(url_string, "url") \
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_hide_string, "windowsHide") \
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")
#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V) \
V(quicclientsession_instance_template, v8::ObjectTemplate) \
V(quicserversession_instance_template, v8::ObjectTemplate) \
V(quicserverstream_instance_template, v8::ObjectTemplate) \
V(quicsocketsendwrap_instance_template, v8::ObjectTemplate)
#else
# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
#endif
#define ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V) \
V(async_wrap_ctor_template, v8::FunctionTemplate) \
V(async_wrap_object_ctor_template, v8::FunctionTemplate) \
V(base_object_ctor_template, v8::FunctionTemplate) \
V(binding_data_ctor_template, v8::FunctionTemplate) \
V(compiled_fn_entry_template, v8::ObjectTemplate) \
V(dir_instance_template, v8::ObjectTemplate) \
V(fd_constructor_template, v8::ObjectTemplate) \
V(fdclose_constructor_template, v8::ObjectTemplate) \
V(filehandlereadwrap_template, v8::ObjectTemplate) \
V(fsreqpromise_constructor_template, v8::ObjectTemplate) \
V(handle_wrap_ctor_template, v8::FunctionTemplate) \
V(histogram_instance_template, v8::ObjectTemplate) \
V(http2settings_constructor_template, v8::ObjectTemplate) \
V(http2stream_constructor_template, v8::ObjectTemplate) \
V(http2ping_constructor_template, v8::ObjectTemplate) \
V(i18n_converter_template, v8::ObjectTemplate) \
V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate) \
V(message_port_constructor_template, v8::FunctionTemplate) \
V(microtask_queue_ctor_template, v8::FunctionTemplate) \
V(pipe_constructor_template, v8::FunctionTemplate) \
V(promise_wrap_template, v8::ObjectTemplate) \
V(sab_lifetimepartner_constructor_template, v8::FunctionTemplate) \
V(script_context_constructor_template, v8::FunctionTemplate) \
V(secure_context_constructor_template, v8::FunctionTemplate) \
V(shutdown_wrap_template, v8::ObjectTemplate) \
V(streambaseoutputstream_constructor_template, v8::ObjectTemplate) \
V(qlogoutputstream_constructor_template, v8::ObjectTemplate) \
V(tcp_constructor_template, v8::FunctionTemplate) \
V(tty_constructor_template, v8::FunctionTemplate) \
V(write_wrap_template, v8::ObjectTemplate) \
V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) \
QUIC_ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \
V(quic_on_socket_close_function, v8::Function) \
V(quic_on_socket_server_busy_function, v8::Function) \
V(quic_on_session_cert_function, v8::Function) \
V(quic_on_session_client_hello_function, v8::Function) \
V(quic_on_session_close_function, v8::Function) \
V(quic_on_session_handshake_function, v8::Function) \
V(quic_on_session_keylog_function, v8::Function) \
V(quic_on_session_path_validation_function, v8::Function) \
V(quic_on_session_use_preferred_address_function, v8::Function) \
V(quic_on_session_qlog_function, v8::Function) \
V(quic_on_session_ready_function, v8::Function) \
V(quic_on_session_status_function, v8::Function) \
V(quic_on_session_ticket_function, v8::Function) \
V(quic_on_session_version_negotiation_function, v8::Function) \
V(quic_on_stream_close_function, v8::Function) \
V(quic_on_stream_error_function, v8::Function) \
V(quic_on_stream_ready_function, v8::Function) \
V(quic_on_stream_reset_function, v8::Function) \
V(quic_on_stream_headers_function, v8::Function) \
V(quic_on_stream_blocked_function, v8::Function)
#else
# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
#endif
#define ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \
V(async_hooks_after_function, v8::Function) \
V(async_hooks_before_function, v8::Function) \
V(async_hooks_callback_trampoline, v8::Function) \
V(async_hooks_binding, v8::Object) \
V(async_hooks_destroy_function, v8::Function) \
V(async_hooks_init_function, v8::Function) \
V(async_hooks_promise_resolve_function, v8::Function) \
V(buffer_prototype_object, v8::Object) \
V(crypto_key_object_constructor, v8::Function) \
V(crypto_key_object_handle_constructor, v8::Function) \
V(crypto_key_object_private_constructor, v8::Function) \
V(crypto_key_object_public_constructor, v8::Function) \
V(crypto_key_object_secret_constructor, v8::Function) \
V(domexception_function, v8::Function) \
V(enhance_fatal_stack_after_inspector, v8::Function) \
V(enhance_fatal_stack_before_inspector, v8::Function) \
V(fs_use_promises_symbol, v8::Symbol) \
V(host_import_module_dynamically_callback, v8::Function) \
V(host_initialize_import_meta_object_callback, v8::Function) \
V(http2session_on_altsvc_function, v8::Function) \
V(http2session_on_error_function, v8::Function) \
V(http2session_on_frame_error_function, v8::Function) \
V(http2session_on_goaway_data_function, v8::Function) \
V(http2session_on_headers_function, v8::Function) \
V(http2session_on_origin_function, v8::Function) \
V(http2session_on_ping_function, v8::Function) \
V(http2session_on_priority_function, v8::Function) \
V(http2session_on_settings_function, v8::Function) \
V(http2session_on_stream_close_function, v8::Function) \
V(http2session_on_stream_trailers_function, v8::Function) \
V(internal_binding_loader, v8::Function) \
V(immediate_callback_function, v8::Function) \
V(inspector_console_extension_installer, v8::Function) \
V(messaging_deserialize_create_object, v8::Function) \
V(message_port, v8::Object) \
V(native_module_require, v8::Function) \
V(performance_entry_callback, v8::Function) \
V(performance_entry_template, v8::Function) \
V(prepare_stack_trace_callback, v8::Function) \
V(process_object, v8::Object) \
V(primordials, v8::Object) \
V(promise_hook_handler, v8::Function) \
V(promise_reject_callback, v8::Function) \
V(script_data_constructor_function, v8::Function) \
V(source_map_cache_getter, v8::Function) \
V(tick_callback_function, v8::Function) \
V(timers_callback_function, v8::Function) \
V(tls_wrap_constructor_function, v8::Function) \
V(trace_category_state_function, v8::Function) \
V(udp_constructor_function, v8::Function) \
V(url_constructor_function, v8::Function) \
QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
class Environment;
struct AllocatedBuffer;
typedef size_t SnapshotIndex;
class IsolateData : public MemoryRetainer {
public:
IsolateData(v8::Isolate* isolate,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform = nullptr,
ArrayBufferAllocator* node_allocator = nullptr,
const std::vector<size_t>* indexes = nullptr);
SET_MEMORY_INFO_NAME(IsolateData)
SET_SELF_SIZE(IsolateData)
void MemoryInfo(MemoryTracker* tracker) const override;
std::vector<size_t> Serialize(v8::SnapshotCreator* creator);
inline uv_loop_t* event_loop() const;
inline MultiIsolatePlatform* platform() const;
inline std::shared_ptr<PerIsolateOptions> options();
inline void set_options(std::shared_ptr<PerIsolateOptions> options);
inline NodeArrayBufferAllocator* node_allocator() const;
inline worker::Worker* worker_context() const;
inline void set_worker_context(worker::Worker* context);
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
#define V(TypeName, PropertyName) \
inline v8::Local<TypeName> PropertyName() const;
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
PER_ISOLATE_SYMBOL_PROPERTIES(VY)
PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VY
#undef VS
#undef VP
inline v8::Local<v8::String> async_wrap_provider(int index) const;
std::unordered_map<const char*, v8::Eternal<v8::String>> static_str_map;
inline v8::Isolate* isolate() const;
IsolateData(const IsolateData&) = delete;
IsolateData& operator=(const IsolateData&) = delete;
IsolateData(IsolateData&&) = delete;
IsolateData& operator=(IsolateData&&) = delete;
private:
void DeserializeProperties(const std::vector<size_t>* indexes);
void CreateProperties();
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
#define V(TypeName, PropertyName) \
v8::Eternal<TypeName> PropertyName ## _;
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
PER_ISOLATE_SYMBOL_PROPERTIES(VY)
PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VY
#undef VS
#undef VP
// Keep a list of all Persistent strings used for AsyncWrap Provider types.
std::array<v8::Eternal<v8::String>, AsyncWrap::PROVIDERS_LENGTH>
async_wrap_providers_;
v8::Isolate* const isolate_;
uv_loop_t* const event_loop_;
NodeArrayBufferAllocator* const node_allocator_;
MultiIsolatePlatform* platform_;
std::shared_ptr<PerIsolateOptions> options_;
worker::Worker* worker_context_ = nullptr;
};
struct ContextInfo {
explicit ContextInfo(const std::string& name) : name(name) {}
const std::string name;
std::string origin;
bool is_default = false;
};
class EnabledDebugList;
class KVStore {
public:
KVStore() = default;
virtual ~KVStore() = default;
KVStore(const KVStore&) = delete;
KVStore& operator=(const KVStore&) = delete;
KVStore(KVStore&&) = delete;
KVStore& operator=(KVStore&&) = delete;
virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate,
v8::Local<v8::String> key) const = 0;
virtual v8::Maybe<std::string> Get(const char* key) const = 0;
virtual void Set(v8::Isolate* isolate,
v8::Local<v8::String> key,
v8::Local<v8::String> value) = 0;
virtual int32_t Query(v8::Isolate* isolate,
v8::Local<v8::String> key) const = 0;
virtual int32_t Query(const char* key) const = 0;
virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0;
virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;
virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const;
virtual v8::Maybe<bool> AssignFromObject(v8::Local<v8::Context> context,
v8::Local<v8::Object> entries);
static std::shared_ptr<KVStore> CreateMapKVStore();
};
namespace per_process {
extern std::shared_ptr<KVStore> system_environment;
}
struct EnvSerializeInfo;
class AsyncHooks : public MemoryRetainer {
public:
SET_MEMORY_INFO_NAME(AsyncHooks)
SET_SELF_SIZE(AsyncHooks)
void MemoryInfo(MemoryTracker* tracker) const override;
// 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,
kPromiseResolve,
kTotals,
kCheck,
kStackLength,
kUsesExecutionAsyncResource,
kFieldsCount,
};
enum UidFields {
kExecutionAsyncId,
kTriggerAsyncId,
kAsyncIdCounter,
kDefaultTriggerAsyncId,
kUidFieldsCount,
};
inline AliasedUint32Array& fields();
inline AliasedFloat64Array& async_id_fields();
inline AliasedFloat64Array& async_ids_stack();
inline v8::Local<v8::Array> js_execution_async_resources();
// Returns the native executionAsyncResource value at stack index `index`.
// Resources provided on the JS side are not stored on the native stack,
// in which case an empty `Local<>` is returned.
// The `js_execution_async_resources` array contains the value in that case.
inline v8::Local<v8::Object> native_execution_async_resource(size_t index);
inline v8::Local<v8::String> provider_string(int idx);
inline void no_force_checks();
inline Environment* env();
inline void push_async_context(double async_id, double trigger_async_id,
v8::Local<v8::Object> execution_async_resource_);
inline bool pop_async_context(double async_id);
inline void clear_async_id_stack(); // Used in fatal exceptions.
AsyncHooks(const AsyncHooks&) = delete;
AsyncHooks& operator=(const AsyncHooks&) = delete;
AsyncHooks(AsyncHooks&&) = delete;
AsyncHooks& operator=(AsyncHooks&&) = delete;
~AsyncHooks() = default;
// Used to set the kDefaultTriggerAsyncId in a scope. This is instead of
// passing the trigger_async_id along with other constructor arguments.
class DefaultTriggerAsyncIdScope {
public:
DefaultTriggerAsyncIdScope() = delete;
explicit DefaultTriggerAsyncIdScope(Environment* env,
double init_trigger_async_id);
explicit DefaultTriggerAsyncIdScope(AsyncWrap* async_wrap);
~DefaultTriggerAsyncIdScope();
DefaultTriggerAsyncIdScope(const DefaultTriggerAsyncIdScope&) = delete;
DefaultTriggerAsyncIdScope& operator=(const DefaultTriggerAsyncIdScope&) =
delete;
DefaultTriggerAsyncIdScope(DefaultTriggerAsyncIdScope&&) = delete;
DefaultTriggerAsyncIdScope& operator=(DefaultTriggerAsyncIdScope&&) =
delete;
private:
AsyncHooks* async_hooks_;
double old_default_trigger_async_id_;
};
struct SerializeInfo {
AliasedBufferInfo async_ids_stack;
AliasedBufferInfo fields;
AliasedBufferInfo async_id_fields;
SnapshotIndex js_execution_async_resources;
std::vector<SnapshotIndex> native_execution_async_resources;
};
SerializeInfo Serialize(v8::Local<v8::Context> context,
v8::SnapshotCreator* creator);
void Deserialize(v8::Local<v8::Context> context);
private:
friend class Environment; // So we can call the constructor.
explicit AsyncHooks(v8::Isolate* isolate, const SerializeInfo* info);
// Stores the ids of the current execution context stack.
AliasedFloat64Array async_ids_stack_;
// Attached to a Uint32Array that tracks the number of active hooks for
// each type.
AliasedUint32Array fields_;
// Attached to a Float64Array that tracks the state of async resources.
AliasedFloat64Array async_id_fields_;
void grow_async_ids_stack();
v8::Global<v8::Array> js_execution_async_resources_;
std::vector<v8::Global<v8::Object>> native_execution_async_resources_;
// Non-empty during deserialization
const SerializeInfo* info_ = nullptr;
};
class ImmediateInfo : public MemoryRetainer {
public:
inline AliasedUint32Array& fields();
inline uint32_t count() const;
inline uint32_t ref_count() const;
inline bool has_outstanding() const;
inline void ref_count_inc(uint32_t increment);
inline void ref_count_dec(uint32_t decrement);
ImmediateInfo(const ImmediateInfo&) = delete;
ImmediateInfo& operator=(const ImmediateInfo&) = delete;
ImmediateInfo(ImmediateInfo&&) = delete;
ImmediateInfo& operator=(ImmediateInfo&&) = delete;
~ImmediateInfo() = default;
SET_MEMORY_INFO_NAME(ImmediateInfo)
SET_SELF_SIZE(ImmediateInfo)
void MemoryInfo(MemoryTracker* tracker) const override;
struct SerializeInfo {
AliasedBufferInfo fields;
};
SerializeInfo Serialize(v8::Local<v8::Context> context,
v8::SnapshotCreator* creator);
void Deserialize(v8::Local<v8::Context> context);
private:
friend class Environment; // So we can call the constructor.
explicit ImmediateInfo(v8::Isolate* isolate, const SerializeInfo* info);
enum Fields { kCount, kRefCount, kHasOutstanding, kFieldsCount };
AliasedUint32Array fields_;
};
class TickInfo : public MemoryRetainer {
public:
inline AliasedUint8Array& fields();
inline bool has_tick_scheduled() const;
inline bool has_rejection_to_warn() const;
SET_MEMORY_INFO_NAME(TickInfo)
SET_SELF_SIZE(TickInfo)
void MemoryInfo(MemoryTracker* tracker) const override;
TickInfo(const TickInfo&) = delete;
TickInfo& operator=(const TickInfo&) = delete;
TickInfo(TickInfo&&) = delete;
TickInfo& operator=(TickInfo&&) = delete;
~TickInfo() = default;
struct SerializeInfo {
AliasedBufferInfo fields;
};
SerializeInfo Serialize(v8::Local<v8::Context> context,
v8::SnapshotCreator* creator);
void Deserialize(v8::Local<v8::Context> context);
private:
friend class Environment; // So we can call the constructor.
explicit TickInfo(v8::Isolate* isolate, const SerializeInfo* info);
enum Fields { kHasTickScheduled = 0, kHasRejectionToWarn, kFieldsCount };
AliasedUint8Array fields_;
};
class TrackingTraceStateObserver :
public v8::TracingController::TraceStateObserver {
public:
explicit TrackingTraceStateObserver(Environment* env) : env_(env) {}
void OnTraceEnabled() override {
UpdateTraceCategoryState();
}
void OnTraceDisabled() override {
UpdateTraceCategoryState();
}
private:
void UpdateTraceCategoryState();
Environment* env_;
};
class ShouldNotAbortOnUncaughtScope {
public:
explicit inline ShouldNotAbortOnUncaughtScope(Environment* env);
inline void Close();
inline ~ShouldNotAbortOnUncaughtScope();
ShouldNotAbortOnUncaughtScope(const ShouldNotAbortOnUncaughtScope&) = delete;
ShouldNotAbortOnUncaughtScope& operator=(
const ShouldNotAbortOnUncaughtScope&) = delete;
ShouldNotAbortOnUncaughtScope(ShouldNotAbortOnUncaughtScope&&) = delete;
ShouldNotAbortOnUncaughtScope& operator=(ShouldNotAbortOnUncaughtScope&&) =
delete;
private:
Environment* env_;
};
class CleanupHookCallback {
public:
CleanupHookCallback(void (*fn)(void*),
void* arg,
uint64_t insertion_order_counter)
: fn_(fn), arg_(arg), insertion_order_counter_(insertion_order_counter) {}
// Only hashes `arg_`, since that is usually enough to identify the hook.
struct Hash {
inline size_t operator()(const CleanupHookCallback& cb) const;
};
// Compares by `fn_` and `arg_` being equal.
struct Equal {
inline bool operator()(const CleanupHookCallback& a,
const CleanupHookCallback& b) const;
};
inline BaseObject* GetBaseObject() const;
private:
friend class Environment;
void (*fn_)(void*);
void* arg_;
// We keep track of the insertion order for these objects, so that we can
// call the callbacks in reverse order when we are cleaning up.
uint64_t insertion_order_counter_;
};
struct PropInfo {
std::string name; // name for debugging
size_t id; // In the list - in case there are any empty entires
SnapshotIndex index; // In the snapshot
};
struct EnvSerializeInfo {
std::vector<std::string> native_modules;
AsyncHooks::SerializeInfo async_hooks;
TickInfo::SerializeInfo tick_info;
ImmediateInfo::SerializeInfo immediate_info;
performance::PerformanceState::SerializeInfo performance_state;
AliasedBufferInfo stream_base_state;
AliasedBufferInfo should_abort_on_uncaught_toggle;
std::vector<PropInfo> persistent_templates;
std::vector<PropInfo> persistent_values;
SnapshotIndex context;
friend std::ostream& operator<<(std::ostream& o, const EnvSerializeInfo& i);
};
class Environment : public MemoryRetainer {
public:
Environment(const Environment&) = delete;
Environment& operator=(const Environment&) = delete;
Environment(Environment&&) = delete;
Environment& operator=(Environment&&) = delete;
SET_MEMORY_INFO_NAME(Environment)
inline size_t SelfSize() const override;
bool IsRootNode() const override { return true; }
void MemoryInfo(MemoryTracker* tracker) const override;
EnvSerializeInfo Serialize(v8::SnapshotCreator* creator);
void CreateProperties();
void DeserializeProperties(const EnvSerializeInfo* info);
typedef void (*BaseObjectIterator)(size_t, BaseObject*);
void ForEachBaseObject(BaseObjectIterator iterator);
void PrintAllBaseObjects();
// Should be called before InitializeInspector()
void InitializeDiagnostics();
#if HAVE_INSPECTOR
// If the environment is created for a worker, pass parent_handle and
// the ownership if transferred into the Environment.
int InitializeInspector(
std::unique_ptr<inspector::ParentInspectorHandle> parent_handle);
#endif
v8::MaybeLocal<v8::Value> BootstrapInternalLoaders();
v8::MaybeLocal<v8::Value> BootstrapNode();
v8::MaybeLocal<v8::Value> RunBootstrapping();
inline size_t async_callback_scope_depth() const;
inline void PushAsyncCallbackScope();
inline void PopAsyncCallbackScope();
static inline Environment* GetCurrent(v8::Isolate* isolate);
static inline Environment* GetCurrent(v8::Local<v8::Context> context);
static inline Environment* GetCurrent(
const v8::FunctionCallbackInfo<v8::Value>& info);
template <typename T>
static inline Environment* GetCurrent(
const v8::PropertyCallbackInfo<T>& info);
// Methods created using SetMethod(), SetPrototypeMethod(), etc. inside
// this scope can access the created T* object using
// GetBindingData<T>(args) later.
template <typename T>
T* AddBindingData(v8::Local<v8::Context> context,
v8::Local<v8::Object> target);
template <typename T, typename U>
static inline T* GetBindingData(const v8::PropertyCallbackInfo<U>& info);
template <typename T>
static inline T* GetBindingData(
const v8::FunctionCallbackInfo<v8::Value>& info);
template <typename T>
static inline T* GetBindingData(v8::Local<v8::Context> context);
typedef std::unordered_map<
FastStringKey,
BaseObjectPtr<BaseObject>,
FastStringKey::Hash> BindingDataStore;
static uv_key_t thread_local_env;
static inline Environment* GetThreadLocalEnv();
// Create an Environment without initializing a main Context. Use
// InitializeMainContext() to initialize a main context for it.
Environment(IsolateData* isolate_data,
v8::Isolate* isolate,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args,
const EnvSerializeInfo* env_info,
EnvironmentFlags::Flags flags,
ThreadId thread_id);
void InitializeMainContext(v8::Local<v8::Context> context,
const EnvSerializeInfo* env_info);
// Create an Environment and initialize the provided main context for it.
Environment(IsolateData* isolate_data,
v8::Local<v8::Context> context,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args,
const EnvSerializeInfo* env_info,
EnvironmentFlags::Flags flags,
ThreadId thread_id);
~Environment() override;
void InitializeLibuv();
inline const std::vector<std::string>& exec_argv();
inline const std::vector<std::string>& argv();
const std::string& exec_path() const;
typedef void (*HandleCleanupCb)(Environment* env,
uv_handle_t* handle,
void* arg);
struct HandleCleanup {
uv_handle_t* handle_;
HandleCleanupCb cb_;
void* arg_;
};
void RegisterHandleCleanups();
void CleanupHandles();
void Exit(int code);
void ExitEnv();
// Register clean-up cb to be called on environment destruction.
inline void RegisterHandleCleanup(uv_handle_t* handle,
HandleCleanupCb cb,
void* arg);
template <typename T, typename OnCloseCallback>
inline void CloseHandle(T* handle, OnCloseCallback callback);
inline void AssignToContext(v8::Local<v8::Context> context,
const ContextInfo& info);
inline v8::Isolate* isolate() const;
inline uv_loop_t* event_loop() const;
inline void TryLoadAddon(
const char* filename,
int flags,
const std::function<bool(binding::DLib*)>& was_loaded);
static inline Environment* from_timer_handle(uv_timer_t* handle);
inline uv_timer_t* timer_handle();
static inline Environment* from_immediate_check_handle(uv_check_t* handle);
inline uv_check_t* immediate_check_handle();
inline uv_idle_t* immediate_idle_handle();
inline void IncreaseWaitingRequestCounter();
inline void DecreaseWaitingRequestCounter();
inline AsyncHooks* async_hooks();
inline ImmediateInfo* immediate_info();
inline TickInfo* tick_info();
inline uint64_t timer_base() const;
inline std::shared_ptr<KVStore> env_vars();
inline void set_env_vars(std::shared_ptr<KVStore> env_vars);
inline IsolateData* isolate_data() const;
inline bool printed_error() const;
inline void set_printed_error(bool value);
void PrintSyncTrace() const;
inline void set_trace_sync_io(bool value);
// This stores whether the --abort-on-uncaught-exception flag was passed
// to Node.
inline bool abort_on_uncaught_exception() const;
inline void set_abort_on_uncaught_exception(bool value);
// This is a pseudo-boolean that keeps track of whether an uncaught exception
// should abort the process or not if --abort-on-uncaught-exception was
// passed to Node. If the flag was not passed, it is ignored.
inline AliasedUint32Array& should_abort_on_uncaught_toggle();
inline AliasedInt32Array& stream_base_state();
// The necessary API for async_hooks.
inline double new_async_id();
inline double execution_async_id();
inline double trigger_async_id();
inline double get_default_trigger_async_id();
// List of id's that have been destroyed and need the destroy() cb called.
inline std::vector<double>* destroy_async_id_list();
std::set<std::string> native_modules_with_cache;
std::set<std::string> native_modules_without_cache;
// This is only filled during deserialization. We use a vector since
// it's only used for tests.
std::vector<std::string> native_modules_in_snapshot;
std::unordered_multimap<int, loader::ModuleWrap*> hash_to_module_map;
std::unordered_map<uint32_t, loader::ModuleWrap*> id_to_module_map;
std::unordered_map<uint32_t, contextify::ContextifyScript*>
id_to_script_map;
std::unordered_map<uint32_t, contextify::CompiledFnEntry*> id_to_function_map;
inline uint32_t get_next_module_id();
inline uint32_t get_next_script_id();
inline uint32_t get_next_function_id();
EnabledDebugList* enabled_debug_list() { return &enabled_debug_list_; }
inline performance::PerformanceState* performance_state();
inline std::unordered_map<std::string, uint64_t>* performance_marks();
void CollectUVExceptionInfo(v8::Local<v8::Value> context,
int errorno,
const char* syscall = nullptr,
const char* message = nullptr,
const char* path = nullptr,
const char* dest = nullptr);
// If this flag is set, calls into JS (if they would be observable
// from userland) must be avoided. This flag does not indicate whether
// calling into JS is allowed from a VM perspective at this point.
inline bool can_call_into_js() const;
inline void set_can_call_into_js(bool can_call_into_js);
// Increase or decrease a counter that manages whether this Environment
// keeps the event loop alive on its own or not. The counter starts out at 0,
// meaning it does not, and any positive value will make it keep the event
// loop alive.
// This is used by Workers to manage their own .ref()/.unref() implementation,
// as Workers aren't directly associated with their own libuv handles.
inline void add_refs(int64_t diff);
inline bool has_run_bootstrapping_code() const;
inline void set_has_run_bootstrapping_code(bool has_run_bootstrapping_code);
inline bool has_serialized_options() const;
inline void set_has_serialized_options(bool has_serialized_options);
inline bool is_main_thread() const;
inline bool should_not_register_esm_loader() const;
inline bool owns_process_state() const;
inline bool owns_inspector() const;
inline bool tracks_unmanaged_fds() const;
inline uint64_t thread_id() const;
inline worker::Worker* worker_context() const;
Environment* worker_parent_env() const;
inline void add_sub_worker_context(worker::Worker* context);
inline void remove_sub_worker_context(worker::Worker* context);
void stop_sub_worker_contexts();
template <typename Fn>
inline void ForEachWorker(Fn&& iterator);
inline bool is_stopping() const;
inline void set_stopping(bool value);
inline std::list<node_module>* extra_linked_bindings();
inline node_module* extra_linked_bindings_head();
inline const Mutex& extra_linked_bindings_mutex() const;
inline bool filehandle_close_warning() const;
inline void set_filehandle_close_warning(bool on);
inline bool emit_insecure_umask_warning() const;
inline void set_emit_insecure_umask_warning(bool on);
inline void set_source_maps_enabled(bool on);
inline bool source_maps_enabled() const;
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<v8::FunctionTemplate>
NewFunctionTemplate(v8::FunctionCallback callback,
v8::Local<v8::Signature> signature =
v8::Local<v8::Signature>(),
v8::ConstructorBehavior behavior =
v8::ConstructorBehavior::kAllow,
v8::SideEffectType side_effect =
v8::SideEffectType::kHasSideEffect);
// Convenience methods for NewFunctionTemplate().
inline void SetMethod(v8::Local<v8::Object> that,
const char* name,
v8::FunctionCallback callback);
inline void SetProtoMethod(v8::Local<v8::FunctionTemplate> that,
const char* name,
v8::FunctionCallback callback);
inline void SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
const char* name,
v8::FunctionCallback callback);
// Safe variants denote the function has no side effects.
inline void SetMethodNoSideEffect(v8::Local<v8::Object> that,
const char* name,
v8::FunctionCallback callback);
inline void SetProtoMethodNoSideEffect(v8::Local<v8::FunctionTemplate> that,
const char* name,
v8::FunctionCallback callback);
void AtExit(void (*cb)(void* arg), void* arg);
void RunAtExitCallbacks();
void RunWeakRefCleanup();
// 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 VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
#define V(TypeName, PropertyName) \
inline v8::Local<TypeName> PropertyName() const;
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
PER_ISOLATE_SYMBOL_PROPERTIES(VY)
PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VS
#undef VY
#undef VP
#define V(PropertyName, TypeName) \
inline v8::Local<TypeName> PropertyName() const; \
inline void set_ ## PropertyName(v8::Local<TypeName> value);
ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
#undef V
inline v8::Local<v8::Context> context() const;
#if HAVE_INSPECTOR
inline inspector::Agent* inspector_agent() const {
return inspector_agent_.get();
}
inline bool is_in_inspector_console_call() const;
inline void set_is_in_inspector_console_call(bool value);
#endif
typedef ListHead<HandleWrap, &HandleWrap::handle_wrap_queue_> HandleWrapQueue;
typedef ListHead<ReqWrapBase, &ReqWrapBase::req_wrap_queue_> ReqWrapQueue;
inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; }
inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; }
inline bool EmitProcessEnvWarning() {
bool current_value = emit_env_nonstring_warning_;
emit_env_nonstring_warning_ = false;
return current_value;
}
inline bool EmitErrNameWarning() {
bool current_value = emit_err_name_warning_;
emit_err_name_warning_ = false;
return current_value;
}
// cb will be called as cb(env) on the next event loop iteration.
// Unlike the JS setImmediate() function, nested SetImmediate() calls will
// be run without returning control to the event loop, similar to nextTick().
template <typename Fn>
inline void SetImmediate(
Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::kRefed);
template <typename Fn>
// This behaves like SetImmediate() but can be called from any thread.
inline void SetImmediateThreadsafe(
Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::kRefed);
// This behaves like V8's Isolate::RequestInterrupt(), but also accounts for
// the event loop (i.e. combines the V8 function with SetImmediate()).
// The passed callback may not throw exceptions.
// This function can be called from any thread.
template <typename Fn>
inline void RequestInterrupt(Fn&& cb);
// This needs to be available for the JS-land setImmediate().
void ToggleImmediateRef(bool ref);
inline void PushShouldNotAbortOnUncaughtScope();
inline void PopShouldNotAbortOnUncaughtScope();
inline bool inside_should_not_abort_on_uncaught_scope() const;
static inline Environment* ForAsyncHooks(AsyncHooks* hooks);
v8::Local<v8::Value> GetNow();
void ScheduleTimer(int64_t duration);
void ToggleTimerRef(bool ref);
inline void AddCleanupHook(void (*fn)(void*), void* arg);
inline void RemoveCleanupHook(void (*fn)(void*), void* arg);
void RunCleanup();
static void BuildEmbedderGraph(v8::Isolate* isolate,
v8::EmbedderGraph* graph,
void* data);
inline std::shared_ptr<EnvironmentOptions> options();
inline std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port();
// The BaseObject count is a debugging helper that makes sure that there are
// no memory leaks caused by BaseObjects staying alive longer than expected
// (in particular, no circular BaseObjectPtr references).
inline void modify_base_object_count(int64_t delta);
inline int64_t base_object_count() const;
inline int32_t stack_trace_limit() const { return 10; }
#if HAVE_INSPECTOR
void set_coverage_connection(
std::unique_ptr<profiler::V8CoverageConnection> connection);
profiler::V8CoverageConnection* coverage_connection();
inline void set_coverage_directory(const char* directory);
inline const std::string& coverage_directory() const;
void set_cpu_profiler_connection(
std::unique_ptr<profiler::V8CpuProfilerConnection> connection);
profiler::V8CpuProfilerConnection* cpu_profiler_connection();
inline void set_cpu_prof_name(const std::string& name);
inline const std::string& cpu_prof_name() const;
inline void set_cpu_prof_interval(uint64_t interval);
inline uint64_t cpu_prof_interval() const;
inline void set_cpu_prof_dir(const std::string& dir);
inline const std::string& cpu_prof_dir() const;
void set_heap_profiler_connection(
std::unique_ptr<profiler::V8HeapProfilerConnection> connection);
profiler::V8HeapProfilerConnection* heap_profiler_connection();
inline void set_heap_prof_name(const std::string& name);
inline const std::string& heap_prof_name() const;
inline void set_heap_prof_dir(const std::string& dir);
inline const std::string& heap_prof_dir() const;
inline void set_heap_prof_interval(uint64_t interval);
inline uint64_t heap_prof_interval() const;
#endif // HAVE_INSPECTOR
inline void set_main_utf16(std::unique_ptr<v8::String::Value>);
inline void set_process_exit_handler(
std::function<void(Environment*, int)>&& handler);
void RunAndClearNativeImmediates(bool only_refed = false);
void RunAndClearInterrupts();
inline std::unordered_map<char*, std::unique_ptr<v8::BackingStore>>*
released_allocated_buffers();
void AddUnmanagedFd(int fd);
void RemoveUnmanagedFd(int fd);
private:
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
const char* errmsg);
std::list<binding::DLib> loaded_addons_;
v8::Isolate* const isolate_;
IsolateData* const isolate_data_;
uv_timer_t timer_handle_;
uv_check_t immediate_check_handle_;
uv_idle_t immediate_idle_handle_;
uv_async_t task_queues_async_;
int64_t task_queues_async_refs_ = 0;
AsyncHooks async_hooks_;
ImmediateInfo immediate_info_;
TickInfo tick_info_;
const uint64_t timer_base_;
std::shared_ptr<KVStore> env_vars_;
bool printed_error_ = false;
bool trace_sync_io_ = false;
bool emit_env_nonstring_warning_ = true;
bool emit_err_name_warning_ = true;
bool emit_filehandle_warning_ = true;
bool emit_insecure_umask_warning_ = true;
bool source_maps_enabled_ = false;
size_t async_callback_scope_depth_ = 0;
std::vector<double> destroy_async_id_list_;
#if HAVE_INSPECTOR
std::unique_ptr<profiler::V8CoverageConnection> coverage_connection_;
std::unique_ptr<profiler::V8CpuProfilerConnection> cpu_profiler_connection_;
std::string coverage_directory_;
std::string cpu_prof_dir_;
std::string cpu_prof_name_;
uint64_t cpu_prof_interval_;
std::unique_ptr<profiler::V8HeapProfilerConnection> heap_profiler_connection_;
std::string heap_prof_dir_;
std::string heap_prof_name_;
uint64_t heap_prof_interval_;
#endif // HAVE_INSPECTOR
std::shared_ptr<EnvironmentOptions> options_;
// options_ contains debug options parsed from CLI arguments,
// while inspector_host_port_ stores the actual inspector host
// and port being used. For example the port is -1 by default
// and can be specified as 0 (meaning any port allocated when the
// server starts listening), but when the inspector server starts
// the inspector_host_port_->port() will be the actual port being
// used.
std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port_;
std::vector<std::string> exec_argv_;
std::vector<std::string> argv_;
std::string exec_path_;
uint32_t module_id_counter_ = 0;
uint32_t script_id_counter_ = 0;
uint32_t function_id_counter_ = 0;
AliasedUint32Array should_abort_on_uncaught_toggle_;
int should_not_abort_scope_counter_ = 0;
std::unique_ptr<TrackingTraceStateObserver> trace_state_observer_;
AliasedInt32Array stream_base_state_;
uint64_t environment_start_time_;
std::unique_ptr<performance::PerformanceState> performance_state_;
std::unordered_map<std::string, uint64_t> performance_marks_;
bool has_run_bootstrapping_code_ = false;
bool has_serialized_options_ = false;
std::atomic_bool can_call_into_js_ { true };
uint64_t flags_;
uint64_t thread_id_;
std::unordered_set<worker::Worker*> sub_worker_contexts_;
static void* const kNodeContextTagPtr;
static int const kNodeContextTag;
#if HAVE_INSPECTOR
std::unique_ptr<inspector::Agent> inspector_agent_;
bool is_in_inspector_console_call_ = false;
#endif
// handle_wrap_queue_ and req_wrap_queue_ needs to be at a fixed offset from
// the start of the class because it is used by
// src/node_postmortem_metadata.cc to calculate offsets and generate debug
// symbols for Environment, which assumes that the position of members in
// memory are predictable. For more information please refer to
// `doc/guides/node-postmortem-support.md`
friend int GenDebugSymbols();
HandleWrapQueue handle_wrap_queue_;
ReqWrapQueue req_wrap_queue_;
std::list<HandleCleanup> handle_cleanup_queue_;
int handle_cleanup_waiting_ = 0;
int request_waiting_ = 0;
EnabledDebugList enabled_debug_list_;
std::list<node_module> extra_linked_bindings_;
Mutex extra_linked_bindings_mutex_;
static void RunTimers(uv_timer_t* handle);
struct ExitCallback {
void (*cb_)(void* arg);
void* arg_;
};
std::list<ExitCallback> at_exit_functions_;
typedef CallbackQueue<void, Environment*> NativeImmediateQueue;
NativeImmediateQueue native_immediates_;
Mutex native_immediates_threadsafe_mutex_;
NativeImmediateQueue native_immediates_threadsafe_;
NativeImmediateQueue native_immediates_interrupts_;
// Also guarded by native_immediates_threadsafe_mutex_. This can be used when
// trying to post tasks from other threads to an Environment, as the libuv
// handle for the immediate queues (task_queues_async_) may not be initialized
// yet or already have been destroyed.
bool task_queues_async_initialized_ = false;
std::atomic<Environment**> interrupt_data_ {nullptr};
void RequestInterruptFromV8();
static void CheckImmediate(uv_check_t* handle);
BindingDataStore bindings_;
// Use an unordered_set, so that we have efficient insertion and removal.
std::unordered_set<CleanupHookCallback,
CleanupHookCallback::Hash,
CleanupHookCallback::Equal> cleanup_hooks_;
uint64_t cleanup_hook_counter_ = 0;
bool started_cleanup_ = false;
int64_t base_object_count_ = 0;
int64_t initial_base_object_count_ = 0;
std::atomic_bool is_stopping_ { false };
std::unordered_set<int> unmanaged_fds_;
std::function<void(Environment*, int)> process_exit_handler_ {
DefaultProcessExitHandler };
template <typename T>
void ForEachBaseObject(T&& iterator);
#define V(PropertyName, TypeName) v8::Global<TypeName> PropertyName ## _;
ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
#undef V
v8::Global<v8::Context> context_;
// Keeps the main script source alive is one was passed to LoadEnvironment().
// We should probably find a way to just use plain `v8::String`s created from
// the source passed to LoadEnvironment() directly instead.
std::unique_ptr<v8::String::Value> main_utf16_;
// Used by AllocatedBuffer::release() to keep track of the BackingStore for
// a given pointer.
std::unordered_map<char*, std::unique_ptr<v8::BackingStore>>
released_allocated_buffers_;
};
} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif // SRC_ENV_H_