Skip to content

Commit 36d4a42

Browse files
jasnellMylesBorins
authored andcommitted
src: move CallbackScope to separate cc/h
PR-URL: #20789 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]>
1 parent 2e99576 commit 36d4a42

File tree

5 files changed

+185
-147
lines changed

5 files changed

+185
-147
lines changed

node.gyp

+2
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@
302302

303303
'sources': [
304304
'src/async_wrap.cc',
305+
'src/callback_scope.cc',
305306
'src/cares_wrap.cc',
306307
'src/connection_wrap.cc',
307308
'src/connect_wrap.cc',
@@ -363,6 +364,7 @@
363364
'src/async_wrap-inl.h',
364365
'src/base_object.h',
365366
'src/base_object-inl.h',
367+
'src/callback_scope.h',
366368
'src/connection_wrap.h',
367369
'src/connect_wrap.h',
368370
'src/env.h',

src/callback_scope.cc

+126
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

+56
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

-111
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,6 @@ using v8::Undefined;
169169
using v8::V8;
170170
using v8::Value;
171171

172-
using AsyncHooks = Environment::AsyncHooks;
173-
174172
static Mutex process_mutex;
175173
static Mutex environ_mutex;
176174

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

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

src/node.h

+1-36
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)