@@ -134,6 +134,48 @@ RetainedObjectInfo* WrapperInfo(uint16_t class_id, Local<Value> wrapper) {
134134// end RetainedAsyncInfo
135135
136136
137+ static void DestroyIdsCb (uv_idle_t * handle) {
138+ uv_idle_stop (handle);
139+
140+ Environment* env = Environment::from_destroy_ids_idle_handle (handle);
141+
142+ HandleScope handle_scope (env->isolate ());
143+ Context::Scope context_scope (env->context ());
144+ Local<Function> fn = env->async_hooks_destroy_function ();
145+
146+ TryCatch try_catch (env->isolate ());
147+
148+ std::vector<double > destroy_ids_list;
149+ destroy_ids_list.swap (*env->destroy_ids_list ());
150+ for (auto current_id : destroy_ids_list) {
151+ // Want each callback to be cleaned up after itself, instead of cleaning
152+ // them all up after the while() loop completes.
153+ HandleScope scope (env->isolate ());
154+ Local<Value> argv = Number::New (env->isolate (), current_id);
155+ MaybeLocal<Value> ret = fn->Call (
156+ env->context (), Undefined (env->isolate ()), 1 , &argv);
157+
158+ if (ret.IsEmpty ()) {
159+ ClearFatalExceptionHandlers (env);
160+ FatalException (env->isolate (), try_catch);
161+ }
162+ }
163+
164+ env->destroy_ids_list ()->clear ();
165+ }
166+
167+
168+ static void PushBackDestroyId (Environment* env, double id) {
169+ if (env->async_hooks ()->fields ()[AsyncHooks::kDestroy ] == 0 )
170+ return ;
171+
172+ if (env->destroy_ids_list ()->empty ())
173+ uv_idle_start (env->destroy_ids_idle_handle (), DestroyIdsCb);
174+
175+ env->destroy_ids_list ()->push_back (id);
176+ }
177+
178+
137179static void SetupHooks (const FunctionCallbackInfo<Value>& args) {
138180 Environment* env = Environment::GetCurrent (args);
139181
@@ -170,6 +212,42 @@ void AsyncWrap::GetAsyncId(const FunctionCallbackInfo<Value>& args) {
170212}
171213
172214
215+ void AsyncWrap::PushAsyncIds (const FunctionCallbackInfo<Value>& args) {
216+ Environment* env = Environment::GetCurrent (args);
217+ // No need for CHECK(IsNumber()) on args because if FromJust() doesn't fail
218+ // then the checks in push_ids() and pop_ids() will.
219+ double async_id = args[0 ]->NumberValue (env->context ()).FromJust ();
220+ double trigger_id = args[1 ]->NumberValue (env->context ()).FromJust ();
221+ env->async_hooks ()->push_ids (async_id, trigger_id);
222+ }
223+
224+
225+ void AsyncWrap::PopAsyncIds (const FunctionCallbackInfo<Value>& args) {
226+ Environment* env = Environment::GetCurrent (args);
227+ double async_id = args[0 ]->NumberValue (env->context ()).FromJust ();
228+ args.GetReturnValue ().Set (env->async_hooks ()->pop_ids (async_id));
229+ }
230+
231+
232+ void AsyncWrap::ClearIdStack (const FunctionCallbackInfo<Value>& args) {
233+ Environment* env = Environment::GetCurrent (args);
234+ env->async_hooks ()->clear_id_stack ();
235+ }
236+
237+
238+ void AsyncWrap::AsyncReset (const FunctionCallbackInfo<Value>& args) {
239+ AsyncWrap* wrap;
240+ ASSIGN_OR_RETURN_UNWRAP (&wrap, args.Holder ());
241+ wrap->AsyncReset ();
242+ }
243+
244+
245+ void AsyncWrap::QueueDestroyId (const FunctionCallbackInfo<Value>& args) {
246+ CHECK (args[0 ]->IsNumber ());
247+ PushBackDestroyId (Environment::GetCurrent (args), args[0 ]->NumberValue ());
248+ }
249+
250+
173251void AsyncWrap::Initialize (Local<Object> target,
174252 Local<Value> unused,
175253 Local<Context> context) {
@@ -178,6 +256,10 @@ void AsyncWrap::Initialize(Local<Object> target,
178256 HandleScope scope (isolate);
179257
180258 env->SetMethod (target, " setupHooks" , SetupHooks);
259+ env->SetMethod (target, " pushAsyncIds" , PushAsyncIds);
260+ env->SetMethod (target, " popAsyncIds" , PopAsyncIds);
261+ env->SetMethod (target, " clearIdStack" , ClearIdStack);
262+ env->SetMethod (target, " addIdToDestroyList" , QueueDestroyId);
181263
182264 v8::PropertyAttribute ReadOnlyDontDelete =
183265 static_cast <v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
@@ -252,37 +334,6 @@ void AsyncWrap::Initialize(Local<Object> target,
252334}
253335
254336
255- void AsyncWrap::DestroyIdsCb (uv_idle_t * handle) {
256- uv_idle_stop (handle);
257-
258- Environment* env = Environment::from_destroy_ids_idle_handle (handle);
259-
260- HandleScope handle_scope (env->isolate ());
261- Context::Scope context_scope (env->context ());
262- Local<Function> fn = env->async_hooks_destroy_function ();
263-
264- TryCatch try_catch (env->isolate ());
265-
266- std::vector<double > destroy_ids_list;
267- destroy_ids_list.swap (*env->destroy_ids_list ());
268- for (auto current_id : destroy_ids_list) {
269- // Want each callback to be cleaned up after itself, instead of cleaning
270- // them all up after the while() loop completes.
271- HandleScope scope (env->isolate ());
272- Local<Value> argv = Number::New (env->isolate (), current_id);
273- MaybeLocal<Value> ret = fn->Call (
274- env->context (), Undefined (env->isolate ()), 1 , &argv);
275-
276- if (ret.IsEmpty ()) {
277- ClearFatalExceptionHandlers (env);
278- FatalException (env->isolate (), try_catch);
279- }
280- }
281-
282- env->destroy_ids_list ()->clear ();
283- }
284-
285-
286337void LoadAsyncWrapperInfo (Environment* env) {
287338 HeapProfiler* heap_profiler = env->isolate ()->GetHeapProfiler ();
288339#define V (PROVIDER ) \
@@ -310,21 +361,14 @@ AsyncWrap::AsyncWrap(Environment* env,
310361
311362
312363AsyncWrap::~AsyncWrap () {
313- if (env ()->async_hooks ()->fields ()[AsyncHooks::kDestroy ] == 0 ) {
314- return ;
315- }
316-
317- if (env ()->destroy_ids_list ()->empty ())
318- uv_idle_start (env ()->destroy_ids_idle_handle (), DestroyIdsCb);
319-
320- env ()->destroy_ids_list ()->push_back (get_id ());
364+ PushBackDestroyId (env (), get_id ());
321365}
322366
323367
324368// Generalized call for both the constructor and for handles that are pooled
325369// and reused over their lifetime. This way a new uid can be assigned when
326370// the resource is pulled out of the pool and put back into use.
327- void AsyncWrap::Reset () {
371+ void AsyncWrap::AsyncReset () {
328372 AsyncHooks* async_hooks = env ()->async_hooks ();
329373 async_id_ = env ()->new_async_id ();
330374 trigger_id_ = env ()->get_init_trigger_id ();
0 commit comments