1 #include <js_native_api.h>
2 #include "../common.h"
3
TestCreateFunctionParameters(napi_env env,napi_callback_info info)4 static napi_value TestCreateFunctionParameters(napi_env env,
5 napi_callback_info info) {
6 napi_status status;
7 napi_value result, return_value;
8
9 NAPI_CALL(env, napi_create_object(env, &return_value));
10
11 status = napi_create_function(NULL,
12 "TrackedFunction",
13 NAPI_AUTO_LENGTH,
14 TestCreateFunctionParameters,
15 NULL,
16 &result);
17
18 add_returned_status(env,
19 "envIsNull",
20 return_value,
21 "Invalid argument",
22 napi_invalid_arg,
23 status);
24
25 napi_create_function(env,
26 NULL,
27 NAPI_AUTO_LENGTH,
28 TestCreateFunctionParameters,
29 NULL,
30 &result);
31
32 add_last_status(env, "nameIsNull", return_value);
33
34 napi_create_function(env,
35 "TrackedFunction",
36 NAPI_AUTO_LENGTH,
37 NULL,
38 NULL,
39 &result);
40
41 add_last_status(env, "cbIsNull", return_value);
42
43 napi_create_function(env,
44 "TrackedFunction",
45 NAPI_AUTO_LENGTH,
46 TestCreateFunctionParameters,
47 NULL,
48 NULL);
49
50 add_last_status(env, "resultIsNull", return_value);
51
52 return return_value;
53 }
54
TestCallFunction(napi_env env,napi_callback_info info)55 static napi_value TestCallFunction(napi_env env, napi_callback_info info) {
56 size_t argc = 10;
57 napi_value args[10];
58 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
59
60 NAPI_ASSERT(env, argc > 0, "Wrong number of arguments");
61
62 napi_valuetype valuetype0;
63 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
64
65 NAPI_ASSERT(env, valuetype0 == napi_function,
66 "Wrong type of arguments. Expects a function as first argument.");
67
68 napi_value* argv = args + 1;
69 argc = argc - 1;
70
71 napi_value global;
72 NAPI_CALL(env, napi_get_global(env, &global));
73
74 napi_value result;
75 NAPI_CALL(env, napi_call_function(env, global, args[0], argc, argv, &result));
76
77 return result;
78 }
79
TestFunctionName(napi_env env,napi_callback_info info)80 static napi_value TestFunctionName(napi_env env, napi_callback_info info) {
81 return NULL;
82 }
83
finalize_function(napi_env env,void * data,void * hint)84 static void finalize_function(napi_env env, void* data, void* hint) {
85 napi_ref ref = data;
86
87 // Retrieve the JavaScript undefined value.
88 napi_value undefined;
89 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
90
91 // Retrieve the JavaScript function we must call.
92 napi_value js_function;
93 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, ref, &js_function));
94
95 // Call the JavaScript function to indicate that the generated JavaScript
96 // function is about to be gc-ed.
97 NAPI_CALL_RETURN_VOID(env, napi_call_function(env,
98 undefined,
99 js_function,
100 0,
101 NULL,
102 NULL));
103
104 // Destroy the persistent reference to the function we just called so as to
105 // properly clean up.
106 NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, ref));
107 }
108
MakeTrackedFunction(napi_env env,napi_callback_info info)109 static napi_value MakeTrackedFunction(napi_env env, napi_callback_info info) {
110 size_t argc = 1;
111 napi_value js_finalize_cb;
112 napi_valuetype arg_type;
113
114 // Retrieve and validate from the arguments the function we will use to
115 // indicate to JavaScript that the function we are about to create is about to
116 // be gc-ed.
117 NAPI_CALL(env, napi_get_cb_info(env,
118 info,
119 &argc,
120 &js_finalize_cb,
121 NULL,
122 NULL));
123 NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
124 NAPI_CALL(env, napi_typeof(env, js_finalize_cb, &arg_type));
125 NAPI_ASSERT(env, arg_type == napi_function, "Argument must be a function");
126
127 // Dynamically create a function.
128 napi_value result;
129 NAPI_CALL(env, napi_create_function(env,
130 "TrackedFunction",
131 NAPI_AUTO_LENGTH,
132 TestFunctionName,
133 NULL,
134 &result));
135
136 // Create a strong reference to the function we will call when the tracked
137 // function is about to be gc-ed.
138 napi_ref js_finalize_cb_ref;
139 NAPI_CALL(env, napi_create_reference(env,
140 js_finalize_cb,
141 1,
142 &js_finalize_cb_ref));
143
144 // Attach a finalizer to the dynamically created function and pass it the
145 // strong reference we created in the previous step.
146 NAPI_CALL(env, napi_wrap(env,
147 result,
148 js_finalize_cb_ref,
149 finalize_function,
150 NULL,
151 NULL));
152
153 return result;
154 }
155
156 EXTERN_C_START
Init(napi_env env,napi_value exports)157 napi_value Init(napi_env env, napi_value exports) {
158 napi_value fn1;
159 NAPI_CALL(env, napi_create_function(
160 env, NULL, NAPI_AUTO_LENGTH, TestCallFunction, NULL, &fn1));
161
162 napi_value fn2;
163 NAPI_CALL(env, napi_create_function(
164 env, "Name", NAPI_AUTO_LENGTH, TestFunctionName, NULL, &fn2));
165
166 napi_value fn3;
167 NAPI_CALL(env, napi_create_function(
168 env, "Name_extra", 5, TestFunctionName, NULL, &fn3));
169
170 napi_value fn4;
171 NAPI_CALL(env, napi_create_function(env,
172 "MakeTrackedFunction",
173 NAPI_AUTO_LENGTH,
174 MakeTrackedFunction,
175 NULL,
176 &fn4));
177
178 napi_value fn5;
179 NAPI_CALL(env, napi_create_function(env,
180 "TestCreateFunctionParameters",
181 NAPI_AUTO_LENGTH,
182 TestCreateFunctionParameters,
183 NULL,
184 &fn5));
185
186 NAPI_CALL(env, napi_set_named_property(env, exports, "TestCall", fn1));
187 NAPI_CALL(env, napi_set_named_property(env, exports, "TestName", fn2));
188 NAPI_CALL(env, napi_set_named_property(env, exports, "TestNameShort", fn3));
189 NAPI_CALL(env, napi_set_named_property(env,
190 exports,
191 "MakeTrackedFunction",
192 fn4));
193
194 NAPI_CALL(env, napi_set_named_property(env,
195 exports,
196 "TestCreateFunctionParameters",
197 fn5));
198
199 return exports;
200 }
201 EXTERN_C_END
202