/*
* 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.
*/
#if __OHOS_PLATFORM__
// need to use a workaround
// as napi_set_instance_data/napi_get_instance_data
// seems to be implemented incorrectly in a way
// that shares single instance data and env for ALL modules.
#define USE_WORKAROUND 1
#else
#define USE_WORKAROUND 0
#endif
#if USE_WORKAROUND
#include
#endif
#include "array.h"
#include "function.h"
#include "object.h"
#include "utils.h"
namespace NapiApi {
MyInstanceState::MyInstanceState(napi_env env, napi_value obj) : env_(env)
{
napi_create_reference(env_, obj, 1, &ref_);
}
MyInstanceState::~MyInstanceState()
{
uint32_t res;
napi_reference_unref(env_, ref_, &res);
}
napi_value MyInstanceState::GetRef()
{
napi_value tmp;
napi_get_reference_value(env_, ref_, &tmp);
return tmp;
}
#if USE_WORKAROUND
namespace {
// workaround os bug
class workaround {
public:
workaround() = default;
workaround(const workaround&) = delete;
workaround(workaround&& other) noexcept
{
cb = other.cb;
hint = other.hint;
data = other.data;
env = other.env;
other.cb = nullptr;
other.hint = nullptr;
other.data = nullptr;
other.env = nullptr;
}
workaround& operator=(const workaround& other) = delete;
workaround& operator=(workaround&& other) noexcept
{
cb = other.cb;
hint = other.hint;
data = other.data;
env = other.env;
other.cb = nullptr;
other.hint = nullptr;
other.data = nullptr;
other.env = nullptr;
return *this;
}
~workaround()
{
if (cb) {
cb(env, data, hint);
}
}
workaround(napi_env e, void* d, napi_finalize c, void* h) : env(e), data(d), cb(c), hint(h) {};
napi_finalize cb { nullptr };
void* hint { nullptr };
void* data { nullptr };
napi_env env { nullptr };
};
BASE_NS::unordered_map workaround_data;
}; // namespace
#endif
void MyInstanceState::GetInstance(napi_env env, void** data)
{
if (!data || !env) {
return;
}
#if USE_WORKAROUND
// workaround os bug
if (!workaround_data.contains((uintptr_t)env)) {
*data = nullptr;
return;
}
*data = workaround_data[(uintptr_t)env].data;
#else
napi_get_instance_data(env, data);
#endif
}
void MyInstanceState::SetInstance(napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint)
{
if (!env) {
return;
}
#if USE_WORKAROUND
// workaround os bug
if (workaround_data.contains((uintptr_t)env)) {
auto& wd = workaround_data[(uintptr_t)env];
wd.env = env;
wd.data = data;
wd.cb = finalize_cb;
wd.hint = finalize_hint;
return;
}
workaround_data.insert({ (uintptr_t)env, { env, data, finalize_cb, finalize_hint } });
#else
napi_set_instance_data(env, data, finalize_cb, finalize_hint);
#endif
}
void MyInstanceState::StoreCtor(BASE_NS::string_view name, napi_value ctor)
{
NapiApi::Object exp(env_, GetRef());
exp.Set(name, ctor);
}
napi_value MyInstanceState::FetchCtor(BASE_NS::string_view name)
{
NapiApi::Object exp(env_, GetRef());
return exp.Get(name);
}
template
bool ValidateType(napi_valuetype jstype, bool isArray)
{
/*
napi_undefined,
napi_null,
napi_symbol,
napi_function,
napi_external,
napi_bigint,
*/
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_string) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_boolean) {
return true;
}
}
// yup..
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_number) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_number) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_number) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_number) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_number) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_number) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_object) {
return true;
}
// allow undefined and null also
if (jstype == napi_undefined) {
return true;
}
if (jstype == napi_null) {
return true;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_object) {
return isArray;
}
}
if constexpr (BASE_NS::is_same_v) {
if (jstype == napi_function) {
return true;
}
// allow undefined and null also
if (jstype == napi_undefined) {
return true;
}
if (jstype == napi_null) {
return true;
}
}
return false;
}
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
template bool ValidateType(napi_valuetype, bool);
} // namespace NapiApi