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