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