Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/async_wrap-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,25 @@ inline double AsyncWrap::get_trigger_async_id() const {
}

inline v8::Local<v8::Value> AsyncWrap::context_frame() const {
return context_frame_.Get(env()->isolate());
auto as_data = object()->GetInternalField(kAsyncContextFrame);
DCHECK_IMPLIES(!as_data.IsEmpty(),
as_data->IsValue() || as_data->IsPrivate());
if (as_data->IsPrivate()) {
DCHECK(as_data.As<v8::Private>()->Name()->SameValue(
env()->empty_context_frame_sentinel_symbol()->Name()));
return {};
}
return as_data.As<v8::Value>();
}

inline void AsyncWrap::set_context_frame(v8::Local<v8::Value> value) {
if (value.IsEmpty()) {
// Empty values are not allowed in internal fields
object()->SetInternalField(kAsyncContextFrame,
env()->empty_context_frame_sentinel_symbol());
} else {
object()->SetInternalField(kAsyncContextFrame, value);
}
}

inline v8::MaybeLocal<v8::Value> AsyncWrap::MakeCallback(
Expand Down Expand Up @@ -89,6 +107,15 @@ inline v8::Local<v8::FunctionTemplate> AsyncWrap::GetConstructorTemplate(
return GetConstructorTemplate(env->isolate_data());
}

// static
v8::Local<v8::FunctionTemplate> AsyncWrap::MakeLazilyInitializedJSTemplate(
Environment* env, int internal_field_count) {
v8::Local<v8::FunctionTemplate> t =
BaseObject::MakeLazilyInitializedJSTemplate(env, internal_field_count);
t->Inherit(AsyncWrap::GetConstructorTemplate(env));
return t;
}

} // namespace node

#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
Expand Down
35 changes: 20 additions & 15 deletions src/async_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,13 @@ void AsyncWrap::AsyncReset(const FunctionCallbackInfo<Value>& args) {
wrap->AsyncReset(resource, execution_async_id);
}

// Useful for debugging async context propagation. Not intended for public use.
void AsyncWrap::GetAsyncContextFrame(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap;
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());

args.GetReturnValue().Set(wrap->context_frame());
}

void AsyncWrap::GetProviderType(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap;
Expand All @@ -341,7 +348,7 @@ void AsyncWrap::EmitDestroy(bool from_gc) {
HandleScope handle_scope(env()->isolate());
USE(object()->Set(env()->context(), env()->resource_symbol(), object()));
}
context_frame_.Reset();
set_context_frame({});
}
}

Expand Down Expand Up @@ -372,6 +379,10 @@ Local<FunctionTemplate> AsyncWrap::GetConstructorTemplate(
FIXED_ONE_BYTE_STRING(isolate_data->isolate(), "AsyncWrap"));
SetProtoMethod(isolate, tmpl, "getAsyncId", AsyncWrap::GetAsyncId);
SetProtoMethod(isolate, tmpl, "asyncReset", AsyncWrap::AsyncReset);
SetProtoMethod(isolate,
tmpl,
"getAsyncContextFrameForDebuggingOnly",
AsyncWrap::GetAsyncContextFrame);
SetProtoMethod(
isolate, tmpl, "getProviderType", AsyncWrap::GetProviderType);
isolate_data->set_async_wrap_ctor_template(tmpl);
Expand Down Expand Up @@ -501,6 +512,7 @@ void AsyncWrap::RegisterExternalReferences(
registry->Register(RegisterDestroyHook);
registry->Register(AsyncWrap::GetAsyncId);
registry->Register(AsyncWrap::AsyncReset);
registry->Register(AsyncWrap::GetAsyncContextFrame);
registry->Register(AsyncWrap::GetProviderType);
}

Expand All @@ -518,9 +530,9 @@ AsyncWrap::AsyncWrap(Environment* env,
}

AsyncWrap::AsyncWrap(Environment* env, Local<Object> object)
: BaseObject(env, object),
context_frame_(env->isolate(),
async_context_frame::current(env->isolate())) {}
: BaseObject(env, object) {
set_context_frame(async_context_frame::current(env->isolate()));
}

// This method is necessary to work around one specific problem:
// Before the init() hook runs, if there is one, the BaseObject() constructor
Expand Down Expand Up @@ -623,7 +635,7 @@ void AsyncWrap::AsyncReset(Local<Object> resource, double execution_async_id) {

EmitTraceAsyncStart();

context_frame_.Reset(isolate, async_context_frame::current(isolate));
set_context_frame(async_context_frame::current(isolate));

EmitAsyncInit(env(), resource,
env()->async_hooks()->provider_string(provider_type()),
Expand Down Expand Up @@ -666,7 +678,7 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
EmitTraceEventBefore();

#ifdef DEBUG
if (context_frame_.IsEmpty()) {
if (context_frame().IsEmpty()) {
ProcessEmitWarning(env(),
"MakeCallback() called without context_frame, "
"likely use after destroy of AsyncWrap.");
Expand All @@ -675,15 +687,8 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,

ProviderType provider = provider_type();
async_context context { get_async_id(), get_trigger_async_id() };
MaybeLocal<Value> ret =
InternalMakeCallback(env(),
object(),
object(),
cb,
argc,
argv,
context,
context_frame_.Get(env()->isolate()));
MaybeLocal<Value> ret = InternalMakeCallback(
env(), object(), object(), cb, argc, argv, context, context_frame());

// This is a static call with cached values because the `this` object may
// no longer be alive at this point.
Expand Down
13 changes: 11 additions & 2 deletions src/async_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ class ExternalReferenceRegistry;

class AsyncWrap : public BaseObject {
public:
enum InternalFields {
kAsyncContextFrame = BaseObject::kInternalFieldCount,
kInternalFieldCount,
};

enum ProviderType {
#define V(PROVIDER) \
PROVIDER_ ## PROVIDER,
Expand Down Expand Up @@ -162,6 +167,8 @@ class AsyncWrap : public BaseObject {
static void ClearAsyncIdStack(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void AsyncReset(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetAsyncContextFrame(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetProviderType(const v8::FunctionCallbackInfo<v8::Value>& args);
static void QueueDestroyAsyncId(
const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down Expand Up @@ -195,6 +202,7 @@ class AsyncWrap : public BaseObject {
inline double get_trigger_async_id() const;

inline v8::Local<v8::Value> context_frame() const;
inline void set_context_frame(v8::Local<v8::Value> value);

void AsyncReset(v8::Local<v8::Object> resource,
double execution_async_id = kInvalidAsyncId);
Expand Down Expand Up @@ -229,14 +237,15 @@ class AsyncWrap : public BaseObject {

bool IsDoneInitializing() const override;

static inline v8::Local<v8::FunctionTemplate> MakeLazilyInitializedJSTemplate(
Environment* env, int internal_field_count = kInternalFieldCount);

private:
ProviderType provider_type_ = PROVIDER_NONE;
bool init_hook_ran_ = false;
// Because the values may be Reset(), cannot be made const.
double async_id_ = kInvalidAsyncId;
double trigger_async_id_ = kInvalidAsyncId;

v8::Global<v8::Value> context_frame_;
};

} // namespace node
Expand Down
9 changes: 5 additions & 4 deletions src/base_object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,16 @@ void BaseObject::LazilyInitializedJSTemplateConstructor(
}

Local<FunctionTemplate> BaseObject::MakeLazilyInitializedJSTemplate(
Environment* env) {
return MakeLazilyInitializedJSTemplate(env->isolate_data());
Environment* env, int internal_field_count) {
return MakeLazilyInitializedJSTemplate(env->isolate_data(),
internal_field_count);
}

Local<FunctionTemplate> BaseObject::MakeLazilyInitializedJSTemplate(
IsolateData* isolate_data) {
IsolateData* isolate_data, int internal_field_count) {
Local<FunctionTemplate> t = NewFunctionTemplate(
isolate_data->isolate(), LazilyInitializedJSTemplateConstructor);
t->InstanceTemplate()->SetInternalFieldCount(BaseObject::kInternalFieldCount);
t->InstanceTemplate()->SetInternalFieldCount(internal_field_count);
return t;
}

Expand Down
4 changes: 2 additions & 2 deletions src/base_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ class BaseObject : public MemoryRetainer {
// the `BaseObject*` pointer) and a constructor that initializes that field
// to `nullptr`.
static v8::Local<v8::FunctionTemplate> MakeLazilyInitializedJSTemplate(
IsolateData* isolate);
IsolateData* isolate, int internal_field_count = kInternalFieldCount);
static v8::Local<v8::FunctionTemplate> MakeLazilyInitializedJSTemplate(
Environment* env);
Environment* env, int internal_field_count = kInternalFieldCount);

// Setter/Getter pair for internal fields that can be passed to SetAccessor.
template <int Field>
Expand Down
12 changes: 3 additions & 9 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2318,19 +2318,13 @@ void Initialize(Local<Object> target,
NODE_DEFINE_CONSTANT(target, DNS_ORDER_IPV4_FIRST);
NODE_DEFINE_CONSTANT(target, DNS_ORDER_IPV6_FIRST);

Local<FunctionTemplate> aiw =
BaseObject::MakeLazilyInitializedJSTemplate(env);
aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<FunctionTemplate> aiw = AsyncWrap::MakeLazilyInitializedJSTemplate(env);
SetConstructorFunction(context, target, "GetAddrInfoReqWrap", aiw);

Local<FunctionTemplate> niw =
BaseObject::MakeLazilyInitializedJSTemplate(env);
niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<FunctionTemplate> niw = AsyncWrap::MakeLazilyInitializedJSTemplate(env);
SetConstructorFunction(context, target, "GetNameInfoReqWrap", niw);

Local<FunctionTemplate> qrw =
BaseObject::MakeLazilyInitializedJSTemplate(env);
qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<FunctionTemplate> qrw = AsyncWrap::MakeLazilyInitializedJSTemplate(env);
SetConstructorFunction(context, target, "QueryReqWrap", qrw);

Local<FunctionTemplate> channel_wrap =
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto_keys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,7 @@ void NativeKeyObject::CreateNativeKeyObjectClass(
Local<FunctionTemplate> t =
NewFunctionTemplate(isolate, NativeKeyObject::New);
t->InstanceTemplate()->SetInternalFieldCount(
KeyObjectHandle::kInternalFieldCount);
NativeKeyObject::kInternalFieldCount);

Local<Value> ctor;
if (!t->GetFunction(env->context()).ToLocal(&ctor))
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/crypto_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ void Sign::Initialize(Environment* env, Local<Object> target) {
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);

t->InstanceTemplate()->SetInternalFieldCount(SignBase::kInternalFieldCount);
t->InstanceTemplate()->SetInternalFieldCount(Sign::kInternalFieldCount);

SetProtoMethod(isolate, t, "init", SignInit);
SetProtoMethod(isolate, t, "update", SignUpdate);
Expand Down Expand Up @@ -437,7 +437,7 @@ void Verify::Initialize(Environment* env, Local<Object> target) {
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);

t->InstanceTemplate()->SetInternalFieldCount(SignBase::kInternalFieldCount);
t->InstanceTemplate()->SetInternalFieldCount(Verify::kInternalFieldCount);

SetProtoMethod(isolate, t, "init", VerifyInit);
SetProtoMethod(isolate, t, "update", VerifyUpdate);
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/crypto_tls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2172,11 +2172,11 @@ void TLSWrap::Initialize(

NODE_DEFINE_CONSTANT(target, HAVE_SSL_TRACE);

Local<FunctionTemplate> t = BaseObject::MakeLazilyInitializedJSTemplate(env);
Local<FunctionTemplate> t = AsyncWrap::MakeLazilyInitializedJSTemplate(env);
Local<String> tlsWrapString =
FIXED_ONE_BYTE_STRING(env->isolate(), "TLSWrap");
t->SetClassName(tlsWrapString);
t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount);
t->InstanceTemplate()->SetInternalFieldCount(TLSWrap::kInternalFieldCount);

Local<FunctionTemplate> get_write_queue_size =
FunctionTemplate::New(env->isolate(),
Expand Down
5 changes: 5 additions & 0 deletions src/crypto/crypto_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class TLSWrap : public AsyncWrap,
public StreamBase,
public StreamListener {
public:
enum InternalFields {
kInternalFieldCount = std::max<uint32_t>(AsyncWrap::kInternalFieldCount,
StreamBase::kInternalFieldCount),
};

enum class Kind {
kClient,
kServer
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ class CryptoJob : public AsyncWrap, public ThreadPoolWork {
v8::Local<v8::FunctionTemplate> job = NewFunctionTemplate(isolate, new_fn);
job->Inherit(AsyncWrap::GetConstructorTemplate(env));
job->InstanceTemplate()->SetInternalFieldCount(
AsyncWrap::kInternalFieldCount);
CryptoJob::kInternalFieldCount);
SetProtoMethod(isolate, job, "run", Run);
SetConstructorFunction(context, target, CryptoJobTraits::JobName, job);
}
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto_x509.cc
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ Local<FunctionTemplate> X509Certificate::GetConstructorTemplate(
Isolate* isolate = env->isolate();
tmpl = NewFunctionTemplate(isolate, nullptr);
tmpl->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
X509Certificate::kInternalFieldCount);
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(env->isolate(), "X509Certificate"));
SetProtoMethodNoSideEffect(isolate, tmpl, "subject", Subject);
Expand Down
1 change: 1 addition & 0 deletions src/env_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
V(arrow_message_private_symbol, "node:arrowMessage") \
V(contextify_context_private_symbol, "node:contextify:context") \
V(decorated_private_symbol, "node:decorated") \
V(empty_context_frame_sentinel_symbol, "node:empty_context_frame_sentinel") \
V(transfer_mode_private_symbol, "node:transfer_mode") \
V(host_defined_option_symbol, "node:host_defined_option_symbol") \
V(js_transferable_wrapper_private_symbol, "node:js_transferable_wrapper") \
Expand Down
7 changes: 6 additions & 1 deletion src/heap_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ class HeapSnapshotStream : public AsyncWrap,
public StreamBase,
public v8::OutputStream {
public:
enum InternalFields {
kInternalFieldCount = std::max<uint32_t>(AsyncWrap::kInternalFieldCount,
StreamBase::kInternalFieldCount),
};

HeapSnapshotStream(
Environment* env,
HeapSnapshotPointer&& snapshot,
Expand Down Expand Up @@ -401,7 +406,7 @@ BaseObjectPtr<AsyncWrap> CreateHeapSnapshotStream(
Local<FunctionTemplate> os = FunctionTemplate::New(env->isolate());
os->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<ObjectTemplate> ost = os->InstanceTemplate();
ost->SetInternalFieldCount(StreamBase::kInternalFieldCount);
ost->SetInternalFieldCount(HeapSnapshotStream::kInternalFieldCount);
os->SetClassName(
FIXED_ONE_BYTE_STRING(env->isolate(), "HeapSnapshotStream"));
StreamBase::AddMethods(env, os);
Expand Down
4 changes: 2 additions & 2 deletions src/histogram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ Local<FunctionTemplate> HistogramBase::GetConstructorTemplate(
Local<String> classname = FIXED_ONE_BYTE_STRING(isolate, "Histogram");
tmpl->SetClassName(classname);
auto instance = tmpl->InstanceTemplate();
instance->SetInternalFieldCount(HistogramImpl::kInternalFieldCount);
instance->SetInternalFieldCount(HistogramBase::kInternalFieldCount);
SetFastMethod(isolate, instance, "record", Record, &fast_record_);
SetFastMethod(
isolate, instance, "recordDelta", RecordDelta, &fast_record_delta_);
Expand Down Expand Up @@ -328,7 +328,7 @@ Local<FunctionTemplate> IntervalHistogram::GetConstructorTemplate(
tmpl->Inherit(HandleWrap::GetConstructorTemplate(env));
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "Histogram"));
auto instance = tmpl->InstanceTemplate();
instance->SetInternalFieldCount(HistogramImpl::kInternalFieldCount);
instance->SetInternalFieldCount(IntervalHistogram::kInternalFieldCount);
HistogramImpl::AddMethods(isolate, tmpl);
SetFastMethod(isolate, instance, "start", Start, &fast_start_);
SetFastMethod(isolate, instance, "stop", Stop, &fast_stop_);
Expand Down
12 changes: 11 additions & 1 deletion src/histogram.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class HistogramImpl {
public:
enum InternalFields {
kSlot = BaseObject::kSlot,
kImplField = BaseObject::kInternalFieldCount,
kImplField = HandleWrap::kInternalFieldCount,
kInternalFieldCount
};

Expand Down Expand Up @@ -133,6 +133,11 @@ class HistogramImpl {

class HistogramBase final : public BaseObject, public HistogramImpl {
public:
enum InternalFields {
kInternalFieldCount = std::max<uint32_t>(
BaseObject::kInternalFieldCount, HistogramImpl::kInternalFieldCount),
};

static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
IsolateData* isolate_data);
static void Initialize(IsolateData* isolate_data,
Expand Down Expand Up @@ -203,6 +208,11 @@ class HistogramBase final : public BaseObject, public HistogramImpl {

class IntervalHistogram final : public HandleWrap, public HistogramImpl {
public:
enum InternalFields {
kInternalFieldCount = std::max<uint32_t>(
HandleWrap::kInternalFieldCount, HistogramImpl::kInternalFieldCount),
};

enum class StartFlags {
NONE,
RESET
Expand Down
3 changes: 1 addition & 2 deletions src/js_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,7 @@ void JSStream::Initialize(Local<Object> target,
Isolate* isolate = env->isolate();

Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()
->SetInternalFieldCount(StreamBase::kInternalFieldCount);
t->InstanceTemplate()->SetInternalFieldCount(JSStream::kInternalFieldCount);
t->Inherit(AsyncWrap::GetConstructorTemplate(env));

SetProtoMethod(isolate, t, "finishWrite", Finish<WriteWrap>);
Expand Down
Loading
Loading