Skip to content

Commit fbd1c49

Browse files
committed
src: move CallbackScope to separate cc/h
PR-URL: nodejs#20789 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
1 parent 27df81c commit fbd1c49

File tree

5 files changed

+185
-147
lines changed

5 files changed

+185
-147
lines changed

node.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@
304304

305305
'sources': [
306306
'src/async_wrap.cc',
307+
'src/callback_scope.cc',
307308
'src/cares_wrap.cc',
308309
'src/connection_wrap.cc',
309310
'src/connect_wrap.cc',
@@ -365,6 +366,7 @@
365366
'src/async_wrap-inl.h',
366367
'src/base_object.h',
367368
'src/base_object-inl.h',
369+
'src/callback_scope.h',
368370
'src/connection_wrap.h',
369371
'src/connect_wrap.h',
370372
'src/env.h',

src/callback_scope.cc

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include "node.h"
2+
#include "callback_scope.h"
3+
#include "async_wrap.h"
4+
#include "async_wrap-inl.h"
5+
#include "env.h"
6+
#include "env-inl.h"
7+
#include "v8.h"
8+
9+
namespace node {
10+
11+
using v8::HandleScope;
12+
using v8::Isolate;
13+
using v8::Local;
14+
using v8::Object;
15+
16+
using AsyncHooks = Environment::AsyncHooks;
17+
18+
CallbackScope::CallbackScope(Isolate* isolate,
19+
Local<Object> object,
20+
async_context asyncContext)
21+
: private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
22+
object,
23+
asyncContext)),
24+
try_catch_(isolate) {
25+
try_catch_.SetVerbose(true);
26+
}
27+
28+
CallbackScope::~CallbackScope() {
29+
if (try_catch_.HasCaught())
30+
private_->MarkAsFailed();
31+
delete private_;
32+
}
33+
34+
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
35+
: InternalCallbackScope(async_wrap->env(),
36+
async_wrap->object(),
37+
{ async_wrap->get_async_id(),
38+
async_wrap->get_trigger_async_id() }) {}
39+
40+
InternalCallbackScope::InternalCallbackScope(Environment* env,
41+
Local<Object> object,
42+
const async_context& asyncContext,
43+
ResourceExpectation expect)
44+
: env_(env),
45+
async_context_(asyncContext),
46+
object_(object),
47+
callback_scope_(env) {
48+
if (expect == kRequireResource) {
49+
CHECK(!object.IsEmpty());
50+
}
51+
52+
if (!env->can_call_into_js()) {
53+
failed_ = true;
54+
return;
55+
}
56+
57+
HandleScope handle_scope(env->isolate());
58+
// If you hit this assertion, you forgot to enter the v8::Context first.
59+
CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
60+
61+
if (asyncContext.async_id != 0) {
62+
// No need to check a return value because the application will exit if
63+
// an exception occurs.
64+
AsyncWrap::EmitBefore(env, asyncContext.async_id);
65+
}
66+
67+
if (!IsInnerMakeCallback()) {
68+
env->tick_info()->set_has_thrown(false);
69+
}
70+
71+
env->async_hooks()->push_async_ids(async_context_.async_id,
72+
async_context_.trigger_async_id);
73+
pushed_ids_ = true;
74+
}
75+
76+
InternalCallbackScope::~InternalCallbackScope() {
77+
Close();
78+
}
79+
80+
void InternalCallbackScope::Close() {
81+
if (closed_) return;
82+
closed_ = true;
83+
HandleScope handle_scope(env_->isolate());
84+
85+
if (pushed_ids_)
86+
env_->async_hooks()->pop_async_id(async_context_.async_id);
87+
88+
if (failed_) return;
89+
90+
if (async_context_.async_id != 0) {
91+
AsyncWrap::EmitAfter(env_, async_context_.async_id);
92+
}
93+
94+
if (IsInnerMakeCallback()) {
95+
return;
96+
}
97+
98+
Environment::TickInfo* tick_info = env_->tick_info();
99+
100+
if (!env_->can_call_into_js()) return;
101+
if (!tick_info->has_scheduled()) {
102+
env_->isolate()->RunMicrotasks();
103+
}
104+
105+
// Make sure the stack unwound properly. If there are nested MakeCallback's
106+
// then it should return early and not reach this code.
107+
if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
108+
CHECK_EQ(env_->execution_async_id(), 0);
109+
CHECK_EQ(env_->trigger_async_id(), 0);
110+
}
111+
112+
if (!tick_info->has_scheduled() && !tick_info->has_promise_rejections()) {
113+
return;
114+
}
115+
116+
Local<Object> process = env_->process_object();
117+
118+
if (!env_->can_call_into_js()) return;
119+
120+
if (env_->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
121+
env_->tick_info()->set_has_thrown(true);
122+
failed_ = true;
123+
}
124+
}
125+
126+
} // namespace node

src/callback_scope.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef SRC_CALLBACK_SCOPE_H_
2+
#define SRC_CALLBACK_SCOPE_H_
3+
4+
#ifdef _WIN32
5+
# ifndef BUILDING_NODE_EXTENSION
6+
# define NODE_EXTERN __declspec(dllexport)
7+
# else
8+
# define NODE_EXTERN __declspec(dllimport)
9+
# endif
10+
#else
11+
# define NODE_EXTERN /* nothing */
12+
#endif
13+
14+
#include "v8.h"
15+
16+
namespace node {
17+
18+
typedef double async_id;
19+
struct async_context {
20+
::node::async_id async_id;
21+
::node::async_id trigger_async_id;
22+
};
23+
24+
class InternalCallbackScope;
25+
26+
/* This class works like `MakeCallback()` in that it sets up a specific
27+
* asyncContext as the current one and informs the async_hooks and domains
28+
* modules that this context is currently active.
29+
*
30+
* `MakeCallback()` is a wrapper around this class as well as
31+
* `Function::Call()`. Either one of these mechanisms needs to be used for
32+
* top-level calls into JavaScript (i.e. without any existing JS stack).
33+
*
34+
* This object should be stack-allocated to ensure that it is contained in a
35+
* valid HandleScope.
36+
*/
37+
class NODE_EXTERN CallbackScope {
38+
public:
39+
CallbackScope(v8::Isolate* isolate,
40+
v8::Local<v8::Object> resource,
41+
async_context asyncContext);
42+
~CallbackScope();
43+
44+
private:
45+
InternalCallbackScope* private_;
46+
v8::TryCatch try_catch_;
47+
48+
void operator=(const CallbackScope&) = delete;
49+
void operator=(CallbackScope&&) = delete;
50+
CallbackScope(const CallbackScope&) = delete;
51+
CallbackScope(CallbackScope&&) = delete;
52+
};
53+
54+
} // namespace node
55+
56+
#endif // SRC_CALLBACK_SCOPE_H_

src/node.cc

Lines changed: 0 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,6 @@ using v8::Undefined;
170170
using v8::V8;
171171
using v8::Value;
172172

173-
using AsyncHooks = Environment::AsyncHooks;
174-
175173
static Mutex process_mutex;
176174
static Mutex environ_mutex;
177175

@@ -924,115 +922,6 @@ void RemoveEnvironmentCleanupHook(v8::Isolate* isolate,
924922
env->RemoveCleanupHook(fun, arg);
925923
}
926924

927-
928-
CallbackScope::CallbackScope(Isolate* isolate,
929-
Local<Object> object,
930-
async_context asyncContext)
931-
: private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
932-
object,
933-
asyncContext)),
934-
try_catch_(isolate) {
935-
try_catch_.SetVerbose(true);
936-
}
937-
938-
CallbackScope::~CallbackScope() {
939-
if (try_catch_.HasCaught())
940-
private_->MarkAsFailed();
941-
delete private_;
942-
}
943-
944-
InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
945-
: InternalCallbackScope(async_wrap->env(),
946-
async_wrap->object(),
947-
{ async_wrap->get_async_id(),
948-
async_wrap->get_trigger_async_id() }) {}
949-
950-
InternalCallbackScope::InternalCallbackScope(Environment* env,
951-
Local<Object> object,
952-
const async_context& asyncContext,
953-
ResourceExpectation expect)
954-
: env_(env),
955-
async_context_(asyncContext),
956-
object_(object),
957-
callback_scope_(env) {
958-
if (expect == kRequireResource) {
959-
CHECK(!object.IsEmpty());
960-
}
961-
962-
if (!env->can_call_into_js()) {
963-
failed_ = true;
964-
return;
965-
}
966-
967-
HandleScope handle_scope(env->isolate());
968-
// If you hit this assertion, you forgot to enter the v8::Context first.
969-
CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
970-
971-
if (asyncContext.async_id != 0) {
972-
// No need to check a return value because the application will exit if
973-
// an exception occurs.
974-
AsyncWrap::EmitBefore(env, asyncContext.async_id);
975-
}
976-
977-
if (!IsInnerMakeCallback()) {
978-
env->tick_info()->set_has_thrown(false);
979-
}
980-
981-
env->async_hooks()->push_async_ids(async_context_.async_id,
982-
async_context_.trigger_async_id);
983-
pushed_ids_ = true;
984-
}
985-
986-
InternalCallbackScope::~InternalCallbackScope() {
987-
Close();
988-
}
989-
990-
void InternalCallbackScope::Close() {
991-
if (closed_) return;
992-
closed_ = true;
993-
HandleScope handle_scope(env_->isolate());
994-
995-
if (pushed_ids_)
996-
env_->async_hooks()->pop_async_id(async_context_.async_id);
997-
998-
if (failed_) return;
999-
1000-
if (async_context_.async_id != 0) {
1001-
AsyncWrap::EmitAfter(env_, async_context_.async_id);
1002-
}
1003-
1004-
if (IsInnerMakeCallback()) {
1005-
return;
1006-
}
1007-
1008-
Environment::TickInfo* tick_info = env_->tick_info();
1009-
1010-
if (!env_->can_call_into_js()) return;
1011-
if (!tick_info->has_scheduled()) {
1012-
env_->isolate()->RunMicrotasks();
1013-
}
1014-
1015-
// Make sure the stack unwound properly. If there are nested MakeCallback's
1016-
// then it should return early and not reach this code.
1017-
if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
1018-
CHECK_EQ(env_->execution_async_id(), 0);
1019-
CHECK_EQ(env_->trigger_async_id(), 0);
1020-
}
1021-
1022-
if (!tick_info->has_scheduled() && !tick_info->has_promise_rejections()) {
1023-
return;
1024-
}
1025-
1026-
Local<Object> process = env_->process_object();
1027-
1028-
if (!env_->can_call_into_js()) return;
1029-
1030-
if (env_->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
1031-
env_->tick_info()->set_has_thrown(true);
1032-
failed_ = true;
1033-
}
1034-
}
1035-
1036925
MaybeLocal<Value> InternalMakeCallback(Environment* env,
1037926
Local<Object> recv,
1038927
const Local<Function> callback,

src/node.h

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "v8.h" // NOLINT(build/include_order)
6464
#include "v8-platform.h" // NOLINT(build/include_order)
6565
#include "node_version.h" // NODE_MODULE_VERSION
66+
#include "callback_scope.h"
6667

6768
#define NODE_MAKE_VERSION(major, minor, patch) \
6869
((major) * 0x1000 + (minor) * 0x100 + (patch))
@@ -593,12 +594,6 @@ typedef void (*promise_hook_func) (v8::PromiseHookType type,
593594
v8::Local<v8::Value> parent,
594595
void* arg);
595596

596-
typedef double async_id;
597-
struct async_context {
598-
::node::async_id async_id;
599-
::node::async_id trigger_async_id;
600-
};
601-
602597
/* Registers an additional v8::PromiseHook wrapper. This API exists because V8
603598
* itself supports only a single PromiseHook. */
604599
NODE_EXTERN void AddPromiseHook(v8::Isolate* isolate,
@@ -647,36 +642,6 @@ NODE_EXTERN async_context EmitAsyncInit(v8::Isolate* isolate,
647642
NODE_EXTERN void EmitAsyncDestroy(v8::Isolate* isolate,
648643
async_context asyncContext);
649644

650-
class InternalCallbackScope;
651-
652-
/* This class works like `MakeCallback()` in that it sets up a specific
653-
* asyncContext as the current one and informs the async_hooks and domains
654-
* modules that this context is currently active.
655-
*
656-
* `MakeCallback()` is a wrapper around this class as well as
657-
* `Function::Call()`. Either one of these mechanisms needs to be used for
658-
* top-level calls into JavaScript (i.e. without any existing JS stack).
659-
*
660-
* This object should be stack-allocated to ensure that it is contained in a
661-
* valid HandleScope.
662-
*/
663-
class NODE_EXTERN CallbackScope {
664-
public:
665-
CallbackScope(v8::Isolate* isolate,
666-
v8::Local<v8::Object> resource,
667-
async_context asyncContext);
668-
~CallbackScope();
669-
670-
private:
671-
InternalCallbackScope* private_;
672-
v8::TryCatch try_catch_;
673-
674-
void operator=(const CallbackScope&) = delete;
675-
void operator=(CallbackScope&&) = delete;
676-
CallbackScope(const CallbackScope&) = delete;
677-
CallbackScope(CallbackScope&&) = delete;
678-
};
679-
680645
/* An API specific to emit before/after callbacks is unnecessary because
681646
* MakeCallback will automatically call them for you.
682647
*

0 commit comments

Comments
 (0)