@@ -134,43 +134,38 @@ napi_status NewExternalString(napi_env env,
134
134
return status;
135
135
}
136
136
137
- class TrackedStringResource : public Finalizer , RefTracker {
137
+ class TrackedStringResource : private RefTracker {
138
138
public:
139
139
TrackedStringResource (napi_env env,
140
140
napi_finalize finalize_callback,
141
141
void * data,
142
142
void * finalize_hint)
143
- : Finalizer (env, finalize_callback, data, finalize_hint) {
143
+ : RefTracker(), finalizer_ (env, finalize_callback, data, finalize_hint) {
144
144
Link (finalize_callback == nullptr ? &env->reflist
145
145
: &env->finalizing_reflist );
146
146
}
147
147
148
148
protected:
149
- // The only time Finalize() gets called before Dispose() is if the
149
+ // The only time Finalize() gets called before destructor is if the
150
150
// environment is dying. Finalize() expects that the item will be unlinked,
151
- // so we do it here. V8 will still call Dispose() on us later, so we don't do
152
- // any deleting here. We just null out env_ to avoid passing a stale pointer
153
- // to the user's finalizer when V8 does finally call Dispose() .
151
+ // so we do it here. V8 will still call destructor on us later, so we don't do
152
+ // any deleting here. We just null out env to avoid passing a stale pointer
153
+ // to the user's finalizer when V8 does finally call destructor .
154
154
void Finalize () override {
155
155
Unlink ();
156
- env_ = nullptr ;
156
+ finalizer_. ResetEnv () ;
157
157
}
158
158
159
- ~TrackedStringResource () {
160
- if (finalize_callback_ == nullptr ) return ;
161
- if (env_ == nullptr ) {
162
- // The environment is dead. Call the finalizer directly.
163
- finalize_callback_ (nullptr , finalize_data_, finalize_hint_);
164
- } else {
165
- // The environment is still alive. Let's remove ourselves from its list
166
- // of references and call the user's finalizer.
167
- Unlink ();
168
- env_->CallFinalizer (finalize_callback_, finalize_data_, finalize_hint_);
169
- }
159
+ ~TrackedStringResource () override {
160
+ Unlink ();
161
+ finalizer_.CallFinalizer ();
170
162
}
163
+
164
+ private:
165
+ Finalizer finalizer_;
171
166
};
172
167
173
- class ExternalOneByteStringResource
168
+ class ExternalOneByteStringResource final
174
169
: public v8::String::ExternalOneByteStringResource,
175
170
TrackedStringResource {
176
171
public:
@@ -191,8 +186,8 @@ class ExternalOneByteStringResource
191
186
const size_t length_;
192
187
};
193
188
194
- class ExternalStringResource : public v8 ::String::ExternalStringResource,
195
- TrackedStringResource {
189
+ class ExternalStringResource final : public v8::String::ExternalStringResource,
190
+ TrackedStringResource {
196
191
public:
197
192
ExternalStringResource (napi_env env,
198
193
char16_t * string,
@@ -368,7 +363,7 @@ inline napi_status Unwrap(napi_env env,
368
363
if (action == RemoveWrap) {
369
364
CHECK (obj->DeletePrivate (context, NAPI_PRIVATE_KEY (context, wrapper))
370
365
.FromJust ());
371
- if (reference->ownership () == Ownership ::kUserland ) {
366
+ if (reference->ownership () == ReferenceOwnership ::kUserland ) {
372
367
// When the wrap is been removed, the finalizer should be reset.
373
368
reference->ResetFinalizer ();
374
369
} else {
@@ -400,10 +395,16 @@ class CallbackBundle {
400
395
bundle->env = env;
401
396
402
397
v8::Local<v8::Value> cbdata = v8::External::New (env->isolate , bundle);
403
- Reference ::New (
404
- env, cbdata, 0 , Ownership ::kRuntime , Delete, bundle, nullptr );
398
+ ReferenceWithFinalizer ::New (
399
+ env, cbdata, 0 , ReferenceOwnership ::kRuntime , Delete, bundle, nullptr );
405
400
return cbdata;
406
401
}
402
+
403
+ static CallbackBundle* FromCallbackData (v8::Local<v8::Value> data) {
404
+ return reinterpret_cast <CallbackBundle*>(data.As <v8::External>()->Value ());
405
+ }
406
+
407
+ public:
407
408
napi_env env; // Necessary to invoke C++ NAPI callback
408
409
void * cb_data; // The user provided callback data
409
410
napi_callback cb;
@@ -415,71 +416,9 @@ class CallbackBundle {
415
416
}
416
417
};
417
418
418
- // Base class extended by classes that wrap V8 function and property callback
419
- // info.
420
- class CallbackWrapper {
421
- public:
422
- inline CallbackWrapper (napi_value this_arg, size_t args_length, void * data)
423
- : _this(this_arg), _args_length(args_length), _data(data) {}
424
-
425
- virtual napi_value GetNewTarget () = 0;
426
- virtual void Args (napi_value* buffer, size_t bufferlength) = 0;
427
- virtual void SetReturnValue (napi_value value) = 0;
428
-
429
- napi_value This () { return _this; }
430
-
431
- size_t ArgsLength () { return _args_length; }
432
-
433
- void * Data () { return _data; }
434
-
435
- protected:
436
- const napi_value _this;
437
- const size_t _args_length;
438
- void * _data;
439
- };
440
-
441
- class CallbackWrapperBase : public CallbackWrapper {
442
- public:
443
- inline CallbackWrapperBase (const v8::FunctionCallbackInfo<v8::Value>& cbinfo,
444
- const size_t args_length)
445
- : CallbackWrapper(
446
- JsValueFromV8LocalValue (cbinfo.This()), args_length, nullptr),
447
- _cbinfo(cbinfo) {
448
- _bundle = reinterpret_cast <CallbackBundle*>(
449
- cbinfo.Data ().As <v8::External>()->Value ());
450
- _data = _bundle->cb_data ;
451
- }
452
-
453
- protected:
454
- inline void InvokeCallback () {
455
- napi_callback_info cbinfo_wrapper = reinterpret_cast <napi_callback_info>(
456
- static_cast <CallbackWrapper*>(this ));
457
-
458
- // All other pointers we need are stored in `_bundle`
459
- napi_env env = _bundle->env ;
460
- napi_callback cb = _bundle->cb ;
461
-
462
- napi_value result = nullptr ;
463
- bool exceptionOccurred = false ;
464
- env->CallIntoModule ([&](napi_env env) { result = cb (env, cbinfo_wrapper); },
465
- [&](napi_env env, v8::Local<v8::Value> value) {
466
- exceptionOccurred = true ;
467
- if (env->terminatedOrTerminating ()) {
468
- return ;
469
- }
470
- env->isolate ->ThrowException (value);
471
- });
472
-
473
- if (!exceptionOccurred && (result != nullptr )) {
474
- this ->SetReturnValue (result);
475
- }
476
- }
477
-
478
- const v8::FunctionCallbackInfo<v8::Value>& _cbinfo;
479
- CallbackBundle* _bundle;
480
- };
481
-
482
- class FunctionCallbackWrapper : public CallbackWrapperBase {
419
+ // Wraps up v8::FunctionCallbackInfo.
420
+ // The class must be stack allocated.
421
+ class FunctionCallbackWrapper {
483
422
public:
484
423
static void Invoke (const v8::FunctionCallbackInfo<v8::Value>& info) {
485
424
FunctionCallbackWrapper cbwrapper (info);
@@ -514,41 +453,70 @@ class FunctionCallbackWrapper : public CallbackWrapperBase {
514
453
return napi_clear_last_error (env);
515
454
}
516
455
517
- explicit FunctionCallbackWrapper (
518
- const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
519
- : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
520
-
521
- napi_value GetNewTarget () override {
522
- if (_cbinfo.IsConstructCall ()) {
523
- return v8impl::JsValueFromV8LocalValue (_cbinfo.NewTarget ());
456
+ napi_value GetNewTarget () {
457
+ if (cbinfo_.IsConstructCall ()) {
458
+ return v8impl::JsValueFromV8LocalValue (cbinfo_.NewTarget ());
524
459
} else {
525
460
return nullptr ;
526
461
}
527
462
}
528
463
529
- /* virtual*/
530
- void Args (napi_value* buffer, size_t buffer_length) override {
464
+ void Args (napi_value* buffer, size_t buffer_length) {
531
465
size_t i = 0 ;
532
- size_t min = std::min (buffer_length, _args_length );
466
+ size_t min_arg_count = std::min (buffer_length, ArgsLength () );
533
467
534
- for (; i < min; i += 1 ) {
535
- buffer[i] = v8impl:: JsValueFromV8LocalValue (_cbinfo [i]);
468
+ for (; i < min_arg_count; ++i ) {
469
+ buffer[i] = JsValueFromV8LocalValue (cbinfo_ [i]);
536
470
}
537
471
538
472
if (i < buffer_length) {
539
473
napi_value undefined =
540
- v8impl:: JsValueFromV8LocalValue (v8::Undefined (_cbinfo .GetIsolate ()));
541
- for (; i < buffer_length; i += 1 ) {
474
+ JsValueFromV8LocalValue (v8::Undefined (cbinfo_ .GetIsolate ()));
475
+ for (; i < buffer_length; ++i ) {
542
476
buffer[i] = undefined;
543
477
}
544
478
}
545
479
}
546
480
547
- /* virtual*/
548
- void SetReturnValue (napi_value value) override {
549
- v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue (value);
550
- _cbinfo.GetReturnValue ().Set (val);
481
+ napi_value This () { return JsValueFromV8LocalValue (cbinfo_.This ()); }
482
+
483
+ size_t ArgsLength () { return static_cast <size_t >(cbinfo_.Length ()); }
484
+
485
+ void * Data () { return bundle_->cb_data ; }
486
+
487
+ private:
488
+ explicit FunctionCallbackWrapper (
489
+ const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
490
+ : cbinfo_(cbinfo),
491
+ bundle_(CallbackBundle::FromCallbackData(cbinfo.Data())) {}
492
+
493
+ void InvokeCallback () {
494
+ napi_callback_info cbinfo_wrapper =
495
+ reinterpret_cast <napi_callback_info>(this );
496
+
497
+ // All other pointers we need are stored in `_bundle`
498
+ napi_env env = bundle_->env ;
499
+ napi_callback cb = bundle_->cb ;
500
+
501
+ napi_value result = nullptr ;
502
+ bool exceptionOccurred = false ;
503
+ env->CallIntoModule ([&](napi_env env) { result = cb (env, cbinfo_wrapper); },
504
+ [&](napi_env env, v8::Local<v8::Value> value) {
505
+ exceptionOccurred = true ;
506
+ if (env->terminatedOrTerminating ()) {
507
+ return ;
508
+ }
509
+ env->isolate ->ThrowException (value);
510
+ });
511
+
512
+ if (!exceptionOccurred && (result != nullptr )) {
513
+ cbinfo_.GetReturnValue ().Set (V8LocalValueFromJsValue (result));
514
+ }
551
515
}
516
+
517
+ private:
518
+ const v8::FunctionCallbackInfo<v8::Value>& cbinfo_;
519
+ CallbackBundle* bundle_;
552
520
};
553
521
554
522
inline napi_status Wrap (napi_env env,
@@ -579,24 +547,29 @@ inline napi_status Wrap(napi_env env,
579
547
// before then, then the finalize callback will never be invoked.)
580
548
// Therefore a finalize callback is required when returning a reference.
581
549
CHECK_ARG (env, finalize_cb);
582
- reference = v8impl::Reference::New (env,
583
- obj,
584
- 0 ,
585
- v8impl::Ownership::kUserland ,
586
- finalize_cb,
587
- native_object,
588
- finalize_hint);
550
+ reference = v8impl::ReferenceWithFinalizer::New (
551
+ env,
552
+ obj,
553
+ 0 ,
554
+ v8impl::ReferenceOwnership::kUserland ,
555
+ finalize_cb,
556
+ native_object,
557
+ finalize_hint);
589
558
*result = reinterpret_cast <napi_ref>(reference);
590
- } else {
559
+ } else if (finalize_cb != nullptr ) {
591
560
// Create a self-deleting reference.
592
- reference = v8impl::Reference ::New (
561
+ reference = v8impl::ReferenceWithFinalizer ::New (
593
562
env,
594
563
obj,
595
564
0 ,
596
- v8impl::Ownership ::kRuntime ,
565
+ v8impl::ReferenceOwnership ::kRuntime ,
597
566
finalize_cb,
598
567
native_object,
599
- finalize_cb == nullptr ? nullptr : finalize_hint);
568
+ finalize_hint);
569
+ } else {
570
+ // Create a self-deleting reference.
571
+ reference = v8impl::ReferenceWithData::New (
572
+ env, obj, 0 , v8impl::ReferenceOwnership::kRuntime , native_object);
600
573
}
601
574
602
575
CHECK (obj->SetPrivate (context,
@@ -621,27 +594,46 @@ inline bool CanBeHeldWeakly(v8::Local<v8::Value> value) {
621
594
622
595
} // end of anonymous namespace
623
596
597
+ void Finalizer::ResetEnv () {
598
+ env_ = nullptr ;
599
+ }
600
+
624
601
void Finalizer::ResetFinalizer () {
625
602
finalize_callback_ = nullptr ;
626
603
finalize_data_ = nullptr ;
627
604
finalize_hint_ = nullptr ;
628
605
}
629
606
607
+ void Finalizer::CallFinalizer () {
608
+ napi_finalize finalize_callback = finalize_callback_;
609
+ void * finalize_data = finalize_data_;
610
+ void * finalize_hint = finalize_hint_;
611
+ ResetFinalizer ();
612
+
613
+ if (finalize_callback == nullptr ) return ;
614
+ if (env_ == nullptr ) {
615
+ // The environment is dead. Call the finalizer directly.
616
+ finalize_callback (nullptr , finalize_data, finalize_hint);
617
+ } else {
618
+ env_->CallFinalizer (finalize_callback, finalize_data, finalize_hint);
619
+ }
620
+ }
621
+
630
622
TrackedFinalizer::TrackedFinalizer (napi_env env,
631
623
napi_finalize finalize_callback,
632
624
void * finalize_data,
633
625
void * finalize_hint)
634
- : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
635
- RefTracker() {
636
- Link (finalize_callback == nullptr ? &env->reflist : &env->finalizing_reflist );
637
- }
626
+ : RefTracker(),
627
+ finalizer_(env, finalize_callback, finalize_data, finalize_hint) {}
638
628
639
629
TrackedFinalizer* TrackedFinalizer::New (napi_env env,
640
630
napi_finalize finalize_callback,
641
631
void * finalize_data,
642
632
void * finalize_hint) {
643
- return new TrackedFinalizer (
633
+ TrackedFinalizer* finalizer = new TrackedFinalizer (
644
634
env, finalize_callback, finalize_data, finalize_hint);
635
+ finalizer->Link (&env->finalizing_reflist );
636
+ return finalizer;
645
637
}
646
638
647
639
// When a TrackedFinalizer is being deleted, it may have been queued to call its
@@ -650,115 +642,44 @@ TrackedFinalizer::~TrackedFinalizer() {
650
642
// Remove from the env's tracked list.
651
643
Unlink ();
652
644
// Try to remove the finalizer from the scheduled second pass callback.
653
- env_ ->DequeueFinalizer (this );
645
+ finalizer_. env () ->DequeueFinalizer (this );
654
646
}
655
647
656
648
void TrackedFinalizer::Finalize () {
657
- FinalizeCore (/* deleteMe:*/ true );
658
- }
659
-
660
- void TrackedFinalizer::FinalizeCore (bool deleteMe) {
661
- // Swap out the field finalize_callback so that it can not be accidentally
662
- // called more than once.
663
- napi_finalize finalize_callback = finalize_callback_;
664
- void * finalize_data = finalize_data_;
665
- void * finalize_hint = finalize_hint_;
666
- ResetFinalizer ();
667
-
668
- // Either the RefBase is going to be deleted in the finalize_callback or not,
669
- // it should be removed from the tracked list.
670
649
Unlink ();
671
- // If the finalize_callback is present, it should either delete the
672
- // derived RefBase, or the RefBase ownership was set to Ownership::kRuntime
673
- // and the deleteMe parameter is true.
674
- if (finalize_callback != nullptr ) {
675
- env_->CallFinalizer (finalize_callback, finalize_data, finalize_hint);
676
- }
677
-
678
- if (deleteMe) {
679
- delete this ;
680
- }
681
- }
682
-
683
- // Wrapper around v8impl::Persistent that implements reference counting.
684
- RefBase::RefBase (napi_env env,
685
- uint32_t initial_refcount,
686
- Ownership ownership,
687
- napi_finalize finalize_callback,
688
- void * finalize_data,
689
- void * finalize_hint)
690
- : TrackedFinalizer(env, finalize_callback, finalize_data, finalize_hint),
691
- refcount_(initial_refcount),
692
- ownership_(ownership) {}
693
-
694
- RefBase* RefBase::New (napi_env env,
695
- uint32_t initial_refcount,
696
- Ownership ownership,
697
- napi_finalize finalize_callback,
698
- void * finalize_data,
699
- void * finalize_hint) {
700
- return new RefBase (env,
701
- initial_refcount,
702
- ownership,
703
- finalize_callback,
704
- finalize_data,
705
- finalize_hint);
706
- }
707
-
708
- void * RefBase::Data () {
709
- return finalize_data_;
710
- }
711
-
712
- uint32_t RefBase::Ref () {
713
- return ++refcount_;
714
- }
715
-
716
- uint32_t RefBase::Unref () {
717
- if (refcount_ == 0 ) {
718
- return 0 ;
719
- }
720
- return --refcount_;
650
+ finalizer_.CallFinalizer ();
651
+ delete this ;
721
652
}
722
653
723
- uint32_t RefBase::RefCount () {
724
- return refcount_;
725
- }
726
-
727
- void RefBase::Finalize () {
728
- // If the RefBase is not Ownership::kRuntime, userland code should delete it.
729
- // Delete it if it is Ownership::kRuntime.
730
- FinalizeCore (/* deleteMe:*/ ownership_ == Ownership::kRuntime );
731
- }
732
-
733
- template <typename ... Args>
734
- Reference::Reference (napi_env env, v8::Local<v8::Value> value, Args&&... args)
735
- : RefBase(env, std::forward<Args>(args)...),
654
+ Reference::Reference (napi_env env,
655
+ v8::Local<v8::Value> value,
656
+ uint32_t initial_refcount,
657
+ ReferenceOwnership ownership)
658
+ : RefTracker(),
736
659
persistent_ (env->isolate, value),
660
+ refcount_(initial_refcount),
661
+ ownership_(ownership),
737
662
can_be_weak_(CanBeHeldWeakly(value)) {
738
- if (RefCount () == 0 ) {
663
+ if (refcount_ == 0 ) {
739
664
SetWeak ();
740
665
}
741
666
}
742
667
743
668
Reference::~Reference () {
744
669
// Reset the handle. And no weak callback will be invoked.
745
670
persistent_.Reset ();
671
+
672
+ // Remove from the env's tracked list.
673
+ Unlink ();
746
674
}
747
675
748
676
Reference* Reference::New (napi_env env,
749
677
v8::Local<v8::Value> value,
750
678
uint32_t initial_refcount,
751
- Ownership ownership,
752
- napi_finalize finalize_callback,
753
- void * finalize_data,
754
- void * finalize_hint) {
755
- return new Reference (env,
756
- value,
757
- initial_refcount,
758
- ownership,
759
- finalize_callback,
760
- finalize_data,
761
- finalize_hint);
679
+ ReferenceOwnership ownership) {
680
+ Reference* reference = new Reference (env, value, initial_refcount, ownership);
681
+ reference->Link (&env->reflist );
682
+ return reference;
762
683
}
763
684
764
685
uint32_t Reference::Ref () {
@@ -767,32 +688,29 @@ uint32_t Reference::Ref() {
767
688
if (persistent_.IsEmpty ()) {
768
689
return 0 ;
769
690
}
770
- uint32_t refcount = RefBase::Ref ();
771
- if (refcount == 1 && can_be_weak_) {
691
+ if (++refcount_ == 1 && can_be_weak_) {
772
692
persistent_.ClearWeak ();
773
693
}
774
- return refcount ;
694
+ return refcount_ ;
775
695
}
776
696
777
697
uint32_t Reference::Unref () {
778
698
// When the persistent_ is cleared in the WeakCallback, and a second pass
779
699
// callback is pending, return 0 unconditionally.
780
- if (persistent_.IsEmpty ()) {
700
+ if (persistent_.IsEmpty () || refcount_ == 0 ) {
781
701
return 0 ;
782
702
}
783
- uint32_t old_refcount = RefCount ();
784
- uint32_t refcount = RefBase::Unref ();
785
- if (old_refcount == 1 && refcount == 0 ) {
703
+ if (--refcount_ == 0 ) {
786
704
SetWeak ();
787
705
}
788
- return refcount ;
706
+ return refcount_ ;
789
707
}
790
708
791
- v8::Local<v8::Value> Reference::Get () {
709
+ v8::Local<v8::Value> Reference::Get (napi_env env ) {
792
710
if (persistent_.IsEmpty ()) {
793
711
return v8::Local<v8::Value>();
794
712
} else {
795
- return v8::Local<v8::Value>::New (env_ ->isolate , persistent_);
713
+ return v8::Local<v8::Value>::New (env ->isolate , persistent_);
796
714
}
797
715
}
798
716
@@ -801,12 +719,30 @@ void Reference::Finalize() {
801
719
// be invoked again.
802
720
persistent_.Reset ();
803
721
804
- // Chain up to perform the rest of the finalization.
805
- RefBase::Finalize ();
722
+ // If the Reference is not ReferenceOwnership::kRuntime, userland code should
723
+ // delete it. Delete it if it is ReferenceOwnership::kRuntime.
724
+ bool deleteMe = ownership_ == ReferenceOwnership::kRuntime ;
725
+
726
+ // Whether the Reference is going to be deleted in the finalize_callback
727
+ // or not, it should be removed from the tracked list.
728
+ Unlink ();
729
+
730
+ // If the finalize_callback is present, it should either delete the
731
+ // derived Reference, or the Reference ownership was set to
732
+ // ReferenceOwnership::kRuntime and the deleteMe parameter is true.
733
+ CallUserFinalizer ();
734
+
735
+ if (deleteMe) {
736
+ delete this ;
737
+ }
806
738
}
807
739
808
- // Mark the reference as weak and eligible for collection
809
- // by the gc.
740
+ // Call the Finalize immediately since there is no user finalizer to call.
741
+ void Reference::InvokeFinalizerFromGC () {
742
+ Finalize ();
743
+ }
744
+
745
+ // Mark the reference as weak and eligible for collection by the GC.
810
746
void Reference::SetWeak () {
811
747
if (can_be_weak_) {
812
748
persistent_.SetWeak (this , WeakCallback, v8::WeakCallbackType::kParameter );
@@ -815,14 +751,76 @@ void Reference::SetWeak() {
815
751
}
816
752
}
817
753
818
- // The N-API finalizer callback may make calls into the engine. V8's heap is
819
- // not in a consistent state during the weak callback, and therefore it does
820
- // not support calls back into it. Enqueue the invocation of the finalizer.
754
+ // Static function called by GC. Delegate the call to the reference instance.
821
755
void Reference::WeakCallback (const v8::WeakCallbackInfo<Reference>& data) {
822
756
Reference* reference = data.GetParameter ();
823
- // The reference must be reset during the weak callback as the API protocol.
757
+ // The reference must be reset during the weak callback per V8 API protocol.
824
758
reference->persistent_ .Reset ();
825
- reference->env_ ->InvokeFinalizerFromGC (reference);
759
+ reference->InvokeFinalizerFromGC ();
760
+ }
761
+
762
+ ReferenceWithData* ReferenceWithData::New (napi_env env,
763
+ v8::Local<v8::Value> value,
764
+ uint32_t initial_refcount,
765
+ ReferenceOwnership ownership,
766
+ void * data) {
767
+ ReferenceWithData* reference =
768
+ new ReferenceWithData (env, value, initial_refcount, ownership, data);
769
+ reference->Link (&env->reflist );
770
+ return reference;
771
+ }
772
+
773
+ ReferenceWithData::ReferenceWithData (napi_env env,
774
+ v8::Local<v8::Value> value,
775
+ uint32_t initial_refcount,
776
+ ReferenceOwnership ownership,
777
+ void * data)
778
+ : Reference(env, value, initial_refcount, ownership), data_(data) {}
779
+
780
+ ReferenceWithFinalizer* ReferenceWithFinalizer::New (
781
+ napi_env env,
782
+ v8::Local<v8::Value> value,
783
+ uint32_t initial_refcount,
784
+ ReferenceOwnership ownership,
785
+ napi_finalize finalize_callback,
786
+ void * finalize_data,
787
+ void * finalize_hint) {
788
+ ReferenceWithFinalizer* reference =
789
+ new ReferenceWithFinalizer (env,
790
+ value,
791
+ initial_refcount,
792
+ ownership,
793
+ finalize_callback,
794
+ finalize_data,
795
+ finalize_hint);
796
+ reference->Link (&env->finalizing_reflist );
797
+ return reference;
798
+ }
799
+
800
+ ReferenceWithFinalizer::ReferenceWithFinalizer (napi_env env,
801
+ v8::Local<v8::Value> value,
802
+ uint32_t initial_refcount,
803
+ ReferenceOwnership ownership,
804
+ napi_finalize finalize_callback,
805
+ void * finalize_data,
806
+ void * finalize_hint)
807
+ : Reference(env, value, initial_refcount, ownership),
808
+ finalizer_ (env, finalize_callback, finalize_data, finalize_hint) {}
809
+
810
+ ReferenceWithFinalizer::~ReferenceWithFinalizer () {
811
+ // Try to remove the finalizer from the scheduled second pass callback.
812
+ finalizer_.env ()->DequeueFinalizer (this );
813
+ }
814
+
815
+ void ReferenceWithFinalizer::CallUserFinalizer () {
816
+ finalizer_.CallFinalizer ();
817
+ }
818
+
819
+ // The Node-API finalizer callback may make calls into the engine. V8's heap is
820
+ // not in a consistent state during the weak callback, and therefore it does
821
+ // not support calls back into it. Enqueue the invocation of the finalizer.
822
+ void ReferenceWithFinalizer::InvokeFinalizerFromGC () {
823
+ finalizer_.env ()->InvokeFinalizerFromGC (this );
826
824
}
827
825
828
826
/* *
@@ -2051,8 +2049,8 @@ napi_status NAPI_CDECL napi_get_cb_info(
2051
2049
CHECK_ENV (env);
2052
2050
CHECK_ARG (env, cbinfo);
2053
2051
2054
- v8impl::CallbackWrapper * info =
2055
- reinterpret_cast <v8impl::CallbackWrapper *>(cbinfo);
2052
+ v8impl::FunctionCallbackWrapper * info =
2053
+ reinterpret_cast <v8impl::FunctionCallbackWrapper *>(cbinfo);
2056
2054
2057
2055
if (argv != nullptr ) {
2058
2056
CHECK_ARG (env, argc);
@@ -2078,8 +2076,8 @@ napi_status NAPI_CDECL napi_get_new_target(napi_env env,
2078
2076
CHECK_ARG (env, cbinfo);
2079
2077
CHECK_ARG (env, result);
2080
2078
2081
- v8impl::CallbackWrapper * info =
2082
- reinterpret_cast <v8impl::CallbackWrapper *>(cbinfo);
2079
+ v8impl::FunctionCallbackWrapper * info =
2080
+ reinterpret_cast <v8impl::FunctionCallbackWrapper *>(cbinfo);
2083
2081
2084
2082
*result = info->GetNewTarget ();
2085
2083
return napi_clear_last_error (env);
@@ -2605,13 +2603,13 @@ napi_create_external(napi_env env,
2605
2603
if (finalize_cb) {
2606
2604
// The Reference object will delete itself after invoking the finalizer
2607
2605
// callback.
2608
- v8impl::Reference ::New (env,
2609
- external_value,
2610
- 0 ,
2611
- v8impl::Ownership ::kRuntime ,
2612
- finalize_cb,
2613
- data,
2614
- finalize_hint);
2606
+ v8impl::ReferenceWithFinalizer ::New (env,
2607
+ external_value,
2608
+ 0 ,
2609
+ v8impl::ReferenceOwnership ::kRuntime ,
2610
+ finalize_cb,
2611
+ data,
2612
+ finalize_hint);
2615
2613
}
2616
2614
2617
2615
*result = v8impl::JsValueFromV8LocalValue (external_value);
@@ -2746,7 +2744,7 @@ napi_status NAPI_CDECL napi_create_reference(napi_env env,
2746
2744
}
2747
2745
2748
2746
v8impl::Reference* reference = v8impl::Reference::New (
2749
- env, v8_value, initial_refcount, v8impl::Ownership ::kUserland );
2747
+ env, v8_value, initial_refcount, v8impl::ReferenceOwnership ::kUserland );
2750
2748
2751
2749
*result = reinterpret_cast <napi_ref>(reference);
2752
2750
return napi_clear_last_error (env);
@@ -2802,7 +2800,7 @@ napi_status NAPI_CDECL napi_reference_unref(napi_env env,
2802
2800
2803
2801
v8impl::Reference* reference = reinterpret_cast <v8impl::Reference*>(ref);
2804
2802
2805
- if (reference->RefCount () == 0 ) {
2803
+ if (reference->refcount () == 0 ) {
2806
2804
return napi_set_last_error (env, napi_generic_failure);
2807
2805
}
2808
2806
@@ -2828,7 +2826,7 @@ napi_status NAPI_CDECL napi_get_reference_value(napi_env env,
2828
2826
CHECK_ARG (env, result);
2829
2827
2830
2828
v8impl::Reference* reference = reinterpret_cast <v8impl::Reference*>(ref);
2831
- *result = v8impl::JsValueFromV8LocalValue (reference->Get ());
2829
+ *result = v8impl::JsValueFromV8LocalValue (reference->Get (env ));
2832
2830
2833
2831
return napi_clear_last_error (env);
2834
2832
}
@@ -3439,10 +3437,10 @@ napi_add_finalizer(napi_env env,
3439
3437
3440
3438
// Create a self-deleting reference if the optional out-param result is not
3441
3439
// set.
3442
- v8impl::Ownership ownership = result == nullptr
3443
- ? v8impl::Ownership ::kRuntime
3444
- : v8impl::Ownership ::kUserland ;
3445
- v8impl::Reference* reference = v8impl::Reference ::New (
3440
+ v8impl::ReferenceOwnership ownership =
3441
+ result == nullptr ? v8impl::ReferenceOwnership ::kRuntime
3442
+ : v8impl::ReferenceOwnership ::kUserland ;
3443
+ v8impl::Reference* reference = v8impl::ReferenceWithFinalizer ::New (
3446
3444
env, v8_value, 0 , ownership, finalize_cb, finalize_data, finalize_hint);
3447
3445
3448
3446
if (result != nullptr ) {
@@ -3485,15 +3483,16 @@ napi_status NAPI_CDECL napi_set_instance_data(node_api_basic_env basic_env,
3485
3483
napi_env env = const_cast <napi_env>(basic_env);
3486
3484
CHECK_ENV (env);
3487
3485
3488
- v8impl::RefBase* old_data = static_cast <v8impl::RefBase*>(env->instance_data );
3486
+ v8impl::TrackedFinalizer* old_data =
3487
+ static_cast <v8impl::TrackedFinalizer*>(env->instance_data );
3489
3488
if (old_data != nullptr ) {
3490
3489
// Our contract so far has been to not finalize any old data there may be.
3491
3490
// So we simply delete it.
3492
3491
delete old_data;
3493
3492
}
3494
3493
3495
- env->instance_data = v8impl::RefBase::New (
3496
- env, 0 , v8impl::Ownership:: kRuntime , finalize_cb, data, finalize_hint);
3494
+ env->instance_data =
3495
+ v8impl::TrackedFinalizer::New (env , finalize_cb, data, finalize_hint);
3497
3496
3498
3497
return napi_clear_last_error (env);
3499
3498
}
@@ -3503,9 +3502,10 @@ napi_status NAPI_CDECL napi_get_instance_data(node_api_basic_env env,
3503
3502
CHECK_ENV (env);
3504
3503
CHECK_ARG (env, data);
3505
3504
3506
- v8impl::RefBase* idata = static_cast <v8impl::RefBase*>(env->instance_data );
3505
+ v8impl::TrackedFinalizer* idata =
3506
+ static_cast <v8impl::TrackedFinalizer*>(env->instance_data );
3507
3507
3508
- *data = (idata == nullptr ? nullptr : idata->Data ());
3508
+ *data = (idata == nullptr ? nullptr : idata->data ());
3509
3509
3510
3510
return napi_clear_last_error (env);
3511
3511
}
0 commit comments