Skip to content

Commit c54398c

Browse files
committed
chore: adopt node make_callback tests
1 parent aa2faf0 commit c54398c

File tree

6 files changed

+210
-3
lines changed

6 files changed

+210
-3
lines changed

packages/node-addon-examples/src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ function assertLogs(cb: () => void, expectedMessages: string[]) {
1515
cb();
1616
if (expectedMessages.length > 0) {
1717
errors.push(
18-
new Error(
19-
`Missing expected message(s): ${expectedMessages.join(", ")}`,
20-
),
18+
new Error(`Missing expected message(s): ${expectedMessages.join(", ")}`)
2119
);
2220
}
2321
} finally {
@@ -85,5 +83,6 @@ export const suites: Record<
8583
require("../tests/buffers/addon.js");
8684
},
8785
async: () => require("../tests/async/addon.js") as () => Promise<void>,
86+
make_callback: () => require("../tests/make_callback/addon.js"),
8887
},
8988
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
project(tests-make_callback)
3+
4+
add_compile_definitions(NAPI_VERSION=8)
5+
6+
add_library(addon SHARED addon.c ${CMAKE_JS_SRC})
7+
set_target_properties(addon PROPERTIES PREFIX "" SUFFIX ".node")
8+
target_include_directories(addon PRIVATE ${CMAKE_JS_INC})
9+
target_link_libraries(addon PRIVATE ${CMAKE_JS_LIB})
10+
target_compile_features(addon PRIVATE cxx_std_17)
11+
12+
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
13+
# Generate node.lib
14+
execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})
15+
endif()
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <assert.h>
2+
#include <node_api.h>
3+
#include <stdio.h>
4+
#include "../RuntimeNodeApiTestsCommon.h"
5+
6+
#define MAX_ARGUMENTS 10
7+
#define RESERVED_ARGS 3
8+
9+
static napi_value MakeCallback(napi_env env, napi_callback_info info) {
10+
size_t argc = MAX_ARGUMENTS;
11+
size_t n;
12+
napi_value args[MAX_ARGUMENTS];
13+
// NOLINTNEXTLINE (readability/null_usage)
14+
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
15+
16+
NODE_API_ASSERT(env, argc > 0, "Wrong number of arguments");
17+
printf("Make callback called with %zu arguments\n", argc);
18+
19+
napi_value resource = args[0];
20+
napi_value recv = args[1];
21+
napi_value func = args[2];
22+
23+
napi_value argv[MAX_ARGUMENTS - RESERVED_ARGS];
24+
for (n = RESERVED_ARGS; n < argc; n += 1) {
25+
argv[n - RESERVED_ARGS] = args[n];
26+
}
27+
28+
napi_valuetype func_type;
29+
30+
NODE_API_CALL(env, napi_typeof(env, func, &func_type));
31+
32+
napi_value resource_name;
33+
NODE_API_CALL(env,
34+
napi_create_string_utf8(env, "test", NAPI_AUTO_LENGTH, &resource_name));
35+
36+
napi_async_context context;
37+
NODE_API_CALL(env, napi_async_init(env, resource, resource_name, &context));
38+
39+
napi_value result;
40+
if (func_type == napi_function) {
41+
NODE_API_CALL(env,
42+
napi_make_callback(
43+
env, context, recv, func, argc - RESERVED_ARGS, argv, &result));
44+
} else {
45+
NODE_API_ASSERT(env, false, "Unexpected argument type");
46+
}
47+
48+
NODE_API_CALL(env, napi_async_destroy(env, context));
49+
50+
return result;
51+
}
52+
53+
static napi_value Init(napi_env env, napi_value exports) {
54+
napi_value fn;
55+
NODE_API_CALL(env,
56+
napi_create_function(
57+
// NOLINTNEXTLINE (readability/null_usage)
58+
env,
59+
NULL,
60+
NAPI_AUTO_LENGTH,
61+
MakeCallback,
62+
NULL,
63+
&fn));
64+
NODE_API_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn));
65+
return exports;
66+
}
67+
68+
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/* eslint-disable @typescript-eslint/no-require-imports */
2+
/* eslint-disable no-undef */
3+
const assert = require("assert");
4+
const binding = require("bindings")("addon.node");
5+
const makeCallback = binding.makeCallback;
6+
7+
/**
8+
* Resource should be able to be arbitrary objects without special internal
9+
* slots. Testing with plain object here.
10+
*/
11+
12+
function myMultiArgFunc(arg1, arg2, arg3) {
13+
assert.strictEqual(arg1, 1);
14+
assert.strictEqual(arg2, 2);
15+
assert.strictEqual(arg3, 3);
16+
return 42;
17+
}
18+
19+
module.exports = () => {
20+
const resource = {};
21+
const process = (module.exports = {});
22+
23+
assert.strictEqual(
24+
makeCallback(resource, process, function () {
25+
assert.strictEqual(arguments.length, 0);
26+
assert.strictEqual(this, process);
27+
return 42;
28+
}),
29+
42
30+
);
31+
32+
assert.strictEqual(
33+
makeCallback(
34+
resource,
35+
process,
36+
function (x) {
37+
assert.strictEqual(arguments.length, 1);
38+
assert.strictEqual(this, process);
39+
assert.strictEqual(x, 1337);
40+
return 42;
41+
},
42+
1337
43+
),
44+
42
45+
);
46+
47+
assert.strictEqual(
48+
makeCallback(resource, process, myMultiArgFunc, 1, 2, 3),
49+
42
50+
);
51+
52+
// TODO(node-api): napi_make_callback needs to support
53+
// strings passed for the func argument
54+
//
55+
// const recv = {
56+
// one: function () {
57+
// assert.strictEqual(0, arguments.length);
58+
// assert.strictEqual(this, recv);
59+
// return 42;
60+
// },
61+
// two: function (x) {
62+
// assert.strictEqual(1, arguments.length);
63+
// assert.strictEqual(this, recv);
64+
// assert.strictEqual(x, 1339);
65+
// return 42;
66+
// },
67+
// };
68+
69+
// assert.strictEqual(makeCallback(recv, "one"), 42);
70+
// assert.strictEqual(makeCallback(recv, "two", 1337), 42);
71+
//
72+
// Check that callbacks on a receiver from a different context works.
73+
// const foreignObject = vm.runInNewContext('({ fortytwo() { return 42; } })');
74+
// const foreignObject = { fortytwo: () => 42 };
75+
// assert.strictEqual(makeCallback(foreignObject, "fortytwo"), 42);
76+
77+
// Check that the callback is made in the context of the receiver.
78+
79+
// const target = vm.runInNewContext(`
80+
// (function($Object) {
81+
// if (Object === $Object)
82+
// throw new Error('bad');
83+
// return Object;
84+
// })
85+
// `);
86+
// assert.notStrictEqual(makeCallback(resource, process, target, Object), Object);
87+
88+
// // Runs in inner context.
89+
// const forward = vm.runInNewContext(`
90+
// (function(forward) {
91+
// return forward(Object);
92+
// })
93+
// `);
94+
95+
// // Runs in outer context.
96+
// function endpoint($Object) {
97+
// if (Object === $Object)
98+
// throw new Error('bad');
99+
// return Object;
100+
// }
101+
102+
// assert.strictEqual(makeCallback(resource, process, forward, endpoint), Object);
103+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "addon",
5+
"sources": [ "addon.c" ]
6+
}
7+
]
8+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "make-callback-test",
3+
"version": "0.0.0",
4+
"description": "Tests of runtime async functions",
5+
"main": "addon.js",
6+
"private": true,
7+
"dependencies": {
8+
"bindings": "~1.5.0"
9+
},
10+
"scripts": {
11+
"test": "node addon.js"
12+
},
13+
"gypfile": true
14+
}

0 commit comments

Comments
 (0)