@@ -157,11 +157,11 @@ The context-aware addon can be structured to avoid global static data by
157157performing the following steps: 
158158
159159* defining a class which will hold per-addon-instance data. Such 
160- a class should include a `v8::Persistent <v8::Object>` which will hold a weak 
160+ a class should include a `v8::Global <v8::Object>` which will hold a weak 
161161reference to the addon's `exports` object. The callback associated with the weak 
162162reference will then destroy the instance of the class. 
163163* constructing an instance of this class in the addon initializer such that the 
164- `v8::Persistent <v8::Object>` is set to the `exports` object. 
164+ `v8::Global <v8::Object>` is set to the `exports` object. 
165165* storing the instance of the class in a `v8::External`, and 
166166* passing the `v8::External` to all methods exposed to JavaScript by passing it 
167167to the `v8::FunctionTemplate` constructor which creates the native-backed 
@@ -188,14 +188,6 @@ class AddonData {
188188    exports_.SetWeak(this, DeleteMe, WeakCallbackType::kParameter); 
189189  } 
190190
191-   ~AddonData() { 
192-     if (!exports_.IsEmpty()) { 
193-       // Reset the reference to avoid leaking data. 
194-       exports_.ClearWeak(); 
195-       exports_.Reset(); 
196-     } 
197-   } 
198- 
199191  // Per-addon data. 
200192  int call_count; 
201193
@@ -207,7 +199,7 @@ class AddonData {
207199
208200  // Weak handle to the "exports" object. An instance of this class will be 
209201  // destroyed along with the exports object to which it is weakly bound. 
210-   v8::Persistent <v8::Object> exports_; 
202+   v8::Global <v8::Object> exports_; 
211203}; 
212204
213205static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) { 
@@ -830,7 +822,7 @@ class MyObject : public node::ObjectWrap {
830822
831823  static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 
832824  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args); 
833-   static v8::Persistent<v8::Function> constructor; 
825+ 
834826  double value_; 
835827}; 
836828
@@ -858,12 +850,10 @@ using v8::Local;
858850using v8::NewStringType;
859851using v8::Number;
860852using v8::Object;
861- using v8::Persistent ;
853+ using v8::ObjectTemplate ;
862854using v8::String;
863855using v8::Value;
864856
865- Persistent<Function > MyObject::constructor;
866- 
867857MyObject::MyObject(double value) : value_ (value) {
868858}
869859
@@ -872,21 +862,27 @@ MyObject::~MyObject() {
872862
873863void MyObject::Init(Local<Object > exports) {
874864  Isolate*  isolate = exports->GetIsolate();
865+   Local<Context > context = isolate->GetCurrentContext();
866+ 
867+   Local<ObjectTemplate > addon_data_tpl = ObjectTemplate::New(isolate);
868+   addon_data_tpl->SetInternalFieldCount(1);  // 1 field for the MyObject::New()
869+   Local<Object > addon_data =
870+       addon_data_tpl->NewInstance(context).ToLocalChecked();
875871
876872  // Prepare constructor template
877-   Local<FunctionTemplate > tpl = FunctionTemplate::New(isolate, New);
873+   Local<FunctionTemplate > tpl = FunctionTemplate::New(isolate, New, addon_data );
878874  tpl->SetClassName(String::NewFromUtf8(
879875      isolate, "MyObject", NewStringType::kNormal).ToLocalChecked());
880876  tpl->InstanceTemplate()->SetInternalFieldCount(1);
881877
882878  // Prototype
883879  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
884880
885-   Local<Context > context  = isolate->GetCurrentContext ();
886-   constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked() );
881+   Local<Function > constructor  = tpl->GetFunction(context).ToLocalChecked ();
882+   addon_data->SetInternalField(0, constructor );
887883  exports->Set(context, String::NewFromUtf8(
888884      isolate, "MyObject", NewStringType::kNormal).ToLocalChecked(),
889-                tpl->GetFunction(context).ToLocalChecked() ).FromJust();
885+                constructor ).FromJust();
890886}
891887
892888void MyObject::New(const FunctionCallbackInfo<Value >& args) {
@@ -904,7 +900,8 @@ void MyObject::New(const FunctionCallbackInfo<Value>& args) {
904900    // Invoked as plain function ` MyObject(...) ` , turn into construct call.
905901    const int argc = 1;
906902    Local<Value > argv[ argc]  = { args[ 0]  };
907-     Local<Function > cons = Local<Function >::New(isolate, constructor);
903+     Local<Function > cons =
904+         args.Data().As<Object >()->GetInternalField(0).As<Function >();
908905    Local<Object > result =
909906        cons->NewInstance(context, argc, argv).ToLocalChecked();
910907    args.GetReturnValue().Set(result);
@@ -1029,7 +1026,7 @@ class MyObject : public node::ObjectWrap {
10291026
10301027  static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 
10311028  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args); 
1032-   static v8::Persistent <v8::Function> constructor; 
1029+   static v8::Global <v8::Function> constructor; 
10331030  double value_; 
10341031}; 
10351032
@@ -1047,20 +1044,23 @@ The implementation in `myobject.cc` is similar to the previous example:
10471044
10481045namespace  demo  {
10491046
1047+ using node::AddEnvironmentCleanupHook;
10501048using v8::Context;
10511049using v8::Function;
10521050using v8::FunctionCallbackInfo;
10531051using v8::FunctionTemplate;
1052+ using v8::Global;
10541053using v8::Isolate;
10551054using v8::Local;
10561055using v8::NewStringType;
10571056using v8::Number;
10581057using v8::Object;
1059- using v8::Persistent;
10601058using v8::String;
10611059using v8::Value;
10621060
1063- Persistent<Function > MyObject::constructor;
1061+ // Warning! This is not thread-safe, this addon cannot be used for worker
1062+ // threads.
1063+ Global<Function > MyObject::constructor;
10641064
10651065MyObject::MyObject(double value) : value_ (value) {
10661066}
@@ -1080,6 +1080,10 @@ void MyObject::Init(Isolate* isolate) {
10801080
10811081  Local<Context > context = isolate->GetCurrentContext();
10821082  constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
1083+ 
1084+   AddEnvironmentCleanupHook(isolate, [ ] ( void* )  {
1085+     constructor.Reset();
1086+   }, nullptr);
10831087}
10841088
10851089void MyObject::New(const FunctionCallbackInfo<Value >& args) {
@@ -1246,7 +1250,7 @@ class MyObject : public node::ObjectWrap {
12461250  ~MyObject(); 
12471251
12481252  static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 
1249-   static v8::Persistent <v8::Function> constructor; 
1253+   static v8::Global <v8::Function> constructor; 
12501254  double value_; 
12511255}; 
12521256
@@ -1264,19 +1268,22 @@ The implementation of `myobject.cc` is similar to before:
12641268
12651269namespace  demo  {
12661270
1271+ using node::AddEnvironmentCleanupHook;
12671272using v8::Context;
12681273using v8::Function;
12691274using v8::FunctionCallbackInfo;
12701275using v8::FunctionTemplate;
1276+ using v8::Global;
12711277using v8::Isolate;
12721278using v8::Local;
12731279using v8::NewStringType;
12741280using v8::Object;
1275- using v8::Persistent;
12761281using v8::String;
12771282using v8::Value;
12781283
1279- Persistent<Function > MyObject::constructor;
1284+ // Warning! This is not thread-safe, this addon cannot be used for worker
1285+ // threads.
1286+ Global<Function > MyObject::constructor;
12801287
12811288MyObject::MyObject(double value) : value_ (value) {
12821289}
@@ -1293,6 +1300,10 @@ void MyObject::Init(Isolate* isolate) {
12931300
12941301  Local<Context > context = isolate->GetCurrentContext();
12951302  constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
1303+ 
1304+   AddEnvironmentCleanupHook(isolate, [ ] ( void* )  {
1305+     constructor.Reset();
1306+   }, nullptr);
12961307}
12971308
12981309void MyObject::New(const FunctionCallbackInfo<Value >& args) {
0 commit comments