• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <node_api.h>
2 #include "../../js-native-api/common.h"
3 #include "stdlib.h"
4 
5 static uint32_t finalizeCount = 0;
6 
FreeData(node_api_nogc_env env,void * data,void * hint)7 static void FreeData(node_api_nogc_env env, void* data, void* hint) {
8   NODE_API_NOGC_ASSERT_RETURN_VOID(data != NULL, "Expects non-NULL data.");
9   free(data);
10 }
11 
Finalize(node_api_nogc_env env,void * data,void * hint)12 static void Finalize(node_api_nogc_env env, void* data, void* hint) {
13   ++finalizeCount;
14 }
15 
GetArgValue(napi_env env,napi_callback_info info,napi_value * argValue)16 static napi_status GetArgValue(napi_env env,
17                                napi_callback_info info,
18                                napi_value* argValue) {
19   size_t argc = 1;
20   NODE_API_CHECK_STATUS(
21       napi_get_cb_info(env, info, &argc, argValue, NULL, NULL));
22 
23   NODE_API_ASSERT_STATUS(env, argc == 1, "Expects one arg.");
24   return napi_ok;
25 }
26 
GetArgValueAsIndex(napi_env env,napi_callback_info info,uint32_t * index)27 static napi_status GetArgValueAsIndex(napi_env env,
28                                       napi_callback_info info,
29                                       uint32_t* index) {
30   napi_value argValue;
31   NODE_API_CHECK_STATUS(GetArgValue(env, info, &argValue));
32 
33   napi_valuetype valueType;
34   NODE_API_CHECK_STATUS(napi_typeof(env, argValue, &valueType));
35   NODE_API_ASSERT_STATUS(
36       env, valueType == napi_number, "Argument must be a number.");
37 
38   return napi_get_value_uint32(env, argValue, index);
39 }
40 
GetRef(napi_env env,napi_callback_info info,napi_ref * ref)41 static napi_status GetRef(napi_env env,
42                           napi_callback_info info,
43                           napi_ref* ref) {
44   uint32_t index;
45   NODE_API_CHECK_STATUS(GetArgValueAsIndex(env, info, &index));
46 
47   napi_ref* refValues;
48   NODE_API_CHECK_STATUS(napi_get_instance_data(env, (void**)&refValues));
49   NODE_API_ASSERT_STATUS(env, refValues != NULL, "Cannot get instance data.");
50 
51   *ref = refValues[index];
52   return napi_ok;
53 }
54 
ToUInt32Value(napi_env env,uint32_t value)55 static napi_value ToUInt32Value(napi_env env, uint32_t value) {
56   napi_value result;
57   NODE_API_CALL(env, napi_create_uint32(env, value, &result));
58   return result;
59 }
60 
InitRefArray(napi_env env)61 static napi_status InitRefArray(napi_env env) {
62   // valueRefs array has one entry per napi_valuetype
63   napi_ref* valueRefs = malloc(sizeof(napi_ref) * ((int)napi_bigint + 1));
64   return napi_set_instance_data(env, valueRefs, (napi_finalize)&FreeData, NULL);
65 }
66 
CreateExternal(napi_env env,napi_callback_info info)67 static napi_value CreateExternal(napi_env env, napi_callback_info info) {
68   napi_value result;
69   int* data = (int*)malloc(sizeof(int));
70   *data = 42;
71   NODE_API_CALL(env, napi_create_external(env, data, &FreeData, NULL, &result));
72   return result;
73 }
74 
CreateRef(napi_env env,napi_callback_info info)75 static napi_value CreateRef(napi_env env, napi_callback_info info) {
76   napi_value argValue;
77   NODE_API_CALL(env, GetArgValue(env, info, &argValue));
78 
79   napi_valuetype valueType;
80   NODE_API_CALL(env, napi_typeof(env, argValue, &valueType));
81   uint32_t index = (uint32_t)valueType;
82 
83   napi_ref* valueRefs;
84   NODE_API_CALL(env, napi_get_instance_data(env, (void**)&valueRefs));
85   NODE_API_CALL(env,
86                 napi_create_reference(env, argValue, 1, valueRefs + index));
87 
88   return ToUInt32Value(env, index);
89 }
90 
GetRefValue(napi_env env,napi_callback_info info)91 static napi_value GetRefValue(napi_env env, napi_callback_info info) {
92   napi_ref refValue;
93   NODE_API_CALL(env, GetRef(env, info, &refValue));
94   napi_value value;
95   NODE_API_CALL(env, napi_get_reference_value(env, refValue, &value));
96   return value;
97 }
98 
Ref(napi_env env,napi_callback_info info)99 static napi_value Ref(napi_env env, napi_callback_info info) {
100   napi_ref refValue;
101   NODE_API_CALL(env, GetRef(env, info, &refValue));
102   uint32_t refCount;
103   NODE_API_CALL(env, napi_reference_ref(env, refValue, &refCount));
104   return ToUInt32Value(env, refCount);
105 }
106 
Unref(napi_env env,napi_callback_info info)107 static napi_value Unref(napi_env env, napi_callback_info info) {
108   napi_ref refValue;
109   NODE_API_CALL(env, GetRef(env, info, &refValue));
110   uint32_t refCount;
111   NODE_API_CALL(env, napi_reference_unref(env, refValue, &refCount));
112   return ToUInt32Value(env, refCount);
113 }
114 
DeleteRef(napi_env env,napi_callback_info info)115 static napi_value DeleteRef(napi_env env, napi_callback_info info) {
116   napi_ref refValue;
117   NODE_API_CALL(env, GetRef(env, info, &refValue));
118   NODE_API_CALL(env, napi_delete_reference(env, refValue));
119   return NULL;
120 }
121 
AddFinalizer(napi_env env,napi_callback_info info)122 static napi_value AddFinalizer(napi_env env, napi_callback_info info) {
123   napi_value obj;
124   NODE_API_CALL(env, GetArgValue(env, info, &obj));
125 
126   napi_valuetype valueType;
127   NODE_API_CALL(env, napi_typeof(env, obj, &valueType));
128   NODE_API_ASSERT(env, valueType == napi_object, "Argument must be an object.");
129 
130   NODE_API_CALL(env, napi_add_finalizer(env, obj, NULL, &Finalize, NULL, NULL));
131   return NULL;
132 }
133 
GetFinalizeCount(napi_env env,napi_callback_info info)134 static napi_value GetFinalizeCount(napi_env env, napi_callback_info info) {
135   return ToUInt32Value(env, finalizeCount);
136 }
137 
InitFinalizeCount(napi_env env,napi_callback_info info)138 static napi_value InitFinalizeCount(napi_env env, napi_callback_info info) {
139   finalizeCount = 0;
140   return NULL;
141 }
142 
143 EXTERN_C_START
144 
NAPI_MODULE_INIT()145 NAPI_MODULE_INIT() {
146   finalizeCount = 0;
147   NODE_API_CALL(env, InitRefArray(env));
148 
149   napi_property_descriptor properties[] = {
150       DECLARE_NODE_API_PROPERTY("createExternal", CreateExternal),
151       DECLARE_NODE_API_PROPERTY("createRef", CreateRef),
152       DECLARE_NODE_API_PROPERTY("getRefValue", GetRefValue),
153       DECLARE_NODE_API_PROPERTY("ref", Ref),
154       DECLARE_NODE_API_PROPERTY("unref", Unref),
155       DECLARE_NODE_API_PROPERTY("deleteRef", DeleteRef),
156       DECLARE_NODE_API_PROPERTY("addFinalizer", AddFinalizer),
157       DECLARE_NODE_API_PROPERTY("getFinalizeCount", GetFinalizeCount),
158       DECLARE_NODE_API_PROPERTY("initFinalizeCount", InitFinalizeCount),
159   };
160 
161   NODE_API_CALL(
162       env,
163       napi_define_properties(
164           env, exports, sizeof(properties) / sizeof(*properties), properties));
165 
166   return exports;
167 }
168 
169 EXTERN_C_END
170