1#include <js_native_api.h> 2#include "../common.h" 3#include "../entry_point.h" 4 5static 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 56static 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 81static napi_value TestFunctionName(napi_env env, napi_callback_info info) { 82 return NULL; 83} 84 85static 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 106static 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 142static 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 155EXTERN_C_START 156napi_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} 204EXTERN_C_END 205