Skip to content

Commit

Permalink
src: remove TODOs by fixing memory leaks
Browse files Browse the repository at this point in the history
PR-URL: nodejs/node-addon-api#343
Fixes: nodejs/node-addon-api#333
Reviewed-By: Michael Dawson <[email protected]>
  • Loading branch information
John French committed Oct 2, 2018
1 parent 47b0610 commit 0bd2b63
Show file tree
Hide file tree
Showing 15 changed files with 895 additions and 125 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,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

0 comments on commit 0bd2b63

Please sign in to comment.