4040
4141static inline void metacall_node_exception (napi_env env, napi_status status);
4242
43- static void * metacall_node_napi_to_value (/* loader_impl_node node_impl,*/ napi_env env, napi_value v);
43+ static void * metacall_node_napi_to_value (/* loader_impl_node node_impl,*/ napi_env env, napi_value recv, napi_value v);
4444
4545static 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);
48+
49+ typedef struct metacall_node_callback_closure_type
50+ {
51+ napi_env env;
52+ napi_value callback;
53+ napi_value recv;
54+
55+ } * metacall_node_callback_closure;
56+
4757/* -- Methods -- */
4858
59+ /* BEGIN-TODO: (Maybe) Implement this in the loader, then remove it from here */
60+
61+ void * metacall_node_callback (size_t argc, void * args[], void * data)
62+ {
63+ metacall_node_callback_closure closure = static_cast <metacall_node_callback_closure>(data);
64+ napi_value ret;
65+ napi_status status;
66+ napi_value * argv = NULL ;
67+
68+ if (closure == NULL )
69+ {
70+ return NULL ;
71+ }
72+
73+ if (argc > 0 )
74+ {
75+ argv = static_cast <napi_value *>(malloc (sizeof (napi_value *) * argc));
76+
77+ if (argv == NULL )
78+ {
79+ free (closure);
80+ return NULL ;
81+ }
82+
83+ for (uint32_t args_count = 0 ; args_count < argc; ++args_count)
84+ {
85+ argv[args_count] = metacall_node_value_to_napi (closure->env , args[args_count]);
86+ }
87+ }
88+
89+ status = napi_call_function (closure->env , closure->recv , closure->callback , argc, argv, &ret);
90+
91+ metacall_node_exception (closure->env , status);
92+
93+ free (closure);
94+
95+ if (argv != NULL )
96+ {
97+ free (argv);
98+ }
99+
100+ /* return metacall_node_napi_to_value(closure->env, closure->recv, ret);*/
101+ return NULL ;
102+ }
103+
104+ /* END-TODO */
105+
49106/* BEGIN-TODO: Remove this, it is duplicated code copied from node loader */
50107
51108inline void metacall_node_exception (napi_env env, napi_status status)
@@ -132,7 +189,7 @@ inline void metacall_node_exception(napi_env env, napi_status status)
132189 }
133190}
134191
135- void * metacall_node_napi_to_value (/* loader_impl_node node_impl,*/ napi_env env, napi_value v)
192+ void * metacall_node_napi_to_value (/* loader_impl_node node_impl,*/ napi_env env, napi_value recv, napi_value v)
136193{
137194 void * ret = NULL ;
138195
@@ -220,7 +277,7 @@ void * metacall_node_napi_to_value(/*loader_impl_node node_impl,*/ napi_env env,
220277 metacall_node_exception (env, status);
221278
222279 /* TODO: Review recursion overflow */
223- array_value[iterator] = metacall_node_napi_to_value (/* node_impl,*/ env, element);
280+ array_value[iterator] = metacall_node_napi_to_value (/* node_impl,*/ env, recv, element);
224281 }
225282 }
226283 else if (napi_is_buffer (env, v, &result) == napi_ok && result == true )
@@ -340,15 +397,36 @@ void * metacall_node_napi_to_value(/*loader_impl_node node_impl,*/ napi_env env,
340397 metacall_node_exception (env, status);
341398
342399 /* TODO: Review recursion overflow */
343- tupla[1 ] = metacall_node_napi_to_value (/* node_impl,*/ env, element);
400+ tupla[1 ] = metacall_node_napi_to_value (/* node_impl,*/ env, recv, element);
344401 }
345402 }
346403
347404 }
348405 }
349406 else if (valuetype == napi_function)
350407 {
351- /* TODO */
408+ void * f = metacall_function (" __metacall_node_callback__" );
409+ metacall_node_callback_closure closure = static_cast <metacall_node_callback_closure>(malloc (sizeof (struct metacall_node_callback_closure_type )));
410+ napi_value length;
411+ uint32_t argc;
412+
413+ closure->env = env;
414+ closure->callback = v;
415+ closure->recv = recv;
416+
417+ // Get number of arguments to the callback (this workaround should be reviewed)
418+ status = napi_get_named_property (env, v, " length" , &length);
419+
420+ metacall_node_exception (env, status);
421+
422+ status = napi_get_value_uint32 (env, length, &argc);
423+
424+ metacall_node_exception (env, status);
425+
426+ // Workaround for accepting variable arguments
427+ metacall_function_resize (f, (size_t )argc);
428+
429+ return metacall_value_create_function_closure (f, (void *)closure);
352430 }
353431 else if (valuetype == napi_external)
354432 {
@@ -503,6 +581,18 @@ napi_value metacall_node_value_to_napi(/* loader_impl_node node_impl,*/ napi_env
503581 {
504582 /* TODO: Implement promise properly for await */
505583 }
584+ else if (id == METACALL_FUNCTION)
585+ {
586+ /* TODO: Implement function to pass callbacks through the callback again */
587+ /*
588+ void * f = metacall_value_to_function(arg_value);
589+
590+ // TODO:
591+ status = napi_create_double(env, double_value, &v);
592+
593+ metacall_node_exception(env, status);
594+ */
595+ }
506596 else
507597 {
508598 status = napi_get_undefined (env, &v);
@@ -519,22 +609,37 @@ napi_value metacall_node_value_to_napi(/* loader_impl_node node_impl,*/ napi_env
519609napi_value metacall_node_call (napi_env env, napi_callback_info info)
520610{
521611 size_t argc = 0 ;
612+
522613 napi_get_cb_info (env, info, &argc, NULL , NULL , NULL );
614+
523615 napi_value argv[argc];
524- void *metacallArgs[argc - 1 ];
525- napi_get_cb_info (env, info, &argc, argv, NULL , NULL );
526- char functionName[FUNCTION_NAME_LENGTH];
527- size_t writeNumber;
528- napi_get_value_string_utf8 (env, argv[0 ], functionName, FUNCTION_NAME_LENGTH, &writeNumber);
616+ void * args[argc - 1 ];
617+ napi_value recv;
618+
619+ napi_get_cb_info (env, info, &argc, argv, &recv, NULL );
620+
621+ char name[FUNCTION_NAME_LENGTH];
622+ size_t name_length;
623+
624+ napi_get_value_string_utf8 (env, argv[0 ], name, FUNCTION_NAME_LENGTH, &name_length);
625+
529626 for (size_t i = 1 ; i < argc; i++)
530627 {
531- metacallArgs[i - 1 ] = metacall_node_napi_to_value (env, argv[i]);
628+ args[i - 1 ] = metacall_node_napi_to_value (env, recv, argv[i]);
629+ }
630+
631+ void * ret = metacallv (name, args);
632+
633+ for (size_t args_count = 0 ; args_count < argc - 1 ; ++args_count)
634+ {
635+ metacall_value_destroy (args[args_count]);
532636 }
533637
534- // Phew!!!.... after we are done converting JS types to Metacall Type into a single Array Above
535- void * ptr = metacallv (functionName, metacallArgs);
638+ napi_value result = metacall_node_value_to_napi (env, ret);
536639
537- return metacall_node_value_to_napi (env, ptr);
640+ metacall_value_destroy (ret);
641+
642+ return result;
538643}
539644
540645// this function is the handler of the "metacall_load_from_file"
@@ -732,6 +837,14 @@ napi_value metacall_node_initialize(napi_env env, napi_value exports)
732837 return NULL ;
733838 }
734839
840+ if (metacall_register (" __metacall_node_callback__" , metacall_node_callback, METACALL_INVALID, 0 ) != 0 )
841+ {
842+ /* TODO: Show error message (when error handling is properly implemented in the core lib) */
843+ napi_throw_error (env, NULL , " MetaCall failed to initialize callback support" );
844+
845+ return NULL ;
846+ }
847+
735848 metacall_node_exports (env, exports);
736849
737850 return exports;
0 commit comments