@@ -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