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
20 changes: 16 additions & 4 deletions src/api/callback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "node.h"
#include "v8.h"

#include <optional>

namespace node {

using v8::Context;
Expand Down Expand Up @@ -112,9 +114,12 @@ InternalCallbackScope::InternalCallbackScope(

isolate->SetIdle(false);

// The prior frame is usually undefined: no global handle then.
Local<Value> prior_context_frame =
async_context_frame::exchange(env, context_frame);
// The prior frame is usually undefined: no global handle then. Usually it
// is also the frame of the callback, and there is nothing to set.
Local<Value> prior_context_frame = async_context_frame::current(isolate);
if (prior_context_frame != context_frame) {
async_context_frame::set(env, context_frame);
}
if (!prior_context_frame->IsUndefined()) {
prior_context_frame_.Reset(isolate, prior_context_frame);
}
Expand Down Expand Up @@ -349,7 +354,14 @@ MaybeLocal<Value> InternalMakeCallback(Isolate* isolate,
}
Environment* env = Environment::GetCurrent(context);
CHECK_NOT_NULL(env);
Context::Scope context_scope(env->context());
// Entering the context changes nothing when it is already the entered and
// the current one, which is the common case for addons.
Local<Context> env_context = env->context();
std::optional<Context::Scope> context_scope;
if (isolate->GetEnteredOrMicrotaskContext() != env_context ||
isolate->GetCurrentContext() != env_context) {
context_scope.emplace(env_context);
}
MaybeLocal<Value> ret = InternalMakeCallback(
env, recv, recv, callback, argc, argv, asyncContext, context_frame);
if (ret.IsEmpty() && env->async_callback_scope_depth() == 0) {
Expand Down
16 changes: 12 additions & 4 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void Environment::ResetPromiseHooks(Local<Function> init,
void AsyncHooks::push_async_context(
double async_id,
double trigger_async_id,
std::variant<Local<Object>*, Global<Object>*> resource) {
const std::variant<Local<Object>*, Global<Object>*>& resource) {
std::visit([](auto* ptr) { CHECK_IMPLIES(ptr != nullptr, !ptr->IsEmpty()); },
resource);

Expand Down Expand Up @@ -161,9 +161,13 @@ void AsyncHooks::push_async_context(
// False positive: https://github.com/cpplint/cpplint/issues/410
// NOLINTNEXTLINE(whitespace/newline)
if (std::visit([](auto* ptr) { return ptr != nullptr; }, resource)) {
native_execution_async_resources_.resize(offset + 1);
// Caveat: This is a v8::Local<>* assignment, we do not keep a v8::Global<>!
native_execution_async_resources_[offset] = resource;
if (native_execution_async_resources_.size() == offset) {
native_execution_async_resources_.push_back(resource);
} else {
native_execution_async_resources_.resize(offset + 1);
native_execution_async_resources_[offset] = resource;
}
}
}

Expand Down Expand Up @@ -196,7 +200,11 @@ bool AsyncHooks::pop_async_context(double async_id) {
native_execution_async_resources_[i]);
}
#endif
native_execution_async_resources_.resize(offset);
if (native_execution_async_resources_.size() == offset + 1) {
native_execution_async_resources_.pop_back();
} else {
native_execution_async_resources_.resize(offset);
}
native_execution_async_resources_.shrink_to_fit();
}

Expand Down
2 changes: 1 addition & 1 deletion src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ class AsyncHooks : public MemoryRetainer {
void push_async_context(
double async_id,
double trigger_async_id,
std::variant<v8::Local<v8::Object>*, v8::Global<v8::Object>*>
const std::variant<v8::Local<v8::Object>*, v8::Global<v8::Object>*>&
execution_async_resource);
bool pop_async_context(double async_id);
void clear_async_id_stack(); // Used in fatal exceptions.
Expand Down
Loading