Skip to content

Commit 97a6e04

Browse files
committed
Solve memory leak with return values related to functions, now instead of deleting the return value (which forces to delete the lambda callback when it is anonymous as it does not have references to any handle) we created a finalizer (for old NodeJS versions and newer ones) which deletes the value when it is garbage collected instead of inmedietly after the return.
1 parent 589d38b commit 97a6e04

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

source/ports/node_port/source/node_port.cpp

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,9 @@ napi_value metacall_node_call(napi_env env, napi_callback_info info)
677677
char name[FUNCTION_NAME_LENGTH];
678678
size_t name_length;
679679

680-
napi_get_value_string_utf8(env, argv[0], name, FUNCTION_NAME_LENGTH, &name_length);
680+
napi_status status = napi_get_value_string_utf8(env, argv[0], name, FUNCTION_NAME_LENGTH, &name_length);
681+
682+
metacall_node_exception(env, status);
681683

682684
for (size_t i = 1; i < argc; i++)
683685
{
@@ -693,7 +695,47 @@ napi_value metacall_node_call(napi_env env, napi_callback_info info)
693695

694696
napi_value result = metacall_node_value_to_napi(env, ret);
695697

696-
metacall_value_destroy(ret);
698+
auto finalizer = [](napi_env, void * finalize_data, void *)
699+
{
700+
metacall_value_destroy(finalize_data);
701+
};
702+
703+
// Create a finalizer for the value
704+
#if (NAPI_VERSION < 5)
705+
{
706+
napi_value symbol, external;
707+
708+
status = napi_create_symbol(env, nullptr, &symbol);
709+
710+
metacall_node_exception(env, status);
711+
712+
status = napi_create_external(env, ret, finalizer, nullptr, &external);
713+
714+
metacall_node_exception(env, status);
715+
716+
napi_property_descriptor desc =
717+
{
718+
nullptr,
719+
symbol,
720+
nullptr,
721+
nullptr,
722+
nullptr,
723+
external,
724+
napi_default,
725+
nullptr
726+
};
727+
728+
status = napi_define_properties(env, result, 1, &desc);
729+
730+
metacall_node_exception(env, status);
731+
}
732+
#else // NAPI_VERSION >= 5
733+
{
734+
status = napi_add_finalizer(env, result, ret, finalizer, nullptr, nullptr);
735+
736+
metacall_node_exception(env, status);
737+
}
738+
#endif
697739

698740
return result;
699741
}
@@ -727,7 +769,7 @@ napi_value metacall_node_load_from_file(napi_env env, napi_callback_info info)
727769
int met_result = metacall_load_from_file(tagBuf, file_name_strings, sizeof(file_name_strings)/sizeof(file_name_strings[0]), NULL);
728770
if (met_result > 0)
729771
{
730-
napi_throw_error(env, NULL, "Metacall could not load from file");
772+
napi_throw_error(env, NULL, "MetaCall could not load from file");
731773
return NULL;
732774
}
733775

@@ -773,7 +815,7 @@ napi_value metacall_node_load_from_memory(napi_env env, napi_callback_info info)
773815

774816
if (tag == NULL)
775817
{
776-
napi_throw_error(env, NULL, "Metacall could not load from memory, tag allocation failed");
818+
napi_throw_error(env, NULL, "MetaCall could not load from memory, tag allocation failed");
777819
return NULL;
778820
}
779821

@@ -792,7 +834,7 @@ napi_value metacall_node_load_from_memory(napi_env env, napi_callback_info info)
792834

793835
if (script == NULL)
794836
{
795-
napi_throw_error(env, NULL, "Metacall could not load from memory, script allocation failed");
837+
napi_throw_error(env, NULL, "MetaCall could not load from memory, script allocation failed");
796838
return NULL;
797839
}
798840

@@ -804,7 +846,7 @@ napi_value metacall_node_load_from_memory(napi_env env, napi_callback_info info)
804846
// Load script from memory
805847
if (metacall_load_from_memory(tag, script, script_length, NULL) != 0)
806848
{
807-
napi_throw_error(env, NULL, "Metacall could not load from memory");
849+
napi_throw_error(env, NULL, "MetaCall could not load from memory");
808850
return NULL;
809851
}
810852

source/ports/node_port/test/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,9 @@ describe('metacall', () => {
124124
}, 2, 3), 10);
125125

126126
// Passing callback as a return value
127-
/*
128127
const callback = f.function_ret_lambda(10);
129128
assert.notStrictEqual(callback, undefined);
130129
assert.strictEqual(callback(3), 30);
131-
*/
132130
});
133131
});
134132
});

0 commit comments

Comments
 (0)