/* * Copyright (c) 2021 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 "js_common_utils.h" #include #include #include #include "hilog/log_c.h" #include "js_native_api.h" #include "js_native_api_types.h" #include "log_print.h" namespace OHOS { namespace PreferencesJsKit { using namespace OHOS::NativePreferences; int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, std::string &output) { size_t bufferSize = 0; napi_status status = napi_get_value_string_utf8(env, jsValue, nullptr, 0, &bufferSize); if (status != napi_ok) { LOG_DEBUG("get std::string failed, status = %{public}d", status); return NAPI_TYPE_ERROR; } if (bufferSize > MAX_VALUE_LENGTH) { LOG_ERROR("string must be less than the limit length."); return EXCEED_MAX_LENGTH; } char *buffer = (char *)malloc(bufferSize + 1); if (buffer == nullptr) { LOG_ERROR("malloc failed, buffer is nullptr."); return ERR; } status = napi_get_value_string_utf8(env, jsValue, buffer, bufferSize + 1, &bufferSize); if (status != napi_ok) { free(buffer); LOG_DEBUG("JSUtils::Convert2NativeValue get jsVal failed, status = %{public}d", status); return status; } output = buffer; free(buffer); return napi_ok; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, bool &output) { bool bValue = false; napi_status status = napi_get_value_bool(env, jsValue, &bValue); if (status != napi_ok) { LOG_DEBUG("get bool failed, status = %{public}d", status); return NAPI_TYPE_ERROR; } output = bValue; return napi_ok; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, double &output) { double number = 0.0; napi_status status = napi_get_value_double(env, jsValue, &number); if (status != napi_ok) { LOG_DEBUG("get double failed, status = %{public}d", status); return NAPI_TYPE_ERROR; } output = number; return napi_ok; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, float &output) { LOG_DEBUG("Convert2NativeValue js just support double data not support float"); return NAPI_TYPE_ERROR; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, int32_t &output) { LOG_DEBUG("Convert2NativeValue js just support double data not support int32_t"); return NAPI_TYPE_ERROR; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, int64_t &output) { LOG_DEBUG("Convert2NativeValue js just support double data not support int64_t"); return NAPI_TYPE_ERROR; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, std::vector &output) { bool isTypedarray = false; napi_status result = napi_is_typedarray(env, jsValue, &isTypedarray); if (result != napi_ok || !isTypedarray) { LOG_DEBUG("napi_is_typedarray fail. result %{public}d isTypedarray %{public}d", result, isTypedarray); return NAPI_TYPE_ERROR; } napi_typedarray_type type = napi_uint8_array; size_t length = 0; void *data = nullptr; result = napi_get_typedarray_info(env, jsValue, &type, &length, &data, nullptr, nullptr); if (result != napi_ok) { LOG_ERROR("napi_get_typedarray_info fail"); return result; } if (type != napi_uint8_array) { LOG_ERROR("value is not napi_uint8_array"); return NAPI_TYPE_ERROR; } if (length > MAX_VALUE_LENGTH) { LOG_ERROR("unit8Array must be less than the limit length."); return EXCEED_MAX_LENGTH; } output.clear(); if (length > 0) { output.resize(length); output.assign(static_cast(data), static_cast(data) + length); } return napi_ok; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, Object &output) { if (GetValueType(env, jsValue) != napi_object) { LOG_DEBUG("Not of object type."); return NAPI_TYPE_ERROR; } auto [status, jsonStr] = JsonStringify(env, jsValue); if (status != napi_ok) { LOG_ERROR("json stringify failed."); return status; } return Convert2NativeValue(env, jsonStr, output.valueStr); } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, BigInt &output) { if (GetValueType(env, jsValue) != napi_bigint) { LOG_DEBUG("Not of bigint type."); return NAPI_TYPE_ERROR; } size_t wordCount = 0; napi_status status = napi_get_value_bigint_words(env, jsValue, nullptr, &wordCount, nullptr); if (status != napi_ok || wordCount == 0) { LOG_ERROR("get wordCount failed %{public}d wordCount %{public}zu.", status, wordCount); return status; } output.words_.resize(wordCount); status = napi_get_value_bigint_words(env, jsValue, &output.sign_, &wordCount, output.words_.data()); if (status != napi_ok) { LOG_ERROR("napi_get_value_bigint_words failed %{public}d wordCount %{public}zu.", status, wordCount); return status; } return napi_ok; } int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, std::monostate &value) { return NAPI_TYPE_ERROR; } bool JSUtils::Equals(napi_env env, napi_value value, napi_ref copy) { if (copy == nullptr || env == nullptr) { return (value == nullptr); } napi_value copyValue = nullptr; napi_get_reference_value(env, copy, ©Value); bool isEquals = false; napi_strict_equals(env, value, copyValue, &isEquals); return isEquals; } napi_value JSUtils::Convert2JSValue(napi_env env, int32_t value) { napi_value jsValue; if (napi_create_int32(env, value, &jsValue) != napi_ok) { LOG_DEBUG("Convert int32_t failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, uint32_t value) { napi_value jsValue; if (napi_create_uint32(env, value, &jsValue) != napi_ok) { LOG_DEBUG("Convert uint32_t failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, int64_t value) { napi_value jsValue; if (napi_create_int64(env, value, &jsValue) != napi_ok) { LOG_DEBUG("Convert int64_t failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, bool value) { napi_value jsValue; if (napi_get_boolean(env, value, &jsValue) != napi_ok) { LOG_DEBUG("Convert bool failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, double value) { napi_value jsValue; if (napi_create_double(env, value, &jsValue) != napi_ok) { LOG_DEBUG("Convert double failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, float value) { napi_value jsValue; if (napi_create_double(env, value, &jsValue) != napi_ok) { LOG_DEBUG("Convert float failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &value) { size_t size = value.size(); void *data = nullptr; napi_value buffer = nullptr; napi_status ret = napi_create_arraybuffer(env, size, &data, &buffer); if (ret != napi_ok) { LOG_ERROR("napi_create_arraybuffer failed %{public}d", ret); return nullptr; } if (size != 0) { std::copy(value.begin(), value.end(), static_cast(data)); } napi_value napiValue = nullptr; ret = napi_create_typedarray(env, napi_uint8_array, size, buffer, 0, &napiValue); if (ret != napi_ok) { LOG_ERROR("napi_create_typedarray failed %{public}d", ret); return nullptr; } return napiValue; } napi_value JSUtils::Convert2JSValue(napi_env env, const Object &value) { napi_value jsValue = JsonParse(env, value.valueStr); if (jsValue == nullptr) { LOG_ERROR("Convert object failed"); } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, const std::string &value) { napi_value jsValue = nullptr; if (napi_create_string_utf8(env, value.c_str(), value.size(), &jsValue) != napi_ok) { LOG_DEBUG("Convert std::string failed"); return nullptr; } return jsValue; } napi_value JSUtils::Convert2JSValue(napi_env env, const BigInt &value) { napi_value bigint = nullptr; napi_status status = napi_create_bigint_words(env, value.sign_, value.words_.size(), value.words_.data(), &bigint); if (status != napi_ok || bigint == nullptr) { LOG_ERROR("napi_create_bigint_words failed %{public}d", status); return nullptr; } return bigint; } napi_value JSUtils::Convert2JSValue(napi_env env, const std::monostate &value) { napi_value result = nullptr; napi_get_null(env, &result); return result; } napi_valuetype JSUtils::GetValueType(napi_env env, napi_value value) { napi_valuetype valueType = napi_undefined; napi_typeof(env, value, &valueType); return valueType; } std::tuple JSUtils::JsonStringify(napi_env env, napi_value value) { napi_value global = nullptr; napi_status status = napi_get_global(env, &global); PRE_CHECK_RETURN_CORE(status == napi_ok, PRE_REVT_NOTHING, std::make_tuple(status, nullptr)); napi_value json = nullptr; status = napi_get_named_property(env, global, GLOBAL_JSON, &json); PRE_CHECK_RETURN_CORE(status == napi_ok, PRE_REVT_NOTHING, std::make_tuple(status, nullptr)); napi_value stringify = nullptr; status = napi_get_named_property(env, json, GLOBAL_STRINGIFY, &stringify); PRE_CHECK_RETURN_CORE(status == napi_ok, PRE_REVT_NOTHING, std::make_tuple(status, nullptr)); napi_value res = nullptr; napi_value argv[1] = {value}; status = napi_call_function(env, json, stringify, 1, argv, &res); PRE_CHECK_RETURN_CORE(status == napi_ok, PRE_REVT_NOTHING, std::make_tuple(status, nullptr)); return std::make_tuple(napi_ok, res); } napi_value JSUtils::JsonParse(napi_env env, const std::string &inStr, bool sendable) { if (inStr.empty()) { LOG_ERROR("JsonParse failed, inStr is empty"); return nullptr; } napi_value jsValue = Convert2JSValue(env, inStr); napi_value global = nullptr; PRE_CHECK_RETURN_CORE(napi_get_global(env, &global) == napi_ok, PRE_REVT_NOTHING, nullptr); napi_value json = nullptr; PRE_CHECK_RETURN_CORE( napi_get_named_property(env, global, GLOBAL_JSON, &json) == napi_ok, PRE_REVT_NOTHING, nullptr); napi_value parse = nullptr; PRE_CHECK_RETURN_CORE( napi_get_named_property(env, json, sendable ? GLOBAL_PARSE_SENDABLE : GLOBAL_PARSE, &parse) == napi_ok, PRE_REVT_NOTHING, nullptr); if (GetValueType(env, parse) != napi_function) { LOG_ERROR("Get parse func failed"); return nullptr; } napi_value res = nullptr; napi_value argv[1] = { jsValue }; PRE_CHECK_RETURN_CORE(napi_call_function(env, json, parse, 1, argv, &res) == napi_ok, PRE_REVT_NOTHING, nullptr); return res; } } // namespace PreferencesJsKit } // namespace OHOS