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