11cb0ef41Sopenharmony_ci#define NAPI_VERSION 9 21cb0ef41Sopenharmony_ci#include <assert.h> 31cb0ef41Sopenharmony_ci#include <js_native_api.h> 41cb0ef41Sopenharmony_ci#include <stdlib.h> 51cb0ef41Sopenharmony_ci#include "../common.h" 61cb0ef41Sopenharmony_ci#include "../entry_point.h" 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_cistatic int test_value = 1; 91cb0ef41Sopenharmony_cistatic int finalize_count = 0; 101cb0ef41Sopenharmony_cistatic napi_ref test_reference = NULL; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cistatic napi_value GetFinalizeCount(napi_env env, napi_callback_info info) { 131cb0ef41Sopenharmony_ci napi_value result; 141cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_create_int32(env, finalize_count, &result)); 151cb0ef41Sopenharmony_ci return result; 161cb0ef41Sopenharmony_ci} 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cistatic void FinalizeExternal(napi_env env, void* data, void* hint) { 191cb0ef41Sopenharmony_ci int *actual_value = data; 201cb0ef41Sopenharmony_ci NODE_API_ASSERT_RETURN_VOID(env, actual_value == &test_value, 211cb0ef41Sopenharmony_ci "The correct pointer was passed to the finalizer"); 221cb0ef41Sopenharmony_ci finalize_count++; 231cb0ef41Sopenharmony_ci} 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cistatic napi_value CreateExternal(napi_env env, napi_callback_info info) { 261cb0ef41Sopenharmony_ci int* data = &test_value; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci napi_value result; 291cb0ef41Sopenharmony_ci NODE_API_CALL(env, 301cb0ef41Sopenharmony_ci napi_create_external(env, 311cb0ef41Sopenharmony_ci data, 321cb0ef41Sopenharmony_ci NULL, /* finalize_cb */ 331cb0ef41Sopenharmony_ci NULL, /* finalize_hint */ 341cb0ef41Sopenharmony_ci &result)); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci finalize_count = 0; 371cb0ef41Sopenharmony_ci return result; 381cb0ef41Sopenharmony_ci} 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cistatic napi_value CreateSymbol(napi_env env, napi_callback_info info) { 411cb0ef41Sopenharmony_ci size_t argc = 1; 421cb0ef41Sopenharmony_ci napi_value args[1]; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 451cb0ef41Sopenharmony_ci NODE_API_ASSERT( 461cb0ef41Sopenharmony_ci env, argc == 1, "Expect one argument only (symbol description)"); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci napi_value result_symbol; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_create_symbol(env, args[0], &result_symbol)); 511cb0ef41Sopenharmony_ci return result_symbol; 521cb0ef41Sopenharmony_ci} 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cistatic napi_value CreateSymbolFor(napi_env env, napi_callback_info info) { 551cb0ef41Sopenharmony_ci size_t argc = 1; 561cb0ef41Sopenharmony_ci napi_value args[1]; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci char description[256]; 591cb0ef41Sopenharmony_ci size_t description_length; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 621cb0ef41Sopenharmony_ci NODE_API_ASSERT( 631cb0ef41Sopenharmony_ci env, argc == 1, "Expect one argument only (symbol description)"); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci NODE_API_CALL( 661cb0ef41Sopenharmony_ci env, 671cb0ef41Sopenharmony_ci napi_get_value_string_utf8( 681cb0ef41Sopenharmony_ci env, args[0], description, sizeof(description), &description_length)); 691cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, 701cb0ef41Sopenharmony_ci description_length <= 255, 711cb0ef41Sopenharmony_ci "Cannot accommodate descriptions longer than 255 bytes"); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci napi_value result_symbol; 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci NODE_API_CALL(env, 761cb0ef41Sopenharmony_ci node_api_symbol_for( 771cb0ef41Sopenharmony_ci env, description, description_length, &result_symbol)); 781cb0ef41Sopenharmony_ci return result_symbol; 791cb0ef41Sopenharmony_ci} 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_cistatic napi_value CreateSymbolForEmptyString(napi_env env, napi_callback_info info) { 821cb0ef41Sopenharmony_ci napi_value result_symbol; 831cb0ef41Sopenharmony_ci NODE_API_CALL(env, node_api_symbol_for(env, NULL, 0, &result_symbol)); 841cb0ef41Sopenharmony_ci return result_symbol; 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_cistatic napi_value CreateSymbolForIncorrectLength(napi_env env, napi_callback_info info) { 881cb0ef41Sopenharmony_ci napi_value result_symbol; 891cb0ef41Sopenharmony_ci NODE_API_CALL(env, node_api_symbol_for(env, NULL, 5, &result_symbol)); 901cb0ef41Sopenharmony_ci return result_symbol; 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_cistatic napi_value 941cb0ef41Sopenharmony_ciCreateExternalWithFinalize(napi_env env, napi_callback_info info) { 951cb0ef41Sopenharmony_ci napi_value result; 961cb0ef41Sopenharmony_ci NODE_API_CALL(env, 971cb0ef41Sopenharmony_ci napi_create_external(env, 981cb0ef41Sopenharmony_ci &test_value, 991cb0ef41Sopenharmony_ci FinalizeExternal, 1001cb0ef41Sopenharmony_ci NULL, /* finalize_hint */ 1011cb0ef41Sopenharmony_ci &result)); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci finalize_count = 0; 1041cb0ef41Sopenharmony_ci return result; 1051cb0ef41Sopenharmony_ci} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_cistatic napi_value CheckExternal(napi_env env, napi_callback_info info) { 1081cb0ef41Sopenharmony_ci size_t argc = 1; 1091cb0ef41Sopenharmony_ci napi_value arg; 1101cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL)); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, argc == 1, "Expected one argument."); 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci napi_valuetype argtype; 1151cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_typeof(env, arg, &argtype)); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, argtype == napi_external, "Expected an external value."); 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci void* data; 1201cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_value_external(env, arg, &data)); 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, data != NULL && *(int*)data == test_value, 1231cb0ef41Sopenharmony_ci "An external data value of 1 was expected."); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci return NULL; 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_cistatic napi_value CreateReference(napi_env env, napi_callback_info info) { 1291cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, test_reference == NULL, 1301cb0ef41Sopenharmony_ci "The test allows only one reference at a time."); 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci size_t argc = 2; 1331cb0ef41Sopenharmony_ci napi_value args[2]; 1341cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 1351cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, argc == 2, "Expected two arguments."); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci uint32_t initial_refcount; 1381cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_value_uint32(env, args[1], &initial_refcount)); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci NODE_API_CALL(env, 1411cb0ef41Sopenharmony_ci napi_create_reference(env, args[0], initial_refcount, &test_reference)); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, test_reference != NULL, 1441cb0ef41Sopenharmony_ci "A reference should have been created."); 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci return NULL; 1471cb0ef41Sopenharmony_ci} 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_cistatic napi_value DeleteReference(napi_env env, napi_callback_info info) { 1501cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, test_reference != NULL, 1511cb0ef41Sopenharmony_ci "A reference must have been created."); 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_delete_reference(env, test_reference)); 1541cb0ef41Sopenharmony_ci test_reference = NULL; 1551cb0ef41Sopenharmony_ci return NULL; 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_cistatic napi_value IncrementRefcount(napi_env env, napi_callback_info info) { 1591cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, test_reference != NULL, 1601cb0ef41Sopenharmony_ci "A reference must have been created."); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci uint32_t refcount; 1631cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_reference_ref(env, test_reference, &refcount)); 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci napi_value result; 1661cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_create_uint32(env, refcount, &result)); 1671cb0ef41Sopenharmony_ci return result; 1681cb0ef41Sopenharmony_ci} 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_cistatic napi_value DecrementRefcount(napi_env env, napi_callback_info info) { 1711cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, test_reference != NULL, 1721cb0ef41Sopenharmony_ci "A reference must have been created."); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci uint32_t refcount; 1751cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_reference_unref(env, test_reference, &refcount)); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci napi_value result; 1781cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_create_uint32(env, refcount, &result)); 1791cb0ef41Sopenharmony_ci return result; 1801cb0ef41Sopenharmony_ci} 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_cistatic napi_value GetReferenceValue(napi_env env, napi_callback_info info) { 1831cb0ef41Sopenharmony_ci NODE_API_ASSERT(env, test_reference != NULL, 1841cb0ef41Sopenharmony_ci "A reference must have been created."); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci napi_value result; 1871cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_reference_value(env, test_reference, &result)); 1881cb0ef41Sopenharmony_ci return result; 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_cistatic void DeleteBeforeFinalizeFinalizer( 1921cb0ef41Sopenharmony_ci napi_env env, void* finalize_data, void* finalize_hint) { 1931cb0ef41Sopenharmony_ci napi_ref* ref = (napi_ref*)finalize_data; 1941cb0ef41Sopenharmony_ci napi_value value; 1951cb0ef41Sopenharmony_ci assert(napi_get_reference_value(env, *ref, &value) == napi_ok); 1961cb0ef41Sopenharmony_ci assert(value == NULL); 1971cb0ef41Sopenharmony_ci napi_delete_reference(env, *ref); 1981cb0ef41Sopenharmony_ci free(ref); 1991cb0ef41Sopenharmony_ci} 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_cistatic napi_value ValidateDeleteBeforeFinalize(napi_env env, napi_callback_info info) { 2021cb0ef41Sopenharmony_ci napi_value wrapObject; 2031cb0ef41Sopenharmony_ci size_t argc = 1; 2041cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &wrapObject, NULL, NULL)); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci napi_ref* ref_t = malloc(sizeof(napi_ref)); 2071cb0ef41Sopenharmony_ci NODE_API_CALL(env, 2081cb0ef41Sopenharmony_ci napi_wrap( 2091cb0ef41Sopenharmony_ci env, wrapObject, ref_t, DeleteBeforeFinalizeFinalizer, NULL, NULL)); 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci // Create a reference that will be eligible for collection at the same 2121cb0ef41Sopenharmony_ci // time as the wrapped object by passing in the same wrapObject. 2131cb0ef41Sopenharmony_ci // This means that the FinalizeOrderValidation callback may be run 2141cb0ef41Sopenharmony_ci // before the finalizer for the newly created reference (there is a finalizer 2151cb0ef41Sopenharmony_ci // behind the scenes even though it cannot be passed to napi_create_reference) 2161cb0ef41Sopenharmony_ci // The Finalizer for the wrap (which is different than the finalizer 2171cb0ef41Sopenharmony_ci // for the reference) calls napi_delete_reference validating that 2181cb0ef41Sopenharmony_ci // napi_delete_reference can be called before the finalizer for the 2191cb0ef41Sopenharmony_ci // reference runs. 2201cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_create_reference(env, wrapObject, 0, ref_t)); 2211cb0ef41Sopenharmony_ci return wrapObject; 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ciEXTERN_C_START 2251cb0ef41Sopenharmony_cinapi_value Init(napi_env env, napi_value exports) { 2261cb0ef41Sopenharmony_ci napi_property_descriptor descriptors[] = { 2271cb0ef41Sopenharmony_ci DECLARE_NODE_API_GETTER("finalizeCount", GetFinalizeCount), 2281cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createExternal", CreateExternal), 2291cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createExternalWithFinalize", 2301cb0ef41Sopenharmony_ci CreateExternalWithFinalize), 2311cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("checkExternal", CheckExternal), 2321cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createReference", CreateReference), 2331cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createSymbol", CreateSymbol), 2341cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createSymbolFor", CreateSymbolFor), 2351cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createSymbolForEmptyString", 2361cb0ef41Sopenharmony_ci CreateSymbolForEmptyString), 2371cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("createSymbolForIncorrectLength", 2381cb0ef41Sopenharmony_ci CreateSymbolForIncorrectLength), 2391cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference), 2401cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount), 2411cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount), 2421cb0ef41Sopenharmony_ci DECLARE_NODE_API_GETTER("referenceValue", GetReferenceValue), 2431cb0ef41Sopenharmony_ci DECLARE_NODE_API_PROPERTY("validateDeleteBeforeFinalize", 2441cb0ef41Sopenharmony_ci ValidateDeleteBeforeFinalize), 2451cb0ef41Sopenharmony_ci }; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci NODE_API_CALL(env, napi_define_properties( 2481cb0ef41Sopenharmony_ci env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci return exports; 2511cb0ef41Sopenharmony_ci} 2521cb0ef41Sopenharmony_ciEXTERN_C_END 253