|
5 | 5 | #include "util.h"
|
6 | 6 | #include "util-inl.h"
|
7 | 7 |
|
| 8 | +#include "uv.h" |
8 | 9 | #include "v8.h"
|
9 | 10 | #include "v8-profiler.h"
|
10 | 11 |
|
@@ -182,6 +183,38 @@ void AsyncWrap::Initialize(Local<Object> target,
|
182 | 183 | }
|
183 | 184 |
|
184 | 185 |
|
| 186 | +void AsyncWrap::DestroyIdsCb(uv_idle_t* handle) { |
| 187 | + uv_idle_stop(handle); |
| 188 | + |
| 189 | + Environment* env = Environment::from_destroy_ids_idle_handle(handle); |
| 190 | + // None of the V8 calls done outside the HandleScope leak a handle. If this |
| 191 | + // changes in the future then the SealHandleScope wrapping the uv_run() |
| 192 | + // will catch this can cause the process to abort. |
| 193 | + HandleScope handle_scope(env->isolate()); |
| 194 | + Context::Scope context_scope(env->context()); |
| 195 | + Local<Function> fn = env->async_hooks_destroy_function(); |
| 196 | + |
| 197 | + if (fn.IsEmpty()) |
| 198 | + return env->destroy_ids_list()->clear(); |
| 199 | + |
| 200 | + TryCatch try_catch(env->isolate()); |
| 201 | + |
| 202 | + for (auto current_id : *env->destroy_ids_list()) { |
| 203 | + // Want each callback to be cleaned up after itself, instead of cleaning |
| 204 | + // them all up after the while() loop completes. |
| 205 | + HandleScope scope(env->isolate()); |
| 206 | + Local<Value> argv = Number::New(env->isolate(), current_id); |
| 207 | + MaybeLocal<Value> ret = fn->Call( |
| 208 | + env->context(), Undefined(env->isolate()), 1, &argv); |
| 209 | + |
| 210 | + if (ret.IsEmpty()) { |
| 211 | + ClearFatalExceptionHandlers(env); |
| 212 | + FatalException(env->isolate(), try_catch); |
| 213 | + } |
| 214 | + } |
| 215 | +} |
| 216 | + |
| 217 | + |
185 | 218 | void LoadAsyncWrapperInfo(Environment* env) {
|
186 | 219 | HeapProfiler* heap_profiler = env->isolate()->GetHeapProfiler();
|
187 | 220 | #define V(PROVIDER) \
|
@@ -248,18 +281,10 @@ AsyncWrap::~AsyncWrap() {
|
248 | 281 | if (!ran_init_callback())
|
249 | 282 | return;
|
250 | 283 |
|
251 |
| - Local<Function> fn = env()->async_hooks_destroy_function(); |
252 |
| - if (!fn.IsEmpty()) { |
253 |
| - HandleScope scope(env()->isolate()); |
254 |
| - Local<Value> uid = Number::New(env()->isolate(), get_uid()); |
255 |
| - TryCatch try_catch(env()->isolate()); |
256 |
| - MaybeLocal<Value> ret = |
257 |
| - fn->Call(env()->context(), Null(env()->isolate()), 1, &uid); |
258 |
| - if (ret.IsEmpty()) { |
259 |
| - ClearFatalExceptionHandlers(env()); |
260 |
| - FatalException(env()->isolate(), try_catch); |
261 |
| - } |
262 |
| - } |
| 284 | + if (env()->destroy_ids_list()->empty()) |
| 285 | + uv_idle_start(env()->destroy_ids_idle_handle(), DestroyIdsCb); |
| 286 | + |
| 287 | + env()->destroy_ids_list()->push_back(get_uid()); |
263 | 288 | }
|
264 | 289 |
|
265 | 290 |
|
|
0 commit comments