diff --git a/lib/internal/http.js b/lib/internal/http.js index b20b3cd229efcd..abc24a4c4e0a35 100644 --- a/lib/internal/http.js +++ b/lib/internal/http.js @@ -8,7 +8,10 @@ const { } = primordials; const { setUnrefTimeout } = require('internal/timers'); -const { trace, isTraceCategoryEnabled } = internalBinding('trace_events'); +// The trace variable must not be destructured +// because it might break node snapshot serialization +// ref: https://github.com/nodejs/node/pull/48142#discussion_r1204128367 +const trace_events = internalBinding('trace_events'); const { CHAR_LOWERCASE_B, CHAR_LOWERCASE_E, @@ -38,17 +41,17 @@ function getNextTraceEventId() { } function isTraceHTTPEnabled() { - return isTraceCategoryEnabled('node.http'); + return trace_events.tracingCategories[0] > 0; } const traceEventCategory = 'node,node.http'; function traceBegin(...args) { - trace(CHAR_LOWERCASE_B, traceEventCategory, ...args); + trace_events.trace(CHAR_LOWERCASE_B, traceEventCategory, ...args); } function traceEnd(...args) { - trace(CHAR_LOWERCASE_E, traceEventCategory, ...args); + trace_events.trace(CHAR_LOWERCASE_E, traceEventCategory, ...args); } module.exports = { diff --git a/src/base_object_types.h b/src/base_object_types.h index bb7a0e064b0b72..8bb37d8d795f6d 100644 --- a/src/base_object_types.h +++ b/src/base_object_types.h @@ -17,7 +17,8 @@ namespace node { V(blob_binding_data, BlobBindingData) \ V(process_binding_data, process::BindingData) \ V(timers_binding_data, timers::BindingData) \ - V(url_binding_data, url::BindingData) + V(url_binding_data, url::BindingData) \ + V(trace_events_binding_data, trace_events::BindingData) #define UNSERIALIZABLE_BINDING_TYPES(V) \ V(http2_binding_data, http2::BindingData) \ diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index 55933e3bbef2f3..089e389146b188 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -20,6 +20,7 @@ #include "node_metadata.h" #include "node_process.h" #include "node_snapshot_builder.h" +#include "node_trace_events.h" #include "node_url.h" #include "node_util.h" #include "node_v8.h" diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index bd2eefafb68cbc..2d38d553588f3a 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -1,3 +1,4 @@ +#include "node_trace_events.h" #include "base_object-inl.h" #include "env-inl.h" #include "memory_tracker-inl.h" @@ -20,11 +21,13 @@ using v8::Context; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; +using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::NewStringType; using v8::Object; using v8::String; +using v8::Uint8Array; using v8::Value; class NodeCategorySet : public BaseObject { @@ -165,9 +168,77 @@ void NodeCategorySet::RegisterExternalReferences( registry->Register(NodeCategorySet::Disable); } +namespace trace_events { + +BindingData::BindingData(Realm* realm, v8::Local object) + : SnapshotableObject(realm, object, type_int) { + // Get the pointer of the memory for the flag that + // store if trace is enabled for http the pointer will + // always be the same and if the category does not exist + // it creates: + // https://github.com/nodejs/node/blob/6bbf2a57fcf33266c5859497f8cc32e1389a358a/deps/v8/src/libplatform/tracing/tracing-controller.cc#L322-L342 + auto p = const_cast( + TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("node.http")); + + // NO_OP deleter + // the idea of this chunk of code is to construct + auto nop = [](void*, size_t, void*) {}; + auto bs = v8::ArrayBuffer::NewBackingStore(p, 1, nop, nullptr); + auto ab = v8::ArrayBuffer::New(realm->isolate(), std::move(bs)); + v8::Local u8 = v8::Uint8Array::New(ab, 0, 1); + + object + ->Set(realm->context(), + FIXED_ONE_BYTE_STRING(realm->isolate(), "tracingCategories"), + u8) + .Check(); +} + +bool BindingData::PrepareForSerialization(v8::Local context, + v8::SnapshotCreator* creator) { + return true; +} + +InternalFieldInfoBase* BindingData::Serialize(int index) { + DCHECK_EQ(index, BaseObject::kEmbedderType); + InternalFieldInfo* info = + InternalFieldInfoBase::New(type()); + return info; +} + +void BindingData::Deserialize(v8::Local context, + v8::Local holder, + int index, + InternalFieldInfoBase* info) { + DCHECK_EQ(index, BaseObject::kEmbedderType); + v8::HandleScope scope(context->GetIsolate()); + Realm* realm = Realm::GetCurrent(context); + BindingData* binding = realm->AddBindingData(context, holder); + CHECK_NOT_NULL(binding); +} + +void BindingData::CreatePerContextProperties(Local target, + Local unused, + Local context, + void* priv) { + Realm* realm = Realm::GetCurrent(context); + realm->AddBindingData(context, target); +} + +static void CreatePerContextProperties(Local target, + Local unused, + Local context, + void* priv) { + BindingData::CreatePerContextProperties(target, unused, context, priv); + + NodeCategorySet::Initialize(target, unused, context, priv); +} + +} // namespace trace_events + } // namespace node -NODE_BINDING_CONTEXT_AWARE_INTERNAL(trace_events, - node::NodeCategorySet::Initialize) +NODE_BINDING_CONTEXT_AWARE_INTERNAL( + trace_events, node::trace_events::CreatePerContextProperties) NODE_BINDING_EXTERNAL_REFERENCE( trace_events, node::NodeCategorySet::RegisterExternalReferences) diff --git a/src/node_trace_events.h b/src/node_trace_events.h new file mode 100644 index 00000000000000..a7af9815ed6917 --- /dev/null +++ b/src/node_trace_events.h @@ -0,0 +1,41 @@ +#ifndef SRC_NODE_TRACE_EVENTS_H_ +#define SRC_NODE_TRACE_EVENTS_H_ + +#include +#include "aliased_buffer.h" +#include "node.h" +#include "node_snapshotable.h" +#include "util.h" +#include "v8-fast-api-calls.h" +#include "v8.h" + +#include + +namespace node { +class ExternalReferenceRegistry; + +namespace trace_events { + +class BindingData : public SnapshotableObject { + public: + BindingData(Realm* realm, v8::Local obj); + + using InternalFieldInfo = InternalFieldInfoBase; + + SERIALIZABLE_OBJECT_METHODS() + SET_BINDING_ID(trace_events_binding_data) + SET_NO_MEMORY_INFO() + SET_SELF_SIZE(BindingData) + SET_MEMORY_INFO_NAME(BindingData) + + static void CreatePerContextProperties(v8::Local target, + v8::Local unused, + v8::Local context, + void* priv); +}; + +} // namespace trace_events + +} // namespace node + +#endif // SRC_NODE_TRACE_EVENTS_H_