-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: move CallbackScope to separate cc/h
PR-URL: #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>
- Loading branch information
1 parent
2e99576
commit 36d4a42
Showing
5 changed files
with
185 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#ifndef SRC_CALLBACK_SCOPE_H_ | ||
#define SRC_CALLBACK_SCOPE_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 | ||
|
||
#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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters