mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
doc: update context-aware section of addon doc
Replace the portion of the context-aware addon example that advocates for managing the life cycle of the per-addon-instance data using a weak reference with code that illustrates how to manage its life cycle using an environment cleanup hook. Signed-off-by: Gabriel Schulhof <gabriel.schulhof@intel.com> PR-URL: https://github.com/nodejs/node/pull/28659 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
This commit is contained in:
@@ -155,18 +155,25 @@ they were created.
|
||||
|
||||
The context-aware addon can be structured to avoid global static data by
|
||||
performing the following steps:
|
||||
|
||||
* defining a class which will hold per-addon-instance data. Such
|
||||
a class should include a `v8::Global<v8::Object>` which will hold a weak
|
||||
reference to the addon's `exports` object. The callback associated with the weak
|
||||
reference will then destroy the instance of the class.
|
||||
* constructing an instance of this class in the addon initializer such that the
|
||||
`v8::Global<v8::Object>` is set to the `exports` object.
|
||||
* storing the instance of the class in a `v8::External`, and
|
||||
* passing the `v8::External` to all methods exposed to JavaScript by passing it
|
||||
to the `v8::FunctionTemplate` constructor which creates the native-backed
|
||||
JavaScript functions. The `v8::FunctionTemplate` constructor's third parameter
|
||||
accepts the `v8::External`.
|
||||
* Define a class which will hold per-addon-instance data and which has a static
|
||||
member of the form
|
||||
```C++
|
||||
static void DeleteInstance(void* data) {
|
||||
// Cast `data` to an instance of the class and delete it.
|
||||
}
|
||||
```
|
||||
* Heap-allocate an instance of this class in the addon initializer. This can be
|
||||
accomplished using the `new` keyword.
|
||||
* Call `node::AddEnvironmentCleanupHook()`, passing it the above-created
|
||||
instance and a pointer to `DeleteInstance()`. This will ensure the instance is
|
||||
deleted when the environment is torn down.
|
||||
* Store the instance of the class in a `v8::External`, and
|
||||
* Pass the `v8::External` to all methods exposed to JavaScript by passing it
|
||||
to `v8::FunctionTemplate::New()` or `v8::Function::New()` which creates the
|
||||
native-backed JavaScript functions. The third parameter of
|
||||
`v8::FunctionTemplate::New()` or `v8::Function::New()` accepts the
|
||||
`v8::External` and makes it available in the native callback using the
|
||||
`v8::FunctionCallbackInfo::Data()` method.
|
||||
|
||||
This will ensure that the per-addon-instance data reaches each binding that can
|
||||
be called from JavaScript. The per-addon-instance data must also be passed into
|
||||
@@ -181,25 +188,18 @@ using namespace v8;
|
||||
|
||||
class AddonData {
|
||||
public:
|
||||
AddonData(Isolate* isolate, Local<Object> exports):
|
||||
explicit AddonData(Isolate* isolate):
|
||||
call_count(0) {
|
||||
// Link the existence of this object instance to the existence of exports.
|
||||
exports_.Reset(isolate, exports);
|
||||
exports_.SetWeak(this, DeleteMe, WeakCallbackType::kParameter);
|
||||
// Ensure this per-addon-instance data is deleted at environment cleanup.
|
||||
node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
|
||||
}
|
||||
|
||||
// Per-addon data.
|
||||
int call_count;
|
||||
|
||||
private:
|
||||
// Method to call when "exports" is about to be garbage-collected.
|
||||
static void DeleteMe(const WeakCallbackInfo<AddonData>& info) {
|
||||
delete info.GetParameter();
|
||||
static void DeleteInstance(void* data) {
|
||||
delete static_cast<AddonData*>(data);
|
||||
}
|
||||
|
||||
// Weak handle to the "exports" object. An instance of this class will be
|
||||
// destroyed along with the exports object to which it is weakly bound.
|
||||
v8::Global<v8::Object> exports_;
|
||||
};
|
||||
|
||||
static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
@@ -214,14 +214,17 @@ static void Method(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
NODE_MODULE_INIT(/* exports, module, context */) {
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
|
||||
// Create a new instance of AddonData for this instance of the addon.
|
||||
AddonData* data = new AddonData(isolate, exports);
|
||||
// Wrap the data in a v8::External so we can pass it to the method we expose.
|
||||
// Create a new instance of `AddonData` for this instance of the addon and
|
||||
// tie its life cycle to that of the Node.js environment.
|
||||
AddonData* data = new AddonData(isolate);
|
||||
|
||||
// Wrap the data in a `v8::External` so we can pass it to the method we
|
||||
// expose.
|
||||
Local<External> external = External::New(isolate, data);
|
||||
|
||||
// Expose the method "Method" to JavaScript, and make sure it receives the
|
||||
// Expose the method `Method` to JavaScript, and make sure it receives the
|
||||
// per-addon-instance data we created above by passing `external` as the
|
||||
// third parameter to the FunctionTemplate constructor.
|
||||
// third parameter to the `FunctionTemplate` constructor.
|
||||
exports->Set(context,
|
||||
String::NewFromUtf8(isolate, "method", NewStringType::kNormal)
|
||||
.ToLocalChecked(),
|
||||
|
||||
Reference in New Issue
Block a user