Search code examples
javascriptnode.jscnode-addon-apinode-api

How to iterate JavaScript array using Node-API


I'm building a Node.js addon using Node-API.

Basically, my algorithm takes a js array as the input and then process it inside the addon and return it.

To do any logic for the array I need to loop through it. But I don't know-how. Because I didn't find any array iteration related documents in their documentation or in examples.

So I think this is more about doing it in C. I have added what I tried on the below code, but not working and I have commented out it in the below code.

I also tried to find anything useful inside nodejs source code and node-addon-api but since my knowledge of this is limited, I didn't.

Please give me guidance on how to loop and access each object inside that array.

napi_value avm_simplify(napi_env env, napi_callback_info info) {
  napi_status status;
  napi_value value;

  size_t argc = 1;
  napi_value args[1];
  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
  STATUS_CHECK

  if (argc < 1) {
    napi_throw_type_error(env, NULL, WRONG_ARGUMENTS_ERROR);
    return NULL;
  }

  bool is_array = 0;
  status = napi_is_array(env, args[0], &is_array);
  STATUS_CHECK

  if (!is_array) {
    napi_throw_type_error(env, NULL, "Argument type should be an array");
    return NULL;
  }

  // args[0] equals to something like
  // [1, 2, 3, 4, 5]
  // which is the user input (js array)
  napi_value array = args[0];

  /*
  // This is what I wan't to do.
  int length = sizeof(array) / sizeof(array[0]);
  for (size_t i = 0; i < length; i++) {
      napi_value object = array[i];
      // do some logic with object
  }
  */

  return value;
}

I know this should be much easier using C++, but my module mostly refers to C libraries in future.

Thanks in advance.


Solution

  • I found https://nodejs.org/api/n-api.html to be a nice read

    Here is how I would iterate (with the status check to be added)

    uint32_t length;
    status = napi_get_array_length(env, array, &length);
    for (uint32_t i = 0; i < length; ++i) {
      napi_value ret;
      napi_get_element(env, array, i, &ret);
    
      int32_t myint;
      napi_get_value_int32(env, ret, &myint);
    

    Below a sample which times 2 each element of the input array in place

    // hello.cc using Node-API
    #include <node_api.h>
    #include <assert.h>
    namespace demo {
    
    napi_value Method(napi_env env, napi_callback_info info) {
      napi_status status;
      napi_value value;
    
      size_t argc = 1;
      napi_value args[1];
      status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
      assert(status == napi_ok);
    
      if (argc < 1) {
        napi_throw_type_error(env, NULL, "Wrong number of arguments");
        return NULL;
      }
    
      bool is_array = 0;
      status = napi_is_array(env, args[0], &is_array);
      assert(status == napi_ok);
    
      if (!is_array) {
        napi_throw_type_error(env, NULL, "Argument type should be an array");
        return NULL;
      }
    
      // args[0] equals to something like
      // [1, 2, 3, 4, 5]
      // which is the user input (js array)
      napi_value array = args[0];
    
      if (!array) {
        std::cout<<"array is null"<<std::endl;
        return NULL;
      }
    
    
      uint32_t length;
      status = napi_get_array_length(env, array, &length);
    
      for (uint32_t i = 0; i < length; ++i) {
        napi_value ret;
        napi_get_element(env, array, i, &ret);
    
        int32_t myint;
        napi_get_value_int32(env, ret, &myint);
    
    
        napi_value result;
        napi_create_int32(env, myint * 2, &result);
        napi_set_element(env, array, i, result);
      }
    
      return array;
    }
    
    // copy pasted
    napi_value init(napi_env env, napi_value exports) {
      napi_status status;
      napi_value fn;
    
      status = napi_create_function(env, nullptr, 0, Method, nullptr, &fn);
      if (status != napi_ok) return nullptr;
    
      status = napi_set_named_property(env, exports, "hello", fn);
      if (status != napi_ok) return nullptr;
      return exports;
    }
    
    NAPI_MODULE(NODE_GYP_MODULE_NAME, init)
    
    }  // namespace demo