Skip to content

Commit

Permalink
env: introduce AsyncWrapScope for MakeCallback
Browse files Browse the repository at this point in the history
Do not go through async wrap hooks if we are already within the
`MakeCallback`. This commit allows calling `MakeCallback` recursively.
  • Loading branch information
indutny committed Jan 1, 2016
1 parent 1170b26 commit 2100e96
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/async-wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,25 @@ Local<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
int argc,
Local<Value>* argv) {
CHECK(env()->context() == env()->isolate()->GetCurrentContext());
Local<Object> context = object();

if (env()->in_async_callback()) {
TryCatch try_catch(env()->isolate());
try_catch.SetVerbose(true);

Local<Value> ret = cb->Call(context, argc, argv);

if (try_catch.HasCaught()) {
return Undefined(env()->isolate());
}

return ret;
}

Environment::AsyncCallbackScope async_scope(env());

Local<Function> pre_fn = env()->async_hooks_pre_function();
Local<Function> post_fn = env()->async_hooks_post_function();
Local<Object> context = object();
Local<Object> process = env()->process_object();
Local<Object> domain;
bool has_domain = false;
Expand Down
18 changes: 18 additions & 0 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ inline void Environment::AsyncHooks::set_enable_callbacks(uint32_t flag) {
fields_[kEnableCallbacks] = flag;
}

inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env) :
env_(env) {
env_->set_in_async_callback(true);
}

inline Environment::AsyncCallbackScope::~AsyncCallbackScope() {
env_->set_in_async_callback(false);
}

inline Environment::DomainFlag::DomainFlag() {
for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
}
Expand Down Expand Up @@ -206,6 +215,7 @@ inline Environment::Environment(v8::Local<v8::Context> context,
uv_loop_t* loop)
: isolate_(context->GetIsolate()),
isolate_data_(IsolateData::GetOrCreate(context->GetIsolate(), loop)),
in_async_callback_(false),
timer_base_(uv_now(loop)),
using_domains_(false),
printed_error_(false),
Expand Down Expand Up @@ -323,6 +333,14 @@ inline Environment::AsyncHooks* Environment::async_hooks() {
return &async_hooks_;
}

inline bool Environment::in_async_callback() const {
return in_async_callback_;
}

inline void Environment::set_in_async_callback(bool value) {
in_async_callback_ = value;
}

inline Environment::DomainFlag* Environment::domain_flag() {
return &domain_flag_;
}
Expand Down
13 changes: 13 additions & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,15 @@ class Environment {
DISALLOW_COPY_AND_ASSIGN(AsyncHooks);
};

class AsyncCallbackScope {
public:
explicit AsyncCallbackScope(Environment* env);
~AsyncCallbackScope();

private:
Environment* env_;
};

class DomainFlag {
public:
inline uint32_t* fields();
Expand Down Expand Up @@ -435,6 +444,9 @@ class Environment {
inline void FinishHandleCleanup(uv_handle_t* handle);

inline AsyncHooks* async_hooks();
inline bool in_async_callback() const;

This comment has been minimized.

Copy link
@ofrobots

ofrobots Jan 5, 2016

Do you want to make these private and make AsyncCallbackScope a friend?

inline void set_in_async_callback(bool value);

inline DomainFlag* domain_flag();
inline TickInfo* tick_info();
inline ArrayBufferAllocatorInfo* array_buffer_allocator_info();
Expand Down Expand Up @@ -542,6 +554,7 @@ class Environment {
uv_prepare_t idle_prepare_handle_;
uv_check_t idle_check_handle_;
AsyncHooks async_hooks_;
bool in_async_callback_;
DomainFlag domain_flag_;
TickInfo tick_info_;
ArrayBufferAllocatorInfo array_buffer_allocator_info_;
Expand Down
2 changes: 2 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3196,6 +3196,8 @@ void LoadEnvironment(Environment* env) {
// thrown during process startup.
try_catch.SetVerbose(true);

Environment::AsyncCallbackScope async_scope(env);

env->SetMethod(env->process_object(), "_rawDebug", RawDebug);

Local<Value> arg = env->process_object();
Expand Down

0 comments on commit 2100e96

Please sign in to comment.