Skip to content

Commit 78a36e0

Browse files
trevnorrisMylesBorins
authored andcommitted
async_wrap: unroll unnecessarily DRY code
* Because Emit{Before,After}() will always exit the process if there's an exception there's no need to check a return value. This simplifies the conditions and makes {Pre,Post}CallbackExecution() unnecessary. They have been removed and relevant code has been moved to the respective call sites. Which are: * PromiseHook() never needs to run domains, and without a return value to check place the calls to Emit{Before,After}() on location. * The logic in MakeCallback() is simplified by moving the single calls to Emit{Before,After}() then doing a simpler conditional to check if the domain has been disposed. * Change Domain{Enter,Exit}() to return true if the instance has been disposed. Makes the conditional check in MakeCallback() simpler to reason about. * Add UNREACHABLE() after FatalException() to make sure all error handlers have been cleared and the process really does exit. PR-URL: #14722 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Refael Ackermann <[email protected]>
1 parent 3e73ea8 commit 78a36e0

File tree

3 files changed

+50
-65
lines changed

3 files changed

+50
-65
lines changed

src/async-wrap.cc

+43-59
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static void DestroyIdsCb(uv_timer_t* handle) {
165165
if (ret.IsEmpty()) {
166166
ClearFatalExceptionHandlers(env);
167167
FatalException(env->isolate(), try_catch);
168+
UNREACHABLE();
168169
}
169170
}
170171
} while (!env->destroy_ids_list()->empty());
@@ -218,69 +219,43 @@ bool DomainExit(Environment* env, v8::Local<v8::Object> object) {
218219
}
219220

220221

221-
static bool PreCallbackExecution(AsyncWrap* wrap, bool run_domain_cbs) {
222-
if (wrap->env()->using_domains() && run_domain_cbs) {
223-
bool is_disposed = DomainEnter(wrap->env(), wrap->object());
224-
if (is_disposed)
225-
return false;
226-
}
227-
228-
return AsyncWrap::EmitBefore(wrap->env(), wrap->get_id());
229-
}
230-
231-
232-
bool AsyncWrap::EmitBefore(Environment* env, double async_id) {
222+
void AsyncWrap::EmitBefore(Environment* env, double async_id) {
233223
AsyncHooks* async_hooks = env->async_hooks();
234224

235-
if (async_hooks->fields()[AsyncHooks::kBefore] > 0) {
236-
Local<Value> uid = Number::New(env->isolate(), async_id);
237-
Local<Function> fn = env->async_hooks_before_function();
238-
TryCatch try_catch(env->isolate());
239-
MaybeLocal<Value> ar = fn->Call(
240-
env->context(), Undefined(env->isolate()), 1, &uid);
241-
if (ar.IsEmpty()) {
242-
ClearFatalExceptionHandlers(env);
243-
FatalException(env->isolate(), try_catch);
244-
return false;
245-
}
246-
}
247-
248-
return true;
249-
}
250-
251-
252-
static bool PostCallbackExecution(AsyncWrap* wrap, bool run_domain_cbs) {
253-
if (!AsyncWrap::EmitAfter(wrap->env(), wrap->get_id()))
254-
return false;
225+
if (async_hooks->fields()[AsyncHooks::kBefore] == 0)
226+
return;
255227

256-
if (wrap->env()->using_domains() && run_domain_cbs) {
257-
bool is_disposed = DomainExit(wrap->env(), wrap->object());
258-
if (is_disposed)
259-
return false;
228+
Local<Value> uid = Number::New(env->isolate(), async_id);
229+
Local<Function> fn = env->async_hooks_before_function();
230+
TryCatch try_catch(env->isolate());
231+
MaybeLocal<Value> ar = fn->Call(
232+
env->context(), Undefined(env->isolate()), 1, &uid);
233+
if (ar.IsEmpty()) {
234+
ClearFatalExceptionHandlers(env);
235+
FatalException(env->isolate(), try_catch);
236+
UNREACHABLE();
260237
}
261-
262-
return true;
263238
}
264239

265-
bool AsyncWrap::EmitAfter(Environment* env, double async_id) {
240+
241+
void AsyncWrap::EmitAfter(Environment* env, double async_id) {
266242
AsyncHooks* async_hooks = env->async_hooks();
267243

268-
// If the callback failed then the after() hooks will be called at the end
269-
// of _fatalException().
270-
if (async_hooks->fields()[AsyncHooks::kAfter] > 0) {
271-
Local<Value> uid = Number::New(env->isolate(), async_id);
272-
Local<Function> fn = env->async_hooks_after_function();
273-
TryCatch try_catch(env->isolate());
274-
MaybeLocal<Value> ar = fn->Call(
275-
env->context(), Undefined(env->isolate()), 1, &uid);
276-
if (ar.IsEmpty()) {
277-
ClearFatalExceptionHandlers(env);
278-
FatalException(env->isolate(), try_catch);
279-
return false;
280-
}
281-
}
244+
if (async_hooks->fields()[AsyncHooks::kAfter] == 0)
245+
return;
282246

283-
return true;
247+
// If the user's callback failed then the after() hooks will be called at the
248+
// end of _fatalException().
249+
Local<Value> uid = Number::New(env->isolate(), async_id);
250+
Local<Function> fn = env->async_hooks_after_function();
251+
TryCatch try_catch(env->isolate());
252+
MaybeLocal<Value> ar = fn->Call(
253+
env->context(), Undefined(env->isolate()), 1, &uid);
254+
if (ar.IsEmpty()) {
255+
ClearFatalExceptionHandlers(env);
256+
FatalException(env->isolate(), try_catch);
257+
UNREACHABLE();
258+
}
284259
}
285260

286261
class PromiseWrap : public AsyncWrap {
@@ -373,9 +348,9 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
373348
CHECK_NE(wrap, nullptr);
374349
if (type == PromiseHookType::kBefore) {
375350
env->async_hooks()->push_ids(wrap->get_id(), wrap->get_trigger_id());
376-
PreCallbackExecution(wrap, false);
351+
AsyncWrap::EmitBefore(wrap->env(), wrap->get_id());
377352
} else if (type == PromiseHookType::kAfter) {
378-
PostCallbackExecution(wrap, false);
353+
AsyncWrap::EmitAfter(wrap->env(), wrap->get_id());
379354
if (env->current_async_id() == wrap->get_id()) {
380355
// This condition might not be true if async_hooks was enabled during
381356
// the promise callback execution.
@@ -696,18 +671,27 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
696671
get_id(),
697672
get_trigger_id());
698673

699-
if (!PreCallbackExecution(this, true)) {
674+
// Return v8::Undefined() because returning an empty handle will cause
675+
// ToLocalChecked() to abort.
676+
if (env()->using_domains() && DomainEnter(env(), object())) {
700677
return Undefined(env()->isolate());
701678
}
702679

703-
// Finally... Get to running the user's callback.
680+
// No need to check a return value because the application will exit if an
681+
// exception occurs.
682+
AsyncWrap::EmitBefore(env(), get_id());
683+
704684
MaybeLocal<Value> ret = cb->Call(env()->context(), object(), argc, argv);
705685

706686
if (ret.IsEmpty()) {
707687
return ret;
708688
}
709689

710-
if (!PostCallbackExecution(this, true)) {
690+
AsyncWrap::EmitAfter(env(), get_id());
691+
692+
// Return v8::Undefined() because returning an empty handle will cause
693+
// ToLocalChecked() to abort.
694+
if (env()->using_domains() && DomainExit(env(), object())) {
711695
return Undefined(env()->isolate());
712696
}
713697

src/async-wrap.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ class AsyncWrap : public BaseObject {
113113
double id,
114114
double trigger_id);
115115

116-
static bool EmitBefore(Environment* env, double id);
117-
static bool EmitAfter(Environment* env, double id);
116+
static void EmitBefore(Environment* env, double id);
117+
static void EmitAfter(Environment* env, double id);
118118

119119
inline ProviderType provider_type() const;
120120

@@ -148,6 +148,7 @@ class AsyncWrap : public BaseObject {
148148

149149
void LoadAsyncWrapperInfo(Environment* env);
150150

151+
// Return value is an indicator whether the domain was disposed.
151152
bool DomainEnter(Environment* env, v8::Local<v8::Object> object);
152153
bool DomainExit(Environment* env, v8::Local<v8::Object> object);
153154

src/node.cc

+4-4
Original file line numberDiff line numberDiff line change
@@ -1334,8 +1334,9 @@ MaybeLocal<Value> MakeCallback(Environment* env,
13341334
asyncContext.trigger_async_id);
13351335

13361336
if (asyncContext.async_id != 0) {
1337-
if (!AsyncWrap::EmitBefore(env, asyncContext.async_id))
1338-
return Local<Value>();
1337+
// No need to check a return value because the application will exit if
1338+
// an exception occurs.
1339+
AsyncWrap::EmitBefore(env, asyncContext.async_id);
13391340
}
13401341

13411342
ret = callback->Call(env->context(), recv, argc, argv);
@@ -1348,8 +1349,7 @@ MaybeLocal<Value> MakeCallback(Environment* env,
13481349
}
13491350

13501351
if (asyncContext.async_id != 0) {
1351-
if (!AsyncWrap::EmitAfter(env, asyncContext.async_id))
1352-
return Local<Value>();
1352+
AsyncWrap::EmitAfter(env, asyncContext.async_id);
13531353
}
13541354
}
13551355

0 commit comments

Comments
 (0)