• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <js_native_api.h>
5 #include "../common.h"
6 
testStrictEquals(napi_env env,napi_callback_info info)7 static napi_value testStrictEquals(napi_env env, napi_callback_info info) {
8   size_t argc = 2;
9   napi_value args[2];
10   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
11 
12   bool bool_result;
13   napi_value result;
14   NAPI_CALL(env, napi_strict_equals(env, args[0], args[1], &bool_result));
15   NAPI_CALL(env, napi_get_boolean(env, bool_result, &result));
16 
17   return result;
18 }
19 
testGetPrototype(napi_env env,napi_callback_info info)20 static napi_value testGetPrototype(napi_env env, napi_callback_info info) {
21   size_t argc = 1;
22   napi_value args[1];
23   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
24 
25   napi_value result;
26   NAPI_CALL(env, napi_get_prototype(env, args[0], &result));
27 
28   return result;
29 }
30 
testGetVersion(napi_env env,napi_callback_info info)31 static napi_value testGetVersion(napi_env env, napi_callback_info info) {
32   uint32_t version;
33   napi_value result;
34   NAPI_CALL(env, napi_get_version(env, &version));
35   NAPI_CALL(env, napi_create_uint32(env, version, &result));
36   return result;
37 }
38 
doInstanceOf(napi_env env,napi_callback_info info)39 static napi_value doInstanceOf(napi_env env, napi_callback_info info) {
40   size_t argc = 2;
41   napi_value args[2];
42   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
43 
44   bool instanceof;
45   NAPI_CALL(env, napi_instanceof(env, args[0], args[1], &instanceof));
46 
47   napi_value result;
48   NAPI_CALL(env, napi_get_boolean(env, instanceof, &result));
49 
50   return result;
51 }
52 
getNull(napi_env env,napi_callback_info info)53 static napi_value getNull(napi_env env, napi_callback_info info) {
54   napi_value result;
55   NAPI_CALL(env, napi_get_null(env, &result));
56   return result;
57 }
58 
getUndefined(napi_env env,napi_callback_info info)59 static napi_value getUndefined(napi_env env, napi_callback_info info) {
60   napi_value result;
61   NAPI_CALL(env, napi_get_undefined(env, &result));
62   return result;
63 }
64 
createNapiError(napi_env env,napi_callback_info info)65 static napi_value createNapiError(napi_env env, napi_callback_info info) {
66   napi_value value;
67   NAPI_CALL(env, napi_create_string_utf8(env, "xyz", 3, &value));
68 
69   double double_value;
70   napi_status status = napi_get_value_double(env, value, &double_value);
71 
72   NAPI_ASSERT(env, status != napi_ok, "Failed to produce error condition");
73 
74   const napi_extended_error_info *error_info = 0;
75   NAPI_CALL(env, napi_get_last_error_info(env, &error_info));
76 
77   NAPI_ASSERT(env, error_info->error_code == status,
78       "Last error info code should match last status");
79   NAPI_ASSERT(env, error_info->error_message,
80       "Last error info message should not be null");
81 
82   return NULL;
83 }
84 
testNapiErrorCleanup(napi_env env,napi_callback_info info)85 static napi_value testNapiErrorCleanup(napi_env env, napi_callback_info info) {
86   const napi_extended_error_info *error_info = 0;
87   NAPI_CALL(env, napi_get_last_error_info(env, &error_info));
88 
89   napi_value result;
90   bool is_ok = error_info->error_code == napi_ok;
91   NAPI_CALL(env, napi_get_boolean(env, is_ok, &result));
92 
93   return result;
94 }
95 
testNapiTypeof(napi_env env,napi_callback_info info)96 static napi_value testNapiTypeof(napi_env env, napi_callback_info info) {
97   size_t argc = 1;
98   napi_value args[1];
99   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
100 
101   napi_valuetype argument_type;
102   NAPI_CALL(env, napi_typeof(env, args[0], &argument_type));
103 
104   napi_value result = NULL;
105   if (argument_type == napi_number) {
106     NAPI_CALL(env, napi_create_string_utf8(
107         env, "number", NAPI_AUTO_LENGTH, &result));
108   } else if (argument_type == napi_string) {
109     NAPI_CALL(env, napi_create_string_utf8(
110         env, "string", NAPI_AUTO_LENGTH, &result));
111   } else if (argument_type == napi_function) {
112     NAPI_CALL(env, napi_create_string_utf8(
113         env, "function", NAPI_AUTO_LENGTH, &result));
114   } else if (argument_type == napi_object) {
115     NAPI_CALL(env, napi_create_string_utf8(
116         env, "object", NAPI_AUTO_LENGTH, &result));
117   } else if (argument_type == napi_boolean) {
118     NAPI_CALL(env, napi_create_string_utf8(
119         env, "boolean", NAPI_AUTO_LENGTH, &result));
120   } else if (argument_type == napi_undefined) {
121     NAPI_CALL(env, napi_create_string_utf8(
122         env, "undefined", NAPI_AUTO_LENGTH, &result));
123   } else if (argument_type == napi_symbol) {
124     NAPI_CALL(env, napi_create_string_utf8(
125         env, "symbol", NAPI_AUTO_LENGTH, &result));
126   } else if (argument_type == napi_null) {
127     NAPI_CALL(env, napi_create_string_utf8(
128         env, "null", NAPI_AUTO_LENGTH, &result));
129   }
130   return result;
131 }
132 
133 static bool deref_item_called = false;
deref_item(napi_env env,void * data,void * hint)134 static void deref_item(napi_env env, void* data, void* hint) {
135   (void) hint;
136 
137   NAPI_ASSERT_RETURN_VOID(env, data == &deref_item_called,
138     "Finalize callback was called with the correct pointer");
139 
140   deref_item_called = true;
141 }
142 
deref_item_was_called(napi_env env,napi_callback_info info)143 static napi_value deref_item_was_called(napi_env env, napi_callback_info info) {
144   napi_value it_was_called;
145 
146   NAPI_CALL(env, napi_get_boolean(env, deref_item_called, &it_was_called));
147 
148   return it_was_called;
149 }
150 
wrap_first_arg(napi_env env,napi_callback_info info,napi_finalize finalizer,void * data)151 static napi_value wrap_first_arg(napi_env env,
152                                  napi_callback_info info,
153                                  napi_finalize finalizer,
154                                  void* data) {
155   size_t argc = 1;
156   napi_value to_wrap;
157 
158   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &to_wrap, NULL, NULL));
159   NAPI_CALL(env, napi_wrap(env, to_wrap, data, finalizer, NULL, NULL));
160 
161   return to_wrap;
162 }
163 
wrap(napi_env env,napi_callback_info info)164 static napi_value wrap(napi_env env, napi_callback_info info) {
165   deref_item_called = false;
166   return wrap_first_arg(env, info, deref_item, &deref_item_called);
167 }
168 
unwrap(napi_env env,napi_callback_info info)169 static napi_value unwrap(napi_env env, napi_callback_info info) {
170   size_t argc = 1;
171   napi_value wrapped;
172   void* data;
173 
174   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL));
175   NAPI_CALL(env, napi_unwrap(env, wrapped, &data));
176 
177   return NULL;
178 }
179 
remove_wrap(napi_env env,napi_callback_info info)180 static napi_value remove_wrap(napi_env env, napi_callback_info info) {
181   size_t argc = 1;
182   napi_value wrapped;
183   void* data;
184 
185   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL));
186   NAPI_CALL(env, napi_remove_wrap(env, wrapped, &data));
187 
188   return NULL;
189 }
190 
191 static bool finalize_called = false;
test_finalize(napi_env env,void * data,void * hint)192 static void test_finalize(napi_env env, void* data, void* hint) {
193   finalize_called = true;
194 }
195 
test_finalize_wrap(napi_env env,napi_callback_info info)196 static napi_value test_finalize_wrap(napi_env env, napi_callback_info info) {
197   return wrap_first_arg(env, info, test_finalize, NULL);
198 }
199 
finalize_was_called(napi_env env,napi_callback_info info)200 static napi_value finalize_was_called(napi_env env, napi_callback_info info) {
201   napi_value it_was_called;
202 
203   NAPI_CALL(env, napi_get_boolean(env, finalize_called, &it_was_called));
204 
205   return it_was_called;
206 }
207 
testAdjustExternalMemory(napi_env env,napi_callback_info info)208 static napi_value testAdjustExternalMemory(napi_env env, napi_callback_info info) {
209   napi_value result;
210   int64_t adjustedValue;
211 
212   NAPI_CALL(env, napi_adjust_external_memory(env, 1, &adjustedValue));
213   NAPI_CALL(env, napi_create_double(env, (double)adjustedValue, &result));
214 
215   return result;
216 }
217 
testNapiRun(napi_env env,napi_callback_info info)218 static napi_value testNapiRun(napi_env env, napi_callback_info info) {
219   napi_value script, result;
220   size_t argc = 1;
221 
222   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &script, NULL, NULL));
223 
224   NAPI_CALL(env, napi_run_script(env, script, &result));
225 
226   return result;
227 }
228 
finalizer_only_callback(napi_env env,void * data,void * hint)229 static void finalizer_only_callback(napi_env env, void* data, void* hint) {
230   napi_ref js_cb_ref = data;
231   napi_value js_cb, undefined;
232   NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, js_cb_ref, &js_cb));
233   NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
234   NAPI_CALL_RETURN_VOID(env,
235       napi_call_function(env, undefined, js_cb, 0, NULL, NULL));
236   NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, js_cb_ref));
237 }
238 
add_finalizer_only(napi_env env,napi_callback_info info)239 static napi_value add_finalizer_only(napi_env env, napi_callback_info info) {
240   size_t argc = 2;
241   napi_value argv[2];
242   napi_ref js_cb_ref;
243 
244   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
245   NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &js_cb_ref));
246   NAPI_CALL(env,
247       napi_add_finalizer(env,
248                          argv[0],
249                          js_cb_ref,
250                          finalizer_only_callback,
251                          NULL,
252                          NULL));
253   return NULL;
254 }
255 
256 static const char* env_cleanup_finalizer_messages[] = {
257   "simple wrap",
258   "wrap, removeWrap",
259   "first wrap",
260   "second wrap"
261 };
262 
cleanup_env_finalizer(napi_env env,void * data,void * hint)263 static void cleanup_env_finalizer(napi_env env, void* data, void* hint) {
264   (void) env;
265   (void) hint;
266 
267   printf("finalize at env cleanup for %s\n",
268       env_cleanup_finalizer_messages[(uintptr_t)data]);
269 }
270 
env_cleanup_wrap(napi_env env,napi_callback_info info)271 static napi_value env_cleanup_wrap(napi_env env, napi_callback_info info) {
272   size_t argc = 2;
273   napi_value argv[2];
274   uint32_t value;
275   uintptr_t ptr_value;
276   NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
277 
278   NAPI_CALL(env, napi_get_value_uint32(env, argv[1], &value));
279 
280   ptr_value = value;
281   return wrap_first_arg(env, info, cleanup_env_finalizer, (void*)ptr_value);
282 }
283 
284 EXTERN_C_START
Init(napi_env env,napi_value exports)285 napi_value Init(napi_env env, napi_value exports) {
286   napi_property_descriptor descriptors[] = {
287     DECLARE_NAPI_PROPERTY("testStrictEquals", testStrictEquals),
288     DECLARE_NAPI_PROPERTY("testGetPrototype", testGetPrototype),
289     DECLARE_NAPI_PROPERTY("testGetVersion", testGetVersion),
290     DECLARE_NAPI_PROPERTY("testNapiRun", testNapiRun),
291     DECLARE_NAPI_PROPERTY("doInstanceOf", doInstanceOf),
292     DECLARE_NAPI_PROPERTY("getUndefined", getUndefined),
293     DECLARE_NAPI_PROPERTY("getNull", getNull),
294     DECLARE_NAPI_PROPERTY("createNapiError", createNapiError),
295     DECLARE_NAPI_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup),
296     DECLARE_NAPI_PROPERTY("testNapiTypeof", testNapiTypeof),
297     DECLARE_NAPI_PROPERTY("wrap", wrap),
298     DECLARE_NAPI_PROPERTY("envCleanupWrap", env_cleanup_wrap),
299     DECLARE_NAPI_PROPERTY("unwrap", unwrap),
300     DECLARE_NAPI_PROPERTY("removeWrap", remove_wrap),
301     DECLARE_NAPI_PROPERTY("addFinalizerOnly", add_finalizer_only),
302     DECLARE_NAPI_PROPERTY("testFinalizeWrap", test_finalize_wrap),
303     DECLARE_NAPI_PROPERTY("finalizeWasCalled", finalize_was_called),
304     DECLARE_NAPI_PROPERTY("derefItemWasCalled", deref_item_was_called),
305     DECLARE_NAPI_PROPERTY("testAdjustExternalMemory", testAdjustExternalMemory)
306   };
307 
308   NAPI_CALL(env, napi_define_properties(
309       env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
310 
311   return exports;
312 }
313 EXTERN_C_END
314