• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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