Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ea5be29

Browse filesBrowse files
addaleaxtargos
authored andcommitted
doc: avoid using v8::Persistent in addon docs
Use `v8::Global` where possible. For examples where it applies, also clean up the code and make the code multi-threading-ready, for those where that isn’t easily possible, add a warning about that. PR-URL: #31018 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent 5622543 commit ea5be29
Copy full SHA for ea5be29

File tree

Expand file treeCollapse file tree

1 file changed

+37
-26
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

1 file changed

+37
-26
lines changed
Open diff view settings
Collapse file

‎doc/api/addons.md‎

Copy file name to clipboardExpand all lines: doc/api/addons.md
+37-26Lines changed: 37 additions & 26 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,11 @@ The context-aware addon can be structured to avoid global static data by
157157
performing 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
161161
reference to the addon's `exports` object. The callback associated with the weak
162162
reference 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
167167
to 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
213205
static 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;
858850
using v8::NewStringType;
859851
using v8::Number;
860852
using v8::Object;
861-
using v8::Persistent;
853+
using v8::ObjectTemplate;
862854
using v8::String;
863855
using v8::Value;
864856

865-
Persistent<Function> MyObject::constructor;
866-
867857
MyObject::MyObject(double value) : value_(value) {
868858
}
869859

@@ -872,21 +862,27 @@ MyObject::~MyObject() {
872862

873863
void 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

892888
void 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

10481045
namespace demo {
10491046

1047+
using node::AddEnvironmentCleanupHook;
10501048
using v8::Context;
10511049
using v8::Function;
10521050
using v8::FunctionCallbackInfo;
10531051
using v8::FunctionTemplate;
1052+
using v8::Global;
10541053
using v8::Isolate;
10551054
using v8::Local;
10561055
using v8::NewStringType;
10571056
using v8::Number;
10581057
using v8::Object;
1059-
using v8::Persistent;
10601058
using v8::String;
10611059
using 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

10651065
MyObject::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

10851089
void 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

12651269
namespace demo {
12661270

1271+
using node::AddEnvironmentCleanupHook;
12671272
using v8::Context;
12681273
using v8::Function;
12691274
using v8::FunctionCallbackInfo;
12701275
using v8::FunctionTemplate;
1276+
using v8::Global;
12711277
using v8::Isolate;
12721278
using v8::Local;
12731279
using v8::NewStringType;
12741280
using v8::Object;
1275-
using v8::Persistent;
12761281
using v8::String;
12771282
using 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

12811288
MyObject::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

12981309
void MyObject::New(const FunctionCallbackInfo<Value>& args) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.