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
TestBadReturnExceptionPending(napi_env env,napi_callback_info info)156 static napi_value TestBadReturnExceptionPending(napi_env env, napi_callback_info info) {
157 napi_throw_error(env, "throwing exception", "throwing exception");
158
159 // addons should only ever return a valid napi_value even if an
160 // exception occurs, but we have seen that the C++ wrapper
161 // with exceptions enabled sometimes returns an invalid value
162 // when an exception is thrown. Test that we ignore the return
163 // value then an exeption is pending. We use 0xFFFFFFFF as a value
164 // that should never be a valid napi_value and node seems to
165 // crash if it is not ignored indicating that it is indeed invalid.
166 return (napi_value)(0xFFFFFFFFF);
167 }
168
169 EXTERN_C_START
Init(napi_env env,napi_value exports)170 napi_value Init(napi_env env, napi_value exports) {
171 napi_value fn1;
172 NAPI_CALL(env, napi_create_function(
173 env, NULL, NAPI_AUTO_LENGTH, TestCallFunction, NULL, &fn1));
174
175 napi_value fn2;
176 NAPI_CALL(env, napi_create_function(
177 env, "Name", NAPI_AUTO_LENGTH, TestFunctionName, NULL, &fn2));
178
179 napi_value fn3;
180 NAPI_CALL(env, napi_create_function(
181 env, "Name_extra", 5, TestFunctionName, NULL, &fn3));
182
183 napi_value fn4;
184 NAPI_CALL(env, napi_create_function(env,
185 "MakeTrackedFunction",
186 NAPI_AUTO_LENGTH,
187 MakeTrackedFunction,
188 NULL,
189 &fn4));
190
191 napi_value fn5;
192 NAPI_CALL(env, napi_create_function(env,
193 "TestCreateFunctionParameters",
194 NAPI_AUTO_LENGTH,
195 TestCreateFunctionParameters,
196 NULL,
197 &fn5));
198
199 napi_value fn6;
200 NAPI_CALL(env,
201 napi_create_function(
202 env, "TestBadReturnExceptionPending", NAPI_AUTO_LENGTH,
203 TestBadReturnExceptionPending, NULL, &fn6));
204
205 NAPI_CALL(env, napi_set_named_property(env, exports, "TestCall", fn1));
206 NAPI_CALL(env, napi_set_named_property(env, exports, "TestName", fn2));
207 NAPI_CALL(env, napi_set_named_property(env, exports, "TestNameShort", fn3));
208 NAPI_CALL(env, napi_set_named_property(env,
209 exports,
210 "MakeTrackedFunction",
211 fn4));
212
213 NAPI_CALL(env, napi_set_named_property(env,
214 exports,
215 "TestCreateFunctionParameters",
216 fn5));
217
218 NAPI_CALL(env,
219 napi_set_named_property(
220 env, exports, "TestBadReturnExceptionPending", fn6));
221
222 return exports;
223 }
224 EXTERN_C_END
225