• 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 ECMASCRIPT_NAPI_JSNAPI_HELPER_H
17 #define ECMASCRIPT_NAPI_JSNAPI_HELPER_H
18 
19 #include "ecmascript/ecma_runtime_call_info.h"
20 #include "ecmascript/js_handle.h"
21 #include "ecmascript/js_tagged_value.h"
22 #include "ecmascript/napi/include/jsnapi.h"
23 
24 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
25 #define RETURN_VALUE_IF_ABRUPT(thread, value)                 \
26     do {                                                      \
27         if (thread->HasPendingException()) {                  \
28             LOG_FULL(ERROR) << "occur exception need return"; \
29             return value;                                     \
30         }                                                     \
31     } while (false)
32 
33 #if ECMASCRIPT_ENABLE_NAPI_SPECIAL_CHECK
34 #define LOG_IF_SPECIAL(handleValue, level)                                                       \
35     do {                                                                                         \
36         LOG_ECMA(DEBUG) << "Enable napi special check";                                           \
37         if ((handleValue).GetTaggedValue().IsSpecial()) {                                        \
38             LOG_FULL(level) << "Special value " << (handleValue).GetTaggedType() << " checked!"; \
39         }                                                                                        \
40     } while (false)
41 #else
42 #define LOG_IF_SPECIAL(handleValue, level) static_cast<void>(0)
43 #endif
44 
45 #define CROSS_THREAD_CHECK(vm)                                                                  \
46     [[maybe_unused]] JSThread *thread = (vm)->GetJSThread()
47 
48 #define CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, returnVal)                              \
49     CROSS_THREAD_CHECK(vm);                                                                      \
50     do {                                                                                         \
51         if (thread->HasPendingException()) {                                                     \
52             LOG_ECMA(ERROR) << "Pending exception before " << __FUNCTION__ << " called in line:" \
53                             << __LINE__ << ", exception details as follows:";                    \
54             JSNApi::PrintExceptionInfo(vm);                                                      \
55             return returnVal;                                                                    \
56         }                                                                                        \
57     } while (false)
58 
59 #define CROSS_THREAD_AND_EXCEPTION_CHECK(vm)                                                      \
60     CROSS_THREAD_CHECK(vm);                                                                       \
61     do {                                                                                          \
62         if (thread->HasPendingException()) {                                                      \
63             LOG_ECMA(ERROR) << "Pending exception before " << __FUNCTION__ << " called, in line:" \
64                             << __LINE__ << ", exception details as follows:";                     \
65             JSNApi::PrintExceptionInfo(vm);                                                       \
66             return;                                                                               \
67         }                                                                                         \
68     } while (false)
69 
70 #define SINGLE_THREAD_CHECK_WITH_RETURN(vm, result)                                              \
71     [[maybe_unused]] JSThread *thread = (vm)->GetJSThreadNoCheck();                              \
72     do {                                                                                         \
73         if (thread->HasPendingException()) {                                                     \
74             LOG_ECMA(DEBUG) << "Pending exception before " << __FUNCTION__ << " called in line:" \
75                             << __LINE__ << ", exception details as follows:";                    \
76             JSNApi::PrintExceptionInfo(vm);                                                      \
77             return result;                                                                       \
78         }                                                                                        \
79         if (!(vm)->CheckSingleThread()) {                                                        \
80             LOG_ECMA(DEBUG) << "cross thread to call " << __FUNCTION__ << "is not supported";    \
81             return result;                                                                       \
82         }                                                                                        \
83     } while (false)
84 
85 #define DCHECK_SPECIAL_VALUE(jsValueRef)                                                     \
86     do {                                                                                     \
87         auto val = reinterpret_cast<JSTaggedValue *>(jsValueRef);                            \
88         if (UNLIKELY(val->IsSpecial())) {                                                    \
89             LOG_FULL(ERROR) << "JSNApi special value:0x" << val->GetRawData() << " checked"; \
90             return;                                                                          \
91         }                                                                                    \
92     } while (false)
93 
94 #define DCHECK_SPECIAL_VALUE_WITH_RETURN(jsValueRef, retValue)                               \
95     do {                                                                                     \
96         auto val = reinterpret_cast<JSTaggedValue *>(jsValueRef);                            \
97         if (UNLIKELY(val->IsSpecial())) {                                                    \
98             LOG_FULL(ERROR) << "JSNApi special value:0x" << val->GetRawData() << " checked"; \
99             return (retValue);                                                               \
100         }                                                                                    \
101     } while (false)
102 
103 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
104 #define TYPED_ARRAY_ALL(V) \
105     V(Int8Array)           \
106     V(Uint8Array)          \
107     V(Uint8ClampedArray)   \
108     V(Int16Array)          \
109     V(Uint16Array)         \
110     V(Int32Array)          \
111     V(Uint32Array)         \
112     V(Float32Array)        \
113     V(Float64Array)        \
114     V(BigInt64Array)       \
115     V(BigUint64Array)
116 
117 #define SENDABLE_TYPED_ARRAY_ALL(V) \
118     V(SharedInt8Array)     \
119     V(SharedUint8Array)    \
120     V(SharedInt16Array)    \
121     V(SharedUint16Array)   \
122     V(SharedInt32Array)    \
123     V(SharedUint32Array)   \
124     V(SharedUint8ClampedArray)   \
125     V(SharedFloat32Array)   \
126     V(SharedFloat64Array)   \
127     V(SharedBigInt64Array)  \
128     V(SharedBigUint64Array)
129 
130 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
131 #define EXCEPTION_ERROR_ALL(V)         \
132     V(Error, ERROR)                    \
133     V(RangeError, RANGE_ERROR)         \
134     V(SyntaxError, SYNTAX_ERROR)       \
135     V(ReferenceError, REFERENCE_ERROR) \
136     V(TypeError, TYPE_ERROR)           \
137     V(AggregateError, AGGREGATE_ERROR) \
138     V(EvalError, EVAL_ERROR)           \
139     V(OOMError, OOM_ERROR)             \
140     V(TerminationError, TERMINATION_ERROR)
141 
142 namespace panda {
143 using NativeFinalize = void (*)(EcmaVM *);
144 class JSNApiHelper {
145 public:
146     template<typename T>
ToLocal(ecmascript::JSHandle<ecmascript::JSTaggedValue> from)147     static inline Local<T> ToLocal(ecmascript::JSHandle<ecmascript::JSTaggedValue> from)
148     {
149         return Local<T>(from.GetAddress());
150     }
151 
ToJSTaggedValue(JSValueRef * from)152     static inline ecmascript::JSTaggedValue ToJSTaggedValue(JSValueRef *from)
153     {
154         ASSERT(from != nullptr);
155         return *reinterpret_cast<ecmascript::JSTaggedValue *>(from);
156     }
157 
ToJSMutableHandle(Local<JSValueRef> from)158     static inline ecmascript::JSMutableHandle<ecmascript::JSTaggedValue> ToJSMutableHandle(Local<JSValueRef> from)
159     {
160         ASSERT(!from.IsEmpty());
161         return ecmascript::JSMutableHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(*from));
162     }
163 
ToJSHandle(Local<JSValueRef> from)164     static inline ecmascript::JSHandle<ecmascript::JSTaggedValue> ToJSHandle(Local<JSValueRef> from)
165     {
166         ASSERT(!from.IsEmpty());
167         return ecmascript::JSHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(*from));
168     }
169 
ToJSHandle(JSValueRef * from)170     static inline ecmascript::JSHandle<ecmascript::JSTaggedValue> ToJSHandle(JSValueRef *from)
171     {
172         ASSERT(from != nullptr);
173         return ecmascript::JSHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(from));
174     }
175 };
176 
177 class NativeReferenceHelper {
178 public:
NativeReferenceHelper(EcmaVM * vm,Global<ObjectRef> obj,NativeFinalize callback)179     NativeReferenceHelper(EcmaVM *vm, Global<ObjectRef> obj, NativeFinalize callback)
180         :  vm_(vm), obj_(obj), callback_(callback) {}
~NativeReferenceHelper()181     ~NativeReferenceHelper()
182     {
183         obj_.FreeGlobalHandleAddr();
184     }
FreeGlobalCallBack(void * ref)185     static void FreeGlobalCallBack(void* ref)
186     {
187         auto that = reinterpret_cast<NativeReferenceHelper*>(ref);
188         that->obj_.FreeGlobalHandleAddr();
189     }
190 
NativeFinalizeCallBack(void * ref)191     static void NativeFinalizeCallBack(void* ref)
192     {
193         auto that = reinterpret_cast<NativeReferenceHelper*>(ref);
194         if (that->callback_ != nullptr) {
195             that->callback_(that->vm_);
196         }
197         that->callback_ = nullptr;
198     }
199 
SetWeakCallback()200     void SetWeakCallback()
201     {
202         obj_.SetWeakCallback(this, FreeGlobalCallBack, NativeFinalizeCallBack);
203     }
204 
205 private:
206     EcmaVM *vm_;
207     Global<ObjectRef> obj_;
208     NativeFinalize callback_ = nullptr;
209 };
210 
211 class Callback {
212 public:
213     static ecmascript::JSTaggedValue RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo);
214 };
215 }  // namespace panda
216 #endif  // ECMASCRIPT_NAPI_JSNAPI_HELPER_H
217