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 NODE_API_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 NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
59
60 NODE_API_ASSERT(env, argc > 0, "Wrong number of arguments");
61
62 napi_valuetype valuetype0;
63 NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
64
65 NODE_API_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 NODE_API_CALL(env, napi_get_global(env, &global));
73
74 napi_value result;
75 NODE_API_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 NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
90
91 // Retrieve the JavaScript function we must call.
92 napi_value js_function;
93 NODE_API_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 NODE_API_CALL_RETURN_VOID(env,
98 napi_call_function(env, undefined, js_function, 0, NULL, NULL));
99
100 // Destroy the persistent reference to the function we just called so as to
101 // properly clean up.
102 NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, ref));
103 }
104
MakeTrackedFunction(napi_env env,napi_callback_info info)105 static napi_value MakeTrackedFunction(napi_env env, napi_callback_info info) {
106 size_t argc = 1;
107 napi_value js_finalize_cb;
108 napi_valuetype arg_type;
109
110 // Retrieve and validate from the arguments the function we will use to
111 // indicate to JavaScript that the function we are about to create is about to
112 // be gc-ed.
113 NODE_API_CALL(env,
114 napi_get_cb_info(env, info, &argc, &js_finalize_cb, NULL, NULL));
115 NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments");
116 NODE_API_CALL(env, napi_typeof(env, js_finalize_cb, &arg_type));
117 NODE_API_ASSERT(env, arg_type == napi_function, "Argument must be a function");
118
119 // Dynamically create a function.
120 napi_value result;
121 NODE_API_CALL(env,
122 napi_create_function(
123 env, "TrackedFunction", NAPI_AUTO_LENGTH, TestFunctionName, NULL,
124 &result));
125
126 // Create a strong reference to the function we will call when the tracked
127 // function is about to be gc-ed.
128 napi_ref js_finalize_cb_ref;
129 NODE_API_CALL(env,
130 napi_create_reference(env, js_finalize_cb, 1, &js_finalize_cb_ref));
131
132 // Attach a finalizer to the dynamically created function and pass it the
133 // strong reference we created in the previous step.
134 NODE_API_CALL(env,
135 napi_wrap(
136 env, result, js_finalize_cb_ref, finalize_function, NULL, NULL));
137
138 return result;
139 }
140
TestBadReturnExceptionPending(napi_env env,napi_callback_info info)141 static napi_value TestBadReturnExceptionPending(napi_env env, napi_callback_info info) {
142 napi_throw_error(env, "throwing exception", "throwing exception");
143
144 // addons should only ever return a valid napi_value even if an
145 // exception occurs, but we have seen that the C++ wrapper
146 // with exceptions enabled sometimes returns an invalid value
147 // when an exception is thrown. Test that we ignore the return
148 // value then an exeption is pending. We use 0xFFFFFFFF as a value
149 // that should never be a valid napi_value and node seems to
150 // crash if it is not ignored indicating that it is indeed invalid.
151 return (napi_value)(0xFFFFFFFFF);
152 }
153
154 EXTERN_C_START
Init(napi_env env,napi_value exports)155 napi_value Init(napi_env env, napi_value exports) {
156 napi_value fn1;
157 NODE_API_CALL(env, napi_create_function(
158 env, NULL, NAPI_AUTO_LENGTH, TestCallFunction, NULL, &fn1));
159
160 napi_value fn2;
161 NODE_API_CALL(env, napi_create_function(
162 env, "Name", NAPI_AUTO_LENGTH, TestFunctionName, NULL, &fn2));
163
164 napi_value fn3;
165 NODE_API_CALL(env, napi_create_function(
166 env, "Name_extra", 5, TestFunctionName, NULL, &fn3));
167
168 napi_value fn4;
169 NODE_API_CALL(env,
170 napi_create_function(
171 env, "MakeTrackedFunction", NAPI_AUTO_LENGTH, MakeTrackedFunction,
172 NULL, &fn4));
173
174 napi_value fn5;
175 NODE_API_CALL(env,
176 napi_create_function(
177 env, "TestCreateFunctionParameters", NAPI_AUTO_LENGTH,
178 TestCreateFunctionParameters, NULL, &fn5));
179
180 napi_value fn6;
181 NODE_API_CALL(env,
182 napi_create_function(
183 env, "TestBadReturnExceptionPending", NAPI_AUTO_LENGTH,
184 TestBadReturnExceptionPending, NULL, &fn6));
185
186 NODE_API_CALL(env, napi_set_named_property(env, exports, "TestCall", fn1));
187 NODE_API_CALL(env, napi_set_named_property(env, exports, "TestName", fn2));
188 NODE_API_CALL(env,
189 napi_set_named_property(env, exports, "TestNameShort", fn3));
190 NODE_API_CALL(env,
191 napi_set_named_property(env, exports, "MakeTrackedFunction", fn4));
192
193 NODE_API_CALL(env,
194 napi_set_named_property(
195 env, exports, "TestCreateFunctionParameters", fn5));
196
197 NODE_API_CALL(env,
198 napi_set_named_property(
199 env, exports, "TestBadReturnExceptionPending", fn6));
200
201 return exports;
202 }
203 EXTERN_C_END
204