@@ -155,18 +155,25 @@ they were created.
155155
156156The context-aware addon can be structured to avoid global static data by
157157performing the following steps:
158-
159- * defining a class which will hold per-addon-instance data. Such
160- a class should include a `v8::Global<v8::Object>` which will hold a weak
161- reference to the addon's `exports` object. The callback associated with the weak
162- reference will then destroy the instance of the class.
163- * constructing an instance of this class in the addon initializer such that the
164- `v8::Global<v8::Object>` is set to the `exports` object.
165- * storing the instance of the class in a `v8::External`, and
166- * passing the `v8::External` to all methods exposed to JavaScript by passing it
167- to the `v8::FunctionTemplate` constructor which creates the native-backed
168- JavaScript functions. The `v8::FunctionTemplate` constructor's third parameter
169- accepts the `v8::External`.
158+ * Define a class which will hold per-addon-instance data and which has a static
159+ member of the form
160+ ```C++
161+ static void DeleteInstance(void* data) {
162+ // Cast `data` to an instance of the class and delete it.
163+ }
164+ ```
165+ * Heap-allocate an instance of this class in the addon initializer. This can be
166+ accomplished using the `new` keyword.
167+ * Call `node::AddEnvironmentCleanupHook()`, passing it the above-created
168+ instance and a pointer to `DeleteInstance()`. This will ensure the instance is
169+ deleted when the environment is torn down.
170+ * Store the instance of the class in a `v8::External`, and
171+ * Pass the `v8::External` to all methods exposed to JavaScript by passing it
172+ to `v8::FunctionTemplate::New()` or `v8::Function::New()` which creates the
173+ native-backed JavaScript functions. The third parameter of
174+ `v8::FunctionTemplate::New()` or `v8::Function::New()` accepts the
175+ `v8::External` and makes it available in the native callback using the
176+ `v8::FunctionCallbackInfo::Data()` method.
170177
171178This will ensure that the per-addon-instance data reaches each binding that can
172179be called from JavaScript. The per-addon-instance data must also be passed into
@@ -181,25 +188,18 @@ using namespace v8;
181188
182189class AddonData {
183190 public:
184- AddonData(Isolate* isolate, Local<Object> exports ):
191+ explicit AddonData(Isolate* isolate):
185192 call_count(0) {
186- // Link the existence of this object instance to the existence of exports.
187- exports_.Reset(isolate, exports);
188- exports_.SetWeak(this, DeleteMe, WeakCallbackType::kParameter);
193+ // Ensure this per-addon-instance data is deleted at environment cleanup.
194+ node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
189195 }
190196
191197 // Per-addon data.
192198 int call_count;
193199
194- private:
195- // Method to call when "exports" is about to be garbage-collected.
196- static void DeleteMe(const WeakCallbackInfo<AddonData>& info) {
197- delete info.GetParameter();
200+ static void DeleteInstance(void* data) {
201+ delete static_cast<AddonData*>(data);
198202 }
199-
200- // Weak handle to the "exports" object. An instance of this class will be
201- // destroyed along with the exports object to which it is weakly bound.
202- v8::Global<v8::Object> exports_;
203203};
204204
205205static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -214,14 +214,17 @@ static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
214214NODE_MODULE_INIT(/* exports, module, context */) {
215215 Isolate* isolate = context->GetIsolate();
216216
217- // Create a new instance of AddonData for this instance of the addon.
218- AddonData* data = new AddonData(isolate, exports);
219- // Wrap the data in a v8::External so we can pass it to the method we expose.
217+ // Create a new instance of `AddonData` for this instance of the addon and
218+ // tie its life cycle to that of the Node.js environment.
219+ AddonData* data = new AddonData(isolate);
220+
221+ // Wrap the data in a `v8::External` so we can pass it to the method we
222+ // expose.
220223 Local<External> external = External::New(isolate, data);
221224
222- // Expose the method " Method" to JavaScript, and make sure it receives the
225+ // Expose the method ` Method` to JavaScript, and make sure it receives the
223226 // per-addon-instance data we created above by passing `external` as the
224- // third parameter to the FunctionTemplate constructor.
227+ // third parameter to the ` FunctionTemplate` constructor.
225228 exports->Set(context,
226229 String::NewFromUtf8(isolate, "method", NewStringType::kNormal)
227230 .ToLocalChecked(),
0 commit comments