Search code examples
javascriptc++node.js-addonn-api

Calling JS function multiple times from different node addon methods


I'm trying to initialize my node addon module using JS callback for logging. Initialize method is intended to store callback value for calling from other methods. So I add reference to the callback using napi_create_reference.

But when I'm trying to call the callback from my second addon method MyAddonMethod I receive napi_invalid_arg error.

I've tried to investigate the issue. The call to napi_typeof for the callback value from MyAddonMethod returns napi_invalid_arg too. Looks like the callback value was garbage collected despite my strong reference.

What am I doing wrong? Does napi_create_reference actually prevents callback object from being garbage collected between addon calls?

// JS side:
const addon = require('./addon.node');
function logCallbackFunction(logLine)
{
    console.log("Trace: " + logLine);
}
addon.Initialize(logCallbackFunction);
addon.MyAddonMethod();

// C++ side
// Initialize method:
napi_ref ref;
napi_create_reference(env, value, 1, &ref);
g_Value = value; // store the value somewhere between calls

// MyAddonMethod method: // "env" doesn't change from call to call
napi_valuetype type;
napi_status stat = napi_typeof(env, g_Value, &type); // napi_invalid_arg

Solution

  • I've finally found what I was doing wrong. It is not eligible to store g_Value between calls. Instead napi_ref should be stored and napi_get_reference_value function used in order to extract the corresponded value. So the C++ side code should look like this:

    // Initialize method:
    napi_ref ref;
    napi_create_reference(env, value, 1, &ref);
    g_Ref = ref; // store the reference somewhere between calls
    
    // MyAddonMethod method:
    napi_value referenceValue;
    napi_get_reference_value(env, g_Ref, &referenceValue);
    napi_valuetype type;
    napi_status stat = napi_typeof(env, referenceValue, &type); // napi_ok, napi_function
    

    Of course you should not forget to release the reference using napi_delete_reference when it is not needed anymore.