diff --git a/src/callback_scope.cc b/src/callback_scope.cc index feb7e23b6e5f84..8b407474b333c6 100644 --- a/src/callback_scope.cc +++ b/src/callback_scope.cc @@ -59,7 +59,8 @@ InternalCallbackScope::InternalCallbackScope(Environment* env, AsyncWrap::EmitBefore(env, asyncContext.async_id); } - if (!IsInnerMakeCallback()) { + CHECK_GE(env->makecallback_depth(), 1); + if (env->makecallback_depth() == 1) { env->tick_info()->set_has_thrown(false); } @@ -91,7 +92,7 @@ void InternalCallbackScope::Close() { AsyncWrap::EmitAfter(env_, async_context_.async_id); } - if (IsInnerMakeCallback()) { + if (env_->makecallback_depth() > 1) { return; } diff --git a/src/env-inl.h b/src/env-inl.h index 542cfb6400c0ee..cf9c60f948d613 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -218,8 +218,8 @@ inline Environment::AsyncCallbackScope::~AsyncCallbackScope() { env_->makecallback_cntr_--; } -inline bool Environment::AsyncCallbackScope::in_makecallback() const { - return env_->makecallback_cntr_ > 1; +inline size_t Environment::makecallback_depth() const { + return makecallback_cntr_; } inline Environment::ImmediateInfo::ImmediateInfo(v8::Isolate* isolate) diff --git a/src/env.h b/src/env.h index 5b0a04e03eec51..b1ea04b9a65bb3 100644 --- a/src/env.h +++ b/src/env.h @@ -503,7 +503,6 @@ class Environment { AsyncCallbackScope() = delete; explicit AsyncCallbackScope(Environment* env); ~AsyncCallbackScope(); - inline bool in_makecallback() const; private: Environment* env_; @@ -511,6 +510,8 @@ class Environment { DISALLOW_COPY_AND_ASSIGN(AsyncCallbackScope); }; + inline size_t makecallback_depth() const; + class ImmediateInfo { public: inline AliasedBuffer& fields(); diff --git a/src/node.cc b/src/node.cc index 38b95f8457e8c3..ffec0c8ea8bbe6 100644 --- a/src/node.cc +++ b/src/node.cc @@ -758,7 +758,7 @@ MaybeLocal InternalMakeCallback(Environment* env, CHECK(!recv.IsEmpty()); InternalCallbackScope scope(env, recv, asyncContext); if (scope.Failed()) { - return Undefined(env->isolate()); + return MaybeLocal(); } Local domain_cb = env->domain_callback(); @@ -773,15 +773,13 @@ MaybeLocal InternalMakeCallback(Environment* env, } if (ret.IsEmpty()) { - // NOTE: For backwards compatibility with public API we return Undefined() - // if the top level call threw. scope.MarkAsFailed(); - return scope.IsInnerMakeCallback() ? ret : Undefined(env->isolate()); + return MaybeLocal(); } scope.Close(); if (scope.Failed()) { - return Undefined(env->isolate()); + return MaybeLocal(); } return ret; @@ -833,8 +831,14 @@ MaybeLocal MakeCallback(Isolate* isolate, // the two contexts need not be the same. Environment* env = Environment::GetCurrent(callback->CreationContext()); Context::Scope context_scope(env->context()); - return InternalMakeCallback(env, recv, callback, - argc, argv, asyncContext); + MaybeLocal ret = InternalMakeCallback(env, recv, callback, + argc, argv, asyncContext); + if (ret.IsEmpty() && env->makecallback_depth() == 0) { + // This is only for legacy compatiblity and we may want to look into + // removing/adjusting it. + return Undefined(env->isolate()); + } + return ret; } diff --git a/src/node_internals.h b/src/node_internals.h index a9eb3398d84f72..d8521f39a1758f 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -543,9 +543,6 @@ class InternalCallbackScope { inline bool Failed() const { return failed_; } inline void MarkAsFailed() { failed_ = true; } - inline bool IsInnerMakeCallback() const { - return callback_scope_.in_makecallback(); - } private: Environment* env_; diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index 7af6d13c61f7d2..1ba2824e4c9992 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -37,6 +37,7 @@ using v8::FunctionTemplate; using v8::HandleScope; using v8::Integer; using v8::Local; +using v8::MaybeLocal; using v8::Object; using v8::String; using v8::Value; @@ -138,13 +139,12 @@ class TimerWrap : public HandleWrap { Environment* env = wrap->env(); HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); - Local ret; + MaybeLocal ret; Local args[1]; do { args[0] = env->GetNow(); - ret = wrap->MakeCallback(env->timers_callback_function(), 1, args) - .ToLocalChecked(); - } while (ret->IsUndefined() && + ret = wrap->MakeCallback(env->timers_callback_function(), 1, args); + } while ((ret.IsEmpty() || ret.ToLocalChecked()->IsUndefined()) && !env->tick_info()->has_thrown() && env->can_call_into_js() && wrap->object()->Get(env->context(),