1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_API_INTERNAL_H
17 #define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_API_INTERNAL_H
18
19 #include <cinttypes>
20
21 #include "napi/native_api.h"
22 #include "native_engine.h"
23 #include "utils/log.h"
24
napi_clear_last_error(napi_env env)25 static inline napi_status napi_clear_last_error(napi_env env)
26 {
27 ((NativeEngine*)env)->ClearLastError();
28 return napi_ok;
29 }
30
31 static inline napi_status napi_set_last_error(napi_env env,
32 napi_status error_code,
33 uint32_t engine_error_code = 0,
34 void* engine_reserved = nullptr)
35 {
36 ((NativeEngine*)env)->SetLastError(error_code, engine_error_code, engine_reserved);
37 return error_code;
38 }
39
40 #define RETURN_STATUS_IF_FALSE(env, condition, status) \
41 if (!(condition)) { \
42 return napi_set_last_error((env), (status)); \
43 }
44
45 #define CHECK_ENV(env) \
46 if ((env) == nullptr) { \
47 return napi_invalid_arg; \
48 }
49
50 #define CHECK_ARG(env, arg) RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg)
51
52 #define NAPI_PREAMBLE(env) \
53 CHECK_ENV((env)); \
54 RETURN_STATUS_IF_FALSE( \
55 (env), \
56 (reinterpret_cast<NativeEngine*>(env))->lastException_.IsEmpty(), \
57 napi_pending_exception); \
58 napi_clear_last_error((env)); \
59 TryCatch tryCatch(env)
60
61 #define GET_RETURN_STATUS(env) \
62 (!tryCatch.HasCaught() \
63 ? napi_ok \
64 : napi_set_last_error((env), napi_pending_exception))
65
66 #define CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj) \
67 bool isObj = (nativeValue)->IsObjectWithoutSwitchState((vm)); \
68 bool isFunc = !isObj ? (nativeValue)->IsFunction((vm)) : true; \
69 RETURN_STATUS_IF_FALSE((env), isObj || isFunc, napi_object_expected); \
70 Local<ObjectRef> (obj); \
71 if (LIKELY(isObj)) { \
72 (obj) = Local<ObjectRef>((nativeValue)); \
73 } else { \
74 (obj) = (nativeValue)->ToEcmaObjectWithoutSwitchState((vm)); \
75 }
76
77 #define CROSS_THREAD_CHECK(env) \
78 do { \
79 NativeEngine* engine = reinterpret_cast<NativeEngine*>((env)); \
80 if (UNLIKELY(engine->IsCrossThreadCheckEnabled())) { \
81 ThreadId tid = NativeEngine::GetCurSysTid(); \
82 if (tid != engine->GetSysTid()) { \
83 HILOG_FATAL("current napi interface cannot run in multi-thread, " \
84 "thread id: %{public}d, current thread id: %{public}d", \
85 engine->GetSysTid(), tid); \
86 }; \
87 }; \
88 } while (0)
89
90 #define WEAK_CROSS_THREAD_CHECK(env) \
91 do { \
92 NativeEngine* engine = reinterpret_cast<NativeEngine*>((env)); \
93 if (UNLIKELY(engine->IsCrossThreadCheckEnabled())) { \
94 ThreadId tid = NativeEngine::GetCurSysTid(); \
95 if (tid != engine->GetSysTid()) { \
96 std::string stack; \
97 bool backtrace = DumpHybridStack(engine->GetEcmaVm(), stack, 0, 8); \
98 HILOG_ERROR("current napi interface cannot run in multi-thread, " \
99 "thread id: %{public}d, current thread id: %{public}d" \
100 "\n%{public}s", \
101 engine->GetSysTid(), tid, backtrace ? stack.c_str() : "Faild to backtrace."); \
102 }; \
103 }; \
104 } while (0)
105
106 #define LOG_IF_SPECIAL(engine, condition, fmt, ...) \
107 do { \
108 if ((condition)) { \
109 HILOG_FATAL(fmt, ##__VA_ARGS__); \
110 } else { \
111 std::string stack; \
112 bool backtrace = DumpHybridStack((engine)->GetEcmaVm(), stack, 0, 8); \
113 HILOG_ERROR(fmt "\n%{public}s", ##__VA_ARGS__, backtrace ? stack.c_str() : "Faild to backtrace."); \
114 } \
115 } while (0)
116
117 #ifndef LIKELY
118 #define LIKELY(exp) (__builtin_expect((exp) != 0, true)) // NOLINT(cppcoreguidelines-macro-usage)
119 #endif
120
121 #ifndef UNLIKELY
122 #define UNLIKELY(exp) (__builtin_expect((exp) != 0, false)) // NOLINT(cppcoreguidelines-macro-usage)
123 #endif
124
ValidEngineCheck(NativeEngine * input,NativeEngine * owner,uint64_t ownerId,const char * func,const char * file,int line)125 inline bool ValidEngineCheck(NativeEngine* input,
126 NativeEngine* owner,
127 uint64_t ownerId,
128 const char* func,
129 const char* file,
130 int line)
131 {
132 if (input != owner) {
133 LOG_IF_SPECIAL(input, UNLIKELY(input->IsCrossThreadCheckEnabled()),
134 "param env not equal to its owner. %{public}s at %{public}s:%{public}d",
135 func, file, line);
136 return false;
137 }
138 if (ownerId != input->GetId()) {
139 LOG_IF_SPECIAL(input, UNLIKELY(input->IsCrossThreadCheckEnabled()),
140 "owner env has been destroyed, "
141 "owner id: %{public}" PRIu64 ", current env id: %{public}" PRIu64 ". "
142 "%{public}s at %{public}s:%{public}d, ",
143 ownerId, input->GetId(), func, file, line);
144 return false;
145 }
146 return true;
147 }
148
149 #define VALID_ENGINE_CHECK(input, owner, id) \
150 ValidEngineCheck((input), (owner), (id), __FUNCTION__, __FILENAME__, __LINE__)
151
152 #ifdef ENABLE_CONTAINER_SCOPE
EnableContainerScope(napi_env env)153 inline bool EnableContainerScope(napi_env env)
154 {
155 NativeEngine* engine = reinterpret_cast<NativeEngine*>(env);
156 return engine->IsContainerScopeEnabled();
157 }
158 #endif
159
160 #define SWITCH_CONTEXT(env) \
161 auto engine = reinterpret_cast<NativeEngine *>(env); \
162 if (UNLIKELY(engine->IsMultiContextEnabled())) { \
163 auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm()); \
164 panda::Local<panda::JSValueRef> envContext = engine->GetContext(); \
165 if (!(envContext == panda::JSNApi::GetCurrentContext(vm))) { \
166 napi_status status = engine->SwitchContext(); \
167 if (status != napi_ok) { \
168 return napi_set_last_error(env, status); \
169 } \
170 } \
171 }
172
173 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_API_INTERNAL_H */
174