/* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "node_api.h" #include #define NAPI_CDECL __cdecl // CC-OFFNXT(G.PRE.06) solid logic #define NAPI_FUNCTIONS(op) \ op(napi_module_register) op(napi_create_function) op(napi_set_named_property) op(napi_create_string_utf8) op( \ napi_add_env_cleanup_hook) op(napi_get_last_error_info) op(napi_get_value_bigint_int64) \ op(napi_get_value_bigint_uint64) op(napi_create_object) op(napi_get_arraybuffer_info) op( \ napi_create_bigint_uint64) op(napi_is_typedarray) op(napi_add_finalizer) op(napi_get_typedarray_info) \ op(napi_set_property) op(napi_get_value_bool) op(napi_coerce_to_string) op(napi_get_value_uint32) op( \ napi_get_value_int32) op(napi_throw) op(napi_get_cb_info) op(napi_create_error) \ op(napi_get_value_string_utf8) op(napi_define_properties) op(napi_delete_reference) op( \ napi_get_reference_value) op(napi_open_handle_scope) op(napi_close_handle_scope) \ op(napi_open_escapable_handle_scope) op(napi_close_escapable_handle_scope) op( \ napi_is_exception_pending) op(napi_create_type_error) op(napi_escape_handle) \ op(napi_get_and_clear_last_exception) op(napi_fatal_error) op(napi_create_double) op( \ napi_typeof) op(napi_get_property) op(napi_get_named_property) op(napi_create_reference) \ op(napi_get_global) op(napi_has_property) op(napi_get_undefined) op(napi_get_value_double) \ op(napi_close_callback_scope) op(napi_async_destroy) op(napi_call_function) \ op(napi_get_value_external) op(napi_throw_error) op(napi_create_int32) \ op(napi_create_external_arraybuffer) op(napi_create_typedarray) \ op(napi_create_string_latin1) op(napi_create_async_work) \ op(napi_delete_async_work) op(napi_queue_async_work) \ op(napi_resolve_deferred) op(napi_reject_deferred) \ op(napi_create_promise) op(napi_create_threadsafe_function) \ op(napi_acquire_threadsafe_function) \ op(napi_release_threadsafe_function) \ op(napi_call_threadsafe_function) \ op(napi_is_dataview) op(napi_is_arraybuffer) \ op(napi_get_dataview_info) \ op(napi_get_boolean) \ op(napi_create_uint32) // CC-OFFNXT(G.PRE.09) code generation // CC-OFFNXT(G.PRE.02) code style #define DECL_NAPI_IMPL(fn_name) decltype(&fn_name) p_##fn_name; NAPI_FUNCTIONS(DECL_NAPI_IMPL) bool LoadNapiFunctions() { static bool isLoaded = false; if (isLoaded) { return true; } HMODULE nodeModule = GetModuleHandle(NULL); FARPROC fn_addr = GetProcAddress(nodeModule, "napi_module_register"); if (fn_addr == NULL) { nodeModule = GetModuleHandleA("node.dll"); if (nodeModule == NULL) { return false; } fn_addr = GetProcAddress(nodeModule, "napi_module_register"); if (fn_addr == NULL) { return false; } } bool apiLoadFailed = false; #define GET_NAPI_IMPL(fn_name) \ fn_addr = GetProcAddress(nodeModule, #fn_name); \ if (fn_addr == NULL) \ /* CC-OFFNXT(G.PRE.10) function scope macro */ \ apiLoadFailed = true; \ /* CC-OFFNXT(G.PRE.09) code generation */ \ p_##fn_name = (decltype(p_##fn_name))fn_addr; // Assign the addresses of the needed functions to the "p*" named pointers. NAPI_FUNCTIONS(GET_NAPI_IMPL); // If any required APIs failed to load, return false if (apiLoadFailed) { return false; } isLoaded = true; return true; } NAPI_EXTERN void NAPI_CDECL napi_module_register(napi_module *mod) { LoadNapiFunctions(); p_napi_module_register(mod); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_last_error_info(napi_env env, const napi_extended_error_info **result) { LoadNapiFunctions(); return p_napi_get_last_error_info(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bigint_int64(napi_env env, napi_value value, int64_t *result, bool *lossless) { LoadNapiFunctions(); return p_napi_get_value_bigint_int64(env, value, result, lossless); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bigint_uint64(napi_env env, napi_value value, uint64_t *result, bool *lossless) { LoadNapiFunctions(); return p_napi_get_value_bigint_uint64(env, value, result, lossless); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_object(napi_env env, napi_value *result) { LoadNapiFunctions(); return p_napi_create_object(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_arraybuffer_info(napi_env env, napi_value arraybuffer, void **data, size_t *byte_length) { LoadNapiFunctions(); return p_napi_get_arraybuffer_info(env, arraybuffer, data, byte_length); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_bigint_uint64(napi_env env, uint64_t value, napi_value *result) { LoadNapiFunctions(); return p_napi_create_bigint_uint64(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_is_typedarray(napi_env env, napi_value value, bool *result) { LoadNapiFunctions(); return p_napi_is_typedarray(env, value, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_add_finalizer(napi_env env, napi_value js_object, void *finalize_data, napi_finalize finalize_cb, void *finalize_hint, napi_ref *result) { LoadNapiFunctions(); return p_napi_add_finalizer(env, js_object, finalize_data, finalize_cb, finalize_hint, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_get_typedarray_info(napi_env env, napi_value typedarray, napi_typedarray_type *type, size_t *length, void **data, napi_value *arraybuffer, size_t *byte_offset) { LoadNapiFunctions(); return p_napi_get_typedarray_info(env, typedarray, type, length, data, arraybuffer, byte_offset); } NAPI_EXTERN napi_status NAPI_CDECL napi_set_property(napi_env env, napi_value object, napi_value key, napi_value value) { LoadNapiFunctions(); return p_napi_set_property(env, object, key, value); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bool(napi_env env, napi_value value, bool *result) { LoadNapiFunctions(); return p_napi_get_value_bool(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_string(napi_env env, napi_value value, napi_value *result) { LoadNapiFunctions(); return p_napi_coerce_to_string(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_int32(napi_env env, napi_value value, int32_t *result) { LoadNapiFunctions(); return p_napi_get_value_int32(env, value, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_get_cb_info(napi_env env, napi_callback_info cbinfo, size_t *argc, napi_value *argv, napi_value *this_arg, void **data) { LoadNapiFunctions(); return p_napi_get_cb_info(env, cbinfo, argc, argv, this_arg, data); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_string_utf8(napi_env env, const char *str, size_t length, napi_value *result) { LoadNapiFunctions(); return p_napi_create_string_utf8(env, str, length, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_throw(napi_env env, napi_value error) { LoadNapiFunctions(); return p_napi_throw(env, error); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value *result) { LoadNapiFunctions(); return p_napi_create_error(env, code, msg, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_string_utf8(napi_env env, napi_value value, char *buf, size_t bufsize, size_t *result) { LoadNapiFunctions(); return p_napi_get_value_string_utf8(env, value, buf, bufsize, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_define_properties(napi_env env, napi_value object, size_t property_count, const napi_property_descriptor *properties) { LoadNapiFunctions(); return p_napi_define_properties(env, object, property_count, properties); } NAPI_EXTERN napi_status NAPI_CDECL napi_delete_reference(napi_env env, napi_ref ref) { LoadNapiFunctions(); return p_napi_delete_reference(env, ref); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_reference_value(napi_env env, napi_ref ref, napi_value *result) { LoadNapiFunctions(); return p_napi_get_reference_value(env, ref, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_open_handle_scope(napi_env env, napi_handle_scope *result) { LoadNapiFunctions(); return p_napi_open_handle_scope(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_close_handle_scope(napi_env env, napi_handle_scope scope) { LoadNapiFunctions(); return p_napi_close_handle_scope(env, scope); } NAPI_EXTERN napi_status NAPI_CDECL napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle_scope *result) { return p_napi_open_escapable_handle_scope(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope scope) { LoadNapiFunctions(); return p_napi_close_escapable_handle_scope(env, scope); } NAPI_EXTERN napi_status NAPI_CDECL napi_is_exception_pending(napi_env env, bool *result) { LoadNapiFunctions(); return p_napi_is_exception_pending(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_property(napi_env env, napi_value object, napi_value key, napi_value *result) { LoadNapiFunctions(); return p_napi_get_property(env, object, key, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_uint32(napi_env env, napi_value value, uint32_t *result) { LoadNapiFunctions(); return p_napi_get_value_uint32(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_typeof(napi_env env, napi_value value, napi_valuetype *result) { LoadNapiFunctions(); return p_napi_typeof(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_and_clear_last_exception(napi_env env, napi_value *result) { LoadNapiFunctions(); return p_napi_get_and_clear_last_exception(env, result); } // CC-OFFNXT(G.NAM.03) false positive NAPI_EXTERN NAPI_NO_RETURN void NAPI_CDECL napi_fatal_error(const char *location, size_t locationLen, const char *message, size_t messageLen) { LoadNapiFunctions(); p_napi_fatal_error(location, locationLen, message, messageLen); // Not reachable, but not represented in type signature. UNREACHABLE(); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_external(napi_env env, napi_value value, void **result) { LoadNapiFunctions(); return p_napi_get_value_external(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_double(napi_env env, double value, napi_value *result) { LoadNapiFunctions(); return p_napi_create_double(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_type_error(napi_env env, napi_value code, napi_value msg, napi_value *result) { LoadNapiFunctions(); return p_napi_create_type_error(env, code, msg, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_named_property(napi_env env, napi_value object, const char *utf8name, napi_value *result) { LoadNapiFunctions(); return p_napi_get_named_property(env, object, utf8name, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref *result) { LoadNapiFunctions(); return p_napi_create_reference(env, value, initial_refcount, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, napi_value escapee, napi_value *result); NAPI_EXTERN napi_status NAPI_CDECL napi_get_global(napi_env env, napi_value *result) { LoadNapiFunctions(); return p_napi_get_global(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_has_property(napi_env env, napi_value object, napi_value key, bool *result) { LoadNapiFunctions(); return p_napi_has_property(env, object, key, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_create_function(napi_env env, const char *utf8name, size_t length, napi_callback cb, void *data, napi_value *result) { LoadNapiFunctions(); return p_napi_create_function(env, utf8name, length, cb, data, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, napi_value escapee, napi_value *result) { LoadNapiFunctions(); return p_napi_escape_handle(env, scope, escapee, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_undefined(napi_env env, napi_value *result) { LoadNapiFunctions(); return p_napi_get_undefined(env, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_double(napi_env env, napi_value value, double *result) { LoadNapiFunctions(); return p_napi_get_value_double(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_close_callback_scope(napi_env env, napi_callback_scope scope) { LoadNapiFunctions(); return p_napi_close_callback_scope(env, scope); } NAPI_EXTERN napi_status NAPI_CDECL napi_async_destroy(napi_env env, napi_async_context async_context) { LoadNapiFunctions(); return p_napi_async_destroy(env, async_context); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_call_function(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv, napi_value *result) { LoadNapiFunctions(); return p_napi_call_function(env, recv, func, argc, argv, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_throw_error(napi_env env, const char *code, const char *msg) { LoadNapiFunctions(); return p_napi_throw_error(env, code, msg); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_int32(napi_env env, int32_t value, napi_value *result) { LoadNapiFunctions(); return p_napi_create_int32(env, value, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_create_external_arraybuffer(napi_env env, void *external_data, size_t byte_length, napi_finalize finalize_cb, void *finalize_hint, napi_value *result) { LoadNapiFunctions(); return p_napi_create_external_arraybuffer(env, external_data, byte_length, finalize_cb, finalize_hint, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_create_typedarray(napi_env env, napi_typedarray_type type, size_t length, napi_value array_buffer, size_t byte_offset, napi_value *result) { LoadNapiFunctions(); return p_napi_create_typedarray(env, type, length, array_buffer, byte_offset, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_string_latin1(napi_env env, const char *str, size_t length, napi_value *result) { LoadNapiFunctions(); return p_napi_create_string_latin1(env, str, length, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_create_async_work(napi_env env, napi_value async_resource, napi_value async_resource_name, napi_async_execute_callback execute, napi_async_complete_callback complete, void *data, napi_async_work *result) { LoadNapiFunctions(); return p_napi_create_async_work(env, async_resource, async_resource_name, execute, complete, data, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_delete_async_work(napi_env env, napi_async_work work) { LoadNapiFunctions(); return p_napi_delete_async_work(env, work); } NAPI_EXTERN napi_status NAPI_CDECL napi_queue_async_work(napi_env env, napi_async_work work) { LoadNapiFunctions(); return p_napi_queue_async_work(env, work); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_promise(napi_env env, napi_deferred *deferred, napi_value *promise) { LoadNapiFunctions(); return p_napi_create_promise(env, deferred, promise); } NAPI_EXTERN napi_status NAPI_CDECL napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution) { LoadNapiFunctions(); return p_napi_resolve_deferred(env, deferred, resolution); } NAPI_EXTERN napi_status NAPI_CDECL napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection) { LoadNapiFunctions(); return p_napi_reject_deferred(env, deferred, rejection); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_create_threadsafe_function( napi_env env, napi_value func, napi_value async_resource, napi_value async_resource_name, size_t max_queue_size, size_t initial_thread_count, void *thread_finalize_data, napi_finalize thread_finalize_cb, void *context, napi_threadsafe_function_call_js call_js_cb, napi_threadsafe_function *result) { LoadNapiFunctions(); return p_napi_create_threadsafe_function(env, func, async_resource, async_resource_name, max_queue_size, initial_thread_count, thread_finalize_data, thread_finalize_cb, context, call_js_cb, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_acquire_threadsafe_function(napi_threadsafe_function func) { LoadNapiFunctions(); return p_napi_acquire_threadsafe_function(func); } NAPI_EXTERN napi_status NAPI_CDECL napi_release_threadsafe_function(napi_threadsafe_function func, napi_threadsafe_function_release_mode mode) { LoadNapiFunctions(); return p_napi_release_threadsafe_function(func, mode); } NAPI_EXTERN napi_status NAPI_CDECL napi_call_threadsafe_function(napi_threadsafe_function func, void *data, napi_threadsafe_function_call_mode is_blocking) { LoadNapiFunctions(); return p_napi_call_threadsafe_function(func, data, is_blocking); } NAPI_EXTERN napi_status NAPI_CDECL napi_is_dataview(napi_env env, napi_value value, bool *result) { LoadNapiFunctions(); return p_napi_is_dataview(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_is_arraybuffer(napi_env env, napi_value value, bool *result) { LoadNapiFunctions(); return p_napi_is_arraybuffer(env, value, result); } // CC-OFFNXT(G.FUN.01, huge_method) solid logic NAPI_EXTERN napi_status NAPI_CDECL napi_get_dataview_info(napi_env env, napi_value dataview, size_t *bytelength, void **data, napi_value *arraybuffer, size_t *byte_offset) { LoadNapiFunctions(); return p_napi_get_dataview_info(env, dataview, bytelength, data, arraybuffer, byte_offset); } NAPI_EXTERN napi_status NAPI_CDECL napi_set_named_property(napi_env env, napi_value object, const char *utf8name, napi_value value) { LoadNapiFunctions(); return p_napi_set_named_property(env, object, utf8name, value); } NAPI_EXTERN napi_status NAPI_CDECL napi_get_boolean(napi_env env, bool value, napi_value *result) { LoadNapiFunctions(); return p_napi_get_boolean(env, value, result); } NAPI_EXTERN napi_status NAPI_CDECL napi_create_uint32(napi_env env, uint32_t value, napi_value *result) { LoadNapiFunctions(); return p_napi_create_uint32(env, value, result); }