1
+ #include " async_wrap.h"
1
2
#include " env-inl.h"
2
3
#include " node.h"
3
4
#include " node_errors.h"
@@ -16,18 +17,55 @@ using v8::Context;
16
17
using v8::Function;
17
18
using v8::FunctionCallbackInfo;
18
19
using v8::Isolate;
20
+ using v8::Just;
19
21
using v8::kPromiseHandlerAddedAfterReject ;
20
22
using v8::kPromiseRejectAfterResolved ;
21
23
using v8::kPromiseRejectWithNoHandler ;
22
24
using v8::kPromiseResolveAfterResolved ;
23
25
using v8::Local;
26
+ using v8::Maybe;
24
27
using v8::Number;
28
+ using v8::Nothing;
25
29
using v8::Object;
26
30
using v8::Promise;
27
31
using v8::PromiseRejectEvent;
28
32
using v8::PromiseRejectMessage;
29
33
using v8::Value;
30
34
35
+ static Maybe<double > GetAssignedPromiseAsyncId (Environment* env,
36
+ Local<Promise> promise,
37
+ Local<Value> id_symbol) {
38
+ Local<Value> maybe_async_id;
39
+ if (!promise->Get (env->context (), id_symbol).ToLocal (&maybe_async_id)) {
40
+ return Nothing<double >();
41
+ }
42
+ return maybe_async_id->IsNumber ()
43
+ ? maybe_async_id->NumberValue (env->context ())
44
+ : v8::Just (AsyncWrap::kInvalidAsyncId );
45
+ }
46
+
47
+ static Maybe<double > GetAssignedPromiseWrapAsyncId (Environment* env,
48
+ Local<Promise> promise,
49
+ Local<Value> id_symbol) {
50
+ // This check is imperfect. If the internal field is set, it should
51
+ // be an object. If it's not, we just ignore it. Ideally v8 would
52
+ // have had GetInternalField returning a MaybeLocal but this works
53
+ // for now.
54
+ Local<Value> promiseWrap = promise->GetInternalField (0 );
55
+ if (promiseWrap->IsObject ()) {
56
+ Local<Value> maybe_async_id;
57
+ if (!promiseWrap.As <Object>()->Get (env->context (), id_symbol).ToLocal (&maybe_async_id)) {
58
+ return Nothing<double >();
59
+ }
60
+ return maybe_async_id->IsNumber ()
61
+ ? maybe_async_id->NumberValue (env->context ())
62
+ : v8::Just (AsyncWrap::kInvalidAsyncId );
63
+ }
64
+ else {
65
+ return Nothing<double >();
66
+ }
67
+ }
68
+
31
69
void PromiseRejectCallback (PromiseRejectMessage message) {
32
70
static std::atomic<uint64_t > unhandledRejections{0 };
33
71
static std::atomic<uint64_t > rejectionsHandledAfter{0 };
@@ -76,12 +114,39 @@ void PromiseRejectCallback(PromiseRejectMessage message) {
76
114
77
115
Local<Value> args[] = { type, promise, value };
78
116
79
- // V8 does not expect this callback to have a scheduled exceptions once it
80
- // returns, so we print them out in a best effort to do something about it
81
- // without failing silently and without crashing the process.
117
+ double async_id = AsyncWrap::kInvalidAsyncId ;
118
+ double trigger_async_id = AsyncWrap::kInvalidAsyncId ;
119
+ GetAssignedPromiseAsyncId (env, promise, env->async_id_symbol ())
120
+ .To (&async_id);
121
+ GetAssignedPromiseAsyncId (env, promise, env->trigger_async_id_symbol ())
122
+ .To (&trigger_async_id);
123
+
124
+ GetAssignedPromiseWrapAsyncId (env, promise, env->async_id_symbol ())
125
+ .To (&async_id);
126
+ GetAssignedPromiseWrapAsyncId (env, promise, env->trigger_async_id_symbol ())
127
+ .To (&trigger_async_id);
128
+
129
+ if (async_id != AsyncWrap::kInvalidAsyncId &&
130
+ trigger_async_id != AsyncWrap::kInvalidAsyncId ) {
131
+ env->async_hooks ()->push_async_context (
132
+ async_id, trigger_async_id, promise);
133
+ }
134
+
82
135
TryCatchScope try_catch (env);
83
136
USE (callback->Call (
84
137
env->context (), Undefined (isolate), arraysize (args), args));
138
+
139
+ if (async_id != AsyncWrap::kInvalidAsyncId &&
140
+ trigger_async_id != AsyncWrap::kInvalidAsyncId &&
141
+ env->execution_async_id () == async_id) {
142
+ // This condition might not be true if async_hooks was enabled during
143
+ // the promise callback execution.
144
+ env->async_hooks ()->pop_async_context (async_id);
145
+ }
146
+
147
+ // V8 does not expect this callback to have a scheduled exceptions once it
148
+ // returns, so we print them out in a best effort to do something about it
149
+ // without failing silently and without crashing the process.
85
150
if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
86
151
fprintf (stderr, " Exception in PromiseRejectCallback:\n " );
87
152
PrintCaughtException (isolate, env->context (), try_catch);
0 commit comments