Skip to content

src: begin restructuring node.cc for better maintainability #20789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
4 changes: 4 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,12 @@

'sources': [
'src/async_wrap.cc',
'src/callback_scope.cc',
'src/cares_wrap.cc',
'src/connection_wrap.cc',
'src/connect_wrap.cc',
'src/env.cc',
'src/exceptions.cc',
'src/fs_event_wrap.cc',
'src/handle_wrap.cc',
'src/js_stream.cc',
Expand Down Expand Up @@ -366,10 +368,12 @@
'src/async_wrap-inl.h',
'src/base_object.h',
'src/base_object-inl.h',
'src/callback_scope.h',
'src/connection_wrap.h',
'src/connect_wrap.h',
'src/env.h',
'src/env-inl.h',
'src/exceptions.h',
'src/handle_wrap.h',
'src/js_stream.h',
'src/module_wrap.h',
Expand Down
126 changes: 126 additions & 0 deletions src/callback_scope.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "node.h"
#include "callback_scope.h"
#include "async_wrap.h"
#include "async_wrap-inl.h"
#include "env.h"
#include "env-inl.h"
#include "v8.h"

namespace node {

using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;

using AsyncHooks = Environment::AsyncHooks;

CallbackScope::CallbackScope(Isolate* isolate,
Local<Object> object,
async_context asyncContext)
: private_(new InternalCallbackScope(Environment::GetCurrent(isolate),
object,
asyncContext)),
try_catch_(isolate) {
try_catch_.SetVerbose(true);
}

CallbackScope::~CallbackScope() {
if (try_catch_.HasCaught())
private_->MarkAsFailed();
delete private_;
}

InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap)
: InternalCallbackScope(async_wrap->env(),
async_wrap->object(),
{ async_wrap->get_async_id(),
async_wrap->get_trigger_async_id() }) {}

InternalCallbackScope::InternalCallbackScope(Environment* env,
Local<Object> object,
const async_context& asyncContext,
ResourceExpectation expect)
: env_(env),
async_context_(asyncContext),
object_(object),
callback_scope_(env) {
if (expect == kRequireResource) {
CHECK(!object.IsEmpty());
}

if (!env->can_call_into_js()) {
failed_ = true;
return;
}

HandleScope handle_scope(env->isolate());
// If you hit this assertion, you forgot to enter the v8::Context first.
CHECK_EQ(Environment::GetCurrent(env->isolate()), env);

if (asyncContext.async_id != 0) {
// No need to check a return value because the application will exit if
// an exception occurs.
AsyncWrap::EmitBefore(env, asyncContext.async_id);
}

if (!IsInnerMakeCallback()) {
env->tick_info()->set_has_thrown(false);
}

env->async_hooks()->push_async_ids(async_context_.async_id,
async_context_.trigger_async_id);
pushed_ids_ = true;
}

InternalCallbackScope::~InternalCallbackScope() {
Close();
}

void InternalCallbackScope::Close() {
if (closed_) return;
closed_ = true;
HandleScope handle_scope(env_->isolate());

if (pushed_ids_)
env_->async_hooks()->pop_async_id(async_context_.async_id);

if (failed_) return;

if (async_context_.async_id != 0) {
AsyncWrap::EmitAfter(env_, async_context_.async_id);
}

if (IsInnerMakeCallback()) {
return;
}

Environment::TickInfo* tick_info = env_->tick_info();

if (!env_->can_call_into_js()) return;
if (!tick_info->has_scheduled()) {
env_->isolate()->RunMicrotasks();
}

// Make sure the stack unwound properly. If there are nested MakeCallback's
// then it should return early and not reach this code.
if (env_->async_hooks()->fields()[AsyncHooks::kTotals]) {
CHECK_EQ(env_->execution_async_id(), 0);
CHECK_EQ(env_->trigger_async_id(), 0);
}

if (!tick_info->has_scheduled() && !tick_info->has_promise_rejections()) {
return;
}

Local<Object> process = env_->process_object();

if (!env_->can_call_into_js()) return;

if (env_->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
env_->tick_info()->set_has_thrown(true);
failed_ = true;
}
}

} // namespace node
47 changes: 47 additions & 0 deletions src/callback_scope.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef SRC_CALLBACK_SCOPE_H_
#define SRC_CALLBACK_SCOPE_H_

#include "core.h"
#include "v8.h"

namespace node {

typedef double async_id;
struct async_context {
::node::async_id async_id;
::node::async_id trigger_async_id;
};

class InternalCallbackScope;

/* This class works like `MakeCallback()` in that it sets up a specific
* asyncContext as the current one and informs the async_hooks and domains
* modules that this context is currently active.
*
* `MakeCallback()` is a wrapper around this class as well as
* `Function::Call()`. Either one of these mechanisms needs to be used for
* top-level calls into JavaScript (i.e. without any existing JS stack).
*
* This object should be stack-allocated to ensure that it is contained in a
* valid HandleScope.
*/
class NODE_EXTERN CallbackScope {
public:
CallbackScope(v8::Isolate* isolate,
v8::Local<v8::Object> resource,
async_context asyncContext);
~CallbackScope();

private:
InternalCallbackScope* private_;
v8::TryCatch try_catch_;

void operator=(const CallbackScope&) = delete;
void operator=(CallbackScope&&) = delete;
CallbackScope(const CallbackScope&) = delete;
CallbackScope(CallbackScope&&) = delete;
};

} // namespace node

#endif // SRC_CALLBACK_SCOPE_H_
44 changes: 44 additions & 0 deletions src/core.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef SRC_CORE_H_
#define SRC_CORE_H_

#ifdef _WIN32
# ifndef BUILDING_NODE_EXTENSION
# define NODE_EXTERN __declspec(dllexport)
# else
# define NODE_EXTERN __declspec(dllimport)
# endif
#else
# define NODE_EXTERN /* nothing */
#endif

#define NODE_MAKE_VERSION(major, minor, patch) \
((major) * 0x1000 + (minor) * 0x100 + (patch))

#ifdef __clang__
# define NODE_CLANG_AT_LEAST(major, minor, patch) \
(NODE_MAKE_VERSION(major, minor, patch) <= \
NODE_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__))
#else
# define NODE_CLANG_AT_LEAST(major, minor, patch) (0)
#endif

#ifdef __GNUC__
# define NODE_GNUC_AT_LEAST(major, minor, patch) \
(NODE_MAKE_VERSION(major, minor, patch) <= \
NODE_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__))
#else
# define NODE_GNUC_AT_LEAST(major, minor, patch) (0)
#endif

#if NODE_CLANG_AT_LEAST(2, 9, 0) || NODE_GNUC_AT_LEAST(4, 5, 0)
# define NODE_DEPRECATED(message, declarator) \
__attribute__((deprecated(message))) declarator
#elif defined(_MSC_VER)
# define NODE_DEPRECATED(message, declarator) \
__declspec(deprecated) declarator
#else
# define NODE_DEPRECATED(message, declarator) \
declarator
#endif

#endif // SRC_CORE_H_
Loading