1#include <node_api.h> 2#include <assert.h> 3#include "../../js-native-api/common.h" 4 5#define MAX_ARGUMENTS 10 6#define RESERVED_ARGS 3 7 8static napi_value MakeCallback(napi_env env, napi_callback_info info) { 9 size_t argc = MAX_ARGUMENTS; 10 size_t n; 11 napi_value args[MAX_ARGUMENTS]; 12 // NOLINTNEXTLINE (readability/null_usage) 13 NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 14 15 NODE_API_ASSERT(env, argc > 0, "Wrong number of arguments"); 16 17 napi_value async_context_wrap = args[0]; 18 napi_value recv = args[1]; 19 napi_value func = args[2]; 20 21 napi_value argv[MAX_ARGUMENTS - RESERVED_ARGS]; 22 for (n = RESERVED_ARGS; n < argc; n += 1) { 23 argv[n - RESERVED_ARGS] = args[n]; 24 } 25 26 napi_valuetype func_type; 27 NODE_API_CALL(env, napi_typeof(env, func, &func_type)); 28 29 napi_async_context context; 30 NODE_API_CALL(env, napi_unwrap(env, async_context_wrap, (void**)&context)); 31 32 napi_value result; 33 if (func_type == napi_function) { 34 NODE_API_CALL(env, napi_make_callback( 35 env, context, recv, func, argc - RESERVED_ARGS, argv, &result)); 36 } else { 37 NODE_API_ASSERT(env, false, "Unexpected argument type"); 38 } 39 40 return result; 41} 42 43static void AsyncDestroyCb(napi_env env, void* data, void* hint) { 44 napi_status status = napi_async_destroy(env, (napi_async_context)data); 45 // We cannot use NODE_API_ASSERT_RETURN_VOID because we need to have a JS 46 // stack below in order to use exceptions. 47 assert(status == napi_ok); 48} 49 50#define CREATE_ASYNC_RESOURCE_ARGC 2 51 52static napi_value CreateAsyncResource(napi_env env, napi_callback_info info) { 53 napi_value async_context_wrap; 54 NODE_API_CALL(env, napi_create_object(env, &async_context_wrap)); 55 56 size_t argc = CREATE_ASYNC_RESOURCE_ARGC; 57 napi_value args[CREATE_ASYNC_RESOURCE_ARGC]; 58 // NOLINTNEXTLINE (readability/null_usage) 59 NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 60 61 napi_value resource = args[0]; 62 napi_value js_destroy_on_finalizer = args[1]; 63 napi_valuetype resource_type; 64 NODE_API_CALL(env, napi_typeof(env, resource, &resource_type)); 65 if (resource_type != napi_object) { 66 resource = NULL; 67 } 68 69 napi_value resource_name; 70 NODE_API_CALL(env, napi_create_string_utf8( 71 env, "test_async", NAPI_AUTO_LENGTH, &resource_name)); 72 73 napi_async_context context; 74 NODE_API_CALL(env, napi_async_init(env, resource, resource_name, &context)); 75 76 bool destroy_on_finalizer = true; 77 if (argc == 2) { 78 NODE_API_CALL(env, napi_get_value_bool(env, js_destroy_on_finalizer, &destroy_on_finalizer)); 79 } 80 if (resource_type == napi_object && destroy_on_finalizer) { 81 NODE_API_CALL(env, napi_add_finalizer( 82 env, resource, (void*)context, AsyncDestroyCb, NULL, NULL)); 83 } 84 NODE_API_CALL(env, napi_wrap(env, async_context_wrap, context, NULL, NULL, NULL)); 85 return async_context_wrap; 86} 87 88#define DESTROY_ASYNC_RESOURCE_ARGC 1 89 90static napi_value DestroyAsyncResource(napi_env env, napi_callback_info info) { 91 size_t argc = DESTROY_ASYNC_RESOURCE_ARGC; 92 napi_value args[DESTROY_ASYNC_RESOURCE_ARGC]; 93 // NOLINTNEXTLINE (readability/null_usage) 94 NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 95 NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); 96 97 napi_value async_context_wrap = args[0]; 98 99 napi_async_context async_context; 100 NODE_API_CALL(env, 101 napi_remove_wrap(env, async_context_wrap, (void**)&async_context)); 102 NODE_API_CALL(env, napi_async_destroy(env, async_context)); 103 104 return async_context_wrap; 105} 106 107static 108napi_value Init(napi_env env, napi_value exports) { 109 napi_value fn; 110 NODE_API_CALL(env, napi_create_function( 111 // NOLINTNEXTLINE (readability/null_usage) 112 env, NULL, NAPI_AUTO_LENGTH, MakeCallback, NULL, &fn)); 113 NODE_API_CALL(env, napi_set_named_property(env, exports, "makeCallback", fn)); 114 NODE_API_CALL(env, napi_create_function( 115 // NOLINTNEXTLINE (readability/null_usage) 116 env, NULL, NAPI_AUTO_LENGTH, CreateAsyncResource, NULL, &fn)); 117 NODE_API_CALL(env, napi_set_named_property( 118 env, exports, "createAsyncResource", fn)); 119 120 NODE_API_CALL(env, napi_create_function( 121 // NOLINTNEXTLINE (readability/null_usage) 122 env, NULL, NAPI_AUTO_LENGTH, DestroyAsyncResource, NULL, &fn)); 123 NODE_API_CALL(env, napi_set_named_property( 124 env, exports, "destroyAsyncResource", fn)); 125 126 return exports; 127} 128 129NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 130