@@ -186,49 +186,41 @@ inline static napi_status ConcludeDeferred(napi_env env,
186186}
187187
188188// Wrapper around v8impl::Persistent that implements reference counting.
189- class Reference : protected Finalizer , RefTracker {
189+ class RefBase : protected Finalizer , RefTracker {
190190 protected:
191- Reference (napi_env env,
192- v8::Local<v8::Value> value,
193- uint32_t initial_refcount,
194- bool delete_self,
195- napi_finalize finalize_callback,
196- void * finalize_data,
197- void * finalize_hint)
191+ RefBase (napi_env env,
192+ uint32_t initial_refcount,
193+ bool delete_self,
194+ napi_finalize finalize_callback,
195+ void * finalize_data,
196+ void * finalize_hint)
198197 : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
199- _persistent (env->isolate, value),
200198 _refcount (initial_refcount),
201199 _delete_self(delete_self) {
202- if (initial_refcount == 0 ) {
203- _persistent.SetWeak (
204- this , FinalizeCallback, v8::WeakCallbackType::kParameter );
205- }
206200 Link (finalize_callback == nullptr
207201 ? &env->reflist
208202 : &env->finalizing_reflist );
209203 }
210204
211205 public:
212- void * Data () {
206+ static RefBase* New (napi_env env,
207+ uint32_t initial_refcount,
208+ bool delete_self,
209+ napi_finalize finalize_callback,
210+ void * finalize_data,
211+ void * finalize_hint) {
212+ return new RefBase (env,
213+ initial_refcount,
214+ delete_self,
215+ finalize_callback,
216+ finalize_data,
217+ finalize_hint);
218+ }
219+
220+ inline void * Data () {
213221 return _finalize_data;
214222 }
215223
216- static Reference* New (napi_env env,
217- v8::Local<v8::Value> value,
218- uint32_t initial_refcount,
219- bool delete_self,
220- napi_finalize finalize_callback = nullptr ,
221- void * finalize_data = nullptr ,
222- void * finalize_hint = nullptr ) {
223- return new Reference (env,
224- value,
225- initial_refcount,
226- delete_self,
227- finalize_callback,
228- finalize_data,
229- finalize_hint);
230- }
231-
232224 // Delete is called in 2 ways. Either from the finalizer or
233225 // from one of Unwrap or napi_delete_reference.
234226 //
@@ -244,7 +236,7 @@ class Reference : protected Finalizer, RefTracker {
244236 // The second way this is called is from
245237 // the finalizer and _delete_self is set. In this case we
246238 // know we need to do the deletion so just do it.
247- static void Delete (Reference * reference) {
239+ static inline void Delete (RefBase * reference) {
248240 reference->Unlink ();
249241 if ((reference->RefCount () != 0 ) ||
250242 (reference->_delete_self ) ||
@@ -257,40 +249,23 @@ class Reference : protected Finalizer, RefTracker {
257249 }
258250 }
259251
260- uint32_t Ref () {
261- if (++_refcount == 1 ) {
262- _persistent.ClearWeak ();
263- }
264-
265- return _refcount;
252+ inline uint32_t Ref () {
253+ return ++_refcount;
266254 }
267255
268- uint32_t Unref () {
256+ inline uint32_t Unref () {
269257 if (_refcount == 0 ) {
270258 return 0 ;
271259 }
272- if (--_refcount == 0 ) {
273- _persistent.SetWeak (
274- this , FinalizeCallback, v8::WeakCallbackType::kParameter );
275- }
276-
277- return _refcount;
260+ return --_refcount;
278261 }
279262
280- uint32_t RefCount () {
263+ inline uint32_t RefCount () {
281264 return _refcount;
282265 }
283266
284- v8::Local<v8::Value> Get () {
285- if (_persistent.IsEmpty ()) {
286- return v8::Local<v8::Value>();
287- } else {
288- return v8::Local<v8::Value>::New (_env->isolate , _persistent);
289- }
290- }
291-
292267 protected:
293- void Finalize (bool is_env_teardown = false ) override {
268+ inline void Finalize (bool is_env_teardown = false ) override {
294269 if (_finalize_callback != nullptr ) {
295270 _env->CallIntoModuleThrow ([&](napi_env env) {
296271 _finalize_callback (
@@ -310,6 +285,68 @@ class Reference : protected Finalizer, RefTracker {
310285 }
311286 }
312287
288+ private:
289+ uint32_t _refcount;
290+ bool _delete_self;
291+ };
292+
293+ class Reference : public RefBase {
294+ protected:
295+ template <typename ... Args>
296+ Reference (napi_env env,
297+ v8::Local<v8::Value> value,
298+ Args&&... args)
299+ : RefBase(env, std::forward<Args>(args)...),
300+ _persistent (env->isolate, value) {
301+ if (RefCount () == 0 ) {
302+ _persistent.SetWeak (
303+ this , FinalizeCallback, v8::WeakCallbackType::kParameter );
304+ }
305+ }
306+
307+ public:
308+ static inline Reference* New (napi_env env,
309+ v8::Local<v8::Value> value,
310+ uint32_t initial_refcount,
311+ bool delete_self,
312+ napi_finalize finalize_callback = nullptr ,
313+ void * finalize_data = nullptr ,
314+ void * finalize_hint = nullptr ) {
315+ return new Reference (env,
316+ value,
317+ initial_refcount,
318+ delete_self,
319+ finalize_callback,
320+ finalize_data,
321+ finalize_hint);
322+ }
323+
324+ inline uint32_t Ref () {
325+ uint32_t refcount = RefBase::Ref ();
326+ if (refcount == 1 ) {
327+ _persistent.ClearWeak ();
328+ }
329+ return refcount;
330+ }
331+
332+ inline uint32_t Unref () {
333+ uint32_t old_refcount = RefCount ();
334+ uint32_t refcount = RefBase::Unref ();
335+ if (old_refcount == 1 && refcount == 0 ) {
336+ _persistent.SetWeak (
337+ this , FinalizeCallback, v8::WeakCallbackType::kParameter );
338+ }
339+ return refcount;
340+ }
341+
342+ inline v8::Local<v8::Value> Get () {
343+ if (_persistent.IsEmpty ()) {
344+ return v8::Local<v8::Value>();
345+ } else {
346+ return v8::Local<v8::Value>::New (_env->isolate , _persistent);
347+ }
348+ }
349+
313350 private:
314351 // The N-API finalizer callback may make calls into the engine. V8's heap is
315352 // not in a consistent state during the weak callback, and therefore it does
@@ -332,8 +369,6 @@ class Reference : protected Finalizer, RefTracker {
332369 }
333370
334371 v8impl::Persistent<v8::Value> _persistent;
335- uint32_t _refcount;
336- bool _delete_self;
337372};
338373
339374class ArrayBufferReference final : public Reference {
@@ -354,7 +389,7 @@ class ArrayBufferReference final : public Reference {
354389 }
355390
356391 private:
357- void Finalize (bool is_env_teardown) override {
392+ inline void Finalize (bool is_env_teardown) override {
358393 if (is_env_teardown) {
359394 v8::HandleScope handle_scope (_env->isolate );
360395 v8::Local<v8::Value> ab = Get ();
@@ -3101,9 +3136,19 @@ napi_status napi_set_instance_data(napi_env env,
31013136 void * finalize_hint) {
31023137 CHECK_ENV (env);
31033138
3104- env->instance_data .data = data;
3105- env->instance_data .finalize_cb = finalize_cb;
3106- env->instance_data .hint = finalize_hint;
3139+ v8impl::RefBase* old_data = static_cast <v8impl::RefBase*>(env->instance_data );
3140+ if (old_data != nullptr ) {
3141+ // Our contract so far has been to not finalize any old data there may be.
3142+ // So we simply delete it.
3143+ v8impl::RefBase::Delete (old_data);
3144+ }
3145+
3146+ env->instance_data = v8impl::RefBase::New (env,
3147+ 0 ,
3148+ true ,
3149+ finalize_cb,
3150+ data,
3151+ finalize_hint);
31073152
31083153 return napi_clear_last_error (env);
31093154}
@@ -3113,7 +3158,9 @@ napi_status napi_get_instance_data(napi_env env,
31133158 CHECK_ENV (env);
31143159 CHECK_ARG (env, data);
31153160
3116- *data = env->instance_data .data ;
3161+ v8impl::RefBase* idata = static_cast <v8impl::RefBase*>(env->instance_data );
3162+
3163+ *data = (idata == nullptr ? nullptr : idata->Data ());
31173164
31183165 return napi_clear_last_error (env);
31193166}
0 commit comments