Skip to content

Commit 44c1e33

Browse files
committed
src: allow references to be copyable in APIs
allow non-copyable callbacks be finalizer parameters Fixes: nodejs/node-addon-api#301 PR-URL: nodejs/node-addon-api#915 Reviewed-By: Michael Dawson <[email protected]>
1 parent 7cc5457 commit 44c1e33

File tree

5 files changed

+69
-8
lines changed

5 files changed

+69
-8
lines changed

napi-inl.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,7 +1345,8 @@ inline bool Object::InstanceOf(const Function& constructor) const {
13451345
template <typename Finalizer, typename T>
13461346
inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
13471347
details::FinalizeData<T, Finalizer>* finalizeData =
1348-
new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
1348+
new details::FinalizeData<T, Finalizer>(
1349+
{std::move(finalizeCallback), nullptr});
13491350
napi_status status =
13501351
details::AttachData(_env,
13511352
*this,
@@ -1363,7 +1364,8 @@ inline void Object::AddFinalizer(Finalizer finalizeCallback,
13631364
T* data,
13641365
Hint* finalizeHint) {
13651366
details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1366-
new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1367+
new details::FinalizeData<T, Finalizer, Hint>(
1368+
{std::move(finalizeCallback), finalizeHint});
13671369
napi_status status =
13681370
details::AttachData(_env,
13691371
*this,
@@ -1395,7 +1397,8 @@ inline External<T> External<T>::New(napi_env env,
13951397
Finalizer finalizeCallback) {
13961398
napi_value value;
13971399
details::FinalizeData<T, Finalizer>* finalizeData =
1398-
new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
1400+
new details::FinalizeData<T, Finalizer>(
1401+
{std::move(finalizeCallback), nullptr});
13991402
napi_status status = napi_create_external(
14001403
env,
14011404
data,
@@ -1417,7 +1420,8 @@ inline External<T> External<T>::New(napi_env env,
14171420
Hint* finalizeHint) {
14181421
napi_value value;
14191422
details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1420-
new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1423+
new details::FinalizeData<T, Finalizer, Hint>(
1424+
{std::move(finalizeCallback), finalizeHint});
14211425
napi_status status = napi_create_external(
14221426
env,
14231427
data,
@@ -1509,7 +1513,8 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
15091513
Finalizer finalizeCallback) {
15101514
napi_value value;
15111515
details::FinalizeData<void, Finalizer>* finalizeData =
1512-
new details::FinalizeData<void, Finalizer>({ finalizeCallback, nullptr });
1516+
new details::FinalizeData<void, Finalizer>(
1517+
{std::move(finalizeCallback), nullptr});
15131518
napi_status status = napi_create_external_arraybuffer(
15141519
env,
15151520
externalData,
@@ -1533,7 +1538,8 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
15331538
Hint* finalizeHint) {
15341539
napi_value value;
15351540
details::FinalizeData<void, Finalizer, Hint>* finalizeData =
1536-
new details::FinalizeData<void, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1541+
new details::FinalizeData<void, Finalizer, Hint>(
1542+
{std::move(finalizeCallback), finalizeHint});
15371543
napi_status status = napi_create_external_arraybuffer(
15381544
env,
15391545
externalData,
@@ -2153,7 +2159,8 @@ inline Buffer<T> Buffer<T>::New(napi_env env,
21532159
Finalizer finalizeCallback) {
21542160
napi_value value;
21552161
details::FinalizeData<T, Finalizer>* finalizeData =
2156-
new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
2162+
new details::FinalizeData<T, Finalizer>(
2163+
{std::move(finalizeCallback), nullptr});
21572164
napi_status status = napi_create_external_buffer(
21582165
env,
21592166
length * sizeof (T),
@@ -2177,7 +2184,8 @@ inline Buffer<T> Buffer<T>::New(napi_env env,
21772184
Hint* finalizeHint) {
21782185
napi_value value;
21792186
details::FinalizeData<T, Finalizer, Hint>* finalizeData =
2180-
new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
2187+
new details::FinalizeData<T, Finalizer, Hint>(
2188+
{std::move(finalizeCallback), finalizeHint});
21812189
napi_status status = napi_create_external_buffer(
21822190
env,
21832191
length * sizeof (T),

test/binding.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Object InitError(Env env);
3434
Object InitExternal(Env env);
3535
Object InitFunction(Env env);
3636
Object InitHandleScope(Env env);
37+
Object InitMovableCallbacks(Env env);
3738
Object InitMemoryManagement(Env env);
3839
Object InitName(Env env);
3940
Object InitObject(Env env);
@@ -101,6 +102,7 @@ Object Init(Env env, Object exports) {
101102
exports.Set("function", InitFunction(env));
102103
exports.Set("name", InitName(env));
103104
exports.Set("handlescope", InitHandleScope(env));
105+
exports.Set("movable_callbacks", InitMovableCallbacks(env));
104106
exports.Set("memory_management", InitMemoryManagement(env));
105107
exports.Set("object", InitObject(env));
106108
#ifndef NODE_ADDON_API_DISABLE_DEPRECATED

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
'external.cc',
2626
'function.cc',
2727
'handlescope.cc',
28+
'movable_callbacks.cc',
2829
'memory_management.cc',
2930
'name.cc',
3031
'object/delete_property.cc',

test/movable_callbacks.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "napi.h"
2+
3+
using namespace Napi;
4+
5+
Value createExternal(const CallbackInfo& info) {
6+
FunctionReference ref = Reference<Function>::New(info[0].As<Function>(), 1);
7+
auto ret = External<char>::New(
8+
info.Env(),
9+
nullptr,
10+
[ref = std::move(ref)](Napi::Env /*env*/, char* /*data*/) {
11+
ref.Call({});
12+
});
13+
14+
return ret;
15+
}
16+
17+
Object InitMovableCallbacks(Env env) {
18+
Object exports = Object::New(env);
19+
20+
exports["createExternal"] = Function::New(env, createExternal);
21+
22+
return exports;
23+
}

test/movable_callbacks.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
const buildType = process.config.target_defaults.default_configuration;
3+
const common = require('./common');
4+
const testUtil = require('./testUtil');
5+
6+
Promise.all([
7+
test(require(`./build/${buildType}/binding.node`).movable_callbacks),
8+
test(require(`./build/${buildType}/binding_noexcept.node`).movable_callbacks),
9+
]).catch(e => {
10+
console.error(e);
11+
process.exitCode = 1;
12+
});
13+
14+
async function test(binding) {
15+
await testUtil.runGCTests([
16+
'External',
17+
() => {
18+
const fn = common.mustCall(() => {
19+
// noop
20+
}, 1);
21+
const external = binding.createExternal(fn);
22+
},
23+
() => {
24+
// noop, wait for gc
25+
}
26+
]);
27+
}

0 commit comments

Comments
 (0)