@@ -186,49 +186,41 @@ inline static napi_status ConcludeDeferred(napi_env env,
186
186
}
187
187
188
188
// Wrapper around v8impl::Persistent that implements reference counting.
189
- class Reference : protected Finalizer , RefTracker {
189
+ class RefBase : protected Finalizer , RefTracker {
190
190
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)
198
197
: Finalizer(env, finalize_callback, finalize_data, finalize_hint),
199
- _persistent (env->isolate, value),
200
198
_refcount (initial_refcount),
201
199
_delete_self(delete_self) {
202
- if (initial_refcount == 0 ) {
203
- _persistent.SetWeak (
204
- this , FinalizeCallback, v8::WeakCallbackType::kParameter );
205
- }
206
200
Link (finalize_callback == nullptr
207
201
? &env->reflist
208
202
: &env->finalizing_reflist );
209
203
}
210
204
211
205
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 () {
213
221
return _finalize_data;
214
222
}
215
223
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
-
232
224
// Delete is called in 2 ways. Either from the finalizer or
233
225
// from one of Unwrap or napi_delete_reference.
234
226
//
@@ -244,7 +236,7 @@ class Reference : protected Finalizer, RefTracker {
244
236
// The second way this is called is from
245
237
// the finalizer and _delete_self is set. In this case we
246
238
// know we need to do the deletion so just do it.
247
- static void Delete (Reference * reference) {
239
+ static inline void Delete (RefBase * reference) {
248
240
reference->Unlink ();
249
241
if ((reference->RefCount () != 0 ) ||
250
242
(reference->_delete_self ) ||
@@ -257,40 +249,23 @@ class Reference : protected Finalizer, RefTracker {
257
249
}
258
250
}
259
251
260
- uint32_t Ref () {
261
- if (++_refcount == 1 ) {
262
- _persistent.ClearWeak ();
263
- }
264
-
265
- return _refcount;
252
+ inline uint32_t Ref () {
253
+ return ++_refcount;
266
254
}
267
255
268
- uint32_t Unref () {
256
+ inline uint32_t Unref () {
269
257
if (_refcount == 0 ) {
270
258
return 0 ;
271
259
}
272
- if (--_refcount == 0 ) {
273
- _persistent.SetWeak (
274
- this , FinalizeCallback, v8::WeakCallbackType::kParameter );
275
- }
276
-
277
- return _refcount;
260
+ return --_refcount;
278
261
}
279
262
280
- uint32_t RefCount () {
263
+ inline uint32_t RefCount () {
281
264
return _refcount;
282
265
}
283
266
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
-
292
267
protected:
293
- void Finalize (bool is_env_teardown = false ) override {
268
+ inline void Finalize (bool is_env_teardown = false ) override {
294
269
if (_finalize_callback != nullptr ) {
295
270
_env->CallIntoModuleThrow ([&](napi_env env) {
296
271
_finalize_callback (
@@ -310,6 +285,68 @@ class Reference : protected Finalizer, RefTracker {
310
285
}
311
286
}
312
287
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
+
313
350
private:
314
351
// The N-API finalizer callback may make calls into the engine. V8's heap is
315
352
// not in a consistent state during the weak callback, and therefore it does
@@ -332,8 +369,6 @@ class Reference : protected Finalizer, RefTracker {
332
369
}
333
370
334
371
v8impl::Persistent<v8::Value> _persistent;
335
- uint32_t _refcount;
336
- bool _delete_self;
337
372
};
338
373
339
374
class ArrayBufferReference final : public Reference {
@@ -354,7 +389,7 @@ class ArrayBufferReference final : public Reference {
354
389
}
355
390
356
391
private:
357
- void Finalize (bool is_env_teardown) override {
392
+ inline void Finalize (bool is_env_teardown) override {
358
393
if (is_env_teardown) {
359
394
v8::HandleScope handle_scope (_env->isolate );
360
395
v8::Local<v8::Value> ab = Get ();
@@ -3023,9 +3058,19 @@ napi_status napi_set_instance_data(napi_env env,
3023
3058
void * finalize_hint) {
3024
3059
CHECK_ENV (env);
3025
3060
3026
- env->instance_data .data = data;
3027
- env->instance_data .finalize_cb = finalize_cb;
3028
- env->instance_data .hint = finalize_hint;
3061
+ v8impl::RefBase* old_data = static_cast <v8impl::RefBase*>(env->instance_data );
3062
+ if (old_data != nullptr ) {
3063
+ // Our contract so far has been to not finalize any old data there may be.
3064
+ // So we simply delete it.
3065
+ v8impl::RefBase::Delete (old_data);
3066
+ }
3067
+
3068
+ env->instance_data = v8impl::RefBase::New (env,
3069
+ 0 ,
3070
+ true ,
3071
+ finalize_cb,
3072
+ data,
3073
+ finalize_hint);
3029
3074
3030
3075
return napi_clear_last_error (env);
3031
3076
}
@@ -3035,7 +3080,9 @@ napi_status napi_get_instance_data(napi_env env,
3035
3080
CHECK_ENV (env);
3036
3081
CHECK_ARG (env, data);
3037
3082
3038
- *data = env->instance_data .data ;
3083
+ v8impl::RefBase* idata = static_cast <v8impl::RefBase*>(env->instance_data );
3084
+
3085
+ *data = (idata == nullptr ? nullptr : idata->Data ());
3039
3086
3040
3087
return napi_clear_last_error (env);
3041
3088
}
0 commit comments