Skip to content

Commit efa7c14

Browse files
committed
Add base implementation for returning callbacks in node port.
1 parent c1e8f56 commit efa7c14

File tree

3 files changed

+55
-11
lines changed

3 files changed

+55
-11
lines changed

source/ports/node_port/source/node_port.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ static void * metacall_node_napi_to_value(/* loader_impl_node node_impl,*/ napi_
4444

4545
static napi_value metacall_node_value_to_napi(/* loader_impl_node node_impl,*/ napi_env env, void * arg);
4646

47-
static void * metacall_node_callback(size_t argc, void * args[], void * data);
47+
static void * metacall_node_callback_value_to_napi(size_t argc, void * args[], void * data);
48+
49+
static napi_value metacall_node_callback_napi_to_value(napi_env env, napi_callback_info info);
4850

4951
typedef struct metacall_node_callback_closure_type
5052
{
@@ -58,7 +60,7 @@ typedef struct metacall_node_callback_closure_type
5860

5961
/* BEGIN-TODO: (Maybe) Implement this in the loader, then remove it from here */
6062

61-
void * metacall_node_callback(size_t argc, void * args[], void * data)
63+
void * metacall_node_callback_value_to_napi(size_t argc, void * args[], void * data)
6264
{
6365
metacall_node_callback_closure closure = static_cast<metacall_node_callback_closure>(data);
6466
napi_value ret;
@@ -119,6 +121,38 @@ void * metacall_node_callback(size_t argc, void * args[], void * data)
119121
return result;
120122
}
121123

124+
napi_value metacall_node_callback_napi_to_value(napi_env env, napi_callback_info info)
125+
{
126+
void * f = NULL;
127+
size_t iterator, argc = 0;
128+
129+
napi_get_cb_info(env, info, &argc, NULL, NULL, NULL);
130+
131+
napi_value argv[argc];
132+
void * args[argc];
133+
napi_value recv;
134+
135+
napi_get_cb_info(env, info, &argc, argv, &recv, &f);
136+
137+
for (iterator = 0; iterator < argc; ++iterator)
138+
{
139+
args[iterator] = metacall_node_napi_to_value(env, recv, argv[iterator]);
140+
}
141+
142+
void * ret = metacallfv(f, args);
143+
144+
for (iterator = 0; iterator < argc; ++iterator)
145+
{
146+
metacall_value_destroy(args[iterator]);
147+
}
148+
149+
napi_value result = metacall_node_value_to_napi(env, ret);
150+
151+
metacall_value_destroy(ret);
152+
153+
return result;
154+
}
155+
122156
/* END-TODO */
123157

124158
/* BEGIN-TODO: Remove this, it is duplicated code copied from node loader */
@@ -423,7 +457,7 @@ void * metacall_node_napi_to_value(/*loader_impl_node node_impl,*/ napi_env env,
423457
}
424458
else if (valuetype == napi_function)
425459
{
426-
void * f = metacall_function("__metacall_node_callback__");
460+
void * f = metacall_function("__metacall_node_callback_value_to_napi__");
427461
metacall_node_callback_closure closure = static_cast<metacall_node_callback_closure>(malloc(sizeof(struct metacall_node_callback_closure_type)));
428462
napi_value length;
429463
uint32_t argc;
@@ -609,15 +643,11 @@ napi_value metacall_node_value_to_napi(/* loader_impl_node node_impl,*/ napi_env
609643
}
610644
else if (id == METACALL_FUNCTION)
611645
{
612-
/* TODO: Implement function to pass callbacks through the callback again */
613-
/*
614646
void * f = metacall_value_to_function(arg_value);
615647

616-
// TODO:
617-
status = napi_create_double(env, double_value, &v);
648+
status = napi_create_function(env, NULL, 0, metacall_node_callback_napi_to_value, f, &v);
618649

619650
metacall_node_exception(env, status);
620-
*/
621651
}
622652
else
623653
{
@@ -863,7 +893,7 @@ napi_value metacall_node_initialize(napi_env env, napi_value exports)
863893
return NULL;
864894
}
865895

866-
if (metacall_register("__metacall_node_callback__", metacall_node_callback, METACALL_INVALID, 0) != 0)
896+
if (metacall_register("__metacall_node_callback_value_to_napi__", metacall_node_callback_value_to_napi, METACALL_INVALID, 0) != 0)
867897
{
868898
/* TODO: Show error message (when error handling is properly implemented in the core lib) */
869899
napi_throw_error(env, NULL, "MetaCall failed to initialize callback support");

source/ports/node_port/test/index.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,23 @@ describe('metacall', () => {
110110
describe('callback', () => {
111111
it('callback (py)', () => {
112112
const f = require('function.py');
113-
const c = 5;
114113
assert.notStrictEqual(f, undefined);
114+
115+
// Passing callback as an argument
116+
const c = 5;
115117
assert.strictEqual(f.function_with_args((a, b) => {
116118
const result = a + b + c;
119+
assert.strictEqual(a, 2);
120+
assert.strictEqual(b, 3);
121+
assert.strictEqual(c, 5);
117122
console.log(`${a} + ${b} + ${c} = ${result}`);
118123
return result;
119124
}, 2, 3), 10);
125+
126+
// Passing callback as a return value
127+
const callback = f.function_ret_lambda(10);
128+
assert.notStrictEqual(callback, undefined);
129+
assert.strictEqual(callback(3), 30);
120130
});
121131
});
122132
});

source/scripts/python/function/source/function.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ def function_with_args(cb, left, right):
88
print('Executing:', cb, '(', left, ',', right, ')');
99
return cb(left, right);
1010

11+
def print_and_return(x):
12+
print('Executing lambda with argument:', x);
13+
return x;
14+
1115
def function_ret_lambda(y):
1216
print('Returning lambda with captured arg:', y);
13-
return lambda x: x * y
17+
return lambda x: print_and_return(x) * y

0 commit comments

Comments
 (0)