• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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