diff --git a/src/env-inl.h b/src/env-inl.h index 956153bb965f44..4b6f147f64778c 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -541,8 +541,15 @@ Environment::scheduled_immediate_count() { return scheduled_immediate_count_; } -void Environment::SetImmediate(native_immediate_callback cb, void* data) { - native_immediate_callbacks_.push_back({ cb, data }); +void Environment::SetImmediate(native_immediate_callback cb, + void* data, + v8::Local obj) { + native_immediate_callbacks_.push_back({ + cb, + data, + std::unique_ptr>( + obj.IsEmpty() ? nullptr : new v8::Persistent(isolate_, obj)) + }); if (scheduled_immediate_count_[0] == 0) ActivateImmediateCheck(); scheduled_immediate_count_[0] = scheduled_immediate_count_[0] + 1; diff --git a/src/env.cc b/src/env.cc index 8c3b43d2102cb1..e105fcd7c57ef1 100644 --- a/src/env.cc +++ b/src/env.cc @@ -224,6 +224,8 @@ void Environment::RunAndClearNativeImmediates() { native_immediate_callbacks_.swap(list); for (const auto& cb : list) { cb.cb_(this, cb.data_); + if (cb.keep_alive_) + cb.keep_alive_->Reset(); } #ifdef DEBUG diff --git a/src/env.h b/src/env.h index 6113e6d2de26ea..0d231ba447da3e 100644 --- a/src/env.h +++ b/src/env.h @@ -686,7 +686,11 @@ class Environment { bool EmitNapiWarning(); typedef void (*native_immediate_callback)(Environment* env, void* data); - inline void SetImmediate(native_immediate_callback cb, void* data); + // cb will be called as cb(env, data) on the next event loop iteration. + // obj will be kept alive between now and after the callback has run. + inline void SetImmediate(native_immediate_callback cb, + void* data, + v8::Local obj = v8::Local()); // This needs to be available for the JS-land setImmediate(). void ActivateImmediateCheck(); @@ -754,6 +758,7 @@ class Environment { struct NativeImmediateCallback { native_immediate_callback cb_; void* data_; + std::unique_ptr> keep_alive_; }; std::vector native_immediate_callbacks_; void RunAndClearNativeImmediates();