Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TODOs to address memory leaks #343

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ npm install
npm test
```

To avoid testing the deprecated portions of the API run
```
npm install
npm test --disable-deprecated
```

Take a look and get inspired by our **[test suite](https://github.com/nodejs/node-addon-api/tree/master/test)**

<a name="resources"></a>
Expand Down
114 changes: 102 additions & 12 deletions doc/property_descriptor.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,31 @@ Value TestFunction(const CallbackInfo& info) {
}

Void Init(Env env) {
// Accessor
PropertyDescriptor pd1 = PropertyDescriptor::Accessor("pd1", TestGetter);
PropertyDescriptor pd2 = PropertyDescriptor::Accessor("pd2", TestGetter, TestSetter);

// Function
PropertyDescriptor pd3 = PropertyDescriptor::Function("function", TestFunction);

// Value
Boolean true_bool = Boolean::New(env, true);
PropertyDescriptor pd4 = PropertyDescriptor::Value("boolean value", TestFunction, napi_writable);

// Assign to an Object
// Create an object.
Object obj = Object::New(env);

// Accessor
PropertyDescriptor pd1 = PropertyDescriptor::Accessor(env,
obj,
"pd1",
TestGetter);
PropertyDescriptor pd2 = PropertyDescriptor::Accessor(env,
obj,
"pd2",
TestGetter,
TestSetter);
// Function
PropertyDescriptor pd3 = PropertyDescriptor::Function(env,
"function",
TestFunction);
// Value
Boolean true_bool = Boolean::New(env, true);
PropertyDescriptor pd4 =
PropertyDescriptor::Value("boolean value",
Napi::Boolean::New(env, true),
napi_writable);

// Assign properties to the object.
obj.DefineProperties({pd1, pd2, pd3, pd4});
}
```
Expand Down Expand Up @@ -71,6 +83,32 @@ The name of the property can be any of the following types:
- `napi_value value`
- `Napi::Name`

**This signature is deprecated. It will result in a memory leak if used.**

```cpp
static Napi::PropertyDescriptor Napi::PropertyDescriptor::Accessor (
Napi::Env env,
Napi::Object object,
___ name,
Getter getter,
napi_property_attributes attributes = napi_default,
void *data = nullptr);
```

* `[in] env`: The environemnt in which to create this accessor.
* `[in] object`: The object on which the accessor will be defined.
* `[in] name`: The name used for the getter function.
* `[in] getter`: A getter function.
* `[in] attributes`: Potential attributes for the getter function.
* `[in] data`: A pointer to data of any type, default is a null pointer.

Returns a `Napi::PropertyDescriptor` that contains a `Getter` accessor.

The name of the property can be any of the following types:
- `const char*`
- `const std::string &`
- `Napi::Name`

```cpp
static Napi::PropertyDescriptor Napi::PropertyDescriptor::Accessor (___ name,
Getter getter,
Expand All @@ -93,6 +131,34 @@ The name of the property can be any of the following types:
- `napi_value value`
- `Napi::Name`

**This signature is deprecated. It will result in a memory leak if used.**

```cpp
static Napi::PropertyDescriptor Napi::PropertyDescriptor::Accessor (
Napi::Env env,
Napi::Object object,
___ name,
Getter getter,
Setter setter,
napi_property_attributes attributes = napi_default,
void *data = nullptr);
```

* `[in] env`: The environemnt in which to create this accessor.
* `[in] object`: The object on which the accessor will be defined.
* `[in] name`: The name of the getter and setter function.
* `[in] getter`: The getter function.
* `[in] setter`: The setter function.
* `[in] attributes`: Potential attributes for the getter function.
* `[in] data`: A pointer to data of any type, default is a null pointer.

Returns a `Napi::PropertyDescriptor` that contains a `Getter` and `Setter` function.

The name of the property can be any of the following types:
- `const char*`
- `const std::string &`
- `Napi::Name`

### Function

```cpp
Expand All @@ -115,6 +181,30 @@ The name of the property can be any of the following types:
- `napi_value value`
- `Napi::Name`

**This signature is deprecated. It will result in a memory leak if used.**

```cpp
static Napi::PropertyDescriptor Napi::PropertyDescriptor::Function (
Napi::Env env,
___ name,
Callable cb,
napi_property_attributes attributes = napi_default,
void *data = nullptr);
```

* `[in] env`: The environemnt in which to create this accessor.
* `[in] name`: The name of the Callable function.
* `[in] cb`: The function
* `[in] attributes`: Potential attributes for the getter function.
* `[in] data`: A pointer to data of any type, default is a null pointer.

Returns a `Napi::PropertyDescriptor` that contains a callable `Napi::Function`.

The name of the property can be any of the following types:
- `const char*`
- `const std::string &`
- `Napi::Name`

### Value

```cpp
Expand Down
3 changes: 3 additions & 0 deletions doc/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,6 @@ To use **N-API** in a native module:

At build time, the N-API back-compat library code will be used only when the
targeted node version *does not* have N-API built-in.

The preprocessor directive `NODE_ADDON_API_DISABLE_DEPRECATED` can be defined at
compile time before including `napi.h` to skip the definition of deprecated APIs.
192 changes: 192 additions & 0 deletions napi-inl.deprecated.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#ifndef SRC_NAPI_INL_DEPRECATED_H_
#define SRC_NAPI_INL_DEPRECATED_H_

////////////////////////////////////////////////////////////////////////////////
// PropertyDescriptor class
////////////////////////////////////////////////////////////////////////////////

template <typename Getter>
inline PropertyDescriptor
PropertyDescriptor::Accessor(const char* utf8name,
Getter getter,
napi_property_attributes attributes,
void* /*data*/) {
typedef details::CallbackData<Getter, Napi::Value> CbData;
// TODO: Delete when the function is destroyed
auto callbackData = new CbData({ getter, nullptr });

return PropertyDescriptor({
utf8name,
nullptr,
nullptr,
CbData::Wrapper,
nullptr,
nullptr,
attributes,
callbackData
});
}

template <typename Getter>
inline PropertyDescriptor PropertyDescriptor::Accessor(const std::string& utf8name,
Getter getter,
napi_property_attributes attributes,
void* data) {
return Accessor(utf8name.c_str(), getter, attributes, data);
}

template <typename Getter>
inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
Getter getter,
napi_property_attributes attributes,
void* /*data*/) {
typedef details::CallbackData<Getter, Napi::Value> CbData;
// TODO: Delete when the function is destroyed
auto callbackData = new CbData({ getter, nullptr });

return PropertyDescriptor({
nullptr,
name,
nullptr,
CbData::Wrapper,
nullptr,
nullptr,
attributes,
callbackData
});
}

template <typename Getter>
inline PropertyDescriptor PropertyDescriptor::Accessor(Name name,
Getter getter,
napi_property_attributes attributes,
void* data) {
napi_value nameValue = name;
return PropertyDescriptor::Accessor(nameValue, getter, attributes, data);
}

template <typename Getter, typename Setter>
inline PropertyDescriptor PropertyDescriptor::Accessor(const char* utf8name,
Getter getter,
Setter setter,
napi_property_attributes attributes,
void* /*data*/) {
typedef details::AccessorCallbackData<Getter, Setter> CbData;
// TODO: Delete when the function is destroyed
auto callbackData = new CbData({ getter, setter });

return PropertyDescriptor({
utf8name,
nullptr,
nullptr,
CbData::GetterWrapper,
CbData::SetterWrapper,
nullptr,
attributes,
callbackData
});
}

template <typename Getter, typename Setter>
inline PropertyDescriptor PropertyDescriptor::Accessor(const std::string& utf8name,
Getter getter,
Setter setter,
napi_property_attributes attributes,
void* data) {
return Accessor(utf8name.c_str(), getter, setter, attributes, data);
}

template <typename Getter, typename Setter>
inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
Getter getter,
Setter setter,
napi_property_attributes attributes,
void* /*data*/) {
typedef details::AccessorCallbackData<Getter, Setter> CbData;
// TODO: Delete when the function is destroyed
auto callbackData = new CbData({ getter, setter });

return PropertyDescriptor({
nullptr,
name,
nullptr,
CbData::GetterWrapper,
CbData::SetterWrapper,
nullptr,
attributes,
callbackData
});
}

template <typename Getter, typename Setter>
inline PropertyDescriptor PropertyDescriptor::Accessor(Name name,
Getter getter,
Setter setter,
napi_property_attributes attributes,
void* data) {
napi_value nameValue = name;
return PropertyDescriptor::Accessor(nameValue, getter, setter, attributes, data);
}

template <typename Callable>
inline PropertyDescriptor PropertyDescriptor::Function(const char* utf8name,
Callable cb,
napi_property_attributes attributes,
void* /*data*/) {
typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
typedef details::CallbackData<Callable, ReturnType> CbData;
// TODO: Delete when the function is destroyed
auto callbackData = new CbData({ cb, nullptr });

return PropertyDescriptor({
utf8name,
nullptr,
CbData::Wrapper,
nullptr,
nullptr,
nullptr,
attributes,
callbackData
});
}

template <typename Callable>
inline PropertyDescriptor PropertyDescriptor::Function(const std::string& utf8name,
Callable cb,
napi_property_attributes attributes,
void* data) {
return Function(utf8name.c_str(), cb, attributes, data);
}

template <typename Callable>
inline PropertyDescriptor PropertyDescriptor::Function(napi_value name,
Callable cb,
napi_property_attributes attributes,
void* /*data*/) {
typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
typedef details::CallbackData<Callable, ReturnType> CbData;
// TODO: Delete when the function is destroyed
auto callbackData = new CbData({ cb, nullptr });

return PropertyDescriptor({
nullptr,
name,
CbData::Wrapper,
nullptr,
nullptr,
nullptr,
attributes,
callbackData
});
}

template <typename Callable>
inline PropertyDescriptor PropertyDescriptor::Function(Name name,
Callable cb,
napi_property_attributes attributes,
void* data) {
napi_value nameValue = name;
return PropertyDescriptor::Function(nameValue, cb, attributes, data);
}

#endif // !SRC_NAPI_INL_DEPRECATED_H_
Loading